4

HTML5 キャンバスでピクセル操作を行う最初の試みとして、背景画像の特定の部分を変更するコードを作成しました。マスク イメージを使用して、変更が必要な特定の部分をマークしています。そして、一度に1ピクセルずつ2本の垂直線を描いています。私のコードは次のようになります:

var backgroundTemp=[0,0,false];

function generateBg(){
    var bgGenCanvas  = document.getElementById("backgroundGenerator");
    var bgGenCtx = bgGenCanvas.getContext("2d");

    var bgMaskCanvas  = document.getElementById("backgroundMask");
    var bgMaskCtx = bgMaskCanvas.getContext("2d");

    if(backgroundTemp[0]==0){
        var img = new Image();
        img.onload=function(){
            bgGenCtx.drawImage(this,0,0);
            backgroundTemp[0]++;
            generateBg();
        }
        backgroundTemp[0]++;
        img.src = 'images/ordnerGreen.png';
    }
    if(backgroundTemp[1]==0){
        var img = new Image();
        img.onload=function(){
            bgMaskCtx.drawImage(this,0,0);
            backgroundTemp[1]++;
            generateBg();
        }
        backgroundTemp[1]++;
        img.src = 'images/ordnerMask.png';
    }
    if(backgroundTemp[0]==2 && backgroundTemp[1]==2 && backgroundTemp[2]==false){
        backgroundTemp[2]=true;
        var newColor=hexToRgb(settings.ordnerColor);
        var genData = bgGenCtx.getImageData(0,0,bgGenCanvas.width,bgGenCanvas.height);
        var maskData = bgMaskCtx.getImageData(0,0,bgMaskCanvas.width,bgMaskCanvas.height);
        var darkenAt1=796*4;
        var darkenAt2=996*4;
        var widthPerLine=bgGenCanvas.width*4;
        for(var i=0;i<maskData.data.length;i+=4){
            var currentLine=Math.ceil(i/widthPerLine);

            var red=maskData.data[i];
            var green=maskData.data[i+1];
            var blue=maskData.data[i+2];

            if(red==255 && green==255 && blue==255){
                red=newColor.r;
                green=newColor.g;
                blue=newColor.b;
                if(darkenAt1==i || darkenAt2==i){
                    red-=Math.floor(red/4);
                    green-=Math.floor(green/4);
                    blue-=Math.floor(blue/4);
                    if(darkenAt1==i){
                        darkenAt1+=parseInt(widthPerLine);
                    }
                    if(darkenAt2==i){
                        darkenAt2+=parseInt(widthPerLine);
                    }
                }
                genData.data[i]=red;
                genData.data[i+1]=green;
                genData.data[i+2]=blue;
            }
        }
        bgGenCtx.putImageData(genData,0,0);
        document.getElementById('viewerBackground').style.backgroundImage="url('"+bgGenCanvas.toDataURL()+"')";
    }
}

$(window).load(function(){generateBg();});

最初はランダムに機能したり、機能しなかったりしました。結果が空になることもあれば、元の画像や変更された画像になることもあります。画像の読み込みが完了していない可能性があると考えたので、両方が確実に読み込まれるように構成を追加しました。これは Firefox と Chrome で機能しました。ただし、IE では問題は解決せず、F5 を押すたびにランダムな結果が得られます。

誰でもこれを修正する方法を知っていますか?

4

1 に答える 1

2

画像の読み込み速度 (およびキャッシュ内での可用性) によっては、ピクセルの反復を 1 回だけではなく 3 回実行することになる場合があります。

最悪の場合、イメージの src が指定されるとすぐに onLoad リスナーが実行されます (イメージがキャッシュで利用可能な場合)。

これを回避するには、画像を順番にロードし (つまり、backgroundTemp[0] onLoad 関数から backgroundTemp[1] 画像をロードする)、backgroundTemp[1] onLoad からピクセル反復処理を開始する必要があります。

于 2012-10-21T20:07:56.960 に答える