停止 canvas 线宽变化时的清除

Stop canvas clearing on lineWidth change

我有一个 React 应用程序,可让您绘制 select 不同的线宽。

代码:

const [sliderVal, setSliderVal] = useState(1) 
const canvasRef = useRef(null)
useEffect(() => {
    const canvas = canvasRef.current
    const ctx = canvas.getContext('2d')

    ctx.canvas.width = window.innerWidth;
    ctx.canvas.height = window.innerHeight;


    /* Mouse Capturing Work */
    var mouse = {x: 0, y: 0};
    var last_mouse = {x: 0, y: 0};

    canvas.addEventListener('mousemove', function(e) {
        last_mouse.x = mouse.x;
        last_mouse.y = mouse.y;

        mouse.x = e.pageX - this.offsetLeft;
        mouse.y = e.pageY - this.offsetTop;

        canvas.style.cursor = "crosshair";
    }, false);


    /* Drawing on Paint App */
    ctx.lineWidth = sliderVal;
    ctx.lineJoin = 'round';
    ctx.lineCap = 'round';
    ctx.strokeStyle = 'blue';

    canvas.addEventListener('mousedown', function() {
        canvas.addEventListener('mousemove', onPaint, false);
    }, false);

    canvas.addEventListener('mouseup', function() {
        canvas.removeEventListener('mousemove', onPaint, false);
    }, false);

    var onPaint = function() {
        ctx.beginPath();
        ctx.moveTo(last_mouse.x, last_mouse.y);
        ctx.lineTo(mouse.x, mouse.y);
        ctx.closePath();
        ctx.stroke();
    };
}, [sliderVal])

我正在努力做到这一点,如果 sliderVal 改变整个 canvas 不会重新渲染,只有线宽会。现在它可以工作但是如果我 select 一个新的 lineWidth 整个 canvas 被清除。

我建议您不要以这种方式使用 eventListener,ReactJS 中的 canvas 已经有一些您可以访问和传递函数的方法。这种处理 canvas 的新方法解决了您的问题:

  const [sliderVal, setSliderVal] = useState(1);
  const [mouse, setMouse] = useState({
    x: 0,
    y: 0,
    lastX: 0,
    lastY: 0,
    click: false
  });
  const canvasRef = useRef(null);

  const paint = (e) => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    const bounds = canvas.getBoundingClientRect();
    setMouse({
      ...mouse,
      x: e.pageX - bounds.left - window.scrollX,
      y: e.pageY - bounds.top - window.scrollY,
      lastX: mouse.x,
      lastY: mouse.y
    });
    ctx.lineWidth = sliderVal;
    ctx.lineJoin = "round";
    ctx.lineCap = "round";
    ctx.strokeStyle = "blue";
    if (mouse.click) {
      ctx.beginPath();
      ctx.moveTo(mouse.lastX, mouse.lastY);
      ctx.lineTo(mouse.x, mouse.y);
      ctx.closePath();
      ctx.stroke();
    }
  };
  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    ctx.canvas.width = window.innerWidth;
    ctx.canvas.height = window.innerHeight;
    canvas.style.cursor = "crosshair";
  }, []);
  return (
      <canvas
        onMouseDown={() => setMouse({ ...mouse, click: true })}
        onMouseMove={(e) => paint(e)}
        onMouseUp={() => setMouse({ ...mouse, click: false })}
        ref={canvasRef}
      />

我分享一个codesandbox功能解决方案