You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使React.createRef()创建的Canvas的onMouseDown事件生效?

解决React.createRef实现Canvas鼠标事件中onMouseDown失效的问题

以下是修正后的完整实现,完全对齐你提供的参考代码功能,解决onMouseDown事件失效的问题:

import React, { Component } from 'react';

export default class Canvas extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isDown: false,
      previousPointX: '',
      previousPointY: ''
    };
    // 初始化createRef引用
    this.canvasRef = React.createRef();
    this.handleMouseDown = this.handleMouseDown.bind(this);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.handleMouseUp = this.handleMouseUp.bind(this);
  }

  render() {
    return (
      <div>
        <canvas
          ref={this.canvasRef}
          width={640}
          height={425}
          onMouseDown={this.handleMouseDown}
          onMouseMove={this.handleMouseMove}
          onMouseUp={this.handleMouseUp}
        />
      </div>
    );
  }

  handleMouseDown(event) {
    console.log(event);
    this.setState(
      {
        isDown: true,
        previousPointX: event.offsetX,
        previousPointY: event.offsetY
      },
      () => {
        // 直接通过current属性获取canvas DOM元素
        const canvas = this.canvasRef.current;
        const x = event.offsetX;
        const y = event.offsetY;
        const ctx = canvas.getContext('2d');
        console.log(x, y);
        ctx.moveTo(x, y);
        ctx.lineTo(x + 1, y + 1);
        ctx.stroke();
      }
    );
  }

  handleMouseMove(event) {
    // 补充拖拽画线逻辑(可选,对齐参考代码可保留空实现)
    if (this.state.isDown) {
      const canvas = this.canvasRef.current;
      const ctx = canvas.getContext('2d');
      ctx.lineTo(event.offsetX, event.offsetY);
      ctx.stroke();
    }
  }

  handleMouseUp(event) {
    this.setState({ isDown: false });
    const canvas = this.canvasRef.current;
    const x = event.offsetX;
    const y = event.offsetY;
    const ctx = canvas.getContext('2d');

    ctx.moveTo(this.state.previousPointX, this.state.previousPointY);
    ctx.lineTo(x, y);
    ctx.stroke();
    ctx.closePath();
  }

  componentDidMount() {
    const canvas = this.canvasRef.current;
    const ctx = canvas.getContext('2d');
    ctx.fillStyle = 'rgb(200,255,255)';
    ctx.fillRect(0, 0, 640, 425);
  }
}

关键修改说明

  1. 正确使用createRef:

    • 在构造函数中通过this.canvasRef = React.createRef()创建引用,替代旧的字符串ref="canvas"写法
    • 获取Canvas DOM元素时直接使用this.canvasRef.current,无需ReactDOM.findDOMNode,这是createRef的标准用法,避免了旧API的潜在问题
  2. 事件处理简化:

    • React合成事件已包含offsetX/offsetY等所需属性,不需要额外提取nativeEvent,直接将事件对象传递给处理函数即可
  3. 确保状态更新后获取DOM:

    • 在setState的回调函数中执行绘图逻辑,保证状态更新完成后再操作Canvas元素,避免异步更新导致的元素未就绪问题

内容的提问来源于stack exchange,提问作者A.G.Progm.Enthusiast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:33:47