0

I am facing a problem. I am drawing rectangles on click and drag. I am storing these rectangles in array. Whenever I push newly made Rectangle in the array the old stored rectangles gets updated with the last pushed rectangle. For example - suppose my array(named data) contains Rectangles as - [Rectangle 1, Rectangle 2]. Now if I add 3rd rectangle the updated array is like - [rectangle 3, rectangle 3, rectangle 3]. please tell me where i am wrong and help me resolve this problem.

//I am drawing rectangles in handleMouseMove function and updating the array in handleMouseUp. I am using var data = [] to store array

import React from 'react';

var rect = {};
var shape = {};
var data = [];

export default class MyCanvas extends React.Component {
    constructor(props) {
        super (props);

        this.state = {
            imageLink : 'some link',
            shapes : [],
            isDown : false,
        };

        this.handleClick = this.handleClick.bind (this);
        this.hanldeMouseMove = this.hanldeMouseMove.bind (this);        
        this.handleMouseDown = this.handleMouseDown.bind (this);        
        this.handleMouseUp = this.handleMouseUp.bind (this);        
    }

    componentDidMount() {
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext ("2d");

        const img = this.refs.image;

        canvas.height = img.height;
        canvas.width = img.width;

        img.onload = () => {
            ctx.drawImage (img, 0, 0);
        }

        var rectX = canvas.offsetLeft;
        var rectY = canvas.offsetTop;

        canvas.addEventListener ('mousemove', (e) => {this.hanldeMouseMove (e, canvas, img)}, false);
        canvas.addEventListener ('mousedown', (e) => {this.handleMouseDown (e)}, false);
        canvas.addEventListener ('mouseup', () => {this.handleMouseUp(canvas)}, false);
    }

    hanldeMouseMove(e, canvas, img) {
        if (this.state.isDown) {
            rect.w = (e.pageX - canvas.offsetLeft) - rect.startX;
            rect.h = (e.pageY - canvas.offsetTop) - rect.startY ;

            const ctx = canvas.getContext ("2d");

            // Rectangles are drawn here
            ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
            ctx.drawImage(img, 0, 0);
            ctx.strokeRect (rect.startX, rect.startY, rect.w, rect.h);

            shape = rect;
        }
    }

    handleMouseDown(e) {
        rect.startX = e.offsetX;
        rect.startY = e.offsetY;
        this.setState ({isDown : true});

    }

    // updating the array here
    handleMouseUp(canvas) {
        this.setState ({isDown : false});
        data.push(shape);
        console.log(data);
    }

    render() {
        return (
            <div className="container">
                <canvas ref = "canvas" />
                <img ref = "image" alt = "Link is Broken" src = {this.state.imageLink} className = "d-none" />
            </ div>
        );
    }
}

2 Answers 2

2

There is single referance for rect and its getting copied and updated everytime in the array.So,all element in the array show same element.

instead of

shape = rect;

do liek this,

shape = Object.assign({},rect);
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks it worked. But why wasn't it working with above one? I mean whats the difference between these two
Object always referred by reference .as I mentioned ,its only one reference and its used for all element.
Yeah, my mistake. Thanks
0

Data object should be in your state and you have to keep in mind that React works with immutable objects.

 handleMouseUp(canvas) {
    var newDataArray = this.state.data.slice();    
    newDataArray.push(shape);   
    this.setState({data:newDataArray})  
 }  

this.state.data.slice() creates a shallow copy of the array, making it immutable

With ES6, you can also use the better way, which is

handleMouseUp(canvas) {
    this.setState(previousState => ({
        data: [...previousState.data, shape]
    }));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.