尝试着色简单的PNG并在画布中的遮罩元素内绘制

时间:2015-10-31 22:57:57

标签: javascript canvas png pixel composite

我尝试创建一个HTML画布,放置一个矩形......然后INSIDE THAT矩形,绘制各种形状和RGBa PNG ......所有这些都剪切在矩形的尺寸内。然后我按下HTML按钮输入时尝试更改PNG的颜色。 (代码中的进一步评论。)

继承问题...... A.你必须绘制一个临时画布并应用" GlobalCompositeOperation source-atop"就在裁剪矩形之后。之后绘制的所有内容都成功剪裁成矩形。然后将整个事物复制(绘制)到MAIN画布上。我被告知要这样做,以便编程在"复合"之后识别MULTIPLE元素。操作。我不得不说这是美丽的!但是这里的问题B ......

转到" getData"在图像上(为了改变颜色),我认为你必须将图像放在画布上,并且所有的图像像素操作都会搞砸了#34;复合物"操作,所以我尝试将PNG绘制到第三个画布,进行像素更改,然后将其绘制到临时画布上......将其添加到其余元素中...... THEEENNN将其全部绘制到主画布上。不行。见代码。请帮助,我疯了,足以咀嚼中子。

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<canvas id="theCanvas" width="200" height="200" style="border:2px solid #000000;"></canvas>
<canvas id="tempCanvas" width="200" height="200" style="display:none;"></canvas>
<canvas id="anotherCanvas" width="200" height="200" style="display:none;"></canvas>
<form>
<input type="button" id="changeColor" value="Click to Change Color of Graphic">
</form>
<script type="text/javascript" src="hereWeGoAgain_GHELP.js"></script>
</body>
</html>
//------------------------------------- JS
window.addEventListener("load", eventWindowLoaded, false);

function eventWindowLoaded () {
    canvasApp();
}
function canvasApp() {

    var canvas = document.getElementById('theCanvas');// the main canvas, where it all goes in the end
    var context = canvas.getContext('2d');

    var tempCanvas = document.getElementById('tempCanvas');// the canvas to do my "source-atop" stuff...
    var tempContext = tempCanvas.getContext('2d');

    var anotherCanvas = document.getElementById('anotherCanvas');
    var anotherContext = anotherCanvas.getContext('2d');

// ...and Im thinking I should draw the RGBA PNG here, before placing it in the temp canvas, with the other elements

    var cc = document.getElementById('changeColor');
    cc.addEventListener('click', function(){changeColorFunction('ff0000');}, false);
// the HTML form button to change the PNG color

    var colorOfThePlacedPNG = "#000000";
    var imagesToLoad = 0;
    var imagesLoaded = 0;

    function drawScreen() {

        tempContext.fillStyle="#999999";
        tempContext.fillRect(0,0,200,200); //color the whole temp canvas area grey....
        tempContext.fillStyle="#2baae1";
        tempContext.fillRect(30,30,140,140);//now draw a light blue rect inside....

        tempContext.globalCompositeOperation="source-atop"; // now make everything drawn AFTERWARDS be clipped (masked) inside the blue rect

// when I comment out the above "global Comp Op"... everything draws to the main canvas normally...just not clipped(masked) however

        tempContext.fillStyle="#f47e1f";
        tempContext.fillRect(150,100,150,150);//SO heres an orange box intentionally clipped off the bottom right in the blue rect
        tempContext.fillStyle="#d89bc5";
        tempContext.fillRect(40,50,80,200);//AND heres a light purple rect intentionally clipped at the bottom of the blue rect

        getTheImageData(); //draw PNG to another canvas, convert image data, put in tempContext

        //tempContext.restore();//dont know if I need this
        context.drawImage(tempCanvas, 0, 0);// and then FINALLY draw all to the main canvas
        }
        var loaded = function(){
            imagesLoaded += 1;
            if(imagesLoaded === imagesToLoad){ 
                drawScreen();
            }
        }
    var loadImage = function(url){
            var image = new Image();   
            image.addEventListener("load",loaded);
            imagesToLoad += 1;
            image.src = url;
            return image;
            }
    function changeColorFunction(e) {
            colorOfThePlacedPNG = e;
            drawScreen();
    }
    function getTheImageData(){
        anotherContext.drawImage(testPNGimage, 0, 0);// draw to the third canvas(another canvas)
            var imgData = anotherContext.getImageData(0, 0, 200, 200);
                    // how do i color it red? ....like #ff0000 ???
            var i;
            for (i = 0; i < imgData.data.length; i += 4) {
                imgData.data[i] = 255 - imgData.data[i];
                imgData.data[i+1] = 255 - imgData.data[i+1];
                imgData.data[i+2] = 255 - imgData.data[i+2];
                imgData.data[i+3] = 255;
            }
            tempContext.putImageData(imgData, 0, 0);
    }
        var testPNGimage = loadImage("test.png");// the PNG is just a 75X75px black squiggle drawn in pshop
}

