Konva – trap an image in a framing shape

So you have a space where the user is allowed to upload an image. You need to let the user position the image but you need to clip off any overflow. Here’s an approach…

TLDR: See the demo code at CodePen.

The trick here is to use a Konva Group. Add to the group the shape that you want to use as the frame for the image – I used a rect but you could use any Konva shape. Now set the group’s clip region to match the frame shape’s position and shape. This hides everything in the group but outside of the clip region. All we need to do now is to add a Konva Image to the group and load up the image you want displayed.

There are a couple of specific attributes to set.

  1. After adding the image to the frame group, set it’s zIndex to 0 by calling image.moveToBottom(). This is because we want the image underneath the frame shape.
  2. Make the image draggable.
  3. Set the frame shape’s listening attribute to false. This allows the image to receive the mouse or touch events.

Thats all there is to it. If you want to show the user the overflowing part of the image then clone the frames image and add the clone to the layer (not the frame group!). Set its z-index to one lower than the frame group so that it is underneath the frame group, and set it’s opacity to something like 0.3 to give it a good fade compared to the image segment that is visible in the frame. Now add a dragBoundFunc to the original image and in it set the clone image position to the same position as the main image.

What happens is that as the main image in the frame is dragged, it’s clone is moved and positioned to follow. This illustrates visually the relationship between the users image and the frame.

Thanks for reading.

VW March 2022

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: