【问题标题】:Changing Image colour through Javascript通过 Javascript 更改图像颜色
【发布时间】:2015-04-02 19:00:42
【问题描述】:

我一直希望在使用点击事件时更改图像的颜色。

我看到了这篇文章,第一个也是主要的对马克杯的回应非常好。

但是,我需要使用类而不是 ID,因为我需要更改多个图像的颜色。当我将代码更改为 getElementsByClassName 而不是 byID 时,它不再起作用。

我当然把 ID=mug 改成 class=mug。

我在代码中看不到任何其他会导致问题的地方,因此我们将不胜感激。

我不能在原版上发布,所以在这里添加。原文链接是: How to change color of an image using jquery

这是代码:

<img src="mug.png" id="mug" width="25%" height="25%" onload="getPixels(this)" />
<input type="text" id="color" value="#6491ee" />
<input type="button" value="change color" onclick="changeColor()">

<script type="text/javascript">
    var mug = document.getElementById("mug");
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    var originalPixels = null;
    var currentPixels = null;

    function HexToRGB(Hex)
    {
        var Long = parseInt(Hex.replace(/^#/, ""), 16);
        return {
            R: (Long >>> 16) & 0xff,
            G: (Long >>> 8) & 0xff,
            B: Long & 0xff
        };
    }

    function changeColor()
    {
        if(!originalPixels) return; // Check if image has loaded
        var newColor = HexToRGB(document.getElementById("color").value);

        for(var I = 0, L = originalPixels.data.length; I < L; I += 4)
        {
            if(currentPixels.data[I + 3] > 0)
            {
                currentPixels.data[I] = originalPixels.data[I] / 255 * newColor.R;
                currentPixels.data[I + 1] = originalPixels.data[I + 1] / 255 * newColor.G;
                currentPixels.data[I + 2] = originalPixels.data[I + 2] / 255 * newColor.B;
            }
        }

        ctx.putImageData(currentPixels, 0, 0);
        mug.src = canvas.toDataURL("image/png");
    }

    function getPixels(img)
    {
        canvas.width = img.width;
        canvas.height = img.height;

        ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
        originalPixels = ctx.getImageData(0, 0, img.width, img.height);
        currentPixels = ctx.getImageData(0, 0, img.width, img.height);

        img.onload = null;
    }
</script>

谢谢

【问题讨论】:

  • 你用的是什么浏览器? document.getElementsByClassName("mug") 应该返回一个数组而不是单个对象
  • 为我工作:ID:jsfiddle.net/d6fmjadygetElementsByClassNamejsfiddle.net/d6fmjady/1
  • 感谢 Pawel,最后遗漏了所有重要的 [0]。但是,这仅返回第一张图像,正如预期的那样。仅将第二张图像更改为 [1],依此类推。我已经看过并看到我需要按照以下方式运行一些东西: var i;对于 (i = 0; i

标签: javascript colors


【解决方案1】:

我认为这可能与浏览器支持有关,因为document.getElementByClassName("mug"); 应该返回一个元素数组(旧浏览器可能不支持它)。在这一点上,很容易迭代每个杯子并像这样改变颜色

<img src="mug.png" id="mug" width="25%" height="25%" onload="getPixels(this)" />
<input type="text" id="color" value="#6491ee" />
<input type="button" value="change color" onclick="changeMugsColor()">

<script type="text/javascript">
    var mug = document.getElementsByClassName("mug");
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    var originalPixels = null;
    var currentPixels = null;

    function HexToRGB(Hex)
    {
        var Long = parseInt(Hex.replace(/^#/, ""), 16);
        return {
            R: (Long >>> 16) & 0xff,
            G: (Long >>> 8) & 0xff,
            B: Long & 0xff
        };
    }

    function changeMugsColor() {
        for (var ii = 0; ii < mug.length; ii++) {
            changeColor(mug[ii]);
        }
    }

    function changeColor(amug)
    {
        if(!originalPixels) return; // Check if image has loaded
        var newColor = HexToRGB(document.getElementById("color").value);

        for(var I = 0, L = originalPixels.data.length; I < L; I += 4)
        {
            if(currentPixels.data[I + 3] > 0)
            {
                currentPixels.data[I] = originalPixels.data[I] / 255 * newColor.R;
                currentPixels.data[I + 1] = originalPixels.data[I + 1] / 255 * newColor.G;
                currentPixels.data[I + 2] = originalPixels.data[I + 2] / 255 * newColor.B;
            }
        }

        ctx.putImageData(currentPixels, 0, 0);
        amug.src = canvas.toDataURL("image/png");
    }

    function getPixels(img)
    {
        canvas.width = img.width;
        canvas.height = img.height;

        ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
        originalPixels = ctx.getImageData(0, 0, img.width, img.height);
        currentPixels = ctx.getImageData(0, 0, img.width, img.height);

        img.onload = null;
    }
</script>

我还没有运行代码,但它应该可以工作

【讨论】:

  • 已经快速完成了,但还没有工作。根据我对 getelementsbyclassname 的了解,我需要运行类似 var i; 的东西。 for (i = 0; i
【解决方案2】:

我不知道您正在尝试如何自定义工作,但一个简单的解决方法是使用过滤器创建第二个类,然后在点击事件中添加该类。

<img src='mug.png' id='mug' class='unfiltered-pic'  onclick="changeColor(this)>
<style>
.unfiltered-pic {
     width: 25%
     height: 25%
}

.filtered-pic {
    filter: hue-rotate(/*degree on color wheel*/deg)
}
</style>
<script>
function changeColor(element) {
     element.setAttribute('class', 'filtered-pic');
}
</script>

您可以通过 css-filters here 选择各种过滤器。使用 hue-rotate 更改色调(颜色)。使用色轮来确定您想去的地方。

如果您想切换到使用类来一次更改所有这些,您可以这样做:

<img src='mug.png' id='mug' class='unfiltered-pic'  onclick="changeColor()>
<style>
.unfiltered-pic {
     width: 25%
     height: 25%
}

.filtered-pic {
    filter: filter function /*See Link*/
}
</style>
<script>
var pics = document.getElementByClassName('unfiltered-pic')
function changeColor() {
     for(var i=0; i < pics.length; i++) {
         pics[i].setAttribute('class', 'filtered-pic');
     }
}
</script>

如果您需要任何说明或其他帮助,请告诉我。

【讨论】:

  • 谢谢,稍后会更多地研究这个解决方案,一直在研究上面的第一个选项。
  • 好的,看过这个,我之前确实看过使用过滤器,但除非我遗漏了一些东西,否则它不能改变为指定的颜色,只是过滤效果?第二位: for(var i=0..... 是我需要实现以使其应用于所有图像(如果指定 [0] 则不仅仅是一个)但是我不确定如何实现这是我上面的原始代码,因此我们将不胜感激。
  • 我添加了对 hue-rotate 的解释,它将让您更改为特定的颜色。你有没有特别想要得到的?我会偏离解构图片,更改像素并将其重新组合在一起。这是一个工作密集型的过程,它们是可以帮助您实现目标的其他工具,例如过滤器。
  • 谢谢,抱歉我没有看到色调添加。你是对的,通过过滤器完成它可能会更容易满足我的需求,尽管我到目前为止使用的方法确实提供了一些非常好的结果,这些结果看起来与仅仅在顶部放置过滤器不同。即使我最终使用过滤器选项,我认为完成另一种方法会很好,因为它可能在未来被证明是有用的。到目前为止,它的加载和工作速度也非常快,但一旦扩展到我需要的所有图像,情况可能就不是这样了。我会试试过滤器选项,明天再发回。谢谢
  • 看了一下,但它显然在 IE 中不起作用?如果不是,那么就不能真正使用它 atm,这很遗憾,因为它似乎是一个很好的解决方案。
【解决方案3】:

好的,花了一些时间,但通过结合给出的建议和额外的搜索,找到了满足我需求的解决方案。

到目前为止,每条建议都让我受益匪浅,但我需要的特定功能存在一些问题,所以我发布这个以防它帮助其他人。

我正在使用 元素:

我需要一个主图像,并且它们顶部有一些较小的图像,如果单击图像或单击主图像外部的按钮,它们会改变颜色。

<div style="position: absolute; top: 0px; left: 0px;"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="0px" height="0px"><defs><filter id="desaturate"> <feColorMatrix 
  type="matrix"
  values="0.5 0 0 0 0
          0.2 0 0 0 0
          0.9 0 0 0 0
          0 0 0 1 0" /></filter></defs></svg></div>

这些值设置颜色变化。这是一个反复试验的 atm,因为我还没有找到一个好的颜色指南,但是周围有足够的地方可以通过。

我遇到了由使用 元素引起的随机空间和定位问题。所以我把它放在一个绝对定位的潜水中,并将元素的大小设置为“0”“0”,这样它就不会占用空间,也不会影响页面上的任何其他内容。

ID 指定了这个特定的颜色。然后,您可以将此颜色更改应用于任意数量的图像,如下所示:

<div style="position: relative; top: 000px; left: 000px; z-index: 1; display: inline;">
<svg class="svgClass" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="450px" height="900px">
<image xlink:href="main_image.png" width="450" height="900" />
<image xlink:href="small_image1.png" class="ChangeImageColour ChangeImageColourClick" width="79" height="198" x="110px" y="100px" />
<image xlink:href="small_image2.png" class="ChangeImageColour ChangeImageColourClick" width="79" height="198" x="150px" y="130px" /></svg></div>

再次,为了避免 SVG 的位置和间距问题,我将图像的 元素的大小设置为与主图像相同的大小,并将它们全部放在一个

中,然后可以定位在页面上的正确位置。如果您希望图像以这种方式重叠,则需要将所有图像放在同一个 元素中,否则在某些浏览器中可能会出现显示位置和间距问题。

您可以使用“x”和“y”将每个图像单独放置在主图像的顶部。您还必须指定图像的高度和宽度。

一旦你有你的 来指定颜色,你的图像的 元素,你现在只需要使用类和 ID 属性和以下代码将该颜色应用于你想要的图像:

<script>
  var $shape = $( '.ChangeImageColour' );
$( '.ChangeImageColourClick' ).click(function() {
          if ( $shape.attr( 'filter' ) )
     $shape.removeAttr( 'filter' );
  else
     $shape.attr( 'filter', 'url(#desaturate)' );
});
</script>

我希望在图像或按钮上的点击事件之后发生颜色变化。只需使用匹配的“click”类创建一个按钮,在本例中为“ChangeImageColourClick”。因此,您可以创建任何要单击的内容并更改颜色。此单击添加要更改的设置颜色的 ID (#desaturate)。如果任何匹配元素已经具有 ID,则将其删除。

这会产生切换颜色变化的效果。它将更改同一类的任何匹配图像的颜色。

如果不需要,你当然可以不使用点击事件,或者从颜色更改“on”开始,然后点击删除等。

注意:您可以有多个带有图像的 元素并应用相同的颜色更改。只需确保将 元素尺寸设置为所需的确切尺寸,即使它为 0。如果将其留空,则会出现一些间距问题。

我需要将图像放在相同的 中,因为它们是在页面上占据相同空间的 png 图像。如果您的图像不重叠,您应该使用单独的 元素或每个图像或图像集,并将 元素的尺寸设置为该图像的大小,并且您不应该有任何奇怪的间距和定位问题在某些浏览器中。

我认为这说明了一切。

它可以很好地满足我的需要,并且是相当简洁的编码,特别是因为您只需设置一次颜色并应用于多个图像。

请注意我所做的一些注释,以确保它按您的需要显示。

感谢大家的帮助,如果有任何相关的内容会更新。

如果您有任何问题,请在此处发布。我不是专家,但现在已经对此进行了相当多的研究,并且可能已经尝试并测试了大多数陷阱

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 2018-07-25
    • 1970-01-01
    • 2012-04-10
    • 2010-10-18
    • 2013-03-29
    相关资源
    最近更新 更多