Подход размытия копии смайликов (предложенный 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()
- просто смещение его, как текстатень и меньше как размытие.
Другой подход, который позволил бы вам получить более точный цвет, - это нарисовать его на холсте.Если у вас есть холст, то в основном это изображение, чтобы те библиотеки, которые вы упомянули, могли работать.
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>
Как только вы это получите, есть пара различных способов получить среднее значение.Можно было бы просто получить необработанные пиксели, исключить цвет фона, а затем математически усреднить остаток.Так как холст непрозрачен, вы можете использовать уловку старой школы по заполнению действительно уродливым цветом:
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>