1 个答案:

答案 0 :(得分:0)

你过度复杂了!

画布中内置了裁剪方法。

使用剪辑而不是合成和多幅画布。

执行此操作,所有新图纸将被剪裁在140x140 rect:

context.beginPath();
context.rect(30,30,140,140);
context.clip();

以下是对代码的简化重新设计:

  1. 在画布上画一个灰色的矩形。
  2. 在[30,30]处画一个蓝色的140x140矩形。
  3. 使用context.clip()
  4. 将所有新图纸剪切为蓝色矩形
  5. 画一个剪裁的橙色矩形。
  6. 画一个剪裁的紫色矩形。
  7. 取消剪辑,以便在画布的任何位置都可以看到新图纸。
  8. 绘制波浪形图像(未剪裁)。
  9. 使用.getImageData反转每个像素的颜色。
  10. 和演示:

    &#13;
    &#13;
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    var img=new Image();
    img.crossOrigin='anonymous';
    img.onload=start;
    img.src="https://dl.dropboxusercontent.com/u/139992952/multple/squiggle.png";
    function start(){
    
      //color the whole canvas area grey....
      ctx.fillStyle="#999999";
      ctx.fillRect(0,0,200,200); 
    
      //now draw a light blue rect inside....
      ctx.fillStyle="#2baae1";
      ctx.beginPath();
      ctx.rect(30,30,140,140);
      ctx.fill();
    
      // save the unclipped context state
      ctx.save();
    
      // cause all new drawings to be clipped inside
      // the blue 140x140 rect at [30,30]
      ctx.clip();
    
      //SO heres an orange box intentionally clipped off the bottom right in the blue rect
      ctx.fillStyle="#f47e1f";
      ctx.fillRect(150,100,150,150);
    
      //AND heres a light purple rect intentionally clipped at the bottom of the blue rect
      ctx.fillStyle="#d89bc5";
      ctx.fillRect(40,50,80,200);
    
      // restore the context state (releases clipping for new drawings)
      ctx.restore();
    
      // draw the squiggley line image -- it's not clipped in the blue rect
      ctx.drawImage(img,0,0);
    
      // invert the colors using getImageData
      var imgData = ctx.getImageData(0, 0, 200, 200);
      var i;
      for (i = 0; i < imgData.data.length; i += 4) {
        imgData.data[i] = 255 - imgData.data[i];
        imgData.data[i+1] = 255 - imgData.data[i+1];
        imgData.data[i+2] = 255 - imgData.data[i+2];
        imgData.data[i+3] = 255;
      }
      ctx.putImageData(imgData, 0, 0);
    
    }
    &#13;
    body{ background-color: ivory; }
    #canvas{border:1px solid red; margin:0 auto; }
    &#13;
    <canvas id="canvas" width=200 height=200></canvas>
    &#13;
    &#13;
    &#13;