Pardeep Sharma
Pardeep Sharma

Reputation: 293

Drawing a straight line using mouse events on canvas in ReactJs

I want to draw a straight line. I achieved to draw dots when i click on canvas and move my cursor and also it stop drawing when i release my mouse button.

But I need to draw straight line. I find solution on stackoverflow but they are in Jquery and Javascript. I don't want to use JQuery.

Some solution suggest that create 2 canvas 1 for store line and 1 for drawing lines on canvas.

But I know that it can be achieved by single canvas and I am very close to achieve this.

following is my code.

export default class CanvasComponent extends React.Component{
constructor(props) {
    super(props);
    this.state={
        isDown: false
    }
    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){
    console.log(event);

    this.setState({
        isDown: true
    },()=>{

        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){
    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(x,y);
        ctx.lineTo(x+1,y+1);
        ctx.stroke();
        ctx.closePath();
    }

}
handleMouseUp(){
    this.setState({
        isDown: false
    })
}
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);
}

}

Upvotes: 2

Views: 6272

Answers (2)

Soma Sarkar
Soma Sarkar

Reputation: 866

you need to store the previous point in state. In handleMouseUp(i.e. OnMouseUp) event, you need to draw the lines between previous point and current point. here is the changed code:

    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);
    }
}

Upvotes: 2

WiRa
WiRa

Reputation: 998

Keep the first coordinates as global or class variables, so you can draw the line on second click.

Do you need to show a temporary line when the cursor moves? Then add a second layer on which you draw a line with the same coordinates at every mouse move (clear the layer before redraw!)

Upvotes: 0

Related Questions