我刚刚将 react-color
模块添加到此 Canvas 页面。当用户选择一种颜色时,strokeStyle
会正确更改为该颜色,但它也会重置整个 Canvas ,使其成为一张白板。有什么方法可以改变这个,这样只是颜色本身改变,但 Canvas 不重置?我尝试添加 shouldComponentUpdate
但这只使得颜色根本没有改变。
import React from 'react';
import { Layer, Stage, Image } from 'react-konva';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { GithubPicker } from 'react-color';
class Canvas extends React.Component {
constructor(props) {
super(props);
this.canvasEvent = this.canvasEvent.bind(this);
this.props.socket.on('canvas_update', data => {
const idToUpdate = data.canvasId == 1 ? 'drawing2' : 'drawing1';
const node = document.createElement('p');
const textNode = document.createTextNode('test');
node.appendChild(textNode);
document.getElementById(idToUpdate).appendChild(node);
console.log(data.canvasJSON);
this.updateKonva(idToUpdate, data.canvasJSON);
//this.renderDisabledKonva(undefined, data.canvasJSON, data.canvasId);
});
this.state = {
background: '#fff',
};
}
canvasEvent(canvasJSON) {
this.props.socket.emit('canvas_event', { roomId: this.props.roomId, canvasJSON: canvasJSON, canvasId: this.props.canvasId }, () => {});
}
handleChangeComplete = (color) => {
this.setState({ background: color.hex });
};
renderTools() {
return (
<div className="tool">
Tool:
<select id="tool">
<option value="brush">Brush</option>
<option value="eraser">Eraser</option>
</select>
</div>
);
}
renderKonva(container) {
const that = this;
const width = 400; // window.innerWidth;
const height = 400; // window.innerHeight - 25;
// first we need Konva core things: stage and layer
const stage = new Konva.Stage({
container: `drawing${this.props.canvasId}`,
width: width,
height: height
});
const layer = new Konva.Layer({});
stage.add(layer);
// then we are going to draw into special canvas element
const canvas = document.createElement('canvas');
canvas.width = stage.width() / 1.5;
canvas.height = stage.height() / 1.5;
// created canvas we can add to layer as 'Konva.Image' element
let image = new Konva.Image({
image: canvas,
x: stage.width() / 6,
y: stage.height() / 6,
stroke: '#05AFF2',
shadowBlur: 5,
});
layer.add(image);
stage.draw();
// Now we need to get access to context element
const context = canvas.getContext('2d');
context.strokeStyle = this.state.background;
context.lineJoin = 'round';
context.lineWidth = 5;
let isPaint = false;
let lastPointerPosition;
let mode = 'brush';
// now we need to bind some events
// we need to start drawing on mousedown
// and stop drawing on mouseup
stage.on('contentMousedown.proto', () => {
isPaint = true;
lastPointerPosition = stage.getPointerPosition();
});
stage.on('contentMouseup.proto', () => {
isPaint = false;
});
// and core function - drawing
stage.on('contentMousemove.proto', () => {
if (!isPaint) {
return;
}
if (mode === 'brush') {
context.lineWidth = 5;
context.globalCompositeOperation = 'source-over';
}
if (mode === 'eraser') {
context.lineWidth = 15;
context.globalCompositeOperation = 'destination-out';
}
context.beginPath();
let localPos = {
x: lastPointerPosition.x - image.x(),
y: lastPointerPosition.y - image.y(),
};
context.moveTo(localPos.x, localPos.y);
const pos = stage.getPointerPosition();
localPos = {
x: pos.x - image.x(),
y: pos.y - image.y(),
};
context.lineTo(localPos.x, localPos.y);
context.closePath();
context.stroke();
lastPointerPosition = pos;
layer.draw();
const dataURL = stage.toDataURL();
// window.open(dataURL);
that.canvasEvent(dataURL);
// that.canvasEvent(stage.toJSON());
// console.log(layer);
});
const select = document.getElementById('tool');
select.addEventListener('change', () => {
mode = select.value;
});
}
render() {
return (
<div className="container">
{this.renderTools()}
<GithubPicker onChangeComplete={this.handleChangeComplete} color={this.state.background} />
<div id={'drawing' + this.props.canvasId} ref={ref => this.renderKonva(ref)} />
</div>
);
}
}
const mapStateToProps = state => ({
isAuthenticated: state.authReducer.isAuthenticated,
user: state.authReducer,
roomId: state.roomReducer.currentUserRoom,
});
const mapDispatchToProps = dispatch => bindActionCreators({}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(Canvas);
最佳答案
我可以想出几种方法来解决这个问题:
- 如果您想保留任何类型的信息,只需将其添加到状态中即可。在重新渲染期间,只需引用状态即可确保事物仍按原样渲染。
- 将事物分解为更小的组件并向其中添加shouldComponentUpdate。不断分解事物,直到获得所需的精细控制。请记住,此函数还将下一个 props 和下一个状态作为参数传递,因此您可以观察这些属性,并且仅在与组件相关的内容发生更改时才进行渲染,否则返回 false。
注意:如果您正在使用外部库,react-color,并且您试图阻止它的某些组件渲染,但无权访问它,您可以在它周围放置一个包装组件纯粹是为了控制渲染条件。
我希望这有帮助!
关于javascript - 有没有办法在 React 中每次状态更改时不重新加载 Canvas 的一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45356983/