I am trying to dynamically make and move Rectangles in React Konva. The problem is that sometimes my code runs perfectly fine, sometimes it throws error and sometimes rectangles don't get update and move properly.
I was not facing any problem till I made the functionality of updating state whenever the rectangle is moved. i am calling handleDragStart and handleDragEnd for this purpose. In handleDragStart I select the rectangle and put it in selectedrectangle variable and then in handleDragEnd I delete this rectangle from state and add the updated rectangle.
Problem 1 - The error shows that selectedRectangle is still null. It's not updated in handleDragStart function which it should.
Problem 2 - When I move Rectangles they move arbitrarily anywhere in the stage. When I draw new rectangle the shift back to their original drawn position.
Please help me find the problem and resolve it.
var index;
var selectedRectangle = null;
export default class MyRectangle extends React.Component {
constructor(props) {
super(props);
this.state = {
shapes : [],
isDrawing : false,
isDrawingMode : true,
image : null,
}
this.handleDragStart = this.handleDragStart.bind (this);
this.handleDragEnd = this.handleDragEnd.bind (this);
}
componentDidMount() {
const image = new window.Image();
image.src = this.props.image;
image.onload = () => {
this.setState ({
image: image
});
};
}
handleClick = (e) => {
if (!this.state.isDrawingMode) {
return;
}
if (this.state.isDrawing) {
this.setState ({
isDrawing: !this.state.isDrawing,
})
return;
}
const newShapes = this.state.shapes.slice();
newShapes.push ({
x: e.evt.layerX,
y: e.evt.layerY,
width: 0,
height: 0,
});
this.setState ({
isDrawing: true,
shapes: newShapes,
});
}
handleMouseMove = (e) => {
if (!this.state.isDrawingMode) return;
const mouseX = e.evt.layerX;
const mouseY = e.evt.layerY;
if (this.state.isDrawing) {
const currShapeIndex = this.state.shapes.length - 1;
const currShape = this.state.shapes[currShapeIndex];
const newWidth = mouseX - currShape.x;
const newHeight = mouseY - currShape.y;
const newShapesList = this.state.shapes.slice();
newShapesList[currShapeIndex] = {
x: currShape.x,
y: currShape.y,
width: newWidth,
height: newHeight
}
this.setState ({
shapes: newShapesList,
});
}
}
handleCheckboxChange = () => {
this.setState ({
isDrawingMode: !this.state.isDrawingMode,
})
}
handleDragStart(e) {
this.state.shapes.map ((sh) => {
if ((sh.x < e.evt.layerX) && (sh.y < e.evt.layerY) && ((sh.x + sh.width) > e.evt.layerX) && ((sh.y + sh.height) > e.evt.layerY)) {
selectedRectangle = sh;
}
});
console.log(selectedRectangle)
}
handleDragEnd (e) {
console.log(selectedRectangle)
index = this.state.shapes.indexOf (selectedRectangle);
this.state.shapes.splice(index, 1);
console.log(index);
selectedRectangle.x = e.target._lastPos.x;
selectedRectangle.y = e.target._lastPos.y;
this.setState({shapes : [...this.state.shapes, selectedRectangle]});
console.log(this.state.shapes)
}
render() {
return (
<div>
<input type = "checkbox" checked = {this.state.isDrawingMode} onChange = {this.handleCheckboxChange} />
<label>Drawing Mode</label>
<Stage
ref = 'stage'
width = {window.innerWidth}
height = {window.innerHeight}
onContentClick = {this.handleClick}
onContentMouseMove = {this.handleMouseMove}
>
<Layer ref = 'layer'>
<Image image = {this.state.image} />
{this.state.shapes.map((shape) => {
return (
<Group>
<Rect
x = {shape.x}
y = {shape.y}
width = {shape.width}
height = {shape.height}
isDrawingMode = {this.state.isDrawingMode}
strokeWidth = {2}
draggable = "true"
stroke="yellow"
fill="green"
opacity={0.4}
onDragStart = {(e) => this.handleDragStart(e)}
onDragEnd = {(e) => this.handleDragEnd(e)}
/>
</Group >
);
})}
</Layer>
</Stage>
<button onClick={this.sendData}>Submit</button>
</div>
);
}
}