アプリ版:「スタンプのみでお礼する」機能のリリースについて

ファイルのアップロード機能を作成していて、アップロードする場所にカメラの画像を配置しているのですが、ファイルをアップロードするとその下に画像や動画やpdfが表示されてしまいます。
ファイルを選択したあと?アップロード後?にカメラの画像を見えなくしてその上からアップロードファイルを表示することは出来ますでしょうか?

※参考サイト
http://www.irasuto.cfbx.jp/掲示板テスト/

<form method="post">
<div class="image-partial">
<h2>動画・画像をアップロード(Upload video・image)<span class="required">※ファイルサイズ15MB以内、JPG/GIF/PNG/MP4</span></h2>
<div class="image-selector-button">
<label>
<div class="image-camera-icon">
<img src="<?php echo $camera_url; ?>" style="height: 100px;">
</div>
<input type="file" class="attach" name="attach[]" accept=".png, .jpg, .jpeg, .pdf, .mp4" style="display: none;">
</label>
<input type="hidden" class="attachdel" name="attachdel[]">
<button type="button" class="attachclear">clear</button>
<div class="viewer"><?php echo $attach[0]; ?></div>
</div>
<div class="image-selector-button">
<label>
<div class="image-camera-icon">
<img src="<?php echo $camera_url; ?>" style="height: 100px;">
</div>
<input type="file" class="attach" name="attach[]" accept=".png, .jpg, .jpeg, .pdf, .mp4" style="display: none;">
</label>
<input type="hidden" class="attachdel" name="attachdel[]">
<button type="button" class="attachclear">clear</button>
<div class="viewer"><?php echo $attach[1]; ?></div>
</div>
</div>
</form>

<script>
const attach = document.querySelectorAll('.attach');
const del = document.querySelectorAll('.attachdel');
const clear = document.querySelectorAll('.attachclear');
const viewer = document.querySelectorAll('.viewer');
for (let i = 0; i < attach.length; i++) {
attach[i].addEventListener('change', () => {
if (attach[i].files[0].size > 15 * 1024 * 1024) {
alert('ファイルサイズが 15MBバイトを超えています');
return;
}
del[i].value = "";
viewer[i].innerHTML = "";
if (attach[i].files.length !== 0) {
const reader = new FileReader();
reader.onload = () => {
var child = null;
if (reader.result.indexOf("data:image/jpeg;base64,") === 0 ||
reader.result.indexOf("data:image/png;base64,") === 0) {
child = document.createElement("img");
} else if (reader.result.indexOf("data:video/mp4;base64,") === 0) {
child = document.createElement("video");
child.setAttribute("controls", null);
} else if (reader.result.indexOf("data:application/pdf;base64,") === 0) {
child = document.createElement("iframe");
} else {
alert("対象外のファイルです");
alert(reader.result);
attach[i].value = "";
}
if (child !== null) {
child.style.height = "100px";
child.src = reader.result;
viewer[i].appendChild(child);
}
};
reader.readAsDataURL(attach[i].files[0]);
}
});
clear[i].addEventListener('click', () => {
attach[i].value = "";
del[i].value = "1";
viewer[i].innerHTML = "";
});
}
</script>

A 回答 (3件)

No2です。



>ファイルを削除することもできなくなるのではないでしょうか?
「ファイルを削除」するわけではなくて、表示を消すだけだと思いますけれど? 違うのかな?
消去するのなら、Clearボタンでできるのではないでしょうか?
(ボタンは表示されたままなので、押すことは可能です)
もしも、表示中の画像クリックでも消したければ、そちらにも同様のイベントを設定しておけば可能になります。

No2の表示の変化で良いのかどうかも不明のままですけれど、まだ意味が伝わらないようなので、No2に簡単なスクリプトを追加してみました。
動作イメージだけなので、受付けるのは画像(=.jpg .png)だけにしてあります。
(イベントは、カメラの画像とClearボタンのみ)
 Chrome、fx で動作確認。

※ 質問者様がお求めのものに合っているのかが不明ですが、これ以上は説明のしようもないので、違っているならスルーしてください。

<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
/* 通常時のレイアウト */
form > div { display: flex; }
.image-selector-button {
position: relative;
margin: .3em;
}
.image-selector-button label img {
width: 200px; height: 100px;
}
.image-selector-button input { display: none; }

/* 画像表示時のレイアウト */
.image-selector-button.image-on label { visibility: hidden; }
.image-selector-button.image-on .viewer {
position: absolute;
top:0; left: 0;
width: 100%; height: 100px;
overflow: hidden;
}
</style>
</head>
<body>
<form method="post">
<div>
<div class="image-selector-button">
<label>
<div><img src="img/camera.jpg"></div>
<input type="file" accept=".png, .jpg">
</label>
<input type="hidden">
<button type="button">clear</button>
<div class="viewer"></div>
</div>
</div>
</form>

<script>
(()=>{
const
fileTypes = ['image/jpeg','image/png'],
wrap = document.querySelector('form > div'),
P = e => e.closest('.image-selector-button'),
V = e => P(e).querySelector('.viewer'),
C = (e, s) => P(e).classList[s]('image-on');

for(let i = 0; i<3; i++)
wrap.appendChild(wrap.firstElementChild.cloneNode(1));

/* クリアボタン */
wrap.addEventListener('click', (e, t = e.target) => {
if(t.nodeName != 'BUTTON' || t.type != 'button') return;
V(t).innerHTML = '';
C(t, 'remove');
});

/* 画像登録 */
wrap.addEventListener('change', (e, t = e.target) => {
if(t.nodeName != 'INPUT' || t.type != 'file') return;
if(t.files.length == 0 || !fileTypes.includes(t.files[0].type)) return;
const img = document.createElement('img');
img.src = URL.createObjectURL(t.files[0]);
img.style.height = '100px';
V(t).appendChild(img);
C(t, 'add');
});
})();
</script>
</body>
</html>
    • good
    • 1
この回答へのお礼

回答ありがとうございます、クラスをあらかじめ2つ用意した状態で切り替えることで、cssで表示非表示を切り替えるという感じでしょうか?

お礼日時:2023/06/12 22:45

No1です。



>A.おそらく下記のアップロードファイル削除のことだと思いますが
違います。
下にある画像がはみ出して見えてしまう可能性を防止するために、visibility: hidden; にすると言う意味です。
(縦長画像を入力すると、下の画像がはみ出して見えるはず)
非表示にすると、設定してあるイベントも効かなくなりますが、画像表示中はイベントが効かなくても良いものと推測しました。
clear等で親のクラスを削除すれば、最初の表示に戻るので、再度イベントも感知できるようになります。


あまり意味が伝わっていないようですので、簡略化した例を以下に。
元のHTMLの構造はほぼそのままです。(属性等は簡略化してあります)
左側の div を、仮に、現状で画像を表示した状態と考えてください。
(画像部分には、お手元の適当な画像を入れてください)

右側も、全く同じHTMLですが、親要素に「image-on」のクラスを付してあります。
No1の回答はこのクラスを付すことで、画像を入れ替えたように見せることが可能という意味です。
(ご質問の内容は、このような表示になさりたいということではないかと解釈しました)
クラスを外せば左側のレイアウトに戻りますが、その際には、実際には入力画像は消されていて表示されないはずと推測します。


<!DOCTYPE HTML>
<html lang="ja">
<head><title>Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<style>
/* 通常時のレイアウト */
form > div { display: flex; }
.image-selector-button {
position: relative;
margin: .3em;
}
.image-selector-button label img {
width: 200px; height: 100px;
}
.image-selector-button input { display: none; }

/* 画像表示時のレイアウト */
.image-selector-button.image-on label { visibility: hidden; }
.image-selector-button.image-on .viewer {
position: absolute;
top:0; left: 0;
width: 100%; height: 100px;
overflow: hidden;
}
</style>
</head>
<body>

