虽然HTML原生的input可以实现拾色器功能,但是很多时候我们需要自己设置样式和交互方式,就需要自己手动写一个滴管取色的组件,目前比较通用的一个方案就是将dom转换成二进制图片数据,再由canvas读取色值来实现自定义的拾色器滴管功能。
运行截图:
完整demo代码:(感兴趣的可以直接复制完整demo代码本地运行)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拾色器滴管取色</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
margin: 0;
position: relative;
}
.color-box {
width: 50px;
height: 50px;
display: inline-block;
margin: 5px;
border: 1px solid #000;
}
#color-display {
width: 100px;
height: 50px;
border: 1px solid #000;
margin-top: 10px;
}
#color-canvas {
position: absolute;
display: none;
cursor: crosshair;
}
#magnifier-canvas{
position: absolute;
width: 120px;
height: 120px;
display: none;
}
</style>
</head>
<body>
<div id="container">
<h1>Color Picker with Circular Magnifier</h1>
<!-- 颜色方块 -->
<div class="color-box" style="background-color: #FF5733;"></div>
<div class="color-box" style="background-color: #33FF57;"></div>
<div class="color-box" style="background-color: #3357FF;"></div>
<div class="color-box" style="background-color: #FF33A6;"></div>
<div class="color-box" style="background-color: #33FFF6;"></div>
<div class="color-box" style="background-color: #FFBD33;"></div>
<button id="capture-button">Capture and Pick Color</button>
<div id="color-display"></div>
</div>
<canvas id="color-canvas"></canvas>
<canvas id="magnifier-canvas" width="120" height="120"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const captureButton = document.getElementById('capture-button');
const colorDisplay = document.getElementById('color-display');
const colorCanvas = document.getElementById('color-canvas');
const magnifierCanvas = document.getElementById('magnifier-canvas');
const container = document.getElementById('container');
const body = document.body;
let ctx, magnifierCtx;
captureButton.addEventListener('click', async function() {
try {
// 异步捕捉当前页面状态
const dataUrl = await domtoimage.toPng(body);
const img = new Image();
img.src = dataUrl;
img.onload = function() {
// 将 canvas 的大小和位置设置为覆盖整个页面
colorCanvas.width = window.innerWidth;
colorCanvas.height = window.innerHeight;
colorCanvas.style.left = '0';
colorCanvas.style.top = '0';
// 显示放大器
magnifierCanvas.style.display = 'block';
// 在 canvas 上绘制页面截图
ctx = colorCanvas.getContext('2d');
ctx.drawImage(img, 0, 0);
// 显示 canvas 并隐藏原始内容
colorCanvas.style.display = 'block';
// 恢复原始页面内容可见
container.style.visibility = 'hidden';
magnifierCtx = magnifierCanvas.getContext('2d');
// 监听鼠标移动事件
colorCanvas.addEventListener('mousemove', handleMouseMove);
// 监听鼠标点击事件进行颜色选择
colorCanvas.addEventListener('click', handleClick);
};
} catch (error) {
console.error('Error capturing the page:', error);
}
});
function handleMouseMove(event) {
const x = event.clientX;
const y = event.clientY;
// 绘制圆形放大镜
drawCircularMagnifier(x, y);
// 放大镜在鼠标旁边显示
magnifierCanvas.style.left = `${event.pageX + 10}px`;
magnifierCanvas.style.top = `${event.pageY + 10}px`;
}
function handleClick(event) {
const x = event.clientX;
const y = event.clientY;
// 获取点击位置的颜色数据
const pixelData = ctx.getImageData(x, y, 1, 1).data;
const r = pixelData[0];
const g = pixelData[1];
const b = pixelData[2];
const a = pixelData[3] / 255;
const rgbaColor = `rgba(${r}, ${g}, ${b}, ${a})`;
colorDisplay.style.backgroundColor = rgbaColor;
colorDisplay.textContent = rgbaColor;
// 取色完成后隐藏 canvas 和放大镜
colorCanvas.style.display = 'none';
magnifierCanvas.style.display = 'none';
magnifierCanvas.style.display = 'none';
// 恢复原始页面内容可见
container.style.visibility = 'visible';
// 解除事件监听器
colorCanvas.removeEventListener('mousemove', handleMouseMove);
colorCanvas.removeEventListener('click', handleClick);
}
function drawCircularMagnifier(x, y) {
const magnification = 3;
const magnifierSize = 100;
const radius = magnifierSize / 2;
// 清空画布
magnifierCtx.clearRect(0, 0, magnifierCanvas.width, magnifierCanvas.height);
// 绘制圆形放大镜区域
magnifierCtx.save();
magnifierCtx.beginPath();
magnifierCtx.arc(radius + 10, radius + 10, radius, 0, Math.PI * 2);
magnifierCtx.closePath();
magnifierCtx.clip();
// 放大镜显示放大的页面内容
magnifierCtx.drawImage(colorCanvas, x - magnifierSize / (2 * magnification), y - magnifierSize / (2 * magnification), magnifierSize / magnification, magnifierSize / magnification, 10, 10, magnifierSize, magnifierSize);
magnifierCtx.restore();
magnifierCtx.strokeStyle = '#000';
magnifierCtx.lineWidth = 2;
magnifierCtx.stroke();
// 显示放大镜
magnifierCanvas.style.display = 'block';
}
});
</script>
</body>
</html>
这样基本是可以做到定制化的取色器功能了,但是这样还是有一些问题,具体什么问题以及如何解决,可以参考:EyeDropper 实现拾色器(滴管取色)功能-CSDN博客
标签:canvas,const,colorCanvas,style,取色,magnifierCtx,display,滴管 From: https://blog.csdn.net/qq_35322029/article/details/141068800