How to use react to draw rectangles over objects in an image?
componentDidMount
will be called only once from React, after the component is mounted.
Since you want to draw something every time a user clicks on the canvas, you have to do that in a place that it's called at every rendering, like inside the render
function itself.
Something like this:
import React, { Component } from 'react'
import { render } from 'react-dom'
import {Row} from 'react-bootstrap';
class TagImg extends Component {
constructor(props){
super(props);
this.state={
rects:[[110, 30, 70, 70], [40, 30, 70, 70]]
};
this.tagPerson = this.tagPerson.bind(this);
}
tagPerson(e){
var x = e.offsetX,
y = e.offsetY;
for(var i=0;i<this.props.rects.length;i++) { // check whether:
if(x > this.props.rects[i][0] // mouse x between x and x + width
&& x < this.props.rects[i][0] + this.props.rects[i][2]
&& y > this.props.rects[i][1] // mouse y between y and y + height
&& y < this.props.rects[i][1] + this.props.rects[i][3]) {
alert('Rectangle ' + i + ' clicked');
}
}
}
drawRects() {
const ctx = this.refs.canvas.getContext('2d');
ctx.drawImage(myImage, 0, 0, 300, 200);
ctx.beginPath();
ctx.strokeStyle="white";
// for(var i=0;i<this.state.rects.length;i++) {
// // ctx.rect(this.state.rects[i][0], // fill at (x, y) with (width, height)
// // this.state.rects[i][1],
// // this.state.rects[i][2],
// // this.state.rects[i][3]);
// console.log("helloo");
// }
console.log(this.state.rects);
ctx.stroke();
}
componentDidMount() {
console.log("componentDidMount");
var myImage = new Image();
myImage.onload = this.drawRects.bind(this);
myImage.src = this.props.path;
}
render() {
drawRects();
return (
<div>
<form id="afterUpload" action="" method="post" encType="multipart/form-data">
<Row id="image_preview" className="row">
<canvas ref="canvas" onClick={this.tagPerson}/>
</Row>
</form>
</div>
);
}
}
export default TagImg;
In the code I'm downloading the image once, in the componentDidMount
method. And I'm running the drawRects()
method at every rendering, so every time you call a setState
you'll have your new rects
ayakhaled
Updated on July 02, 2022Comments
-
ayakhaled almost 2 years
I'm using react and HTML5 canvas to draw rectangles over faces on an image, but react life-cycle is limiting me from doing this.
As I should use refs to reference to the canvas and this have to be done in componentDidMount() and I could not get props or states inside this function.
Here is the code:
import React, { Component } from 'react' import { render } from 'react-dom' import {Row} from 'react-bootstrap'; import '../App.css'; class TagImg extends Component { constructor(props){ super(props); this.state={ rects:[[110, 30, 70, 70], [40, 30, 70, 70]], ctx : '' }; this.tagPerson = this.tagPerson.bind(this); } tagPerson(e){ var x = e.offsetX, y = e.offsetY; for(var i=0;i<this.props.rects.length;i++) { // check whether: if(x > this.props.rects[i][0] // mouse x between x and x + width && x < this.props.rects[i][0] + this.props.rects[i][2] && y > this.props.rects[i][1] // mouse y between y and y + height && y < this.props.rects[i][1] + this.props.rects[i][3]) { alert('Rectangle ' + i + ' clicked'); } } } componentDidMount() { console.log("componentDidMount"); const ctx = this.refs.canvas.getContext('2d'); var myImage = new Image(); myImage.onload = function() { var width = myImage.naturalWidth; // this will be 300 var height = myImage.naturalHeight; // this will be 400 ctx.drawImage(myImage, 0, 0, 300, 200); ctx.beginPath(); ctx.strokeStyle="white"; // for(var i=0;i<this.state.rects.length;i++) { // // ctx.rect(this.state.rects[i][0], // fill at (x, y) with (width, height) // // this.state.rects[i][1], // // this.state.rects[i][2], // // this.state.rects[i][3]); // console.log("helloo"); // } console.log(this.state.rects); ctx.stroke(); } myImage.src = this.props.path; } render() { return ( <div> <form id="afterUpload" action="" method="post" encType="multipart/form-data"> <Row id="image_preview" className="row"> <canvas ref="canvas" onClick={this.tagPerson}/> </Row> </form> </div> ); } } export default TagImg;
After searching I figured out that I could use componentWillRecieveProps() but did not understand how to use it in my case.