简体   繁体   English

通过Javascript更改图像颜色

[英]Changing Image colour through Javascript

I have been looking to change the colour of an image when a click event is used. 我一直在寻找使用单击事件时更改图像的颜色。

I Came across this post, which the first and main response with the Mug works really well. 我遇到了这篇文章,其中第一个和主要的回应与Mug工作得非常好。

However, I need to use class, rather than ID, as I need to change the colour of more than one image. 但是,我需要使用类而不是ID,因为我需要更改多个图像的颜色。 When I change the code to getElementsByClassName, instead of byID, it no longer works. 当我将代码更改为getElementsByClassName而不是byID时,它不再有效。

I of course change the ID=mug to class=mug. 我当然把ID =杯子改为class = mug。

I can't see anywhere else in the code that would cause a problem, so any help would be appreciated. 我无法在代码中看到任何会导致问题的其他地方,所以任何帮助都将不胜感激。

I can't post on the original so adding here. 我不能发布原文,所以在这里添加。 Original link is: How to change color of an image using jquery 原始链接是: 如何使用jquery更改图像的颜色

This is the code: 这是代码:

<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>

Thanks 谢谢

I don't know how custom of a job you are trying, but a simple fix would be to make a second class with a filter, then add that class at the click event. 我不知道你正在尝试的工作的自定义,但一个简单的解决方法是使用过滤器创建第二个类,然后在click事件中添加该类。

<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>

You can choose various filters through css-filters here . 您可以在此处通过css-filters选择各种过滤器。 Use hue-rotate to change the hue(color). 使用hue-rotate更改色调(颜色)。 Use a color wheel to determine where you want to go. 使用色轮确定您要去的地方。

If you would like to switch to using class to change all of them at once, you can do this instead: 如果您想切换到使用类一次更改所有这些,您可以改为:

<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>

Let me know if you need any clarification or additional help. 如果您需要任何澄清或其他帮助,请与我们联系。

I think it might have something to do with browser support because document.getElementByClassName("mug"); 我认为它可能与浏览器支持有关,因为document.getElementByClassName("mug"); should return an array of elements (older browsers might not support it). 应该返回一个元素数组(旧浏览器可能不支持它)。 At which point it is easy to iterate over each mug and change the colour like so 在这一点上,很容易迭代每个杯子并改变颜色

<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>

I haven't ran the code but it should work 我没有运行代码,但它应该工作

OK, has taken some time but through a combination of the suggestions given and extra searching have found a solution for my needs. 好的,花了一些时间,但通过结合给出的建议和额外的搜索,找到了满足我需求的解决方案。

Each of the suggestions got me so far but there were some issues for the specific functionality I needed, so am posting this in case it helps others. 到目前为止,每个建议都让我感到满意,但是我需要的具体功能存在一些问题,所以我发布这个以防万一。

I am using the < svg > element: 我正在使用<svg>元素:

I required a main image, and them some smaller images on top that would change colour if the image was clicked on, or if a button outside the main image is clicked. 我需要一个主图像,它们顶部有一些较小的图像,如果点击图像,或者点击主图像外的按钮,它会改变颜色。

<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>

The values set the colour change. 值设置颜色更改。 It is trial and error atm as I haven't found a good guide to the colours yet but there are enough around to get by. 这是试验和错误atm,因为我还没有找到一个很好的颜色指南,但有足够的周围来得到。

I had a problem with random spaces and positioning caused by using the < svg > element. 使用<svg>元素导致随机空间和定位问题。 So I have put it inside a dive that is absolutely positioned and set the size of the element to '0' '0' so it takes up no space and doesn't affect anything else on the page. 所以我把它放在一个绝对定位的潜水中,并将元素的大小设置为'0''0',这样它就不会占用任何空间,也不会影响页面上的任何其他内容。

The ID specifies this particular colour. ID指定此特定颜色。 You can then apply this colour change to as many images as you like as follows: 然后,您可以将此颜色更改应用于您喜欢的任意数量的图像,如下所示:

<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>

