Skip to content

Instantly share code, notes, and snippets.

@prappo
Created June 14, 2023 15:22
Show Gist options
  • Save prappo/e1dd1bb31c7affc54ed87ea968e82cf2 to your computer and use it in GitHub Desktop.
Save prappo/e1dd1bb31c7affc54ed87ea968e82cf2 to your computer and use it in GitHub Desktop.
konva js animation
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<style>
body {
font-family: sans-serif;
}
#canvas-wrapper {
width: 720px;
height: 360px;
background: lightgrey;
}
.tools {
display: flex;
justify-content: space-between;
max-width: 720px;
margin: 15px 0;
}
.tools > button {
width: 100px;
margin: 0 5px;
}
.tools > button:nth-of-type(2) {
margin-right: auto;
}
.tools > div {
width: 170px;
}
.tools > div select {
width: calc(100% - 70px);
}
</style>
<script src="https://unpkg.com/konva@9/konva.min.js"></script>
</head>
<body>
<div id="canvas-wrapper"></div>
<div class="tools">
<button onclick="playAnim()">Play</button>
<div>
<label for="item-type">Item Type</label>
<select name="item-type" id="item-val"></select>
</div>
<div>
<label for="animation-type">Animation</label>
<select name="animation-type" id="animation-val"></select>
</div>
</div>
<script>
/* animation list -- START EDIT HERE -- */
const animationType = {
leftToRight: (el, duration) => {
let time = duration;
!time ? (time = 1) : (time = duration);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el.position({
x: 0,
y: stage.height() / 2,
});
el.to({
x: initX,
duration: time,
});
},
rotateExitRight: (el, duration) => {
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
let animRotate = new Konva.Animation((frame) => {
el.rotation(frame.time % 360);
}, layer);
let animMove = new Konva.Animation((frame) => {
el.x(initX + frame.time);
}, layer);
animInit = true;
animRotate.start();
animMove.start();
setTimeout(() => {
animRotate.stop();
animMove.stop();
el.setAttrs({
x: initX,
y: initY,
rotation: 0,
});
layer.draw();
}, 2000);
},
fadeInItem: (el, duration) => {
!duration && (duration = 1);
let initItemProps = el[0].attrs;
el[0].opacity(0);
new Konva.Tween({
node: el[0],
easing: Konva.Easings.EaseIn,
duration: duration,
opacity: 1,
}).play();
},
easingLeftToRight: (el, duration) => {
!duration && (duration = 1);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el.position({
x: -el[0].attrs.x / 2,
y: stage.height() / 2,
});
el.tween = new Konva.Tween({
node: el[0],
x: initX,
easing: Konva.Easings.StrongEaseOut,
duration: duration,
});
el.tween.play();
},
spellTowardsTheScreen: (el, duration) => {
!duration && (duration = 1);
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.StrongEaseIn,
duration: duration,
scaleX: 12,
scaleY: 12,
opacity: 0,
onFinish: function () {
el[0].tween.reset();
},
});
el[0].tween.play();
},
shrinkToCanvas: (el, duration) => {
!duration && (duration = 1);
el[0].scale({
x: 12,
y: 12,
});
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.StrongEaseOut,
duration: duration,
scaleX: 1,
scaleY: 1,
opacity: 1,
});
el[0].tween.play();
},
opacityFadeOut: (el, duration) => {
!duration && (duration = 1);
el[0].tween = new Konva.Tween({
node: el[0],
duration: duration,
opacity: 0,
onFinish: function () {
el[0].tween.reset();
},
});
el[0].tween.play();
},
opacityFadeIn: (el, duration) => {
!duration && (duration = 1);
el[0].opacity(0);
el[0].tween = new Konva.Tween({
node: el[0],
duration: duration,
opacity: 1,
});
el[0].tween.play();
},
typewriting: (el, duration) => {
!duration && (duration = 1);
if (el[0].attrs.name != 'text') return;
const textValue = el[0].getText();
let i = 0;
function typeWriter() {
if (i <= textValue.length) {
el[0].setAttrs({
text: textValue.substr(0, i),
});
layer.draw();
i++;
setTimeout(typeWriter, 50);
}
}
typeWriter();
},
blurFadeIn: (el, duration) => {
!duration && (duration = 0.6);
el[0].blurRasdius(0);
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.EaseInOut,
duration,
blurRadius: 10,
onFinish: function () {
el[0].filters([]);
el[0].blurRadius(0);
layer.add(el[0]);
stage.add(layer);
},
}).play();
el[0].cache();
el[0].filters([Konva.Filters.Blur]);
layer.add(el[0]);
stage.add(layer);
},
fallingAndBouncing: (el, duration) => {
!duration && (duration = 1);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].position({
x: stage.width() / 2,
y: 0,
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.BounceEaseOut,
duration,
});
el[0].tween.play();
},
twistyFallingAndBouncing: (el, duration) => {
!duration && (duration = 1);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].rotate(-30);
el[0].position({
x: stage.width() / 2,
y: 0,
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.BounceEaseOut,
duration,
});
el[0].tween.play();
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.EaseInOut,
duration: duration,
rotation: 0,
});
el[0].tween.play();
},
backEasingMiddleToTop: (el, duration) => {
!duration && (duration = 0.55);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].position({
x: stage.width() / 2,
y: stage.height(),
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.BackEaseOut,
duration,
});
el[0].tween.play();
},
middleToTopAndRotateClassicNegative: (el, duration) => {
!duration && (duration = 1);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].rotate(-30);
el[0].opacity(0);
el[0].position({
x: stage.width() / 2,
y: stage.height(),
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.StrongEaseOut,
duration,
rotation: 0,
opacity: 1,
});
el[0].tween.play();
},
middleToTopAndRotateClassicPositive: (el, duration) => {
!duration && (duration = 1);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].rotate(30);
el[0].opacity(0);
el[0].position({
x: stage.width() / 2,
y: stage.height(),
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.StrongEaseOut,
duration,
rotation: 0,
opacity: 1,
});
el[0].tween.play();
},
middleToTopAndRotateNegative: (el, duration) => {
!duration && (duration = 1.45);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].rotate(-30);
el[0].opacity(0);
el[0].position({
x: stage.width() / 2,
y: stage.height(),
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.ElasticEaseOut,
duration,
rotation: 0,
opacity: 1,
});
el[0].tween.play();
},
middleToTopAndRotatePositive: (el, duration) => {
!duration && (duration = 1.45);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].rotate(30);
el[0].opacity(0);
el[0].position({
x: stage.width() / 2,
y: stage.height(),
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
y: initY,
easing: Konva.Easings.ElasticEaseOut,
duration,
rotation: 0,
opacity: 1,
});
el[0].tween.play();
},
twistyRotatedRightToTheLeft: (el, duration) => {
!duration && (duration = 0.8);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].rotate(30);
el[0].position({
x: stage.width(),
y: initY,
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
easing: Konva.Easings.BackEaseOut,
duration,
});
el[0].tween.play();
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.ElasticEaseOut,
duration: duration + 1.5,
rotation: 0,
});
el[0].tween.play();
},
centeredResizingAndRotationingOnTheMiddle: (el, duration) => {
!duration && (duration = 0.8);
el[0].scale({
x: 0,
y: 0,
});
el[0].rotate(30);
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.BackEaseOut,
duration,
scaleX: 1,
scaleY: 1,
rotation: 0,
});
el[0].tween.play();
},
centeredResizingOnTheMiddle: (el, duration) => {
!duration && (duration = 0.8);
el[0].scale({
x: 0,
y: 0,
});
el[0].tween = new Konva.Tween({
node: el[0],
easing: Konva.Easings.BackEaseOut,
duration,
scaleX: 1,
scaleY: 1,
});
el[0].tween.play();
},
easingRightToTheLeft: (el, duration) => {
!duration && (duration = 1.5);
let initX = el[0].attrs.x;
let initY = el[0].attrs.y;
el[0].position({
x: stage.width() + el[0].attrs.x / 2,
y: stage.height() / 2,
});
el[0].tween = new Konva.Tween({
node: el[0],
x: initX,
easing: Konva.Easings.StrongEaseOut,
duration,
});
el[0].tween.play();
},
};
/* animation list -- END EDIT HERE -- */
/* canvas item types */
const itemType = {
text: () => {
let el = new Konva.Text({
width: 150,
height: 16,
x: stage.width() / 2,
y: stage.height() / 2,
text: 'Simple Text',
fontSize: 30,
fontFamily: 'Calibri',
fill: 'green',
name: 'text',
});
el.setAttr('offset', {
x: el.width() / 2,
y: el.height() / 2,
});
layer.add(el);
layer.draw();
},
shape: () => {
let el = new Konva.Rect({
x: stage.width() / 2,
y: stage.height() / 2,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
name: 'shape',
});
el.setAttr('offset', {
x: el.width() / 2,
y: el.height() / 2,
});
layer.add(el);
layer.draw();
},
image: () => {
let imgUrl =
'https://raw.githubusercontent.com/konvajs/konvajs.github.io/master/apple-touch-icon-180x180.png';
let el = Konva.Image.fromURL(imgUrl, function (el) {
el.setAttrs({
x: stage.width() / 2,
y: stage.height() / 2,
name: 'image',
});
layer.add(el);
layer.batchDraw();
el.setAttr('offset', {
x: el.width() / 2,
y: el.height() / 2,
});
});
},
};
/* create canvas container */
let stage = new Konva.Stage({
container: 'canvas-wrapper',
width: 720,
height: 360,
});
let layer = new Konva.Layer();
stage.add(layer);
itemType['text']();
/* button functions */
/* populate canvas item type */
const itemOptions = document.getElementById('item-val');
for (let type in itemType) {
let typeOf = document.createElement('option');
typeOf.value = type;
typeOf.appendChild(document.createTextNode(type));
itemOptions.appendChild(typeOf);
}
itemOptions.addEventListener('change', () => {
layer.destroy();
layer = new Konva.Layer();
stage.add(layer);
itemType[itemOptions.value]();
console.log(stage);
});
/* populate canvas animation type */
const animationOptions = document.getElementById('animation-val');
for (let type in animationType) {
let typeOf = document.createElement('option');
typeOf.value = type;
typeOf.appendChild(document.createTextNode(type));
animationOptions.appendChild(typeOf);
}
let animInit = false;
function playAnim() {
let animVal = document.getElementById('animation-val').value,
itemVal = document.getElementById('item-val').value;
animationType[animVal](stage.find('.' + itemVal));
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment