javascriptreactjscanvaskonvajsreact-konva

Using React and react-konva (canvas library), how can I allow panning but restrict this to a specific boundary


I have a React application using react-konva, where I have created an application with a canvas that shows a user selected image in the background.
You are able to draw over the image using various canvas tools.
The canvas will scale to the window size using a percentage - this is the scale
The canvas also allows the user to zoom into the image - this is the zoom, the default is 1 i.e. 100%.

I want to allow the user to pan across the image using the viewport, however I do not want the user to be able to pan outside the boundary of the image, the dimensions of the image, in addition to the scale and the zoom are all known.

This image shows an example of what effect I want

This is a part of the code that I am using but am having difficult calculating what x and y coordinate to restrict the viewport to, only the top left corner is apparent (0, 0)

Any advice is appreciated!

// clamp function
function clamp(val, min, max) {
  return val > max ? max : val < min ? min : val
}

<Stage
  width={width}
  height={height}
  scaleX={zoom * (1 / scale)}
  scaleY={zoom * (1 / scale)}
  draggable={tool === "pan" ? true : false}
  x={drag.x}
  y={drag.y}
  dragBoundFunc={pos => {
    return {
      x: clamp(pos.x, ?, 0), // I have tried combinations of width, scale 
      y: clamp(pos.y, ?, 0)  // and zoom but not able to find a solution
    }
  }}
>
   <Layer listening={false}>
       <Img width={width} height={height} scaleX={scale} scaleY={scale} image={image} alt="Image" />
   </Layer>
</Stage>

Solution

  • I have worked out the bound

    dragBoundFunc={pos => {
      return {
         x: clamp(pos.x, -(width * zoom - width), 0),
         y: clamp(pos.y, -(height * zoom - height), 0)
      }
    }}
    

    It works because of the following