The business requirement was to adjust the cursor style of the rotate button in Konva.transformer to a rotation icon. I found a method on Stack Overflow, but it wasn’t entirely suitable for my needs.

 1const stage = new Konva.Stage({
 2  container: 'container',
 3  width: window.innerWidth,
 4  height: window.innerHeight
 5});
 6
 7const layer = new Konva.Layer();
 8stage.add(layer);
 9
10const shape = new Konva.Circle({
11  x: stage.width() / 2,
12  y: stage.height() / 2,
13  radius: 50,
14  fill: 'green'
15});
16layer.add(shape);
17
18const tr = new Konva.Transformer({
19  nodes: [shape]
20})
21layer.add(tr);
22
23
24tr.findOne('.rotater').on('mouseenter', () => {
25  // "content" property is not documented and private
26  // but for now you can use it
27  // it is element where transformer is applying its styles
28  stage.content.style.cursor = 'move';
29});

Later, I discovered that there is a built-in method to change the rotation style.

The modification process was not straightforward. Initially, I wrote it as follows, but there was no change.

1import rotateCursor from './assets/cursor.svg';
2
3roiAreaRef.current.transformer.rotateAnchorCursor(
4	`url("${rotateCursor}")`
5);

After confirming that the path was correct, I realized it might be due to the image size. The default SVG I downloaded was 512512, so I downloaded a 3232 SVG, and the cursor finally changed.

You can supply multiple url() functions separated by commas (url(), url(), auto for example), and the browser will use the earliest appropriate image it can find. Limitations include:

  • Cursor size: if the cursor image is over a certain size it will be ignored (in Gecko for example the limit is 128×128px). You should limit yourself about 32×32px anyway, for maximum compatibility with operating systems and platforms.
  • Browser: In Opera, the custom cursors are just ignored, and the keywords are used instead.
  • Transparency: Translucent cursors are not supported on Windows releases earlier than XP. This is a limitation of the operating system. Transparency works on all platforms.
  • Image format: Most browsers support a wide variety of image formats, but you should stick to something common and web-optimizable for the most part, such as JPG or PNG. You’ll also need to include a CUR format image, as they are required by IE. Animateds PNGs and GIFs will only produce static cursors.

However, there was a new issue: the cursor position seemed to be at the bottom right of the mouse.

url() hotspot-x hotspot-y, keyword;

CSS3 allows you to specify a custom cursor image along with an X and Y number values for the pointer hotspot, for example cursor: url(cursor2.png) 2 2, auto;. If not specified, the hotspot position defaults to the top left corner of the cursor image, or may be read from the meta data inside the image file, in the case of CUR and XBM format files.

The default cursor position is at the top left corner, with x and y being the distance from the top left corner, i.e., the cursor position.

1roiAreaRef.current.transformer.rotateAnchorCursor(
2	`url("${rotateCursor}") 16 16, auto`
3);