I'm working on a small project that allows user to upload image and then the image will be displayed on a canvas.
I'm using react-konva for this.
I have a container component called DesignPage, which manages the state and pass event handlers to its children.
Inside this DesignPage component, I have 2 other components: Tools - Canvas
When I upload an image using Tools component, the image should be displayed on Canvas component.
I'm using react-dropzone inside Tools component to handle file upload
Inside this Canvas component, there is a child component called DesignImage, which is just for displaying the image.
But the thing is, it just doesn't change the image on canvas when I upload.
How can I fix that?
Here is my code:
DesignPage component:
import React, {Component} from 'react';
import {
Row,
Col
} from 'reactstrap';
import Tools from "../components/DesignPage/Tools";
import Canvas from "../components/DesignPage/Canvas";
import Styles from "../components/DesignPage/Styles";
class DesignPage extends Component {
state = {
text: '',
image: '',
files: []
};
static propTypes = {};
handleTextChange = e => {
this.setState({text: e.target.value});
};
handleFileDrop = files => {
this.setState({
files,
image: files[0].preview
});
};
render() {
return <Row>
<Col xs={12} md={4}>
<Tools
files={this.state.files}
onTextChange={this.handleTextChange}
onFileDrop={this.handleFileDrop}/>
</Col>
<Col xs={12} md={5}>
<Canvas
text={this.state.text}
image={this.state.image}/>
</Col>
<Col xs={12} md={3}>
<Styles/>
</Col>
</Row>;
}
}
export default DesignPage;
Tools component:
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
TabContent,
TabPane,
Nav,
NavItem,
NavLink,
Row,
Col,
FormGroup,
Label
} from 'reactstrap';
import classnames from 'classnames';
import Dropzone from 'react-dropzone';
class Tools extends Component {
state = {
activeTab: '1'
};
toggle = (tab) => {
if (this.state.activeTab !== tab) {
this.setState({
activeTab: tab
});
}
};
render() {
return <Row>
<Col xs={12}>
<div>
<Nav tabs justified>
<NavItem>
<NavLink
className={classnames({active: this.state.activeTab === '1'})}
onClick={() => {
this.toggle('1');
}}
>
Text
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({active: this.state.activeTab === '2'})}
onClick={() => {
this.toggle('2');
}}
>
Art
</NavLink>
</NavItem>
</Nav>
<TabContent activeTab={this.state.activeTab}>
<TabPane tabId="1">
<Row>
<Col sm="12">
<FormGroup>
<Label for={"custom-text"}>Enter text below</Label>
<textarea
className={"form-control"}
id={"custom-text"}
onChange={this.props.onTextChange}/>
</FormGroup>
<FormGroup>
<Label for={"font-select"}>Choose a font</Label>
</FormGroup>
</Col>
</Row>
</TabPane>
<TabPane tabId="2">
<Row>
<Col sm="12">
<FormGroup>
<div className="dropzone-container">
<Dropzone onDrop={this.props.onFileDrop}>
<p>Drop a design here, or click to select design to upload.</p>
</Dropzone>
</div>
</FormGroup>
</Col>
</Row>
</TabPane>
</TabContent>
</div>
</Col>
</Row>;
}
}
Tools.propTypes = {
files: PropTypes.array.isRequired,
onTextChange: PropTypes.func.isRequired,
onFileDrop: PropTypes.func.isRequired
};
export default Tools;
Canvas component:
import React from 'react';
import PropTypes from 'prop-types';
import {
Row,
Col
} from 'reactstrap';
import {Stage, Layer} from 'react-konva';
import UserText from "./Canvas/UserText";
import DesignImage from "./Canvas/DesignImage";
const Canvas = props => {
return <Row>
<Col xs={12} className={"canvas-container"}>
<div className={"object-container"}>
<img className={"object-img"} src={"images/iPhone5A.png"} alt={"iPhone5A"}/>
<div className="drawing-area">
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<UserText text={props.text}/>
<DesignImage image={props.image}/>
</Layer>
</Stage>
</div>
</div>
</Col>
</Row>;
};
Canvas.propTypes = {
text: PropTypes.string.isRequired,
image: PropTypes.string.isRequired
};
export default Canvas;
DesignImage component:
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Image} from 'react-konva';
class DesignImage extends Component {
state = {
image: null
};
static propTypes = {
image: PropTypes.string.isRequired
};
componentDidMount() {
const image = new window.Image();
image.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRYTULZCGUVEQJEXt9iB8PU4Kb2FMS9Z6ufR1FnQTdrEl5uBOl52Q';
image.onload = () => {
// setState will redraw layer
// because "image" property is changed
this.setState({
image: image
});
};
}
render() {
return <Image image={this.props.image} draggable={true}/>;
}
}
export default DesignImage;
You need write a code to update the image when the component has a new image from props.
class DesignImage extends Component {
state = {
image: null
};
static propTypes = {
image: PropTypes.string.isRequired
};
componentDidMount() {
this.updateImage();
}
componentDidUpdate() {
this.updateImage();
}
updateImage() {
const image = new window.Image();
image.src = this.props.image;
image.onload = () => {
this.setState({
image: image
});
};
}
render() {
return <Image image={this.state.image} draggable={true}/>;
}
}
来源:https://stackoverflow.com/questions/49736475/react-konva-how-to-change-image-after-uploading