<form method="post">
<div>
<div class="image-selector-button">
<label>
<div><img src="img/camera.jpg"></div>
<input type="file" accept=".png, .jpg">
</label>
<input type="hidden">
<button type="button">clear</button>
<div class="viewer">
<img src="img/photo01.jpg" style="height:100px;">
</div>
</div>

<div class="image-selector-button image-on">
<label>
<div><img src="img/camera.jpg"></div>
<input type="file" accept=".png, .jpg">
</label>
<input type="hidden">
<button type="button">clear</button>
<div class="viewer">
<img src="img/photo01.jpg" style="height:100px;">
</div>
</div>
</div>
</form>
</body>
</html>
    • good
    • 1
この回答へのお礼

A.回答ありがとうございます。
画像表示中はイベントが効かないとのことですが、ファイルを削除することもできなくなるのではないでしょうか?

clear[i].addEventListener('click', () => {
attach[i].value = "";
del[i].value = "1";
viewer[i].innerHTML = "";
});

お礼日時:2023/06/11 23:14

こんばんは



ざっと見ただけですが・・・

>カメラの画像を見えなくしてその上からアップロード
>ファイルを表示することは出来ますでしょうか?
カメラの画像と同じ位置に、新しい画像等を表示したいということですよね?

要素を入れ替えても良いのなら、label要素を削除して、同じ位置に画像等を挿入すれば良いです。
ただし、他のスクリプトが、label等が存在することを前提にしているようなので、文書を変える方法だとスクリプト全体を見直す必要がありそうですね。


現状のままで行いたいのなら、処理はそのままにしておいて、画像を表示する位置(レイアウト)を変えてあげれば、それでも可能と思います。
inline-blockにしているdiv要素を、position: relative; にしておいて、画像を表示したらそのエレメントを
 position: absolute;
 top: 0; left:0;
になるように設定すれば、カメラの画像(=div内の最初の要素)に重なります。
(多分、サイズの指定も必要かも知れません)

ただし、上にくる画像のサイズによっては、下の画像がはみ出して見えてしまう可能性があります。
イベントを使えなくしても良いのなら(多分かまわないのだろうと推測しますが)、下のlabel要素は visibility: hidden; にしてしまうとか。(display:noneでも良いですが、buttonが上に移動します)

複数要素のstyleを変えることになるので、個別に設定していくよりも、親要素に「表示モードを切り替えるクラス」を用意しておいて、親要素のクラス設定だけで、レイアウトを変えられるようにしておくのが簡単そうな気がします。
 ・画像を表示したらクラスを設定
 ・画像を削除したらクラスを削除
のような処理を追加するだけで済むと思いますので。
    • good
    • 1
この回答へのお礼

Q.カメラの画像と同じ位置に、新しい画像等を表示したいということですよね?

A.回答ありがとうございます、そういうことになりますね。


Q.inline-blockにしているdiv要素を、position: relative; にしておいて、画像を表示したらそのエレメントを
 position: absolute;
 top: 0; left:0;
になるように設定すれば、カメラの画像(=div内の最初の要素)に重なります。
(多分、サイズの指定も必要かも知れません)

A.その発想はありませんでしたが、確かに重ねることで下のカメラ画像を隠すことも可能ですね。


Q.イベントを使えなくしても良いのなら(多分かまわないのだろうと推測しますが)、下のlabel要素は visibility: hidden; にしてしまうとか。(display:noneでも良いですが、buttonが上に移動します)

A.おそらく下記のアップロードファイル削除のことだと思いますが、こちらは残したうえで実装したいと考えております。

clear[i].addEventListener('click', () => {
attach[i].value = "";
del[i].value = "1";
viewer[i].innerHTML = "";
});
}


Q.複数要素のstyleを変えることになるので、個別に設定していくよりも、親要素に「表示モードを切り替えるクラス」を用意しておいて、親要素のクラス設定だけで、レイアウトを変えられるようにしておくのが簡単そうな気がします。
 ・画像を表示したらクラスを設定
 ・画像を削除したらクラスを削除
のような処理を追加するだけで済むと思いますので。

A.アドバイスありがとうございます、そのようなことも考えてみます。

お礼日時:2023/06/10 22:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!