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

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

ただいまの
回答率

87.59%

Nuxt.js で画像をリサイズしてblobでプレビュー表示しようとしたところ、画像が表示されませんでした。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,076

score 16

前提・実現したいこと

現在、Nuxt.js を用いて、画像をアップロード・表示するだけのアプリを作成しています。
そこで、

①画像の選択
②画像のアップロード
③画像の表示
④画像の削除

これらの機能は実装できたのですが、画像がデカすぎでキモいのでリサイズ機能を実装したところ、肝心の画像が表示されなくなってしまいましたので、解決したいです。

発生している問題・エラーメッセージ

○画像をリサイズしてアップロード・表示できない。

該当のソースコード

<template>
  <div class="resize-img">
    <!-- 画像選択 -->
    <div v-show="!resizedImg" class="resize-img__post">
      <label for="file" class="resize-img__post__label">
        <input
          id="file"
          ref="fileInput"
          type="file"
          @change="uploadImg"
        >
      </label>
    </div>
    <!-- プレビュー -->
    <div v-show="resizedImg" class="resize-img__preview">
      <div class="resize-img__preview__circle" @click="clearUploadImg">
        <span class="resize-img__preview__circle__close-icon">x</span>
      </div>
      <canvas ref="canvas" class="resize-img__preview__canvas" />
    </div>
  </div>
  <!-- <div class="contents">
    <label v-show="!uploadedImage" class="input-item__label">
      <input type="file" @change="onFileChange">
    </label>
    <div class="preview-item">
      <img v-show="uploadedImage" class="preview-item-file" :src="uploadedImage" alt="">
      <div v-show="uploadedImage" class="preview-item-btn" @click="remove">
        <e-icon class="preview-item-icon">
          close
        </e-icon>
      </div>
    </div>
  </div> -->
</template>

<script>
export default {
  data () {
    return {
      resizedImg: null
    }
  },
  destroyed () {
    this.clearUploadImg()
  },
  methods: {
    uploadImg (e) {
      const file = e.target.files[0]
      const reader = new FileReader()
      reader.onload = (e) => {
        this.generateImgUrl(e.target.result)
      }
      reader.readAsDataURL(file)
    },
    generateImgUrl (file) {
      const image = new Image()
      image.crossOrigin = 'Annonymous'

      image.onload = (e) => {
        const resizedBase64 = this.makeResizeImg(image)
        // リサイズ済みのBase64をblobに変換
        const resizedBlob = this.base64ToBlob(resizedBase64)
        // urlを生成してプレビュー表示できるようにする
        const resizedImg = window.URL.createObjectURL(resizedBlob)
        this.resizdeImg = resizedImg
      }
      image.src = file
    },
    makeResizeImg (image) {
      const canvas = this.$refs.canvas
      const ctx = canvas.getContext('2d') // 2Dコンテキスト
      // 縦横で長い方の最大値を1000とする
      const MAX_SIZE = 1000

      // MAX_SIZEよりも小さかったらそのまま
      if (image.width < MAX_SIZE && image.height < MAX_SIZE) {
        [canvas.width, canvas.height] = [image.width, image.height]
        ctx.drawImage(image, 0, 0)
        return canvas.toDataURL('image/jpeg')
      }

      let dstWidth
      let dstHeight
      // 縦横比の計算
      if (image.width > image.height) {
        dstWidth = MAX_SIZE
        dstHeight = (image.height * MAX_SIZE) / image.width
      } else {
        dstHeight = MAX_SIZE
        dstWidth = (image.width * MAX_SIZE) / image.height
      }
      canvas.width = dstWidth
      canvas.height = dstHeight
      // リサイズ
      ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, dstWidth, dstHeight)

      // data_url形式に変換したものを返す
      return canvas.toDataURL('image/jpeg')
    },
    clearUploadImg () {
      this.resizedImg = null
      if (this.$resf.fileInput && this.$refs.fileInput.value !== undefined) {
        this.$refs.fileInput.value = ''
      }
    },
    base64ToBlob (base64) {
      const bin = atob(base64.replace(/^.*,/, ''))
      const buffer = new Uint8Array(bin.length)
      for (let i = 0; i < bin.length; i++) {
        buffer[i] = bin.charCodeAt(i)
      }
      return new Blob([buffer.buffer], {
        type: 'image/png'
      })
    }
  }
}
// export default {
//   data () {
//     return {
//       uploadedImage: ''
//     }
//   },
//   methods: {
//     onFileChange (e) {
//       const files = e.target.files || e.dataTransfer.files
//       this.createImage(files[0])
//     },
//     // アップロードした画像を表示
//     createImage (file) {
//       const reader = new FileReader()
//       reader.onload = (e) => {
//         this.uploadedImage = e.target.result
//       }
//       reader.readAsDataURL(file)
//     },
//     remove () {
//       this.uploadedImage = false
//     }
//   }
// }
</script>

<style>
/*.resize-img {
  width: 100px;
  height: 100px;
  margin: 0 auto;
  margin-top: 20px;

  &__post {
    border: 1px solid rgba(#000, 0.16);
    line-height: 30rem;

    &__label {
      display: inline-block;
      width: 100%;
      color: rgba(0, 0, 0, 0.4);
      text-align: center;

      & > input {
        display: none;
      }
    }
  }

  &__preview {
    width: 100px;
    height: 100px;

    &__circle {
      position: absolute;
      right: 37px;
      width: 27px;
      height: 27px;
      margin: 5px;
      padding: 2px 9px;
      border-radius: 50%;
      background-color: rgba(0, 0, 0, 0.3);

      &__close-icon {
        color: #fff;
      }
    }

    &__canvas {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  }
}*/
</style>
<template>
  <div>
    <Upload />
  </div>
</template>

<script>
import Upload from '~/components/Upload.vue'

export default {
  components: {
    Upload
  }
}
</script>

試したこと

以下のサイトを写経してみましたが、肝心の画像が表示されませんでした。

画像をリサイズしてblobでプレビュー表示する方法[Vue/Canvas]

補足情報(FW/ツールのバージョンなど)

{
  "name": "",
  "version": "1.0.0",
  "description": "My epic Nuxt.js project",
  "author": "",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
  },
  "dependencies": {
    "@nuxtjs/axios": "^5.8.0",
    "chart.js": "^2.9.3",
    "eslint-plugin-import": "^2.19.1",
    "firebase": "^7.6.0",
    "jquery": "3.4.1",
    "nuxt": "^2.10.2",
    "vue-chartjs": "^3.5.0",
    "yarn": "^1.21.1"
  },
  "devDependencies": {
    "@nuxtjs/eslint-config": "^2.0.0",
    "@nuxtjs/eslint-module": "^1.1.0",
    "@nuxtjs/vuetify": "^1.9.1",
    "babel-eslint": "^10.0.3",
    "eslint": "^6.7.2",
    "eslint-plugin-nuxt": ">=0.5.0"
  }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

すみません!

再度確認したところ、単純なコードミスで無事解決いたしました💦

お騒がせいたしました。。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る