Skip to main content

Complex Tweening Tutorial

This demo combines chained Konva.Tween instances with a Konva.Animation. The tweens change the circle scale. The animation changes the fillLinearGradientColorStops property.

Instructions: Click the shape to start the complex animation with gradient changes.

import Konva from 'konva';

const width = window.innerWidth;
const height = window.innerHeight;

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

const layer = new Konva.Layer();

const circle = new Konva.Circle({
x: width / 2,
y: height / 2,
radius: 70,
fillLinearGradientStartPoint: { x: -50, y: -50 },
fillLinearGradientEndPoint: { x: 50, y: 50 },
fillLinearGradientColorStops: [0, 'red', 1, 'yellow'],
stroke: 'black',
strokeWidth: 4,
draggable: true,
});

layer.add(circle);
stage.add(layer);

let scaleUpTween;
let scaleDownTween;
let gradientAnimation;
let gradientTimer;

const stopAnimation = () => {
scaleUpTween?.destroy();
scaleDownTween?.destroy();
gradientAnimation?.stop();
clearTimeout(gradientTimer);
scaleUpTween = undefined;
scaleDownTween = undefined;
gradientAnimation = undefined;
gradientTimer = undefined;
};

circle.on('click tap', () => {
stopAnimation();

// using regular Konva tween
scaleUpTween = new Konva.Tween({
node: circle,
duration: 1,
scaleX: 1.5,
scaleY: 1.5,
easing: Konva.Easings.EaseInOut,
onFinish: () => {
scaleUpTween.destroy();
scaleUpTween = undefined;
// scale back with another tween
scaleDownTween = new Konva.Tween({
node: circle,
duration: 1,
scaleX: 1,
scaleY: 1,
easing: Konva.Easings.BounceEaseOut,
onFinish: () => {
scaleDownTween.destroy();
scaleDownTween = undefined;
},
});
scaleDownTween.play();
},
});
scaleUpTween.play();

// manually update gradient
let ratio = 0;
gradientAnimation = new Konva.Animation((frame) => {
ratio += frame.timeDiff / 1000;
if (ratio > 1) {
ratio = 0;
}
circle.fillLinearGradientColorStops([
0,
'red',
ratio,
'yellow',
1,
'blue',
]);
}, layer);
gradientAnimation.start();
gradientTimer = setTimeout(() => {
gradientAnimation.stop();
gradientAnimation = undefined;
gradientTimer = undefined;
}, 2000);
});