最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to use react to draw rectangles over objects in an image? - Stack Overflow

programmeradmin1浏览0评论

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 ponentDidMount() 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');
        }
    }
  }

  ponentDidMount() {
    console.log("ponentDidMount");
    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 ponentWillRecieveProps() but did not understand how to use it in my case.

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 ponentDidMount() 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');
        }
    }
  }

  ponentDidMount() {
    console.log("ponentDidMount");
    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 ponentWillRecieveProps() but did not understand how to use it in my case.

Share edited Mar 27, 2017 at 16:29 ayakhaled asked Mar 27, 2017 at 15:24 ayakhaledayakhaled 811 gold badge2 silver badges10 bronze badges 2
  • Did you see the function : ponentWillReceiveProps(nextProps) { ... – Alexandre Nicolas Commented Mar 27, 2017 at 15:38
  • I did but didn't understand how can I use it in my case. – ayakhaled Commented Mar 27, 2017 at 15:56
Add a ment  | 

1 Answer 1

Reset to default 1

ponentDidMount will be called only once from React, after the ponent 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();

  }

  ponentDidMount() {
    console.log("ponentDidMount");
    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 ponentDidMount method. And I'm running the drawRects() method at every rendering, so every time you call a setState you'll have your new rects

发布评论

评论列表(0)

  1. 暂无评论