尝试为简单的 PNG 上色并在 canvas 中绘制遮罩元素
trying to colorize a simple PNG and draw inside a mask element in canvas
我尝试创建一个 HTML canvas,放置一个矩形...然后在该矩形内绘制各种形状和 RGBa PNG...所有这些都被剪裁在尺寸内矩形。然后我尝试在您按下 HTML 按钮输入时更改 PNG 的颜色。 (代码中的进一步注释。)
这是问题... A. 您必须绘制到临时 canvas 并在剪切矩形之后应用 "GlobalCompositeOperation source-atop"。之后绘制的所有内容都成功地剪裁成矩形。然后将整个东西复制(绘制)到 MAIN canvas。有人告诉我这样做是为了让编程在 "composite" 操作后识别多个元素。我不得不说这很好用!!但这是问题 B...
要在图像上设置 "getData"(更改颜色),我认为您必须将图像放在 canvas 上,并且进行所有图像像素操作会搞砸 "composite" 操作,所以我尝试将 PNG 绘制到第三个 canvas,进行像素更改,然后将其绘制到临时 canvas... 将其添加到其余元素。 ...THEEENNN 将其全部绘制到主要 canvas。不起作用。见代码。请大家帮忙,我气死了要嚼中子
<!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
}
你把事情搞得太复杂了!
canvas.
内置了裁剪方法
使用剪辑而不是合成和多个 canvases。
执行此操作,所有新绘图将被裁剪到您的 140x140 矩形内:
context.beginPath();
context.rect(30,30,140,140);
context.clip();
下面是您的代码的简化重新设计:
- 绘制一个灰色矩形填充 canvas。
- 在 [30,30] 处绘制一个 140x140 的蓝色矩形。
- 用
context.clip()
将所有新绘图剪辑到蓝色矩形中
- 画一个剪裁好的橙色矩形。
- 画一个剪裁的紫色矩形。
- 取消剪辑,这样新绘图将在 canvas 上的任何位置可见。
- 绘制波浪形图像(未剪裁)。
- 使用
.getImageData
反转每个像素的颜色。
还有一个演示:
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);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=200 height=200></canvas>
我尝试创建一个 HTML canvas,放置一个矩形...然后在该矩形内绘制各种形状和 RGBa PNG...所有这些都被剪裁在尺寸内矩形。然后我尝试在您按下 HTML 按钮输入时更改 PNG 的颜色。 (代码中的进一步注释。)
这是问题... A. 您必须绘制到临时 canvas 并在剪切矩形之后应用 "GlobalCompositeOperation source-atop"。之后绘制的所有内容都成功地剪裁成矩形。然后将整个东西复制(绘制)到 MAIN canvas。有人告诉我这样做是为了让编程在 "composite" 操作后识别多个元素。我不得不说这很好用!!但这是问题 B...
要在图像上设置 "getData"(更改颜色),我认为您必须将图像放在 canvas 上,并且进行所有图像像素操作会搞砸 "composite" 操作,所以我尝试将 PNG 绘制到第三个 canvas,进行像素更改,然后将其绘制到临时 canvas... 将其添加到其余元素。 ...THEEENNN 将其全部绘制到主要 canvas。不起作用。见代码。请大家帮忙,我气死了要嚼中子
<!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
}
你把事情搞得太复杂了!
canvas.
内置了裁剪方法使用剪辑而不是合成和多个 canvases。
执行此操作,所有新绘图将被裁剪到您的 140x140 矩形内:
context.beginPath();
context.rect(30,30,140,140);
context.clip();
下面是您的代码的简化重新设计:
- 绘制一个灰色矩形填充 canvas。
- 在 [30,30] 处绘制一个 140x140 的蓝色矩形。
- 用
context.clip()
将所有新绘图剪辑到蓝色矩形中
- 画一个剪裁好的橙色矩形。
- 画一个剪裁的紫色矩形。
- 取消剪辑,这样新绘图将在 canvas 上的任何位置可见。
- 绘制波浪形图像(未剪裁)。
- 使用
.getImageData
反转每个像素的颜色。
还有一个演示:
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);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=200 height=200></canvas>