15
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Nuxt.jsでFirebase storageの画像を含む要素をhtml2canvasでimage化してアップロードする

Last updated at Posted at 2018-12-18

概要

タイトルから何を言っているんだ?と思われる方が多数だと思われるので、簡単にやりたいことを書きます。
個人備忘録です。

やりたいこと

Nuxt.jsで構築した画面の一部を画像にしてTwitterで投稿しようとしています。

そのときに、html2canvasを使って、特定のhtml要素をcanvasに変換し、
その後、imageファイルをしてサーバーに転送、twitterに投稿する文を添えてtwitterに投稿します。

ただここで問題になるのが、canvasにする要素に外部から取得した画像(ここではFirebase Storage)を含む場合に、
CORSが邪魔をしてきたりするので、そのときの戦闘風景が以下説明となります。

TL;DR

methods: [
    async drawCanvas () {    
        await html2canvas(document.getElementById("target"), {
            canvas: document.getElementById("result"),
            width: '100%',
            height: '100%',
            letterRendering: 1,
            useCORS: true, // CORSを有効化
        })
    },
    async tweet() {
      var canvas = document.getElementById("result")
      var base64URL = canvas.toDataURL('image/jpeg').replace(/^.*,/, '')
      res = await this.$axios.post(process.env.TWEET_URL, {
        content: hogehoge,
        image: base64URL
      })
    },
],

useCORS を付ければいいいようです。

使用技術

  • Firebase
  • Nuxt.js -> 2.2.0
  • html2canvas -> 1.0.0-alpha.12
  • npm firebase/app -> 0.3.4

説明

状況

id="target" をimageにしてcanvasに描画しようとしています。
target 内のimgにはこれからローカルの画像をアップロードしようとしています。

<template>
  <div id="target">
    <div class="image_display">
      <img
        :v-if="object.imageURL"
        :src="object.imageURL"
        @click="removeImage"
      ></img>
      <v-icon
        v-else
      >edit</v-icon>
      <input
        type="file"
        @change="onFilePicked"
      >
    </div>
  </div>
  <canvas id="result"></canvas>
</template>

<script>
export default {
  data () {
    return {
      object: {
        imageURL: ""
      }
    }
  }
}
</script>

やったこと

【失敗談】 allowTaintを使用する

html2canvasのオプションに allowTaint があり、これを使用するとcanvasに描画したimageに外部から取得したimageも描画されるようになります。

html2canvas(document.getElementById("target"), {
  canvas: document.getElementById("result"),
  width: '100%',
    height: '100%',
  allowTaint: true
})

何がだめなのか?
アップロードする時に、 document.getElementById("result").toDataURL('image/jpeg') をすると

Tainted canvases may not be exported

というエラーが出てしまいます。これは、「canvas内に不純物が入っているためエクスポートできないですよ」と怒られるわけです。

FirebaseにCORS設定

ではどうするかというと、firebase storageの画像に許可をもらいます。
普通に「firebase storage download」とかで検索すると公式のページがトップに表示されます。
ここにも記載があるとおり、CORSの設定が必要になるので設定します。

cors.json
[
  {
    "origin": ["*"],
    "responseHeader": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 86400
  }
]

【Point】

  • ファイル名は何でもいい
  • 適宜CORSの設定
# firebaseにCORS設定
$ gsutil cors set cors.json gs://project-name.appspot.com/
# 設定内容の確認
$ gsutil cors get gs://project-name.appspot.com/

html2canvasをCORSを使って表示する

<script>
...
html2canvas(document.getElementById('target'), {
  canvas: document.getElementById('result'),
  width: '100%',
  height: '100%',
  useCORS: true
}
...
</script>

参考文献

余談

vuetifyを使ってファイルをアップロードする方法

15
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?