前言
色彩在网页设计中很重要。为了让网页看起来更好,我们可以从图片中提取颜色,生成一个调色盘。这样做能快速帮我们找到合适的颜色,让网页设计更和谐。
思路
- 首先将图片画到 canvas 里,可以取出它的每一个像素点的颜色。
- 基于这些像素点来做色彩提取,将出现频率高的颜色取一个近似值(算法复杂)。
- 使用第三方库的图像聚合算法。
基本代码
<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));
}