更改此 png 的 src 后自动更改 png 颜色的问题
problem changing png color automatically after changing the src of this png
这是我想要实现的目标:一个产品设计师,我可以在其中更改图像的 src(我有一个 8 位黑白 png 的集合)并选择此 png 的颜色。
我正在使用 jQuery 和颜色选择器来更改 png 的颜色,它与以下功能配合使用效果很好:
var changeIconColor = (function () {
var canvas = document.createElement("canvas"), // shared instance
context = canvas.getContext("2d");
// set image pixel size and hex color
color = '00ff00';
canvas.width = 1000;
canvas.height = 1000;
function desaturate() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height),
pixels = imageData.data,
i, l, r, g, b, a, average;
for (i = 0, l = pixels.length; i < l; i += 4) {
a = pixels[i + 3];
if (a === 0) {
continue;
} // skip if pixel is transparent
r = pixels[i];
g = pixels[i + 1];
b = pixels[i + 2];
average = (r + g + b) / 3 >>> 0; // quick floor
pixels[i] = pixels[i + 1] = pixels[i + 2] = average;
}
context.putImageData(imageData, 0, 0);
}
function colorize(color, alpha) {
context.globalCompositeOperation = "source-atop";
context.globalAlpha = alpha;
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
// reset
context.globalCompositeOperation = "source-over";
context.globalAlpha = 1;
}
return function (iconElement, color, alpha) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(iconElement, 0, 0, canvas.width, canvas.height);
desaturate();
colorize(color, alpha);
return canvas.toDataURL("image/png", 1);
};
}());
我在颜色选择器上更改颜色时调用它:
$('#mask_insert_1').each(function () {
this.src = changeIconColor(this, $( "#colorpicker_insert_1" ).val(), '1');
});
这会将 png 的黑色像素更改为所选颜色。效果很好。
然后我有另一个函数可以更改此 png 的 src :
$("#select_insert_1").change(function(){
$("#mask_insert_1").show();
$('#mask_insert_1').attr('src','assets/inserts/'+$("#select_insert_1").val()+'.png');
});
当我 select 我的 select 中的另一个选项时,它会更新到 src。
那也行。
但是...当我 select 一个新的 PNG 时,它显示为黑色像素。没关系,应该是这样的。但是我想添加一行代码来在src改变时更新颜色。
我有另一个功能可以在我按下按钮时手动更新 png 的颜色,我试图将它添加到“更改 select”功能中,但它不起作用.. .
$('#mask_insert_1').each(function () { this.src = changeIconColor(this, $( "#colorpicker_insert_1" ).val(), '1'); });
我哪里错了?
非常感谢您阅读我的文章,如果您能提供帮助,我将更加感谢。
AP
当您更改图片的 src 时,图片不会立即更新。您需要做的是向图像添加 onload
事件侦听器并从那里更新它的颜色。
document.getElementById("colorpicker_insert_1").value = "#" + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, "0");
var changeIconColor = (function () {
var canvas = document.createElement("canvas"), // shared instance
context = canvas.getContext("2d");
// set image pixel size and hex color
color = '00ff00';
canvas.width = 100;
canvas.height = 100;
function desaturate() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height),
pixels = imageData.data,
i, l, r, g, b, a, average;
for (i = 0, l = pixels.length; i < l; i += 4) {
a = pixels[i + 3];
if (a === 0) {
continue;
} // skip if pixel is transparent
r = pixels[i];
g = pixels[i + 1];
b = pixels[i + 2];
average = (r + g + b) / 3 >>> 0; // quick floor
pixels[i] = pixels[i + 1] = pixels[i + 2] = average;
}
context.putImageData(imageData, 0, 0);
}
function colorize(color, alpha) {
context.globalCompositeOperation = "source-atop";
context.globalAlpha = alpha;
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
// reset
context.globalCompositeOperation = "source-over";
context.globalAlpha = 1;
}
return function (iconElement, color, alpha) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(iconElement, 0, 0, canvas.width, canvas.height);
desaturate();
colorize(color, alpha);
return canvas.toDataURL("image/png", 1);
};
}());
$("#select_insert_1").change(function(){
$("#mask_insert_1").show();
$('#mask_insert_1').attr('src', $("#select_insert_1").val());
/* show original image */
document.getElementById("img").src = $("#select_insert_1").val();
});
$('#mask_insert_1').each(function () {
const img = this;
let src;
/* add onload event listener */
img.onload = e =>
{
/* do nothing if image generated by changeIconColor() */
if (img.src !== src)
img.src = src = changeIconColor(img, $( "#colorpicker_insert_1" ).val(), '1');
}
/* change color now */
img.onload();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="select_insert_1">
<option value="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">img 1</option>
<option value="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7">img 2</option>
<option value="invalid image data">img 3</option>
</select>
<input id="colorpicker_insert_1" oninput='$("#select_insert_1").trigger("change")'>
<img id="img" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
<img id="mask_insert_1" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
这是我想要实现的目标:一个产品设计师,我可以在其中更改图像的 src(我有一个 8 位黑白 png 的集合)并选择此 png 的颜色。
我正在使用 jQuery 和颜色选择器来更改 png 的颜色,它与以下功能配合使用效果很好:
var changeIconColor = (function () {
var canvas = document.createElement("canvas"), // shared instance
context = canvas.getContext("2d");
// set image pixel size and hex color
color = '00ff00';
canvas.width = 1000;
canvas.height = 1000;
function desaturate() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height),
pixels = imageData.data,
i, l, r, g, b, a, average;
for (i = 0, l = pixels.length; i < l; i += 4) {
a = pixels[i + 3];
if (a === 0) {
continue;
} // skip if pixel is transparent
r = pixels[i];
g = pixels[i + 1];
b = pixels[i + 2];
average = (r + g + b) / 3 >>> 0; // quick floor
pixels[i] = pixels[i + 1] = pixels[i + 2] = average;
}
context.putImageData(imageData, 0, 0);
}
function colorize(color, alpha) {
context.globalCompositeOperation = "source-atop";
context.globalAlpha = alpha;
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
// reset
context.globalCompositeOperation = "source-over";
context.globalAlpha = 1;
}
return function (iconElement, color, alpha) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(iconElement, 0, 0, canvas.width, canvas.height);
desaturate();
colorize(color, alpha);
return canvas.toDataURL("image/png", 1);
};
}());
我在颜色选择器上更改颜色时调用它:
$('#mask_insert_1').each(function () {
this.src = changeIconColor(this, $( "#colorpicker_insert_1" ).val(), '1');
});
这会将 png 的黑色像素更改为所选颜色。效果很好。
然后我有另一个函数可以更改此 png 的 src :
$("#select_insert_1").change(function(){
$("#mask_insert_1").show();
$('#mask_insert_1').attr('src','assets/inserts/'+$("#select_insert_1").val()+'.png');
});
当我 select 我的 select 中的另一个选项时,它会更新到 src。 那也行。
但是...当我 select 一个新的 PNG 时,它显示为黑色像素。没关系,应该是这样的。但是我想添加一行代码来在src改变时更新颜色。
我有另一个功能可以在我按下按钮时手动更新 png 的颜色,我试图将它添加到“更改 select”功能中,但它不起作用.. .
$('#mask_insert_1').each(function () { this.src = changeIconColor(this, $( "#colorpicker_insert_1" ).val(), '1'); });
我哪里错了?
非常感谢您阅读我的文章,如果您能提供帮助,我将更加感谢。 AP
当您更改图片的 src 时,图片不会立即更新。您需要做的是向图像添加 onload
事件侦听器并从那里更新它的颜色。
document.getElementById("colorpicker_insert_1").value = "#" + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, "0");
var changeIconColor = (function () {
var canvas = document.createElement("canvas"), // shared instance
context = canvas.getContext("2d");
// set image pixel size and hex color
color = '00ff00';
canvas.width = 100;
canvas.height = 100;
function desaturate() {
var imageData = context.getImageData(0, 0, canvas.width, canvas.height),
pixels = imageData.data,
i, l, r, g, b, a, average;
for (i = 0, l = pixels.length; i < l; i += 4) {
a = pixels[i + 3];
if (a === 0) {
continue;
} // skip if pixel is transparent
r = pixels[i];
g = pixels[i + 1];
b = pixels[i + 2];
average = (r + g + b) / 3 >>> 0; // quick floor
pixels[i] = pixels[i + 1] = pixels[i + 2] = average;
}
context.putImageData(imageData, 0, 0);
}
function colorize(color, alpha) {
context.globalCompositeOperation = "source-atop";
context.globalAlpha = alpha;
context.fillStyle = color;
context.fillRect(0, 0, canvas.width, canvas.height);
// reset
context.globalCompositeOperation = "source-over";
context.globalAlpha = 1;
}
return function (iconElement, color, alpha) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(iconElement, 0, 0, canvas.width, canvas.height);
desaturate();
colorize(color, alpha);
return canvas.toDataURL("image/png", 1);
};
}());
$("#select_insert_1").change(function(){
$("#mask_insert_1").show();
$('#mask_insert_1').attr('src', $("#select_insert_1").val());
/* show original image */
document.getElementById("img").src = $("#select_insert_1").val();
});
$('#mask_insert_1').each(function () {
const img = this;
let src;
/* add onload event listener */
img.onload = e =>
{
/* do nothing if image generated by changeIconColor() */
if (img.src !== src)
img.src = src = changeIconColor(img, $( "#colorpicker_insert_1" ).val(), '1');
}
/* change color now */
img.onload();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="select_insert_1">
<option value="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">img 1</option>
<option value="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7">img 2</option>
<option value="invalid image data">img 3</option>
</select>
<input id="colorpicker_insert_1" oninput='$("#select_insert_1").trigger("change")'>
<img id="img" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
<img id="mask_insert_1" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">