Rotation Animation tutorial
To animate a shape's rotation with Konva, we can create a new animation with
Konva.Animation
, and define a function which modifies the shape's rotation with each animation frame.
In this tutorial, we'll rotate a blue rectangle about the top left corner, a yellow rectangle about its center, and a red rectangle about an outside point.
For a full list of attributes and methods, check out the Konva.Animation documentation.
- Vanilla
- React
- Vue
import Konva from 'konva'; const stage = new Konva.Stage({ container: 'container', width: window.innerWidth, height: window.innerHeight, }); const layer = new Konva.Layer(); stage.add(layer); // blue rectangle - rotate around top-left corner const blueRect = new Konva.Rect({ x: 50, y: 50, width: 100, height: 50, fill: '#00D2FF', stroke: 'black', strokeWidth: 4, offset: { x: 0, y: 0, }, }); // yellow rectangle - rotate around center const yellowRect = new Konva.Rect({ x: 200, y: 50, width: 100, height: 50, fill: 'yellow', stroke: 'black', strokeWidth: 4, offset: { x: 50, y: 25, }, }); // red rectangle - rotate around point outside shape const redRect = new Konva.Rect({ x: 350, y: 50, width: 100, height: 50, fill: 'red', stroke: 'black', strokeWidth: 4, offset: { x: -50, y: 25, }, }); layer.add(blueRect); layer.add(yellowRect); layer.add(redRect); const angularSpeed = 90; const anim = new Konva.Animation(function(frame) { const angleDiff = (frame.timeDiff \* angularSpeed) / 1000; blueRect.rotate(angleDiff); yellowRect.rotate(angleDiff); redRect.rotate(angleDiff); }, layer); anim.start();
import { Stage, Layer, Rect } from 'react-konva'; import { useEffect, useRef } from 'react'; const App = () => { const blueRectRef = useRef(null); const yellowRectRef = useRef(null); const redRectRef = useRef(null); useEffect(() => { const angularSpeed = 90; const anim = new Konva.Animation((frame) => { const angleDiff = (frame.timeDiff * angularSpeed) / 1000; blueRectRef.current.rotate(angleDiff); yellowRectRef.current.rotate(angleDiff); redRectRef.current.rotate(angleDiff); }, blueRectRef.current.getLayer()); anim.start(); return () => { anim.stop(); }; }, []); return ( <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> <Rect ref={blueRectRef} x={50} y={50} width={100} height={50} fill="#00D2FF" stroke="black" strokeWidth={4} offsetX={0} offsetY={0} /> <Rect ref={yellowRectRef} x={200} y={50} width={100} height={50} fill="yellow" stroke="black" strokeWidth={4} offsetX={50} offsetY={25} /> <Rect ref={redRectRef} x={350} y={50} width={100} height={50} fill="red" stroke="black" strokeWidth={4} offsetX={-50} offsetY={25} /> </Layer> </Stage> ); }; export default App;
<template> <v-stage :config="stageSize"> <v-layer ref="layerRef"> <v-rect ref="blueRectRef" :config="blueRectConfig" /> <v-rect ref="yellowRectRef" :config="yellowRectConfig" /> <v-rect ref="redRectRef" :config="redRectConfig" /> </v-layer> </v-stage> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue'; import Konva from 'konva'; const stageSize = { width: window.innerWidth, height: window.innerHeight }; const blueRectConfig = ref({ x: 50, y: 50, width: 100, height: 50, fill: '#00D2FF', stroke: 'black', strokeWidth: 4, offset: { x: 0, y: 0, } }); const yellowRectConfig = ref({ x: 200, y: 50, width: 100, height: 50, fill: 'yellow', stroke: 'black', strokeWidth: 4, offset: { x: 50, y: 25, } }); const redRectConfig = ref({ x: 350, y: 50, width: 100, height: 50, fill: 'red', stroke: 'black', strokeWidth: 4, offset: { x: -50, y: 25, } }); const layerRef = ref(null); const blueRectRef = ref(null); const yellowRectRef = ref(null); const redRectRef = ref(null); let anim = null; onMounted(() => { const angularSpeed = 90; anim = new Konva.Animation((frame) => { const angleDiff = (frame.timeDiff * angularSpeed) / 1000; blueRectRef.value.getNode().rotate(angleDiff); yellowRectRef.value.getNode().rotate(angleDiff); redRectRef.value.getNode().rotate(angleDiff); }, layerRef.value.getNode()); anim.start(); }); onUnmounted(() => { if (anim) { anim.stop(); } }); </script>