所选图像未显示在画布上
Posted
技术标签:
【中文标题】所选图像未显示在画布上【英文标题】: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"
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 但如果我不使用所选图像不会出现在画布上。你能帮我解决这个问题吗?
【参考方案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 标签并将所选图像作为道具传递?以上是关于所选图像未显示在画布上的主要内容,如果未能解决你的问题,请参考以下文章
图像保存的 con Amazon S3 存储桶未显示在 HTML5 画布上。跨域问题