質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Q&A

解決済

2回答

2548閲覧

Vue.jsブラウザで画像ファイルを選択した時にプレビュー表示がされない。

tkm0604

総合スコア555

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

0グッド

0クリップ

投稿2021/12/01 04:02

編集2021/12/01 04:03

Vue.js 単一コンポーネントに画像ファイルを選択した時にブラウザでプレビュー(canvasとして)されるコードを書いたのですが、プレビューされません。

画像の選択があった場合に処理を実行したいので、computedに画像ファイルを選択した時にプレビュー表示するscriptを書き、previewImageを返したいので、dataにreturn : null(初期値は無)という考えで書いたのですが、
「app.js:14974 Uncaught TypeError: Cannot read properties of undefined (reading '0')」
となってしまいます。

Vue

1<template> 2 <canvas id="preview"></canvas> 3 <input type="file" name="image" accept="image/*" @change="previewImage(obj.files[0])" /> 4 <p> 5 <input type="text" id="canvas_text" value="我輩は犬である" /> 6 <button @click="drawText('preview', 'canvas_text')">文字を描く</button> 7 </p> 8</template> 9 10<script> 11export default { 12 13 data(){ 14 return{ 15 previewImage: null 16 } 17 }, 18 computed: { 19 previewImage: function (obj) { 20 const fileReader = new FileReader(); 21 fileReader.onload = function () { 22 const canvas = document.getElementById("preview"); 23 const ctx = canvas.getContext("2d"); 24 const image = new Image(); 25 image.src = fileReader.result; 26 image.onload = function () { 27 canvas.width = image.width; 28 canvas.height = image.height; 29 ctx.drawImage(image, 0, 0); 30 }; 31 }; 32 fileReader.readAsDataURL(obj.files[0]); 33 }, 34 }, 35 methods: { 36 37 //キャンバスに文字を描く 38 drawText: function (canvas_id, text_id) { 39 const canvas = document.getElementById(canvas_id); 40 const ctx = canvas.getContext("2d"); 41 const text = document.getElementById(text_id); 42 //文字のスタイルを指定 43 ctx.font = "32px serif"; 44 ctx.fillStyle = "#404040"; 45 //文字の配置を指定(左上基準にしたければtop/leftだが、文字の中心座標を指定するのでcenter 46 ctx.textBaseline = "center"; 47 ctx.textAlign = "center"; 48 //座標を指定して文字を描く(座標は画像の中心に) 49 const x = canvas.width / 2; 50 const y = canvas.height / 2; 51 ctx.fillText(text.value, x, y); 52 }, 53 }, 54}; 55</script>

どこを修正すればいいのでしょうか?
また、今回の場合、画像の選択があった場合に処理を実行したいので、computed で良かったのでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

これで問題ないのでは?そもそも、これテンプレートの時点でルール違反(単一ブロックで括られていない)で、エラーとなるはずですが。

this.$refsを使うことで、毎回選択したファイル情報を取得してくれます(document.querySelectorやgetElementByIdと同じ役割を果たしてくれるので便利)

方法は取得したいタグにrefプロパティを設定するだけです。あとは

this.$refs.設定したプロパティ名

で、任意のDOM内の情報取得し放題です。

vue

1<template> 2 <div> 3 <canvas ref="preview"></canvas> 4 <input type="file" name="image" accept="image/*" ref="selectimage" @change="previewImage" /> 5 <p> 6 <input type="text" id="canvas_text" value="我輩は犬である" /> 7 <button @click="drawText('preview', 'canvas_text')">文字を描く</button> 8 </p> 9 </div> 10</template> 11 12/*中略*/ 13methods:{ 14 previewImage: function () { 15 let file = this.$refs.selectimage.files //ファイル情報の取得 16 const canvas = this.$refs.preview; //canvasタグ 17 const fileReader = new FileReader(); 18 fileReader.onload = function () { 19 const ctx = canvas.getContext("2d"); 20 const image = new Image(); 21 image.src = fileReader.result; 22 image.onload = function () { 23 canvas.width = image.width; 24 canvas.height = image.height; 25 ctx.drawImage(image, 0, 0); 26 }; 27 }; 28 fileReader.readAsDataURL(file[0]); 29 } 30}, 31

投稿2021/12/01 08:15

編集2021/12/01 14:23
FKM

総合スコア3647

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tkm0604

2021/12/01 13:31

コメントありがとうございます。 教えていただいたコードに書き換えると、 var canvas = this.$refs.preview; //canvasタグ の箇所で、 Uncaught TypeError: Cannot read properties of undefined (reading 'preview') at FileReader.fileReader.onload というエラーがコンソールに出て、画像がプレビューされません。
tkm0604

2021/12/01 13:34

/*中略*/ とされている箇所は、 data(){ return{ previewImage: null } }, を書くのでしょうか? 上記コードを書くとエラーは消えるのですが、画像はプレビューされません。
FKM

2021/12/01 13:40 編集

canvasタグにref="preview"を記述してますか?それからpreviewImageはメソッド名なのでdataに記述する必要ないですよ。
tkm0604

2021/12/01 13:53 編集

コメントありがとうございます。 何度もすみません。 下記のように書いていますが、画像を選択すると var canvas = this.$refs.preview; //canvasタグ の箇所で app.js:14959 Uncaught TypeError: Cannot read properties of undefined (reading 'preview') at FileReader.fileReader.onload というエラーがでます。 <template> <div> <canvas ref="preview"></canvas> <input type="file" name="image" accept="image/*" ref="selectimage" @change="previewImage" /> <p> <input type="text" id="canvas_text" value="我輩は犬である" /> <button @click="drawText('preview', 'canvas_text')">文字を描く</button> </p> </div> </template> methods: { previewImage: function () { let file = this.$refs.selectimage.files //ファイル情報の取得 const fileReader = new FileReader(); fileReader.onload = function () { const canvas = this.$refs.preview; //canvasタグ const ctx = canvas.getContext("2d"); const image = new Image(); image.src = fileReader.result; image.onload = function () { canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image, 0, 0); }; }; fileReader.readAsDataURL(file[0]); }, } このように書いています。
FKM

2021/12/01 14:24

回答を修正しました。 let file = this.$refs.selectimage.files //ファイル情報の取得 const canvas = this.$refs.preview; //canvasタグ const fileReader = new FileReader(); fileReader.onload = function () { の順に書き換えてください。fileReader.onloadイベント内部では認識できなかったです。
tkm0604

2021/12/01 14:40

実装できました。 「this.$refsを使うことで、毎回選択したファイル情報を取得してくれます」ここが全く思い浮かばなかったです。 また、fileReader.onloadイベント内部では認識できない。 ということも、考えも及ばなかったです。 勉強になりました。 何度も本当にありがとうございます。
guest

0

computedは@changeイベントなどで実行するものではないです。
勝手に実行されており、任意の引数を与えることもできません。
computedは基本的にgetter関数のみと書いてあります。vue2.xでは。
https://jp.vuejs.org/v2/guide/computed.html

watchを使うかmethodsで処理すべきかと。

またdata内とcomputed内とmethods内は同一オブジェクト内のメンバーとして
存在するため、同一の名前を付けることはできないはずです。上書きされてしまう。

ただこれでエラー表示が変わるかどうかはちょっとわからないですね…

コンポーネントは再利用をベースにしているのでidの重複が懸念されるくらいでしょうか。

投稿2021/12/01 05:42

sousuke

総合スコア3830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問