react-konva如何在上传后更改图像?

时间:2018-04-09 15:24:40

标签: reactjs html5-canvas konvajs

我正在开发一个允许用户上传图片的小项目,然后图片将显示在画布上。

我正在使用react-konva

我有一个名为DesignPage的容器组件,管理状态将事件处理程序传递给其子组件。

在这个DesignPage组件中,我还有另外两个组件:工具 - 画布

使用工具组件上传图片时,图片应显示在画布组件上。

我在工具组件中使用react-dropzone来处理文件上传

Canvas 组件中,有一个名为 DesignImage 的子组件,它仅用于显示图像。

但问题是,我上传时它不会改变画布上的图像。

我该如何解决?

这是我的代码:

DesignPage 组件:

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;

工具组件:

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;

画布组件:

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 组件:

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;

1 个答案:

答案 0 :(得分:4)

当组件从道具中获得新图像时,您需要编写代码来更新图像。

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