【问题标题】:Is it possible to get the majority color of an emoji?是否有可能获得表情符号的大多数颜色?
【发布时间】:2018-04-24 23:36:45
【问题描述】:

我想要实现的是将text-shadow 添加到表情符号中,text-shadow 颜色是表情符号中最突出的颜色。

我知道有一些 JavaScript 库可以识别图像中最突出的颜色,但由于 emoji 是技术上的文本,我不确定我该怎么做,甚至根本不知道它是否可能。

我会提供一些我已经尝试过的代码,但老实说,我什至不知道从哪里开始。

.emoji {
  text-shadow: 0px 0px 20px rgba(54, 169, 230, 0.65);
  padding: 3px 6px;
  font-size: 24px;
}
<span class="emoji">????</span>

【问题讨论】:

标签: javascript css shadow emoji


【解决方案1】:

不使用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>

【讨论】:

    【解决方案2】:

    @Sol 提出的另一种解决方案是使用属性来复制图标而不需要 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>

    【讨论】:

    • 我喜欢尽可能避免使用 JS。 @JaneDoe – 考虑不是每个人都启用 JavaScript 的可能性;以这种方式进行操作的用户仍然可以使用投影。
    • @ianrandmckenzie 是的,我意识到,我只是说答案对我来说是最好的解决方案。其他人可能会发现 css 更好。
    【解决方案3】:

    模糊表情符号副本的方法(由 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);
    }
    &lt;span class="emoji" id="blur-me"&gt;?&lt;/span&gt;

    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';
    &lt;span class="emoji"&gt;?&lt;/span&gt;

    【讨论】:

    • 但是如果突出的颜色主要在图标内部呢?我认为我们不仅应该关注突出的颜色,还应该考虑更接近边缘的突出颜色,以便具有表情符号连续性的阴影
    • 您可以通过各种不同的方式对其进行切片和切块以提取颜色。我没有尝试回答这个问题,因为它有很多不同的方法和算法。我只是试图回答如何将其转换为图像,以便您可以使用这些库。我只是提供了一个示例方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    相关资源
    最近更新 更多