【问题标题】:Selected image is not shown on canvas所选图像未显示在画布上
【发布时间】:2017-05-25 16:35:14
【问题描述】:

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

当我这样做时,我没有得到选定的图像 this.props.getSelectedImage.image.image 所以我可以更新 设置画布背景。

image-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;
  }
}

image-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);inside 渲染函数放入时,我得到了选定的图像,但无法在 setBackgroundImage 上设置它所以我可以在画布上显示选定的图像。

我该怎么做?

已经使用react v15.4.2

更新

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

如果我使用 componentDidUpdate 生命周期方法,它可以工作,但我得到以下结果。重新创建了这么多画布,我知道这是因为我在 componentDidUpdate 中创建了一个画布对象来更新画布。我怎样才能清楚地做到这一点?

【问题讨论】:

  • 没有深入研究代码,我的暗示是您正在使用const canvas = new fabric.Canvas('canvas'); 行向 DOM 添加多个画布元素。你能检查一下 DOM,看看每次渲染时是否有新的画布元素吗?
  • 每次我从列表中选择一个新图像时,它都会重新创建新的画布元素。我知道这是因为 componentDidUpdate 但如果我不使用所选图像不会出现在画布上。你能帮我解决这个问题吗?

标签: javascript reactjs canvas redux fabricjs


【解决方案1】:

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

  • 从 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);

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

【讨论】:

  • 如果我想清除画布,那么我应该在创建画布元素之前从 componentDidUpdate 调用 clear 函数,对吧?
  • 在清除画布的情况下,您可以使用 document.getElementById('canvas') 获取旧画布,然后在 componenentDidUpdate 中清除它。
  • 我做了 componentDidUpdate() { const oldCanvas = document.getElementById('canvas'); oldCanvas.clear(); const canvas = new fabric.Canvas('canvas'); this.setCanvasBackground(this.props.getSelectedImage.selectedImage, canvas); } 但我得到 oldCanvas.clear 不是函数错误
  • 还是一样。你可以在这里看到webpackbin.com/EyVxa6JLf。但我不知道为什么我不能在那里使用 componentDidUpdate 生命周期,否则我会收到 object.render is not a function 的错误
  • 如果画布给您带来问题,您是否可以像在 image-list.js 中那样使用 img 标签并将所选图像作为道具传递?
猜你喜欢
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 2015-12-02
相关资源
最近更新 更多