js实现拾色器————color-picker

实现效果

img

demo效果

demo

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 原生版


posted @ 2022-06-24 11:39  VictoriaC~  阅读(1191)  评论(0编辑  收藏  举报