所选图像未显示在画布上

时间:2017-01-11 01:54:59

标签: javascript reactjs canvas redux fabricjs

我正在开发一个应用程序,用户可以从提供的图像列表中选择图像。当用户单击列表中的图像时,所选图像应作为背景显示在画布上。我正在使用reactjs,redux和fabricjs开发它。

  

当我这样做时,我不会选择图像   this.props.getSelectedImage.image.image所以我可以更新   setCanvasBackground。

图片-list.js

class Images extends React.Component {
  renderImages() {
    const { images, selectImage } = this.props;
    return _.map(images, (image, key) =>
      <li key={key}>
        <img
          src={image.image}
          alt={image.id}
          className="responsive-img default-images"
          width="400px"
          onClick={() => selectImage(image)}
        />
      </li>
    );
  }
  render() {
    return (
      <ul className="image-list">
        {this.renderImages()}
      </ul>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    images: state.images
  }
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({ selectImage: selectImage }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Images);

actions.js

export function selectImage(image) {
  return {
    type: 'SELECT_IMAGE',
    payload: image
  }
}

reducers.js

const initialState = {
  selectedImage: require('./img/image1.jpg')
};

export function getSelectedImage(state = initialState, action) {
  switch (action.type) {
    case 'SELECT_IMAGE':
      return Object.assign({}, state, { selectedImage: action.payload.image })
    default:
      return state;
  }
}

图片-board.js

class ImageBoard extends React.Component {
  constructor() {
    super();
    this.state = {
      canvas: undefined,
      selected: undefined
    };
  }

  componentDidMount() {
    const canvas = new fabric.Canvas('canvas');
    this.setCanvasBackground(this.props.getSelectedImage.selectedImage, canvas);
  }

  setCanvasBackground(image, canvas) {
    canvas.setBackgroundImage(image, function(e) {
    let iw = canvas.backgroundImage.width,
          ih = canvas.backgroundImage.height,
          cw = canvas.getWidth(),
          ch = canvas.getHeight();

    let iar = iw/ih,
      car = cw/ch;

    let nw = cw,
      nh = ch;

    if (iar > car){
      nh = ch;
      nw = nh * iar;
    }
    else if (iar < car){
      nw = cw;
      nh = cw/iar;
    }
    canvas.backgroundImage.width = nw;
    canvas.backgroundImage.height = nh;
    canvas.renderAll();
    }.bind(this));
  }

  render() {
    return(
      <div className="image-board">
         <canvas
           id="canvas"
           className="z-depth-1"
           width={600}
           height={400}
         />
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  console.log('state', state);
  return {
    images: state.images,
    getSelectedImage: state.getSelectedImage
  }
};

export default connect(mapStateToProps)(ImageBoard);

现在我可以显示默认图像,但是当点击列表中的图像时无法更改画布中的背景图像。但是当我将console.log('image selected', this.props.getSelectedImage.image.image);置于渲染功能中时,我得到所选图像但无法设置此图像setBackgroundImage所以我可以在画布上显示所选图像。

我该怎么办?

反应v15.4.2已被使用

更新

componentDidUpdate() {
    console.log('componentDidUpdate');
    const canvas = new fabric.Canvas('canvas');
    this.setCanvasBackground(this.props.getSelectedImage.selectedImage, canvas);
  }

如果我使用componentDidUpdate生命周期方法,它可以工作,但我得到以下结果。这么多画布都被重新创建了,我知道它,因为我在componentDidUpdate中创建了一个canvas对象来更新画布。我怎么能以明确的方式做到这一点?

enter image description here

1 个答案:

答案 0 :(得分:0)

我看到两个可能的解决方案:

  • 从DOM中删除旧画布(因此您只能使用新画布):

How to destroy / reload the canvas in html 5?

componentDidUpdate() {
    console.log('componentDidUpdate');
    // Get the old canvas and remove it
    var oldCanvas = document.getElementById('canvas');
    oldCanvas = null;

    // Add your completely new canvas
    const canvas = new fabric.Canvas('canvas');
    this.setCanvasBackground(this.props.getSelectedImage.selectedImage,      canvas);
}
  • 在重新绘制新画布之前清除旧画布:

Redrawing Canvas in HTML5 using Javascript

要清除画布,您需要执行上述链接中提到的操作。如果您使用此方法,请确保不要在componentDidUpdate()中向页面添加新画布。

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    ctx.clearRect(0, 0, 500, 500);

第二个解决方案的链接特别提到,如果不清除画布,绘制的元素将叠加。