Created
June 14, 2023 15:22
-
-
Save prappo/e1dd1bb31c7affc54ed87ea968e82cf2 to your computer and use it in GitHub Desktop.
konva js animation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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