大多数 browser-supported 改变简单PNG图像颜色的方法?
Most browser-supported method to change the color of a simple PNG image?
在网站构建过程中,我在设计中遇到了鼠标悬停样式的方向(由我解释):
这很简单,可以用 js(甚至 css)进行图像交换...但这让我深思。网站上将有几十个这样的图标链接——每个都与文本配对,每个都可能需要额外的颜色,或者调整蓝色。为任何额外的颜色创建每个图像的新版本将是一件令人头疼的事情,如果需要调整任何颜色,那将是一场噩梦。如果您可以使用 css 在一个地方控制文本和图像颜色,那不是很好吗?
我做了一些研究,关于影响图像颜色的流行观点似乎分为使用 CSS3 蒙版或将整个作品放在 SVG 中。 CSS 蒙版因其简单性而成为一个非常有吸引力的选择,但有 one glaring support gap - whereas SVG is recommended by W3C 但似乎依赖于 .svg 格式的图像(.png 解决方案变得复杂且不稳定)。
那么,有没有人知道可以让我有效地更改平面 .png 图像颜色并提供足够浏览器支持的解决方案? simplicity/elegance 的奖励积分,但我会接受任何只需要 .png 图像路径和十六进制颜色的内容。谢谢!
编辑 1:
郑重声明,IE9-10 超出了此处的范围 - 我们只关注 8 和 11。谢谢!
编辑 2: 其他(失败的)注意事项
我考虑过简单地为每个图标创建一个倒置的 "stencil" 并将其覆盖在背景颜色上。然而,这给我们的用户和内容编辑带来了问题,因为这些图标将在其他地方使用,而白色背景上的白色模板是无用的。
另请阅读答案 on this related question,但过滤器似乎不接受十六进制值,也未得到完全支持。图标字体可能有效,但 extensible/modifiable 对 non-savvy 用户来说并不容易 - 这里非常需要 "upload-to-cms" 功能。
答案和演示
I've solved the problem, here is a JSFiddle.
优点
- 非常好用。
- 您可以 select 任何格式的任何颜色 JavaScript。
- 您的图标可以是白色以外的任何颜色。
缺点
为了兼容所有颜色格式,需要tinycolor.js库作为依赖。 (但是:如果您创建自己的颜色转换函数,则可以删除此)
它只适用于 IE9+,因为它使用 HTML5 canvas。 (尽管老实说,为 IE 编写代码总是很痛苦)。
源图像必须在同一台服务器上,因为 canvas 不能从 cross-origin 源中被污染,并且您无法从中获取数据,这就是为什么演示中的源图像位于 Data URI. (However: there is a solution(如果您有兴趣的话)。
HTML
<input type="text" value="#669dbb">
<button>Change color</button>
<img src="data:image/png;base64,(..)">
非常简单,<input>
表示您希望图像更改为的颜色,<button>
用于应用更改。 (顺便说一句,原始值是您的默认图标上的浅蓝色)。
JavaScript
var img = document.querySelector("img");
var button = document.querySelector("button");
var text = document.querySelector("input");
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
button.onclick = function () {
changeColor(text.value);
};
changeColor = function (inputColor) {
canvas.setAttribute("width", img.width);
canvas.setAttribute("height", img.height);
context.drawImage(img, 0, 0);
var dataObject = context.getImageData(0, 0, canvas.width, canvas.height);
var data = dataObject.data;
for (var i = 0; i < data.length; i += 4) {
var r = data[i],
g = data[i + 1],
b = data[i + 2],
a = data[i + 3];
var notTransparent = a != 0;
var nonBackground = ( notTransparent && r != 255 && g != 255 && b != 255 );
if ( nonBackground ) {
var input = tinycolor(inputColor);
var rgb = input.toRgb();
data[i] = rgb.r;
data[i + 1] = rgb.g;
data[i + 2] = rgb.b;
data[i + 3] = a;
}
}
context.putImageData(dataObject, 0, 0);
img.src = canvas.toDataURL();
}
说明
好的,这是怎么回事,我将把我的解释集中在 changeColor()
函数上,因为其他代码块只是后台工作。
- 首先,我们将
<img>
的宽度和高度与 <canvas>
相匹配。
- 然后,我们将图像绘制到canvas。
- 然后,我们从整个canvas中得到像素数组数据。 (更多关于 canvas pixel manipulation。
- 然后我们读取数据(这是一个很长的数组)并获取每个像素值。
- 数组[0] = 红色
- 数组[1] = 绿色
- 数组[2] = 蓝色
- 数组[3] = Alpha.
- 然后,我们检查像素是否不是背景像素,确保它既不透明也不白色。
- 如果不是,我们获取输入颜色并将其设为 RGB。
- 然后,我们修改像素数据并更新canvas。
- 最后,我们从 canvas 得到一个
<img>
来源,方法是将其转换为 Data URI,然后我们更新 <img>
.
还有一件事
现在,虽然这可能很酷,但它需要很多 grunt-work 才能开始,所以我让你更容易,这是一个库,可以让你做你想要:AmazingIcon.js (Github)
它还没有完善,但可以胜任,下面是它的工作原理。
HTML(头)
<script src=tinycolor.js></script>
<script src=amazingicon.js></script>
HTML(正文)
<a class="amazingIcon" href="some-url" data-src="icon-image-url">icon-label</a>
很简单,我们使用data-src
创建一个pseudo-custom属性。
JavaScript
AmazingIcon.parseDocument();
AmazingIcon.hover(function(icon,ev){
icon.setColor("lightblue");
});
AmazingIcon.parseDocument()
函数会将任何带有 class amazingIcon
的锚点转换为神奇图标。
AmazingIcon.hover(callback)
函数将悬停事件应用于所有令人惊叹的图标,悬停事件函数将接收两个 (icon,event)
参数,您可以相应地对其进行操作。 (有关文档的更多信息)
CSS
.AmazingIconObject{
/* Display icons in the same row */
display: inline-block;
/* Aligning icons vertically inside parent */
vertical-align: top;
/* Centering labels */
text-align: center;
/* Sepparation between the icons */
margin-right: 5px;
/* Break label to fit icon width */
word-wrap: break-word;
/* Sets the width of the anchor (not the icon) */
width: 100px;
/* The following properties are design-subjective */
font-family: Verdana;
font-weight: bold;
color: lightcoral;
margin-right: 5px;
text-decoration: none;
}
很简单,如果你想知道更多它是如何工作的,当然一切都在 github,请随意复制和修改代码,请你和任何其他读者。
演示
由于难以使用 non-crossorigin 来源进行演示,我将只向您展示一张它看起来像的图像。
希望对您有所帮助,再见!
在网站构建过程中,我在设计中遇到了鼠标悬停样式的方向(由我解释):
这很简单,可以用 js(甚至 css)进行图像交换...但这让我深思。网站上将有几十个这样的图标链接——每个都与文本配对,每个都可能需要额外的颜色,或者调整蓝色。为任何额外的颜色创建每个图像的新版本将是一件令人头疼的事情,如果需要调整任何颜色,那将是一场噩梦。如果您可以使用 css 在一个地方控制文本和图像颜色,那不是很好吗?
我做了一些研究,关于影响图像颜色的流行观点似乎分为使用 CSS3 蒙版或将整个作品放在 SVG 中。 CSS 蒙版因其简单性而成为一个非常有吸引力的选择,但有 one glaring support gap - whereas SVG is recommended by W3C 但似乎依赖于 .svg 格式的图像(.png 解决方案变得复杂且不稳定)。
那么,有没有人知道可以让我有效地更改平面 .png 图像颜色并提供足够浏览器支持的解决方案? simplicity/elegance 的奖励积分,但我会接受任何只需要 .png 图像路径和十六进制颜色的内容。谢谢!
编辑 1: 郑重声明,IE9-10 超出了此处的范围 - 我们只关注 8 和 11。谢谢!
编辑 2: 其他(失败的)注意事项
我考虑过简单地为每个图标创建一个倒置的 "stencil" 并将其覆盖在背景颜色上。然而,这给我们的用户和内容编辑带来了问题,因为这些图标将在其他地方使用,而白色背景上的白色模板是无用的。
另请阅读答案 on this related question,但过滤器似乎不接受十六进制值,也未得到完全支持。图标字体可能有效,但 extensible/modifiable 对 non-savvy 用户来说并不容易 - 这里非常需要 "upload-to-cms" 功能。
答案和演示
I've solved the problem, here is a JSFiddle.
优点
- 非常好用。
- 您可以 select 任何格式的任何颜色 JavaScript。
- 您的图标可以是白色以外的任何颜色。
缺点
为了兼容所有颜色格式,需要tinycolor.js库作为依赖。 (但是:如果您创建自己的颜色转换函数,则可以删除此)
它只适用于 IE9+,因为它使用 HTML5 canvas。 (尽管老实说,为 IE 编写代码总是很痛苦)。
源图像必须在同一台服务器上,因为 canvas 不能从 cross-origin 源中被污染,并且您无法从中获取数据,这就是为什么演示中的源图像位于 Data URI. (However: there is a solution(如果您有兴趣的话)。
HTML
<input type="text" value="#669dbb">
<button>Change color</button>
<img src="data:image/png;base64,(..)">
非常简单,<input>
表示您希望图像更改为的颜色,<button>
用于应用更改。 (顺便说一句,原始值是您的默认图标上的浅蓝色)。
JavaScript
var img = document.querySelector("img");
var button = document.querySelector("button");
var text = document.querySelector("input");
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
button.onclick = function () {
changeColor(text.value);
};
changeColor = function (inputColor) {
canvas.setAttribute("width", img.width);
canvas.setAttribute("height", img.height);
context.drawImage(img, 0, 0);
var dataObject = context.getImageData(0, 0, canvas.width, canvas.height);
var data = dataObject.data;
for (var i = 0; i < data.length; i += 4) {
var r = data[i],
g = data[i + 1],
b = data[i + 2],
a = data[i + 3];
var notTransparent = a != 0;
var nonBackground = ( notTransparent && r != 255 && g != 255 && b != 255 );
if ( nonBackground ) {
var input = tinycolor(inputColor);
var rgb = input.toRgb();
data[i] = rgb.r;
data[i + 1] = rgb.g;
data[i + 2] = rgb.b;
data[i + 3] = a;
}
}
context.putImageData(dataObject, 0, 0);
img.src = canvas.toDataURL();
}
说明
好的,这是怎么回事,我将把我的解释集中在 changeColor()
函数上,因为其他代码块只是后台工作。
- 首先,我们将
<img>
的宽度和高度与<canvas>
相匹配。 - 然后,我们将图像绘制到canvas。
- 然后,我们从整个canvas中得到像素数组数据。 (更多关于 canvas pixel manipulation。
- 然后我们读取数据(这是一个很长的数组)并获取每个像素值。
- 数组[0] = 红色
- 数组[1] = 绿色
- 数组[2] = 蓝色
- 数组[3] = Alpha.
- 然后,我们检查像素是否不是背景像素,确保它既不透明也不白色。
- 如果不是,我们获取输入颜色并将其设为 RGB。
- 然后,我们修改像素数据并更新canvas。
- 最后,我们从 canvas 得到一个
<img>
来源,方法是将其转换为 Data URI,然后我们更新<img>
.
还有一件事
现在,虽然这可能很酷,但它需要很多 grunt-work 才能开始,所以我让你更容易,这是一个库,可以让你做你想要:AmazingIcon.js (Github)
它还没有完善,但可以胜任,下面是它的工作原理。
HTML(头)
<script src=tinycolor.js></script>
<script src=amazingicon.js></script>
HTML(正文)
<a class="amazingIcon" href="some-url" data-src="icon-image-url">icon-label</a>
很简单,我们使用data-src
创建一个pseudo-custom属性。
JavaScript
AmazingIcon.parseDocument();
AmazingIcon.hover(function(icon,ev){
icon.setColor("lightblue");
});
AmazingIcon.parseDocument()
函数会将任何带有 class amazingIcon
的锚点转换为神奇图标。
AmazingIcon.hover(callback)
函数将悬停事件应用于所有令人惊叹的图标,悬停事件函数将接收两个 (icon,event)
参数,您可以相应地对其进行操作。 (有关文档的更多信息)
CSS
.AmazingIconObject{
/* Display icons in the same row */
display: inline-block;
/* Aligning icons vertically inside parent */
vertical-align: top;
/* Centering labels */
text-align: center;
/* Sepparation between the icons */
margin-right: 5px;
/* Break label to fit icon width */
word-wrap: break-word;
/* Sets the width of the anchor (not the icon) */
width: 100px;
/* The following properties are design-subjective */
font-family: Verdana;
font-weight: bold;
color: lightcoral;
margin-right: 5px;
text-decoration: none;
}
很简单,如果你想知道更多它是如何工作的,当然一切都在 github,请随意复制和修改代码,请你和任何其他读者。
演示
由于难以使用 non-crossorigin 来源进行演示,我将只向您展示一张它看起来像的图像。
希望对您有所帮助,再见!