question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Moving an object on array makes konva objects lose their transform changes like rotation and position

See original GitHub issue

I’m using react-konva, in it I have an array with all my konva objects, and I have a function that brings the selected object to the front or back of this array to create layers on my kanvas.

When I fire this function, the order of objects inside the array works fine but the transform changes on all objects are lost, what can I do to don’t lose this params during this change on the array?

a example of the object

    newSquareObj: {
      x: 20,
      y: 20,
      width: 100,
      height: 50,
      fill: "green",
      id: 0,
      type: 'square',
    },
  changeOrderArray = (front) => {
    let { arrayObjectsLayer, selectedObject } = this.state;
    front ?
      arrayObjectsLayer.push(
        arrayObjectsLayer.splice(
          arrayObjectsLayer.findIndex(
            elt => elt.id === selectedObject.id),
          1)[0]
      )
      : arrayObjectsLayer.unshift(
        arrayObjectsLayer.splice(
          arrayObjectsLayer.findIndex(
            elt => elt.id === selectedObject.id),
          1)[0]
      )
    this.setState({
      arrayObjectsLayer
    });
  }

the loop

  arrayObjectsLayer.map((item, index) => {
    return (
      item.type === 'square' ?
        <RectanguleComponent
          shapeProps={item}
          isSelected={
            selectedObject && item.id === selectedObject.id
          }
          onSelect={() => {
            this.selectShape(item);
          }}
          onChange={newAttrs => {
            const item = arrayObjectsLayer.slice();
            item[index] = newAttrs;
            this.setArrayObject(item);
          }}
        />
        :
        item.type === 'triangule' ?
          <TrianguleComponent
            shapeProps={item}
            isSelected={
              selectedObject && item.id === selectedObject.id
            }
            onSelect={() => {
              this.selectShape(item);
            }}
            onChange={newAttrs => {
              const item = arrayObjectsLayer.slice();
              item[index] = newAttrs;
              this.setArrayObject(item);
            }}
          />
          :
          etc ...

basic component with transformer

export const RectanguleComponent = ({ shapeProps, isSelected, onSelect, onChange }) => {
  const shapeRef = React.useRef();
  const trRef = React.useRef();

  React.useEffect(() => {
    if (isSelected) {
      trRef.current.setNode(shapeRef.current);
      trRef.current.getLayer().batchDraw();
    }
  }, [isSelected]);

  return (
    <React.Fragment>
      <Rect
        onClick={onSelect}
        ref={shapeRef}
        {...shapeProps}
        draggable
        onDragEnd={e => {
          onChange({
            ...shapeProps,
            x: e.target.x(),
            y: e.target.y()
          });
        }}
        onTransformEnd={e => {
          // transformer is changing scale
          const node = shapeRef.current;
          const scaleX = node.scaleX();
          const scaleY = node.scaleY();
          // we will reset it back
          node.scaleX(1);
          node.scaleY(1);
          onChange({
            ...shapeProps,
            x: node.x(),
            y: node.y(),
            width: node.width() * scaleX,
            height: node.height() * scaleY
          });
        }}
      />
      {isSelected && <Transformer ref={trRef} />}
    </React.Fragment>
  );
};

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
lavrtoncommented, Sep 26, 2019

Usually, it is better not to use index as a key, use id instead. Also make sure you save rotation into shapes properties:

onChange({
            ...shapeProps,
            rotation: node.rotation(),
            x: node.x(),
            y: node.y(),
            width: node.width() * scaleX,
            height: node.height() * scaleY
          });
1reaction
ribas14commented, Sep 26, 2019

@lavrton i’m using keys based on the index, I just removed them to be easier to see the code

                     <RectanguleComponent
                        key={index}
                        shapeProps={item}
                        isSelected={
                          selectedObject && item.id === selectedObject.id
                        }
                        onSelect={() => {
                          this.selectShape(item);
                        }}
                        onChange={newAttrs => {
                          const item = arrayObjectsLayer.slice();
                          item[index] = newAttrs;
                          this.setArrayObject(item);
                        }}
                      />
Read more comments on GitHub >

github_iconTop Results From Across the Web

Moving an object on array makes konva objects lose their ...
When I fire this function, the order of objects inside the array works fine but the transform changes on all objects are lost,...
Read more >
What is the difference between position and offset in Konva
When you are changing the offset property it may looks like you are changing position of the node. But actually not. You are...
Read more >
How to resize and rotate canvas shapes with react and konva?
The Idea: you need to create a Konva.Transformer node, and attach it to the required node manually. Instructions: Click on one of the...
Read more >
HTML5 Canvas Transform and Resize events - Konva
Transformer object has special transform events that you can use in your app: transformstart , transform and transformend .
Read more >
HTML5 Canvas Shape select, resize and rotate - Konva
Transformer is a special kind of Konva.Group. It allows you easily resize and rotate any node or set of nodes. To enable it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found