Search code examples
reactjsimagekonvajsreact-konvakonva

How can I fill a konva rect with fillPatternImage in React or create an infinite grid with the same svg image in React


I've already created the masonry grid with konva and React here is the example of how far I have come: https://codesandbox.io/s/masonry-grid-image-konva-react-cp73d

Docs about Konva Image in React https://konvajs.org/docs/react/Images.html

I need to create an infinite grid with the same card Like this image but I'm not being able to fill the rect with background image or fill pattern. I'm not being sure about how to create the img object to fill the rect or how to repeat the same image in an infinite grid with this image... The svg it's in the codesandbox and this is my current code:

Any help with this will be appreciated

import React, { Component } from "react";
import { render } from "react-dom";
import { Stage, Layer, Image, Rect } from "react-konva";
import useImage from "use-image";

const CardImage = () => {
  const [image] = useImage("https://i.sstatic.net/7nF5K.png");
  return <Image image={image} />;
};

const WIDTH = 318;
const HEIGHT = 452;

const App = () => {
  const [stagePos, setStagePos] = React.useState({ x: 200, y: 200 });
  const startX = Math.floor((-stagePos.x - window.innerWidth) / WIDTH) * WIDTH;
  const endX = Math.floor((-stagePos.x + window.innerWidth * 2) / WIDTH) * WIDTH;
  const startY = Math.floor((-stagePos.y - window.innerHeight) / HEIGHT) * HEIGHT;
  const endY = Math.floor((-stagePos.y + window.innerHeight * 2) / HEIGHT) * HEIGHT;

  const gridComponents = [];

  for (var x = startX; x < endX; x += WIDTH) {
    for (var y = startY; y < endY; y += HEIGHT) {

      gridComponents.push(
        <>
          <Rect
            x={3.8 * x}
            y={1.2 * y}
            width={WIDTH}
            height={HEIGHT}
            stroke
            shadowBlur={20}
            cornerRadius={10}
          />
          <Rect
            x={3.8 * x + 405}
            y={1.2 * y + 200}
            width={WIDTH}
            height={HEIGHT}
            stroke
            shadowBlur={20}
            cornerRadius={10}
          />
          <Rect
            x={3.8 * x + 810}
            y={1.2 * y + 400}
            width={WIDTH}
            height={HEIGHT}
            stroke
            shadowBlur={20}
            cornerRadius={10}
          />
          <CardImage />
        </>
      );
    }
  }

  return (
    <Stage
      x={stagePos.x}
      y={stagePos.y}
      width={window.innerWidth}
      height={window.innerHeight}
      draggable
      onDragEnd={(e) => {
        setStagePos(e.currentTarget.position());
      }}
    >
      <Layer>{gridComponents}</Layer>
    </Stage>
  );
};

render(<App />, document.getElementById("root"));

Solution

  • If you want to fill the rectangle with the image you can just use fillPatternImage property.

    <Rect
      width={WIDTH}
      height={HEIGHT}
      shadowBlur={20}
      cornerRadius={10}
      fillPatternImage={image}
    />
    

    To download image you can use a similar way as for Konva.Image and use-image hook https://konvajs.org/docs/react/Images.html

    const [image] = useImage("https://i.sstatic.net/7nF5K.png");
    

    You updated demo: https://codesandbox.io/s/masonry-grid-image-konva-react-forked-s2wku?file=/src/index.js