如何使用反应在图像中的对象上绘制矩形?

时间:2017-03-27 15:24:05

标签: javascript image facebook reactjs canvas

我使用react和HTML5画布在图像上的面上绘制矩形,但反应生命周期限制了我这样做。

因为我应该使用refs来引用画布,这必须在componentDidMount()中完成,我无法在这个函数中获得道具或状态。

以下是代码:

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;

搜索后我发现我可以使用componentWillRecieveProps(),但在我的情况下不明白如何使用它。

1 个答案:

答案 0 :(得分:0)

componentDidMount将在安装组件后仅从React调用一次。

由于您希望每次用户点击画布时都要绘制一些内容,因此您必须在每次渲染时调用它,例如在render函数本身内部。

这样的事情:

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;

在代码中,我使用componentDidMount方法下载图像一次。并且我在每次渲染时都运行drawRects()方法,因此每次拨打setState时,您都会有新的视频