DOM画像処理

【JavaScript】 ダミー画像をオフラインで動的に作成する

更新日:2020/06/03

画像が読み込めないときにダミー画像を表示したかったので、JavaScriptでコードを作成してみました。

 

ダミー画像作成JavaScriptコード

ダミー画像をJavaScriptで作成するのは、それほど難しくありません。

次のような手順でおこないます。

  1. Canvas要素を作成して、描画
  2. Canvas要素のtoDataURLメソッドから得られる値を、IMGタグのsrcにセット

さらに使用方法として、次の2つを想定しています。

  1. IMGタグのonerrorから呼び出す
  2. 手動でIMGタグにダミー画像をセットする

追加の機能として、次の2つを用意します。

  1. 任意の位置にテキストを描画
  2. 任意の位置に直線を描画

この他に矩形や円などを描画したいときは、ご自分で追加してみてください。

JavaScript

/*
* ダミーイメージの作成
*/
const dumyImage = ( imageoptions , image = null ) => {

                       // キャンバスの作成
            const cvs = document.createElement("canvas");

                      // キャンバスのサイズをセット
                      // 参考記事:【JavaScript】 Canvasのサイズが難解で困る
            cvs.setAttribute( "width" , imageoptions[0].width );
            cvs.setAttribute( "height" , imageoptions[0].height );

                      // キャンバスのコンテキスト取得
            const context = cvs.getContext('2d');
            context.save();
                      // キャンバスを指定された色で塗りつぶし
            context.fillStyle = imageoptions[0].color;
            context.fillRect(0,0,imageoptions[0].width,imageoptions[0].height);
            context.restore();

                      // その他のオプション処理
            for( let i = 1 ; i < imageoptions.length ; i ++ ){

                context.save();
                const opt = imageoptions[ i ];

                switch (opt.type) {
                    case "text":  // テキスト描画
                        context.fillStyle = opt.color;
                        context.font = opt.font;
                        context.fillText( opt.value , opt.left , opt.top , imageoptions[0].width - opt.left );
                        break;
                    case "line":  // 直線描画
                        context.beginPath();
                        context.lineWidth = opt.width;
                        context.strokeStyle = opt.color;
                        context.moveTo( opt.x1 , opt.y1 );
                        context.lineTo( opt.x2 , opt.y2 );
                        context.stroke( );
                        break;
                }
                context.restore();
            }

            // IMGタグか?
            if( image && image.nodeType === 1 && image.tagName === "IMG" )
                    imageOrCallBack.src = cvs.toDataURL();

            return { 
                        dataUrl: cvs.toDataURL() , 
                        setImage : dumyImage.dumyFunctions.setImage 
            };

};
/*
* コールバック用IMGタグセットメソッド
*/
dumyImage.dumyFunctions ={
            setImage ( image ) {
                image.src = this.dataUrl;
            }
};

※引数のエラーチェックなどはしていません。必要に応じて、追加してください。

 

使用方法

ダミー画像作成関数

function dumyImage  ( imageoptions , imageOrCallBack = null )

引数1:imageoptions

ダミー画像の形状をオブジェクトの配列で指定します。

imageoptionsのインデックス 0 (imageoptions[0]) は、必ず次の形式にします。

    { 
       width : ダミー画像の幅,
       height : ダミー画像の高さ,
       color : ダミー画像の背景色 
    }

インデックス1以降は、描画するテキストと直線を指定します。

■テキスト

    { 
      type : "text" 固定,
      top : 描画位置のy座標 ,
      left : 描画位置のx位置,
      color : 文字の色 ,
      font : 文字のフォント ,
      value : 描画する文字列 
    }

■直線

    { 
      type:"line" 固定,
      x1 : 始点のx座標,
      y1 : 始点のy座標,
      x2 : 終点のx座標,
      y2 : 終点のy座標,
      color : 直線の色,
      width : 直線の幅 
    }

■設定例

const imageoptions = [
            { width:150,height:150,color:"#ccc" },
            { type:"line",x1:0,y1:0,x2:150,y2:150,color:"#0F0",width:1 },
            { type:"line",x1:150,y1:0,x2:0,y2:150,color:"#0F0",width:1 },
            { type:"text",top:50,left:10,color:"#f00",font:"40px sans-serif",value:"No Data" },
            { type:"text",top:100,left:10,color:"#f0f",font:"20px sans-serif",value:"画像がないよ!!" },
        ];

作成されたダミー画像

引数2:image

imageにimg要素が渡されると、ダミー画像をセットされます。

リターン値:

次のオブジェクトが、リターンされます。

    {
        dataUrl : ダミー画像データ , 
        setImage(imge) : imageに渡されたimg要素に、ダミー画像をセットするメソッド  
    };

 

使用例

dumyImage関数は、主に次の二通りの使用方法を想定しています。

IMGタグのonerror属性で使用する

IMGタグに次のようにonerror属性をセットすることで、画像を読み込めないとき、ダミー画像がセットされます。

HTML

<img  src="…" onerror="dumyImage(imageoptions,this);" >

任意のIMG要素にダミー画像をセットする

次のようにすることで、動的にダミー画像をセットできます。

HTML

<img id="image"   >

JavaScript

window.addEventListener('DOMContentLoaded',()=> {

            const dmyImg = dumyImage( imageoptions );

            dmyImg.setImage( document.getElementById( "image" ) );

        });

onerror属性なしで、読み込めないIMGタグにダミー画像をセットする

IMGタグにonerror属性を記述するのが面倒なとき、次のようにJavaScriptで制御します。

HTML

<div id="imageArea">    
    <img src="image01.jpg"  >
    <img src="image02.jpg"  >
    <img src="image03.jpg"  >
    <img src="image04.jpg"  >
</div>

JavaScript

const dmyImageListener = ()=> {
            window.removeEventListener('DOMContentLoaded',dmyImageListener);

            const errorEvt = e => {
                e.onload = () => { e.onerror = e.succuess = null; };
                e.onerror = () => { dmyImg.setImage( e );}
            };

            const dmyImg = dumyImage( imageoptions );

            document.querySelectorAll("#imageArea img").forEach(
                e => {
                    if( e.complete ){
                        if( e.naturalWidth === 0 && e.naturalWidth === 0 ) {
                            const src = e.src;
                            e.src = "";
                            errorEvt(e);
                            e.src = src;
                        }
                    }else{
                        errorEvt(e);
                    }
                }
            );

};
window.addEventListener('DOMContentLoaded',dmyImageListener);

DOMContentLoadedイベントは、DOM要素が構築されたときに呼び出されます。
この時点で、読み込みが完了している画像と、完了していない画像が存在します。

完了していない画像(completeがfaise)には、onerrorをセットして読み込みエラーイベントを監視します。

完了している画像(completeがtrue)は、画像サイズ(naturalWidthとnaturalWidth)が0のとき、読み込み失敗と判断しています。
しかしdisplay:noneなどで非表示の場合、サイズが0になるという情報があったので、srcを再セットして、再読み込みをおこなっています。
これで、読み込めなかったら、onerrorが実行される(はず)です。

※テストで再現できなかったため、このコードはなんらかの不具合があるかもしれません。

更新日:2020/06/03

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。