Search code examples
javascriptreactjsonmousedown

How to make onMouseDown event working for a canvas created by React.createRef()?


I am trying to make mouse events work on a canvas created though React.createRef(). I have taken reference from below snippet of code from this stackoverflow only which is working perfectly :

import React, {Component} from 'react';
import ReactDOM from 'react-dom';

export default class canvas extends React.Component{
    constructor(props) {
        super(props);
        //added state 
        this.state={
            isDown: false,
            previousPointX:'',
            previousPointY:''
        }
        this.handleMouseDown = this.handleMouseDown.bind(this);
        this.handleMouseMove = this.handleMouseMove.bind(this);
        this.handleMouseUp = this.handleMouseUp.bind(this);
    }
    render() {
        return (
            <div>    
                <canvas id="canvas" ref="canvas"
                        width={640}
                        height={425}
                        onMouseDown={
                            e => {
                                let nativeEvent = e.nativeEvent;
                                this.handleMouseDown(nativeEvent);
                            }}
                        onMouseMove={
                            e => {
                                let nativeEvent = e.nativeEvent;
                                this.handleMouseMove(nativeEvent);
                            }}    
                        onMouseUp={
                            e => {
                                let nativeEvent = e.nativeEvent;
                                this.handleMouseUp(nativeEvent);
                            }}
                />
            </div>    
        );
    }

    handleMouseDown(event){ //added code here
        console.log(event);    
        this.setState({
            isDown: true,
            previousPointX:event.offsetX,
            previousPointY:event.offsetY
        },()=>{    
            const canvas = ReactDOM.findDOMNode(this.refs.canvas);    
            var x = event.offsetX;
            var y = event.offsetY;
            var ctx = canvas.getContext("2d");
            console.log(x,y);
            ctx.moveTo(x,y);
            ctx.lineTo(x+1,y+1);
            ctx.stroke();
        })
    }
    handleMouseMove(event){

    }
    handleMouseUp(event){
        this.setState({
            isDown: false
        });
        //if(this.state.isDown){
            const canvas = ReactDOM.findDOMNode(this.refs.canvas);
            var x = event.offsetX;
            var y = event.offsetY;
            var ctx = canvas.getContext("2d");

            ctx.moveTo(this.state.previousPointX,this.state.previousPointY);
            ctx.lineTo(x,y);
            ctx.stroke();
            ctx.closePath();
        //}
    }
    componentDidMount() {
        const canvas = ReactDOM.findDOMNode(this.refs.canvas);
        const ctx = canvas.getContext("2d");
        ctx.fillStyle = 'rgb(200,255,255)';
        ctx.fillRect(0, 0, 640, 425);
    }
}

Below link is having my attempt using createRef. Apart from the mousedownevent , rest of the part is working. Any help to make the mousedown event work as per the above code behavior will be very helpful.
https://codesandbox.io/s/loving-hertz-4fjdnz?file=/src/App.js
Thanks.


Solution

  • The reason this fails is because of how you are binding the function. In your code, the method gets called right away (with no parameter) and this is why the page crashes. Here is the code in your example I am talking about:

    canvas_page.onmousedown = this.MouseDownEvt();
    

    A better way to do it would be like this:

    canvas_page.onmousedown = this.MouseDownEvt.bind(this);
    

    This passes a reference to the method itself which will correctly populate the e parameter.