是否有可能获得表情符号的主要颜色?
Is it possible to get the majority color of an emoji?
我想要实现的是向表情符号添加 text-shadow
,其中 text-shadow
颜色是表情符号中最突出的颜色。
我知道有 JavaScript 库可以识别图像中最突出的颜色,但由于表情符号在技术上是文本,所以我不确定我将如何做,甚至不知道是否可能。
我会提供一些我已经尝试过的代码,但老实说,我什至不知道从哪里开始。
.emoji {
text-shadow: 0px 0px 20px rgba(54, 169, 230, 0.65);
padding: 3px 6px;
font-size: 24px;
}
<span class="emoji"></span>
另一种不使用 text-shadow
的方法是复制表情符号,将其直接放在原始表情符号的后面并对其进行模糊处理。
您可以直接在 HTML 中创建副本,或者如果使用 js 更方便,如下例所示。
var emoji = document.querySelector("#blur-me");
var copy = emoji.cloneNode(true);
copy.classList.remove("emoji");
emoji.appendChild(copy);
.emoji {
padding: 3px 6px;
font-size: 24px;
position: relative;
display: inline-block;
}
.emoji span {
position: absolute;
left: 6px;
z-index: -1;
filter: blur(10px);
}
<span class="emoji" id="blur-me"></span>
提出的替代答案是使用属性复制图标而不需要 JS。您还可以应用缩放变换使效果更明显:
.emoji {
padding: 3px 6px;
margin:0 5px;
font-size: 24px;
position: relative;
display: inline-block;
z-index: 0;
}
.emoji:before,
.emoji:after{
content: attr(data-icon);
}
.emoji:before {
position: absolute;
z-index: -1;
filter: blur(3px);
transform: scale(1.5);
}
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
模糊表情符号副本的方法(由 sol 提出)是一种有效且相当轻量级的方法。稍微调整一下,您可以获得更像阴影的东西:
var emoji = document.querySelector("#blur-me");
var copy = emoji.cloneNode(true);
copy.classList.remove("emoji");
emoji.appendChild(copy);
.emoji {
padding: 3px 6px;
font-size: 24px;
position: relative;
display: inline-block;
}
.emoji span {
position: absolute;
left: 6px;
z-index: -1;
filter: blur(5px);
transform: scale(.95) translate(5px, 5px);
}
<span class="emoji" id="blur-me"></span>
scale(.95)
是为了补偿它增长的模糊,然后 translate()
只是简单地将它移动到更像文本阴影而不是模糊的地方。
另一种可以让您获得更准确颜色的方法是将其绘制到 canvas。一旦你有了一个 canvas,它基本上是一个图像,所以你提到的那些库可以工作。
const canvas = document.querySelector('canvas');
canvas.width = 30;
canvas.height = 30;
const ctx = canvas.getContext('2d');
ctx.font = "20px Arial";
ctx.fillText("", 0, 20);
canvas {
border: 1px solid #000;
}
.emoji {
text-shadow: rgba(0, 0, 0, .5) 2px 2px 2px;
}
<div class="emoji"></div>
<canvas></canvas>
获得平均值后,您可以通过几种不同的方式获得平均值。一种是只获取原始像素,排除背景颜色,然后对剩余部分进行数学平均。由于 canvas 是不透明的,您可以使用老派的技巧填充非常难看的颜色:
const canvas = document.querySelector('canvas');
canvas.width = 30;
canvas.height = 30;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#121212'; // 12 => 17 in decimal
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "20px Arial";
ctx.fillText("", 0, 20);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// an array in the format [r, g, b, count] decimal
const sums = imageData.data.reduce((r, v, i) => {
if (v === 18) return r; // our fill color, skip
if (i % 4 !== 3) { // i % 4 === 3 is transparent, ignoring
r[i % 4] += v;
r[3]++;
}
return r;
}, [0, 0, 0, 0]);
sums[3] = sums[3] / 3; // divide by 3 since we counted each pixel 3 times
const averages = [Math.floor(sums[0] / sums[3]), Math.floor(sums[1] / sums[3]), Math.floor(sums[2] / sums[3])];
// just to see the color
ctx.fillStyle = `rgb(${averages.join(',')})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas {
border: 1px solid #000;
}
.emoji {
text-shadow: rgba(0, 0, 0, .5) 2px 2px 2px;
}
<div class="emoji"></div>
<canvas></canvas>
显然,这个特定的算法非常基础,并不完美(主要用于演示目的)。还有其他算法或库。如果您调用 canvas.toDataUrl()
,您甚至会得到一个值,您可以在大多数库中像图像一样使用它。
从那里,只需使用计算出的颜色,然后使用 JavaScript 将其设置为 element.style.textShadow
属性即可。
document.querySelector('.emoji').style.textShadow = 'rgb(255, 0, 0) 2px 2px';
<span class="emoji"></span>
我想要实现的是向表情符号添加 text-shadow
,其中 text-shadow
颜色是表情符号中最突出的颜色。
我知道有 JavaScript 库可以识别图像中最突出的颜色,但由于表情符号在技术上是文本,所以我不确定我将如何做,甚至不知道是否可能。
我会提供一些我已经尝试过的代码,但老实说,我什至不知道从哪里开始。
.emoji {
text-shadow: 0px 0px 20px rgba(54, 169, 230, 0.65);
padding: 3px 6px;
font-size: 24px;
}
<span class="emoji"></span>
另一种不使用 text-shadow
的方法是复制表情符号,将其直接放在原始表情符号的后面并对其进行模糊处理。
您可以直接在 HTML 中创建副本,或者如果使用 js 更方便,如下例所示。
var emoji = document.querySelector("#blur-me");
var copy = emoji.cloneNode(true);
copy.classList.remove("emoji");
emoji.appendChild(copy);
.emoji {
padding: 3px 6px;
font-size: 24px;
position: relative;
display: inline-block;
}
.emoji span {
position: absolute;
left: 6px;
z-index: -1;
filter: blur(10px);
}
<span class="emoji" id="blur-me"></span>
.emoji {
padding: 3px 6px;
margin:0 5px;
font-size: 24px;
position: relative;
display: inline-block;
z-index: 0;
}
.emoji:before,
.emoji:after{
content: attr(data-icon);
}
.emoji:before {
position: absolute;
z-index: -1;
filter: blur(3px);
transform: scale(1.5);
}
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
<span class="emoji" data-icon=""></span>
模糊表情符号副本的方法(由 sol 提出)是一种有效且相当轻量级的方法。稍微调整一下,您可以获得更像阴影的东西:
var emoji = document.querySelector("#blur-me");
var copy = emoji.cloneNode(true);
copy.classList.remove("emoji");
emoji.appendChild(copy);
.emoji {
padding: 3px 6px;
font-size: 24px;
position: relative;
display: inline-block;
}
.emoji span {
position: absolute;
left: 6px;
z-index: -1;
filter: blur(5px);
transform: scale(.95) translate(5px, 5px);
}
<span class="emoji" id="blur-me"></span>
scale(.95)
是为了补偿它增长的模糊,然后 translate()
只是简单地将它移动到更像文本阴影而不是模糊的地方。
另一种可以让您获得更准确颜色的方法是将其绘制到 canvas。一旦你有了一个 canvas,它基本上是一个图像,所以你提到的那些库可以工作。
const canvas = document.querySelector('canvas');
canvas.width = 30;
canvas.height = 30;
const ctx = canvas.getContext('2d');
ctx.font = "20px Arial";
ctx.fillText("", 0, 20);
canvas {
border: 1px solid #000;
}
.emoji {
text-shadow: rgba(0, 0, 0, .5) 2px 2px 2px;
}
<div class="emoji"></div>
<canvas></canvas>
获得平均值后,您可以通过几种不同的方式获得平均值。一种是只获取原始像素,排除背景颜色,然后对剩余部分进行数学平均。由于 canvas 是不透明的,您可以使用老派的技巧填充非常难看的颜色:
const canvas = document.querySelector('canvas');
canvas.width = 30;
canvas.height = 30;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#121212'; // 12 => 17 in decimal
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "20px Arial";
ctx.fillText("", 0, 20);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// an array in the format [r, g, b, count] decimal
const sums = imageData.data.reduce((r, v, i) => {
if (v === 18) return r; // our fill color, skip
if (i % 4 !== 3) { // i % 4 === 3 is transparent, ignoring
r[i % 4] += v;
r[3]++;
}
return r;
}, [0, 0, 0, 0]);
sums[3] = sums[3] / 3; // divide by 3 since we counted each pixel 3 times
const averages = [Math.floor(sums[0] / sums[3]), Math.floor(sums[1] / sums[3]), Math.floor(sums[2] / sums[3])];
// just to see the color
ctx.fillStyle = `rgb(${averages.join(',')})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas {
border: 1px solid #000;
}
.emoji {
text-shadow: rgba(0, 0, 0, .5) 2px 2px 2px;
}
<div class="emoji"></div>
<canvas></canvas>
显然,这个特定的算法非常基础,并不完美(主要用于演示目的)。还有其他算法或库。如果您调用 canvas.toDataUrl()
,您甚至会得到一个值,您可以在大多数库中像图像一样使用它。
从那里,只需使用计算出的颜色,然后使用 JavaScript 将其设置为 element.style.textShadow
属性即可。
document.querySelector('.emoji').style.textShadow = 'rgb(255, 0, 0) 2px 2px';
<span class="emoji"></span>