Skip to content

实现图片调色盘

Published:

前言

色彩在网页设计中很重要。为了让网页看起来更好,我们可以从图片中提取颜色,生成一个调色盘。这样做能快速帮我们找到合适的颜色,让网页设计更和谐。

思路

  1. 首先将图片画到 canvas 里,可以取出它的每一个像素点的颜色。
  2. 基于这些像素点来做色彩提取,将出现频率高的颜色取一个近似值(算法复杂)。
  3. 使用第三方库的图像聚合算法。

基本代码

<template>
  <div class="grid">
    <div class="item" v-for="(item, index) in images" :key="item">
      <img
        :src="item"
        crossorigin="anonymous"
        @mouseenter="onMouseEnter($event.target, index)"
        @mouseleave="onMouseLeave"
        :style="{
          opacity: hoverIndex === -1 ? 1 : index === hoverIndex ? 1 : 0.2,
        }"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";

const images = [];
for (let i = 1; i <= 4; i++) {
  images.push(`//picsum.photos/800/800?random=${i}`);
}

const hoverIndex = ref(-1);
async function onMouseEnter(image, index) {
  hoverIndex.value = index;
}
async function onMouseLeave() {
  hoverIndex.value = -1;
}
</script>

<style>
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  justify-content: center;
  height: 100%;
  gap: 1rem;
  padding: 1rem;
  width: fit-content;
  margin: 0 auto;
}

.item {
  display: flex;
  justify-content: center;
}

img {
  width: 400px;
  height: 400px;
  transition: opacity 0.4s ease;

  &:hover {
    transform: scale(1.05);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
  }
}
</style>

接着,使用第三方库 colorthief 来调用一个方法 getPalette ,把图像作为参数传递进去,告诉它取出这个图像里边的前几种颜色,假设我们取3种:

async function onMouseEnter(image, index) {
  hoverIndex.value = index;
  const colors = await colorThief.getPalette(image, 3);
  console.log(colors);
}

现在,将鼠标移到每个图像上,控制台会打印出颜色数组。

接下来,我们只需要做一个 map 映射,把每一种颜色映射成一个字符串:

colors.map(c => `rgb(${c[0]}, ${c[1]}, ${c[2]})`);
console.log(colors);

最后,将这些颜色拿出来,设置为渐变背景的颜色:

async function onMouseEnter(image, index) {
  hoverIndex.value = index;
  let _colors = await colorThief.getPalette(image, 3);
  colors = _colors.map(c => `rgb(${c[0]}, ${c[1]}, ${c[2]})`);

  // 遍历颜色数组,给 html 元素设置 CSS 变量
  colors.forEach((color, index) => {
    html.style.setProperty(`--c${index + 1}`, color);
  });
}

// 鼠标移出时将颜色设置为白色
async function onMouseLeave() {
  hoverIndex.value = -1;
  colors.forEach((color, index) => {
    html.style.setProperty(`--c${index + 1}`, "#fff");
  });
}

对了,别忘了给 html 元素添加渐变:

html {
  background: linear-gradient(var(--c1), var(--c2), var(--c3));
}