【问题标题】:problem changing png color automatically after changing the src of this png更改此 png 的 src 后自动更改 png 颜色的问题
【发布时间】:2021-09-08 01:17:42
【问题描述】:

这是我想要实现的目标:一个产品设计师,我可以在其中更改图像的 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');
});

当我在我的选择中选择另一个选项时,它会更新为 src。 这也可以。

但是...当我选择一个新的 PNG 时,它以黑色像素显示。没关系,应该是这样的。但是我想添加一行代码来在 src 更改时更新颜色。

我有另一个功能可以在我按下按钮时手动更新 png 的颜色,我尝试将它添加到“更改选择”功能中,但它不起作用...

$('#mask_insert_1').each(function () { this.src = changeIconColor(this, $( "#colorpicker_insert_1" ).val(), '1'); });

我哪里错了?

非常感谢您阅读我的内容,如果您能提供帮助,将更加感谢。 美联社

【问题讨论】:

  • 你能把你的代码放在运行sn-p中吗

标签: javascript jquery png color-picker


【解决方案1】:

当您更改图像的 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==">

【讨论】:

  • 哇。非常感谢它的工作!但我认为听众不会停止,页面继续加载......
  • 完成!对不起,我是新来的,我已经潜伏多年了:/
  • 您的代码运行良好,但浏览器一直在加载,直到我停止页面加载。事件侦听器是否始终处于活动状态?有没有办法防止这种情况?我在你的例子中看到它没有发生:/
  • 那是我的错,我的代码也有这个问题,但由于图像是本地的,所以并不明显。我已经更新了代码。
  • 非常感谢!现在完美运行:D
猜你喜欢
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-12
  • 2019-07-19
  • 2020-07-15
相关资源
最近更新 更多