我正在开发一个网页,允许用户自定义进入画布的 PNG 图像的颜色,从而创建具有多种用户选择的颜色的分层图像。
我正在使用此代码的修改版本,以允许多个重新着色的图像进入同一画布。
但是,编辑图像的颜色会导致画布看起来变成空白。 当我只处理一张图像时,我没有遇到这个问题。
提前感谢您的帮助,我很感激。
相关代码:
<table style="display:table; margin-left:auto; margin-right:auto; border:none;">
<tr><td style="border:solid;">Color A</td>
<td style="border:solid;">Color B</td>
<td style="border:solid;">Color C</td>
<td style="border:solid;">Color D</td></tr>
<tr><td style="border:solid;"><input type="color" onchange="drawA()" value="#b6ddca" id="colorA"></td>
<td style="border:solid;"><input type="color" onchange="drawB()" value="#dceab5" id="colorB"></td>
<td style="border:solid;"><input type="color" onchange="drawC()" value="#ffc7ff" id="colorC"></td>
<td style="border:solid;"><input type="color" onchange="drawD()" value="#00a3e2" id="colorD"></td></tr></table>
</div>
<button onclick="drawA(), drawB(), drawC(), drawD()">Submit</button>
<h2>Preview</h2>
<hr>
<canvas id="piccy" width="400" height="400" style="border-color: #ff7dc9; border: solid;"></canvas>
<script>
var c = document.getElementById("piccy");
var ctx = c.getContext("2d");
var imgA = new Image; imgA.src = "https://elamea.com/sprixie/A.png";
var imgB = new Image; imgB.src = "https://elamea.com/sprixie/B.png";
var imgC = new Image; imgC.src = "https://elamea.com/sprixie/C.png";
var imgD = new Image; imgD.src = "https://elamea.com/sprixie/D.png";
var imgL = new Image; imgL.src = "https://elamea.com/sprixie/lines.png";
ctx.drawImage(imgA, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgB, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgL, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgC, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgD, 0, 0, piccy.width, piccy.height);
function drawA() {
hexA = document.getElementById("colorA").value;
// draw color
ctx.fillStyle = hexA;
ctx.fillRect(0, 0, piccy.width, piccy.height);
// set composite mode
ctx.globalCompositeOperation = "destination-in";
// draw image
ctx.drawImage(imgA, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgB, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgL, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgC, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgD, 0, 0, piccy.width, piccy.height);
}
function drawB() {
hexB = document.getElementById("colorB").value;
// draw color
ctx.fillStyle = hexB;
ctx.fillRect(0, 0, piccy.width, piccy.height);
// set composite mode
ctx.globalCompositeOperation = "destination-in";
// draw image
ctx.drawImage(imgA, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgB, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgL, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgC, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgD, 0, 0, piccy.width, piccy.height);
}
function drawC() {
hexC = document.getElementById("colorC").value;
// draw color
ctx.fillStyle = hexC;
ctx.fillRect(0, 0, piccy.width, piccy.height);
// set composite mode
ctx.globalCompositeOperation = "destination-in";
// draw image
ctx.drawImage(imgA, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgB, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgL, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgC, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgD, 0, 0, piccy.width, piccy.height);
}
function drawD() {
hexD = document.getElementById("colorD").value;
// draw color
ctx.fillStyle = hexD;
ctx.fillRect(0, 0, piccy.width, piccy.height);
// set composite mode
ctx.globalCompositeOperation = "destination-in";
// draw image
ctx.drawImage(imgA, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgB, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgL, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgC, 0, 0, piccy.width, piccy.height);
ctx.drawImage(imgD, 0, 0, piccy.width, piccy.height);
}</script>
因此,我添加了一段代码来等待图像全部加载,因为您的代码是在不等待图像加载的情况下启动的,这意味着它并不总是出现 我分解了你的代码以避免重复 最后,对于颜色的更改,这是因为您的更改方法不保持透明度。通过搜索一点,我找到了这个解决方案:https://stackoverflow.com/a/45187676/9947331
我让你看一下代码
//script from https://stackoverflow.com/questions/37854355/wait-for-image-loading-to-complete-in-javascript
async function loadImages(imageUrlArray) {
const promiseArray = []; // create an array for promises
const imageArray = []; // array for the images
for (let imageUrl of imageUrlArray) {
promiseArray.push(new Promise(resolve => {
const img = new Image();
img.onload = function() {
resolve();
};
img.src = imageUrl[0];
imageUrl[1] = img;
}));
}
await Promise.all(promiseArray);
console.log("all images loaded");
}
//Functions edited from https://stackoverflow.com/a/45187676/9947331
function ImageComposite(hexColor, image) {
// draw color
image.ctx.fillStyle = hexColor;
// set composite mode
image.ctx.globalCompositeOperation = "color";
image.ctx.fillRect(0, 0, image.width, image.height);
// set composite mode
ctx.globalCompositeOperation = "source-over";
}
function MaskImage(dest, source) {
dest.ctx.globalCompositeOperation = "destination-in";
dest.ctx.drawImage(source, 0, 0);
dest.ctx.globalCompositeOperation = "source-over";
return dest;
}
function RestoreImage(dest, source) {
dest.ctx.clearRect(0, 0, dest.width, dest.height);
dest.ctx.drawImage(source, 0, 0);
return dest;
}
function imageToCanvas(image) {
const c = document.createElement("canvas");
c.width = image.naturalWidth;
c.height = image.naturalHeight;
c.ctx = c.getContext("2d"); // attach context to the canvas for easy reference
c.ctx.drawImage(image, 0, 0);
return c;
}
var myImages = [
["https://elamea.com/adopts/sprixie/A.png", undefined],
["https://elamea.com/adopts/sprixie/B.png", undefined],
["https://elamea.com/adopts/sprixie/C.png", undefined],
["https://elamea.com/adopts/sprixie/D.png", undefined],
["https://elamea.com/adopts/sprixie/lines.png", undefined]
];
var c = document.getElementById("piccy");
var ctx = c.getContext("2d");
var ImageA;
var ImageB;
var ImageC;
var ImageD;
var ImageLines;
function draw() {
//All images are loaded, we can draw
console.log("drawing");
ImageA = myImages[0][1];
ImageB = myImages[1][1];
ImageC = myImages[2][1];
ImageD = myImages[3][1];
ImageLines = myImages[4][1];
drawAllImageWithComposite();
}
function drawImageOnCanvas(image) {
ctx.drawImage(image, 0, 0, piccy.width, piccy.height);
}
loadImages(myImages).then(draw);
function DrawImageComposite(hexColor, Image) {
var ImageCanvas = imageToCanvas(Image);
ImageComposite(hexColor, ImageCanvas);
MaskImage(ImageCanvas, Image);
drawImageOnCanvas(ImageCanvas);
}
function drawAllImageWithComposite() {
DrawImageComposite(document.getElementById("colorA").value, ImageA);
DrawImageComposite(document.getElementById("colorB").value, ImageB);
DrawImageComposite(document.getElementById("colorC").value, ImageC);
DrawImageComposite(document.getElementById("colorD").value, ImageD);
drawImageOnCanvas(ImageLines);
}
function drawA() {
drawAllImageWithComposite()
}
function drawB() {
drawAllImageWithComposite()
}
function drawC() {
drawAllImageWithComposite()
}
function drawD() {
drawAllImageWithComposite()
}
<table style="display:table; margin-left:auto; margin-right:auto; border:none;">
<tr>
<td style="border:solid;">Color A</td>
<td style="border:solid;">Color B</td>
<td style="border:solid;">Color C</td>
<td style="border:solid;">Color D</td>
</tr>
<tr>
<td style="border:solid;"><input type="color" onchange="drawA()" value="#b6ddca" id="colorA"></td>
<td style="border:solid;"><input type="color" onchange="drawB()" value="#dceab5" id="colorB"></td>
<td style="border:solid;"><input type="color" onchange="drawC()" value="#ffc7ff" id="colorC"></td>
<td style="border:solid;"><input type="color" onchange="drawD()" value="#00a3e2" id="colorD"></td>
</tr>
</table>
<canvas id="piccy" width="400" height="400" style="border-color: #ff7dc9; border: solid;"></canvas>