Javascript 如何让canvas onmousemove处理程序查看最新的React state钩子值?

Javascript 如何让canvas onmousemove处理程序查看最新的React state钩子值?,javascript,reactjs,drag-and-drop,html5-canvas,Javascript,Reactjs,Drag And Drop,Html5 Canvas,我正在编写一个基于画布的超基本图像查看器。我正在尝试实现图像平移。我希望能够按住鼠标键并移动鼠标来平移图像。我使用鼠标上下事件进入和离开“平移模式”。不过,我的鼠标移动处理程序似乎从未看到平移布尔值从false变为true 我试着用箭头函数来编写我的函数,我想这可能是因为它们是DOM处理程序(与this或其他什么有关),但这似乎没有什么区别 我有一个显示平移状态的平视显示器,它会相应地更新,但是我的控制台日志在鼠标移动处理程序中总是将变量显示为false 我怎样才能让这个平移布尔值像您在我的鼠标

我正在编写一个基于画布的超基本图像查看器。我正在尝试实现图像平移。我希望能够按住鼠标键并移动鼠标来平移图像。我使用鼠标上下事件进入和离开“平移模式”。不过,我的鼠标移动处理程序似乎从未看到平移布尔值从false变为true

我试着用箭头函数来编写我的函数,我想这可能是因为它们是DOM处理程序(与
this
或其他什么有关),但这似乎没有什么区别

我有一个显示平移状态的平视显示器,它会相应地更新,但是我的控制台日志在鼠标移动处理程序中总是将变量显示为false

我怎样才能让这个平移布尔值像您在我的鼠标移动处理程序中所期望的那样进行更新

这是我的精简代码,可以在下面的代码笔链接中测试

import * as React from "https://cdn.skypack.dev/react@17.0.1";
import * as ReactDOM from "https://cdn.skypack.dev/react-dom@17.0.1";

type PropsType = {
  url: string;
};

function ImageViewer(props: PropsType) {
  const imgRef = React.useRef(null);
  const canvasRef = React.useRef(null);
  
  const [isDragging, setIsDragging] = React.useState(false);
  
  function imageUrlChangeEffect() {
    imgRef.current.src = props.url;
  }
  
  function componentMountEffect() {
    imgRef.current.onload = handleImageLoad;
    canvasRef.current.onmouseup = handleMouseUp;
    canvasRef.current.onmousedown = handleMouseDown;
    canvasRef.current.onmousemove = handleMouseMove;
  }

  function handleMouseUp() {
    setIsDragging(false);
  }
  
  function handleMouseDown() {
    setIsDragging(true);
  }
  
  function handleMouseMove(ev) {
    const {x, y} = ev;
    console.log({x, y, isDragging});
  }
  
  function handleImageLoad() {
    clearCanvas();
    drawImage();
  }
  
  function clearCanvas() {
    const context = canvasRef.current.getContext("2d");
    context.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
  }
    
  function drawImage() {
    const context = canvasRef.current.getContext("2d");
    context.drawImage(imgRef.current, 0, 0, imgRef.current.width, imgRef.current.height);
  }

  React.useEffect(componentMountEffect, []);
  React.useEffect(imageUrlChangeEffect, [props.url]);

  return (
    <div className="image-viewer">
      <p>is dragging: {isDragging.toString()}</p>
      <canvas ref={canvasRef} width="600" height="200"></canvas>
      <img ref={imgRef} />
    </div>
  );
}

ReactDOM.render(
  <ImageViewer url="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />,
  document.getElementById("container"));
import*as React from”https://cdn.skypack.dev/react@17.0.1";
将*作为ReactDOM从导入”https://cdn.skypack.dev/react-dom@17.0.1";
类型PropsType={
url:string;
};
函数ImageViewer(道具:PropsType){
const imgRef=React.useRef(null);
const canvasRef=React.useRef(null);
常量[IsDraging,SetIsDraging]=React.useState(false);
函数imageUrlChangeEffect(){
imgRef.current.src=props.url;
}
函数componentMountEffect(){
imgRef.current.onload=handleImageLoad;
canvasRef.current.onmouseup=handleMouseUp;
canvasRef.current.onmousedown=handleMouseDown;
canvasRef.current.onmousemove=handleMouseMove;
}
函数handleMouseUp(){
SETISDRAGING(假);
}
函数handleMouseDown(){
SetIsDraging(真);
}
功能手柄移动(ev){
常数{x,y}=ev;
log({x,y,isDraging});
}
函数handleImageLoad(){
clearCanvas();
drawImage();
}
函数clearCanvas(){
const context=canvasRef.current.getContext(“2d”);
clearRect(0,0,canvasRef.current.width,canvasRef.current.height);
}
函数drawImage(){
const context=canvasRef.current.getContext(“2d”);
drawImage(imgRef.current,0,0,imgRef.current.width,imgRef.current.height);
}
React.useffect(componentMountEffect,[]);
React.useffect(imageUrlChangeEffect[props.url]);
返回(
正在拖动:{IsDraging.toString()}

); } ReactDOM.render( , document.getElementById(“容器”);
下面是一个可测试的代码示例。当您移动鼠标并按住鼠标按钮时,必须打开控制台以查看变量的控制台日志,该日志永远不会变为true。您可以看到画布上方的文本发生了变化,显示它正在从false变为true


这里至少有两种解决方案:

解决方案1:

在画布上声明侦听器:


并在
handleMouseMove
中使用本机事件:

const {x, y} = ev.nativeEvent;
解决方案2:

指示
useffect
更新
isDraging
的值:

React.useEffect(componentMountEffect, [isDragging]);

哦,很好。我甚至没有想过要把处理程序放在画布组件上。你了解这件事的根本原因吗,能给我解释一下吗?我以前没有遇到过这个问题,只能假设处理程序在某个时间点被复制或其他东西,因此它捕获了变量的原始值,因此它永远不会改变。我不知道内部结构,但我的想法是,
useffect
将它的依赖关系应用到它的范围