首先,准备好所需的 HTML
结构,并自定义样式,初始代码和效果如下:
<style>
.bgImage {
width: 300px;
height: 150px;
margin-top: 20px;
background-color: gainsboro;
position: relative;
}
#imgBox {
transform: translate(80px, 80px);
width: 130px;
height: 130px;
border-radius: 50%;
border: 3px solid #f8f8f8;
object-fit: cover;
}
</style>
<body>
<input id="imgUploader" type="file" accept="image/*" />
<div class="bgImage">
<!-- 默认图片可替换 -->
<img id="imgBox" src="https://tse1-mm.cn.bing.net/th/id/OIP-C.Y-NsSYXU2YBgwjIfmL879AHaHa?w=163&h=180&c=7&r=0&o=5&dpr=2&pid=1.7" alt="Not image data...">
</div>
</body>
接下来,监听 input
元素的 change
事件,以获取上传图片的相关参数,这里主要是为了获取图片的宽度和高度,然后将图像绘制到 canvas
画布。
// 初始化,监听 change 事件。
const init = function () {
imgUploader.addEventListener('change', handleChange);
}
init();
const handleChange = function (ev) {
const imgFile = ev.target.files[0];
if (!imgFile) {
return;
}
const reader = new FileReader();
reader.onload = function (e) {
const imgUrl = e.target.result;
imgBox.src = imgUrl;
imgBox.crossOrigin = 'anonymous';
imgBox.style.display = 'block';
// 确保图片加载完成后,将图片渲染到画布上。
imgBox.onload = function () {
const { width, height } = imgBox;
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
context.drawImage(imgBox, 0, 0, width, height);
// 获取主题色。
getColor(canvas, context);
}
}
reader.readAsDataURL(imgFile);
}
然后,实现 getColor
函数,主要是通过 canvas
的 getImageData()
方法获取图片每个像素点的 rgba
数据,然后计算所有像素点的平均值,来计算图片主题色。
const getColor = (canvas, context) => {
const { width, height } = canvas;
const { data: imageData } = context.getImageData(0, 0, width, height);
const totalPixels = width * height;
const themeColor = [0, 0, 0, 0];
for (let i = 0; i < imageData.length; i += 4) {
themeColor[0] += imageData[i];
themeColor[1] += imageData[i + 1];
themeColor[2] += imageData[i + 2];
themeColor[3] += imageData[i + 3];
};
for (let i = 0; i < themeColor.length; i++) {
const color = themeColor[i];
themeColor[i] = Math.round(color / totalPixels);
};
const avgRgba = themeColor.join(',');
bgImage.style.background = `rgba(${avgRgba})`;
}
最终实现的效果如下: