1

There is an element in the canvas. Each time I click the button, I want it to rotate 90 degrees around its center point. So when I judge that the origin of this element is not at the center point, I will manually specify its origin to the center point. When I do not use the transformer to rotate or scale it, it works well and can rotate around the center point.However, when I rotate or scale this element through transformer, and then click the button to rotate it, its position is offset, and it can rotate around the center point if I continue to click it. I want it to always rotate 90 degrees around the center point,But I don't know how to solve it. The code is as follows

<button @click="rotate">rotate</button>

let stage = new Konva.Stage({
    container: container,
    width: 800,
    height: 800,
});

let layer = new Konva.Layer();
stage.add(layer);

let rect = new Konva.Rect({
    x:50,
    y:50,
    width: 200,
    height: 150
});
layer.add(rect);

let transformer = new Konva.Transformer({
    rotationSnaps: [0, 90, 180, 270],
    nodes:[rect]
});
layer.add(transformer);

function rotate(){
    if(!rect.attrs.offsetX){
        rect.setAttrs({
            offsetX:rect.attrs.width/2,
            offsetY:rect.attrs.height/2,
            x:rect.attrs.x + rect.attrs.width/2,
            y:rect.attrs.y + rect.attrs.height/2
        })
    }
    rect.rotate(90);
}
wen
  • 11
  • 2
  • Doing math when you have all offset, scale and rotation on a node is very hard. Instead you may avoid using offset it rotate around center using math. See example here https://konvajs.org/docs/posts/Position_vs_Offset.html. Just need to apply scale in rotateAroundCenter sample – lavrton Sep 16 '22 at 17:41

2 Answers2

1

            let stage = new Konva.Stage({
                container: container,
                width: 400,
                height: 400,
            })

            let layer = new Konva.Layer()
            stage.add(layer)

            let rect = new Konva.Rect({
                x: 150,
                y: 150,
                width: 200,
                height: 150,
                fill: "red",

                //set offset
                offsetX: 200 / 2,
                offsetY: 150 / 2,
                
            })

            layer.add(rect)

            let transformer = new Konva.Transformer({
                rotationSnaps: [0, 90, 180, 270],
                nodes: [rect],
            })
            layer.add(transformer)

            function rotate() {
                rect.rotate(10)
            }
<script src="https://unpkg.com/konva@8.3.10/konva.min.js"></script>
<button onclick="rotate()">rotate</button>
<div id="container"></div>
aliang
  • 11
  • 1
0

let $w = 500,
                $h = 500
            let grid = 50
            let stage = new Konva.Stage({
                container: canvas,
                width: $w,
                height: $h,
            })

            let layer = new Konva.Layer()
            stage.add(layer)
            let origin = { x: 100, y: 100 }
            const box = { w: 100, h: 200 }

            let xLine = new Konva.Line({
                points: [0, grid, $w, 50],
                stroke: "#333",
                strokeWidth: 0.2,
                dash: [20, 5],
            })
            xLine.cache()
            let yLine = new Konva.Line({
                points: [grid, 0, grid, $h],
                stroke: "#333",
                strokeWidth: 0.2,
                dash: [20, 5],
            })
            yLine.cache()
            let rect = new Konva.Rect({
                fill: "red",
                x: origin.x,
                y: origin.y,
                width: box.w,
                height: box.h,
            })
            let rect2 = new Konva.Rect({
                fill: "green",
                x: origin.x * 3,
                y: origin.y * 2,
                width: box.w,
                height: box.h,

                //set offset
                offsetX: box.w / 2,
                offsetY: box.h / 2,
            })
            layer.add(rect, rect2)

            var xLineClone, yLineClone
            for (let n = 0; n < $h / grid; n++) {
                xLineClone = xLine.clone({
                    x: 0,
                    y: n * grid,
                    dashEnabled: (n + 1) % 2 != 0,
                })
                xLineClone.cache()
                layer.add(xLineClone)

                yLineClone = yLine.clone({
                    x: n * grid,
                    y: 0,
                    dashEnabled: (n + 1) % 2 != 0,
                })
                yLineClone.cache()
                layer.add(yLineClone)
            }

            function print(e, id) {
                if (e.target) e = e.target
                //$(id).text(JSON.stringify(e.attrs))
                $(id).html(`<p>x:${e.x().toFixed(2)}</p><p>y:${e.y().toFixed(2)}</p>`)
            }
            let transformer = new Konva.Transformer({
                rotationSnaps: [0, 90, 180, 270],
                nodes: [rect],
                anchorStroke: "#4aadfb",
                anchorFill: "yellow",
                anchorSize: 8,
                borderDash: [5, 5],
                borderStroke: "#00d9e1",
                centeredScaling: true,
                keepRatio: true,
                flipEnabled: true,
            }).on("transform", function (e) {
                print(e, "#tips1")
            })

            let transformer2 = new Konva.Transformer({
                rotationSnaps: [0, 90, 180, 270],
                nodes: [rect2],

                centeredScaling: true,
                keepRatio: true,
                flipEnabled: true,
            }).on("transform", function (e) {
                print(e, "#tips2")
            })
            layer.add(transformer, transformer2)

            function rotatePoint({ x, y }, rad) {
                const rcos = Math.cos(rad)
                const rsin = Math.sin(rad)
                return { x: x * rcos - y * rsin, y: y * rcos + x * rsin }
            }

            function rotateAroundCenter(node, rotation) {
                const topLeft = { x: -node.width() / 2, y: -node.height() / 2 }
                const current = rotatePoint(topLeft, Konva.getAngle(node.rotation()))
                const rotated = rotatePoint(topLeft, Konva.getAngle(rotation))
                const dx = rotated.x - current.x,
                    dy = rotated.y - current.y

                node.rotation(rotation)
                node.x(node.x() + dx)
                node.y(node.y() + dy)

                return node
            }
            function rotate() {
                rotateAroundCenter(rect, rect.rotation() + 45)
                print(rect, "#tips1")
            }
            function rotate2() {
                rect2.rotate(45)
                print(rect2, "#tips2")
            }
button {
                margin: 10px;
                padding: 10px;
            }
            #container {
                position: relative;
            }
            .konvajs-content {
                background-color: #c5d3f9;
            }
            .tips {
                width: 150px;
            }
            #tips1 {
                position: absolute;
                top: 10px;
                left: 10px;
            }
            #tips2 {
                position: absolute;
                bottom: 10px;
                left: 300px;
            }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<script src="https://unpkg.com/konva@8.3.10/konva.min.js"></script>
        <div id="container">
            <div id="canvas"></div>
            <div id="tips1" class="tips"></div>
            <div id="tips2" class="tips"></div>
        </div>
        <button onclick="rotate()">[rect1]rotate</button>
        <button onclick="rotate2()">[rect2]rotate</button>
aliang
  • 11
  • 1