Again, to avoid position and spacing issues with SVG, I have set the size of the < svg > element for the images to the same size of the main image, and placed them all within a < div > that can then be positioned in the right place on the page. 同样,为了避免SVG的位置和间距问题,我已经将图像的<svg>元素的大小设置为与主图像相同的大小,并将它们全部放在<div>中,然后可以将其放置在正确的位置在页面上。 If you want images overlapping in this way, you will need to have all the images within the same < svg > element or you may get display position and spacing issues in some browsers. 如果您希望图像以这种方式重叠,则需要将所有图像放在同一个<svg>元素中,否则您可能会在某些浏览器中出现显示位置和间距问题。

You can the position each image individually over the top of the main image using 'x' and 'y'. 您可以使用“x”和“y”将每个图像分别放置在主图像的顶部。 You must also specify the height and width of the image. 您还必须指定图像的高度和宽度。

Once you have your < svg > to specify the colour, and your < svg > element for the images, you now just need to apply that colour to the images you want using class and ID attributes and the following code: 一旦你有<svg>来指定颜色,你的<svg>元素就可以了,你现在只需要使用类和ID属性以及下面的代码将这种颜色应用于你想要的图像:

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

I want the colour change to happen after a click event ether on an image or a button. 我希望在图像或按钮上的单击事件以太后发生颜色更改。 Just create a button with the matching 'click' calss, in this case 'ChangeImageColourClick'. 只需创建一个匹配“click”calss的按钮,在本例中为“ChangeImageColourClick”。 So you can create anything to be clicked on and will change the colour. 因此,您可以创建要点击的任何内容并更改颜色。 This click adds the ID of the set colour to change (#desaturate). 此单击添加要更改的设置颜色的ID(#desaturate)。 If any matching element already has the ID, it is removed. 如果任何匹配元素已具有该ID,则将其删除。

This creates the effect of toggling the colour change. 这会产生切换颜色变化的效果。 It will change the colour of any matching image of the same class. 它将改变同一类的任何匹配图像的颜色。

You can of course not use a click event if not required, or start with the colour change 'on' and click to remove etc. 如果不需要,您当然可以不使用点击事件,或者开始使用颜色更改“打开”并单击以删除等。

Note: You can have multiple < svg > elements with images in and apply the same colour change. 注意:您可以在多个<svg>元素中包含图像并应用相同的颜色更改。 Just make sure you set the < svg > element dimensions to the exact ones you want, even if it is 0. If you leave it blank then you'll get some spacing issues. 只需确保将<svg>元素尺寸设置为您想要的尺寸,即使它是0.如果将其留空,则会出现一些间距问题。

I need to have the images in the same < svg > as they are png images that are occupying the same space on the page. 我需要将图像放在相同的<svg>中,因为它们是占用页面上相同空间的png图像。 If your images are not overlapping you should use separate < svg > elements or each image or image set, and set the dimensions of the < svg > element to the size of that image and you shouldn't have any issues with odd spacing and positioning in some browsers. 如果您的图像没有重叠,您应该使用单独的<svg>元素或每个图像或图像集,并将<svg>元素的尺寸设置为该图像的大小,您不应该有任何奇数间距和定位问题在某些浏览器中。

I think that about explains it all. 我想这就解释了一切。

It works pretty well for what I need, and is a fairly concise bit of coding, especially as you only have to set the colour once and apply to multiple images. 它非常适合我需要的东西,并且是一个相当简洁的编码,特别是因为你只需设置一次颜色并应用于多个图像。

Just be careful of some of the notes I've put to make sure it displays as you need. 请注意我放置的一些注意事项,以确保它根据您的需要显示。

Thanks for all the help, will update if there is anything relevant to add. 感谢所有帮助,如果有任何相关内容需要更新。

If you are having any problems then post on here. 如果您遇到任何问题,请在此处发帖。 I'm not an expert but have looked at this a fair bit now and have probably tried and tested most pitfalls 我不是专家,但现在已经看了很多,并且可能已经尝试并测试了大多数陷阱

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM