Kevin Whitaker
Kevin Whitaker

Reputation: 13435

Konva JS get new point positions for line after dragging or scaling

I have a closed Line shape in Konva, and I need to get the new positions for its points after the object has been dragged. I've tried using the getAbsoluteTransform().point() method described here, but the points it returns seem to be incorrect; if I apply the new points to the shape, it moves the line more than expected, and in some cases will scale it, even if I didn't scale it in any way.

Is there something I'm missing, or do I need to use some other method to determine the new points for the Line?

export const Polygon = ({ obj, listening, selected, onClick, onDragEnd, onDragStart }: Props) => {
    const shape = useRef<Konva.Line>(null);
    const transformer = useRef<Konva.Transformer>(null);

    // instantiate and hide the transformer
    useEffect(() => {
      transformer.current?.nodes([shape.current!]);
      transformer.current?.hide();
    }, []);

    useEffect(() => {
      if (selected) {
        transformer.current?.show();
        transformer.current?.getLayer()?.batchDraw();
      } else {
        transformer.current?.hide();
      }
    }, [selected]);

    const handleDragEnd = () => {
      const next = obj.points.map((coords) => {
        const { x, y } = shape.current!.getAbsoluteTransform().point({
          x: coords[0],
          y: coords[1]
        });
        return [x, y];
      });
      
      // persists the shape to a database; does not do any additional transformations to the points
      onDragEnd(obj.id, [next]);
    };

    return (
      <>
        <Line
          id={obj.id}
          fill={rgba(obj.color, 0.25)}
          stroke={obj.color}
          strokeWidth={2}
          strokeScaleEnabled={false}
          points={flatten(obj.points)}
          closed
          draggable
          listening={listening}
          ref={shape}
          onClick={() => onClick(obj.id)}
          onDragStart={() => onDragStart(obj.id)}
          onDragEnd={handleDragEnd}
        />
        <Transformer
          ref={transformer}
          rotateEnabled={false}
          ignoreStroke
          keepRatio={false}
          borderStroke={obj.color}
        />
      </>
    );

Upvotes: 0

Views: 1448

Answers (1)

Kevin Whitaker
Kevin Whitaker

Reputation: 13435

Turns out I was using the incorrect transformer. I adjusted it based on https://github.com/konvajs/konva/issues/1256. I'm not sure what setting the scale to 1 does, specifically, but it was required to keep the object from jumping around unexpectedly.

    const handleDragEnd = () => {
      const line = shape.current!;
      const transformer = line.getTransform();
      const next = sensor.roiPoints[0].map((coords) => {
        const { x, y } = transformer.point({
          x: coords[0],
          y: coords[1]
        });
        return [x, y];
      });

      line.points(flatten(next));
      line.scaleX(1);
      line.scaleY(1);
      line.x(0);
      line.y(0);
      onDragEnd(sensor.id, [next]);
    };

Upvotes: 1

Related Questions