Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否有一种方法可以避免每次在React中更改状态时重新加载画布的一部分?_Javascript_Reactjs_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 是否有一种方法可以避免每次在React中更改状态时重新加载画布的一部分?

Javascript 是否有一种方法可以避免每次在React中更改状态时重新加载画布的一部分?,javascript,reactjs,canvas,html5-canvas,Javascript,Reactjs,Canvas,Html5 Canvas,我刚刚将react color模块添加到此画布页面。当用户选择一种颜色时,strokeStyle会正确地更改为该颜色,但它也会重置整个画布,使其成为一块白板。有没有办法改变这一点,只改变颜色本身,而不重置画布?我尝试添加shouldComponentUpdate,但这只能使颜色完全不变 import React from 'react'; import { Layer, Stage, Image } from 'react-konva'; import { connect } from 'rea

我刚刚将
react color
模块添加到此画布页面。当用户选择一种颜色时,
strokeStyle
会正确地更改为该颜色,但它也会重置整个画布,使其成为一块白板。有没有办法改变这一点,只改变颜色本身,而不重置画布?我尝试添加
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);
从“React”导入React;
从“react konva”导入{图层、舞台、图像};
从'react redux'导入{connect};
从“redux”导入{bindActionCreators};
从“反应颜色”导入{GithubPicker};
类Canvas扩展了React.Component{
建造师(道具){
超级(道具);
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(节点);
log(data.canvasJSON);
this.updateKonva(idToUpdate,data.canvasJSON);
//this.renderisabledKonva(未定义,data.canvasJSON,data.canvasId);
});
此.state={
背景:“#fff”,
};
}
canvasEvent(canvasJSON){
this.props.socket.emit('canvas_event',{roomId:this.props.roomId,canvasJSON:canvasJSON,canvasId:this.props.canvasId},()=>{});
}
handleChangeComplete=(颜色)=>{
this.setState({background:color.hex});
};
renderTools(){
返回(
工具:
刷子
橡皮擦
);
}
renderKonva(集装箱){
常数=this;
const width=400;//window.innerWidth;
const height=400;//window.innerHeight-25;
//首先,我们需要Konva的核心产品:舞台和舞台
const stage=新Konva.stage({
容器:`drawing${this.props.canvasId}`,
宽度:宽度,
高度:高度
});
const layer=新的Konva.layer({});
阶段。添加(层);
//然后我们将绘制到特殊的画布元素中
const canvas=document.createElement('canvas');
canvas.width=stage.width()/1.5;
canvas.height=stage.height()/1.5;
//已创建画布,我们可以将其作为“Konva.Image”元素添加到图层中
让image=new Konva.image({
图片:画布,
x:stage.width()/6,
y:舞台高度()/6,
笔划:“#05AFF2”,
阴影模糊:5,
});
图层。添加(图像);
stage.draw();
//现在我们需要访问上下文元素
const context=canvas.getContext('2d');
context.strokeStyle=this.state.background;
context.lineJoin='round';
context.lineWidth=5;
让isPaint=false;
让最后一个指针定位;
let mode='brush';
//现在我们需要绑定一些事件
//我们需要开始在mousedown上画图
//停止在鼠标上画画
stage.on('contentMousedown.proto',()=>{
isPaint=true;
lastPointerPosition=stage.getPointerPosition();
});
stage.on('contentMouseup.proto',()=>{
isPaint=false;
});
//和核心功能-绘图
stage.on('contentMousemove.proto',()=>{
如果(!isPaint){
返回;
}
如果(模式=='brush'){
context.lineWidth=5;
context.globalCompositeOperation='source over';
}
如果(模式=='橡皮擦'){
context.lineWidth=15;
context.globalCompositeOperation='destination out';
}
context.beginPath();
设localPos={
x:lastPointerPosition.x-image.x(),
y:lastPointerPosition.y-image.y(),
};
moveTo(localPos.x,localPos.y);
const pos=stage.getPointerPosition();
localPos={
x:pos.x-image.x(),
y:pos.y-image.y(),
};
lineTo(localPos.x,localPos.y);
closePath();
stroke();
lastPointerPosition=pos;
layer.draw();
const dataURL=stage.toDataURL();
//window.open(dataURL);
canvasEvent(dataURL);
//canvasEvent(stage.toJSON());
//控制台日志(层);
});
const select=document.getElementById('tool');
select.addEventListener('change',()=>{
模式=选择值;
});
}
render(){
返回(
{this.renderTools()}
this.renderKonva(ref)}/>
);
}
}
常量mapStateToProps=状态=>({
isAuthenticated:state.authReducer.isAuthenticated,
用户:state.authReducer,
roomId:state.roomReducer.currentUserRoom,
});
const-mapDispatchToProps=dispatch=>bindActionCreators({},dispatch);
导出默认连接(mapStateToProps、mapDispatchToProps)(画布);

虽然我没有找到只进行部分重新加载的方法,但我确实为此制定了一个解决方案:

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);
      this.updateKonva(idToUpdate, data.canvasJSON);
      this.handleChangeComplete = this.handleChangeComplete.bind(this);
      //this.renderDisabledKonva(undefined, data.canvasJSON, data.canvasId);
    });
  }

  handleChangeComplete(color) {
    newColor = color.hex;
  }

  canvasEvent(canvasJSON) {
    this.props.socket.emit('canvas_event', { roomId: this.props.roomId, canvasJSON: canvasJSON, canvasId: this.props.canvasId }, () => {});
  }

  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();
      context.strokeStyle = newColor;
      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} />
        <div id={'drawing' + this.props.canvasId} ref={ref => this.renderKonva(ref)} />
      </div>
    );
  }
}

let newColor = '#fff';

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);
从“React”导入React;
从“react konva”导入{图层、舞台、图像};
从'react redux'导入{connect};
从“redux”导入{bindActionCreators};
从“反应颜色”导入{GithubPicker};
类Canvas扩展了React.Component{
建造师(道具){
超级(道具);
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(节点);
this.updateKonva(idToUpdate,data.canvasJSON);
this.handleChangeComplete=this.handleChangeComplete.bind(this);
//this.renderisabledKonva(未定义,data.canvasJSON,data.canvasId);
});
}
把手更换完成(颜色){
newColor=color.hex;
}
canvasEvent(canvasJSON){
这只袜子