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

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

ただいまの
回答率

87.61%

blobをcanvasに描画したい

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,671

score 45

文字数制限ですべてが出せませんが、画像を読み込んで複数のcavasを利用し、トリミングするものを作ろうとしています。
ファイルを読み込んで描画→トリミングはうまくいきました。

//一部ですが今回の質問部分でうまくいっている
$("#upload_file").change(function() {
    var file = this.files[0];
    if (!file.type.match(/^image\/(png|jpeg|gif)$/)) return;

    var image = new Image();
    console.log(image)
    var reader = new FileReader();

    reader.onload = function(e) {
      image.onload = function() {

        var min_width = Math.min(this.width, max_canvas_size.width);
        var min_height = Math.min(this.height, max_canvas_size.height);
        var scale = Math.min(min_width / this.width, min_height / this.height);
        var size = {width: this.width * scale, height: this.height * scale};

        resizeCanvas(size.width, size.height);
        layer1Ctx.drawImage(image, 0, 0, size.width, size.height);
        updateCanvas();

        $("#upload_button").attr('filename', file.name);
        $("#upload_button").show();

        // load file on base buffer
        base.width = this.width/3;
        base.height = this.height/3;
        baseCtx.drawImage(image, 0, 0,this.width/3,this.height/3);
      }
      image.src = e.target.result;
    }

    reader.readAsDataURL(file);
  });


layer1に描画してほかのcanvasと連携していきます。

今回、すでに保持しているblobデータを描画したいと思っています。
blob:file:///665a1508-78d6-44a0-8020-cfbb47f6d1f3
↑imgUrlです
この描画の仕方が分かりません。
上を少し変えて、

$('#testbtn').click(function(){
    //20201008
    var imgUrl = window.opener.$('#kakusi').text();
    console.log(imgUrl + "画像のアドレス")

    var image = new Image();
    image.src = imgUrl ;
    console.log(image)
    var reader = new FileReader();

    reader.onload = function(e) {
      image.onload = function() {

        var min_width = Math.min(this.width, max_canvas_size.width);
        var min_height = Math.min(this.height, max_canvas_size.height);
        var scale = Math.min(min_width / this.width, min_height / this.height);
        var size = {width: this.width * scale, height: this.height * scale};

        resizeCanvas(size.width, size.height);
        layer1Ctx.drawImage(image, 0, 0, size.width, size.height);
        updateCanvas();


        // load file on base buffer
        base.width = this.width/3;
        base.height = this.height/3;
        baseCtx.drawImage(image, 0, 0,this.width/3,this.height/3);
      }
      image.src = e.target.result;
    }

    reader.URL.createObjectURL(blob) ;
    });


とimageにデータ情報を持たせようとしたのですがうまくいきません。
ネットでいただいた情報を参考にトライ&エラーでやっているので基本的なことが分かっていませんがどなたか教えてください。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • Izumo1101

    2020/10/08 22:36

    自分でもきっと質問自体に不備があるなと感じてはいるのですが・・・申し訳ない。
    2が近いでしょうか。
    親(別)ウィンドウで、フォルダ内にある複数の画像をサムネイル化し表示させ、サムネイルクリックでbodyに動的に挿入するスクリプトを書いています。
    for( var i=0,l=fileList.length; l>i; i++ ) {
    // Blob URLの作成
    var blobUrl = window.URL.createObjectURL( fileList[i] ) ;
    $('.target').append('<a><img id="' + i + '" class="prepep" src="' + blobUrl + '" style="width:5vw"></a>');
    }
    任意のタイミングでクリック動作で画像として記述するため(numは変数)
    var new_node = $('<img class="element" id="panPinchElm' + num + '" src="' + src + '" style="height:100px; width:auto;">');
    と定義していまして、これ自体は想定の動きをします。

    この入手したBlobUrlを生かして子ウィンドウ内でトリミングしたいというのが今回の趣旨。子ウィンドウで再度画像を呼び出せば普通に描画できますが、そのステップを省いてすでに手元にある情報で対処したいということなんです。。。。blob情報からimgとして挿入できるならcanvasにも誘導できるのでは、ということです。

    キャンセル

  • kuma_kuma_

    2020/10/08 23:00 編集

    createObjectURLで画像化したblobは一度表示されると使えなくなります。
    (先のURLに解説があったのですが...)
    またcreateObjectURLのブラウザ対応も廃止だそうです。

    もし目的の事をされるなら<canvas>タグを画像(jpeg or png)に変換してそれをBASE64形式の文字列へ
    変換し
    https://javascript.programmer-reference.com/js-canvas-base64/
    URLに指定する事で内部的に画像データを保留できます。

    あとは選ばれた画像のBASE64形式の文字列から<canvas>へ画像を展開
    https://javascript.programmer-reference.com/js-base64-canvas/
    すればよいのでは?

    ローカルで試す場合
    img.crossOrigin = 'Anonymous';
    というテクニックが必要となります。
    https://www.nabeen.be/post/2019/11/to-data-url-cross-origin/

    キャンセル

  • kairi003

    2020/10/09 05:21

    >> Uncaught TypeError: Cannot read property 'createObjectURL' of undefined
    が二つ目の方で出てるならreader.URLがundefinedなだけだと思うんですが…

    blob->URLはFileReaderでなくURL.createObjectURLで同期的に取れます

    キャンセル

回答 1

0

Fileオブジェクトは Blobオブジェクトの派生であるため、URL.createObjectURL() の引数には File オブジェクトを渡すことができます。

CODEPEN 画像のアップロードプレビュー で実装したものを回答したことがあります。

  • L1-3 : キャッシュ
  • L7 : メモリ解放(キャッシュした 全BlobURL が対象)
  • L29 : Fileオブジェクトから BlobURL を取得しキャッシュする。

Canvas に描画する場合、Image(HTMLImageElement)を描画すると思いますが、Image.src に blobUrl を渡して、load イベントを待ち、描画処理する感じでしょうか。

Web アプリケーションからのファイルの使用 のページにある「オブジェクト URL を利用する」セクションは必読です。

URL.revokeObjectURL() を呼ぶまでメモリ上に存在し続けるので、取扱には、キャッシュするなどの BlobURLの管理が必要になります。


修正コメント内で「createObjectURL() が使えなくなる(らしい)」との意見がありましたので、検索してみると、video に関連する MediaStream に限って言及されているように思いました。

ご質問のコードでは file.type から 画像ファイルのみを切り分けており、
video ではなく「画像」ですので、継続して使えるかもしれませんが、「しばらくの間、開発者コンソールに表示する」というベンダの対応に注意する必要があります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/10/23 23:29

    ご回答ありがとうございます。ぱっと見、私の求めている内容だと感じましたのでご教示いただいた内容を検証させてください。非常に有意義な内容だと感じました。ちょっと潜ってみます。

    キャンセル

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

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

関連した質問

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