Home > Software design >  How to set a custom Size to exporting image in react-konva?
How to set a custom Size to exporting image in react-konva?

Time:03-27

I have created a responsive stage using react-konva, but I cannot find a way to set a custom size to export the image. usually, right-click and saving the image is working as the size in the window at that time has. I wanted to add a button to download the image, but I couldn't set up a way to do that because I'm new to react hooks, I couldn't find a way to set up the data URL. please kindly refer to this

    import React, { Component, useState, useRef, useCallback } from "react";
    import { render } from "react-dom";
    import { Stage, Layer, Text, Image, Rect, Transformer, Circle, Line } from "react-konva";
    import card01 from "../images/01.jpg"
    import useImage from "use-image";
    import "./styless.css";
    import Button from '@mui/material/Button';
    
    const WIDTH = 875;
    const HEIGHT = 500;
    const ZOOM = 1;
    
    class Canvas extends Component {
      state = {
        stageWidth: WIDTH,
        zoom: 1,
      };
    
      render() {
        
        const { containerWidth } = this.props;
        var scale = (containerWidth / WIDTH) * ZOOM;
        let width = WIDTH * scale;
        let height = HEIGHT * scale;
        console.log({ containerWidth, width, height, scale });
    
        const LionImage = () => {
            const [image] = useImage(card01);
            return <Image image={image} width={width} height={height} scale={scale}/>;
          };
    
        return (
          <div style={{ width: `100%`, border: "1px solid grey" }}>
          
            <Stage width={width} height={height} scale={scale}>
              <Layer>
              <LionImage />
              <Text
                x={containerWidth / 10}
                y={scale*35}
                text="Some text"
                fontSize={28}
                fontFamily="Poppins"
                fill="gray"
                scaleX={scale}
                scaleY={scale}
    
                width={width}
                height={height}
              />
              </Layer>
            </Stage>
          </div>
        );
      }
    }
    
    class App extends Component {
      state = {
        zoom: 1
      };
      componentDidMount() {
        this.checkSize();
        window.addEventListener("resize", this.checkSize);
      }
    
      componentWillUnmount() {
        window.removeEventListener("resize", this.checkSize);
      }
    
      checkSize = () => {
    
        const containerWidth = this.container.offsetWidth;
        const containerHeight = this.container.offsetHeight;
        this.setState({ ...this.state, containerWidth, containerHeight });
    
      };
    
      render() {
        const pWidht = this.state.containerWidth
          ? `${this.state.containerWidth * this.state.zoom}px`
          : "100%";
    
        return (
            <>
          
            <div
                style={{ width: "80%", height: "100%", left: "10%", position: "absolute" }}
                ref={(node) => {
                    this.container = node;
                } }
            >
                <div style={{ overflow: "auto;", width: `${pWidht}` }}>
                    <div>
                        <Button color="inherit" size="small" variant="outlined" sx={{boxShadow:3}} style={{marginTop:"20px",marginRight:"10px",marginBottom:"10px", fontSize:"12pt", color:"white"}}
                            type="button"
                            value=" "
                            onClick={() => this.setState({ ...this.state, zoom: this.state.zoom   0.2 })}>   </Button>
                        <Button color="inherit" size="small" variant="outlined" sx={{boxShadow:3}} style={{marginTop:"20px",marginRight:"10px",marginBottom:"10px", fontSize:"12pt", color:"white"}}
                            type="button"
                            value="-"
                            onClick={() => this.setState({ ...this.state, zoom: this.state.zoom - 0.2 })} > - </Button>
                    </div>
                    <Canvas containerWidth={pWidht.replace("px", "")} />
                </div>
            </div>
      
            </>
        );
      }
    }
    
    const X = () => {
      return <App />;
    };
    
    render(<X />, document.getElementById("root"));
    export default App;

CodePudding user response:

You need to use a ref to the Stage and get the image URL and download it.

  1. In your Canvas component create a ref using createRef.
  constructor(props) {
    super(props);
    this.stageRef = createRef(null);
  }
  1. Add the stageRef to your Stage.
<Stage  ... ref={this.stageRef}>
        ...
        ...
</Stage>
  1. Add two following utility functions, downloadURI to download image as a file and handleExport to get the data URI from the ref.
  downloadURI = (uri, name) => {
    var link = document.createElement("a");
    link.download = name;
    link.href = uri;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  handleExport = () => {
    const uri = this.stageRef.current.toDataURL();
    this.downloadURI(uri, "stage.png");
  };
  1. Add a new button with the click handler set to handleExport function.
<button onClick={this.handleExport}>Download</button>

Working example:

Edit practical-elgamal-evik50

  • Related