js实现拾色器————color-picker
实现效果
react 版本示例
jsx部分
import "./styles.css";
import React, { useEffect, useRef, useState } from "react";
export default () => {
const can = useRef(null);
const cur = useRef(null);
const width = 256;
const curColor = "rgba(255,0,0,1)";
const [rgbValue, setRgbValue] = useState([]);
const colorBar = () => {
const ctx = can.current.getContext("2d");
const gradientBar = ctx.createLinearGradient(0, 0, 0, width);
gradientBar.addColorStop(0, "#f00");
gradientBar.addColorStop(1 / 6, "#f0f");
gradientBar.addColorStop(2 / 6, "#00f");
gradientBar.addColorStop(3 / 6, "#0ff");
gradientBar.addColorStop(4 / 6, "#0f0");
gradientBar.addColorStop(5 / 6, "#ff0");
gradientBar.addColorStop(1, "#f00");
ctx.fillStyle = gradientBar;
ctx.fillRect(0, 0, 20, width);
};
const colorBox = (color) => {
const ctx = can.current.getContext("2d");
// 底色填充,也就是(举例红色)到白色
const gradientBase = ctx.createLinearGradient(30, 0, width + 30, 0);
gradientBase.addColorStop(1, color);
gradientBase.addColorStop(0, "rgba(255,255,255,1)");
ctx.fillStyle = gradientBase;
ctx.fillRect(30, 0, width, width);
// 第二次填充,黑色到透明
const gradientScreen = ctx.createLinearGradient(0, 0, 0, width);
gradientScreen.addColorStop(0, "rgba(0,0,0,0)");
gradientScreen.addColorStop(1, "rgba(0,0,0,1)");
ctx.fillStyle = gradientScreen;
ctx.fillRect(30, 0, width, width);
};
useEffect(() => {
colorBar();
colorBox(curColor);
can.current.addEventListener("click", (e) => {
const coorX = e.offsetX || e.layerX;
const coorY = e.offsetY || e.layerY;
const ctx = can.current.getContext("2d");
const imgData = ctx.getImageData(coorX, coorY, 1, 1);
const { data } = imgData;
const rgbaStr = [data[0], data[1], data[2]];
setRgbValue(rgbaStr);
if (coorX && coorX < 20 && coorY >= 0 && coorY < width) {
colorBox(`rgba(${rgbaStr.join(",")})`);
}
// onChange(rgbaStr)
cur.current.style.left = `${coorX}px`;
cur.current.style.top = `${coorY}px`;
// 128===256/2 亮色边框用黑色, 暗色用白色
cur.current.style.outlineColor =
rgbaStr[0] > 128 || rgbaStr[1] > 128 || rgbaStr[2] > 128
? "#000"
: "#fff";
});
}, []);
return (
<div className="colorPicker">
<div className="wrapper">
<canvas className="canvas" width="300" height="300" ref={can} />
<em className="cur" ref={cur} />
</div>
<div>
预览颜色: rgb({rgbValue.join(",")})
{rgbValue.length === 3 && (
<div
style={{
height: 50,
width: 50,
background: `rgba(${rgbValue.join(",")})`
}}
/>
)}
</div>
</div>
);
};
css部分
.colorPicker {
width: 300px;
height: 300px;
background: #fff;
padding: 8px;
z-index: 10;
margin-bottom: 8px;
}
.canvas {
cursor: crosshair;
}
.cur {
width: 3px;
height: 3px;
margin-left: -1px;
margin-top: -1px;
outline: 2px solid rgba(0, 0, 0, 0);
position: absolute;
}
.wrapper {
position: relative;
}
html 原生版