Compare commits

..

10 Commits

Author SHA1 Message Date
bunny 67c49a26a4 同步 2024-07-23 08:26:43 +08:00
bunny e9e0dab2f8 feat: 🚀 complex Tweening 2024-07-17 09:46:25 +08:00
bunny fbf929cc81 page: 📄 common Easings 2024-07-17 08:58:34 +08:00
bunny 1fd9d75928 page: 📄 元素改变时动画 2024-07-17 08:44:54 +08:00
bunny 5ff3d64e23 docs: 📚 修改文档内容 2024-07-16 16:52:40 +08:00
bunny f86dfe348a page: 📄 设置元素的zIndex相关API 2024-07-16 16:52:01 +08:00
bunny 4a19611284 page: 📄 将圆形zIndex设置为1 2024-07-16 16:40:50 +08:00
bunny 07762aec41 feat: 🚀 移动到不同组中 2024-07-16 16:33:32 +08:00
bunny 106f52f71e feat: 🚀 添加组 2024-07-16 16:16:01 +08:00
bunny a42bc7d82d feat: 🚀 字体最小宽度 2024-07-16 15:44:19 +08:00
15 changed files with 751 additions and 188 deletions

View File

@ -1,55 +1,37 @@
```sh ```sh
force update https://konvajs.org/docs/animations/Create_an_Animation.html
text resizing https://konvajs.org/docs/animations/Moving.html
ignore stroke https://konvajs.org/docs/animations/Rotation.html
clipping https://konvajs.org/docs/animations/Scaling.html
simple clip https://konvajs.org/docs/animations/Stop_Animation.html
complex clip
groups, layers and ordering https://konvajs.org/docs/filters/Blur.html
groups https://konvajs.org/docs/filters/Brighten.html
layering https://konvajs.org/docs/filters/Contrast.html
change containers https://konvajs.org/docs/filters/Emboss.html
zindex https://konvajs.org/docs/filters/Enhance.html
filters https://konvajs.org/docs/filters/Grayscale.html
blur https://konvajs.org/docs/filters/HSL.html
brighten https://konvajs.org/docs/filters/HSV.html
contrast https://konvajs.org/docs/filters/RGB.html
emboss https://konvajs.org/docs/filters/Invert.html
enhance https://konvajs.org/docs/filters/Kaleidoscope.html
grayscale https://konvajs.org/docs/filters/Mask.html
hsl https://konvajs.org/docs/filters/Noise.html
hsv https://konvajs.org/docs/filters/Pixelate.html
rgb https://konvajs.org/docs/filters/Custom_Filter.html
invert https://konvajs.org/docs/filters/Multiple_Filters.html
kaleidoscope
mask https://konvajs.org/docs/data_and_serialization/Serialize_a_Stage.html
noise https://konvajs.org/docs/data_and_serialization/Simple_Load.html
pixelate https://konvajs.org/docs/data_and_serialization/Complex_Load.html
custom filter https://konvajs.org/docs/data_and_serialization/Best_Practices.html
multiple filters https://konvajs.org/docs/data_and_serialization/Stage_Data_URL.html
tweens https://konvajs.org/docs/data_and_serialization/High-Quality-Export.html
linear easing
common easings https://konvajs.org/docs/performance/Shape_Redraw.html
all easings https://konvajs.org/docs/performance/Optimize_Strokes.html
finish event https://konvajs.org/docs/performance/Optimize_Animation.html
all controls https://konvajs.org/docs/performance/Batch_Draw.html
tween filter https://konvajs.org/docs/performance/Layer_Management.html
complex tweening ```
animations
create an animation
moving
rotation
scaling
stop animation
selectors
select by id
select by type
select by name
data & serialization & export
serialize a stage
simple load
complex load
json best practices
stage data url
export to hd image
```

View File

@ -27,7 +27,7 @@ const include = [
// 'sortablejs', // 'sortablejs',
// 'swiper/vue', // 'swiper/vue',
// 'mint-filter', // 'mint-filter',
// '@vueuse/core', '@vueuse/core',
// 'vue3-danmaku', // 'vue3-danmaku',
// 'v-contextmenu', // 'v-contextmenu',
// 'vue-pdf-embed', // 'vue-pdf-embed',

View File

@ -1 +1 @@
{"version":1721089915004} {"version":1721355798048}

View File

@ -0,0 +1,90 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import { onMounted, ref } from 'vue';
import Konva from 'konva/lib';
import { Group } from 'konva/lib/Group';
import { Rect } from 'konva/lib/shapes/Rect';
const { width, height } = useWindowSize();
const yellowGroup = ref<Group>();
const blueGroup = ref<Group>();
const box = ref<Rect>();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
yellowGroup.value = new Konva.Group({
x: 100,
y: 100,
draggable: true,
});
blueGroup.value = new Konva.Group({
x: 300,
y: 80,
draggable: true,
});
box.value = new Konva.Rect({
x: 10,
y: 10,
width: 100,
height: 50,
fill: 'red',
stroke: 'black',
});
const yellowCircle = new Konva.Circle({
x: 0,
y: 0,
radius: 50,
fill: 'yellow',
stroke: 'black',
});
const blueCircle = new Konva.Circle({
x: 0,
y: 0,
radius: 50,
fill: 'blue',
stroke: 'black',
});
yellowGroup.value.add(yellowCircle);
yellowGroup.value.add(box.value);
blueGroup.value.add(blueCircle);
layer.add(yellowGroup.value);
layer.add(blueGroup.value);
stage.add(layer);
};
/**
* * 移动到蓝色组
*/
const toBlue = () => {
box.value?.moveTo(blueGroup.value);
};
/**
* * 移动到黄色
*/
const toYellow = () => {
box.value?.moveTo(yellowGroup.value);
};
onMounted(() => {
initial();
});
</script>
<template>
<div class="container-fluid">
<button id="toBlue" class="btn btn-primary" @click="toBlue">Move red box to blue group</button>
<button id="toYellow" class="btn btn-warning" @click="toYellow">Move red box to yellow group</button>
<div id="container"></div>
</div>
</template>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,41 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import { onMounted } from 'vue';
import Konva from 'konva/lib';
const { width, height } = useWindowSize();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
const group = new Konva.Group({ x: 120, y: 40, rotation: 20, draggable: true });
const colors = ['red', 'orange', 'yellow'];
for (let i = 0; i < 3; i++) {
const rect = new Konva.Rect({
x: i * 30,
y: i * 30,
width: 100,
height: 20,
name: `color${colors[i]}`,
fill: colors[i],
stroke: 'black',
strokeWidth: 4,
});
group.add(rect);
}
layer.add(group);
};
onMounted(() => {
initial();
});
</script>
<template>
<div id="container"></div>
</template>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,66 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import { onMounted, ref } from 'vue';
import Konva from 'konva/lib';
import { Rect } from 'konva/lib/shapes/Rect';
const { width, height } = useWindowSize();
const yellowBox = ref<Rect>();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
for (let n = 0; n < 6; n++) {
(function () {
const i = n;
const box = new Konva.Rect({
x: i * 30 + 210,
y: i * 18 + 40,
width: 100,
height: 50,
fill: colors[i],
stroke: 'black',
strokeWidth: 4,
draggable: true,
name: colors[i],
});
box.on('mouseover', function () {
document.body.style.cursor = 'pointer';
});
box.on('mouseout', function () {
document.body.style.cursor = 'default';
});
if (colors[i] === 'yellow') {
yellowBox.value = box;
}
layer.add(box);
})();
}
stage.add(layer);
};
onMounted(() => {
initial();
});
</script>
<template>
<div class="container-fluid">
<div id="buttons">
<button id="toTop" class="btn btn-warning" @click="yellowBox?.moveToTop()">Move yellow box to top</button>
<button id="toBottom" class="btn btn-outline-info" @click="yellowBox?.moveToBottom()">Move yellow box to bottom</button>
<button id="up" class="btn btn-outline-warning" @click="yellowBox?.moveUp()">Move yellow box up</button>
<button id="down " class="btn btn-info" @click="yellowBox?.moveDown()">Move yellow box down</button>
<button id="zIndex" class="btn btn-primary" @click="yellowBox?.setZIndex(3)">Set yellow box zIndex to 3</button>
</div>
<div id="container"></div>
</div>
</template>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,55 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import Konva from 'konva/lib';
import { onMounted, ref } from 'vue';
import { Circle } from 'konva/lib/shapes/Circle';
const { width, height } = useWindowSize();
const circle = ref<Circle>();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
const group = new Konva.Group();
layer.add(group);
circle.value = new Konva.Circle({
x: 70,
y: 70,
fill: 'red',
radius: 30,
});
group.add(circle.value);
const blackRect = new Konva.Rect({
x: 20,
y: 20,
fill: 'black',
width: 100,
height: 100,
});
group.add(blackRect);
};
/**
* * 将圆形zIndex设置为1
*/
const updateCircle = () => {
circle.value!.zIndex(1);
};
onMounted(() => {
initial();
});
</script>
<template>
<div class="container-fluid">
<button class="btn btn-primary" @click="updateCircle">将圆形zIndex设置为1</button>
<div id="container"></div>
</div>
</template>
<style scoped lang="scss"></style>

View File

@ -1,153 +1,48 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue'; import { onMounted, ref } from 'vue';
import { useWindowSize } from '@vueuse/core'; import { useEventListener, useWindowSize } from '@vueuse/core';
import Konva from 'konva/lib'; import Konva from 'konva/lib';
import { rect1, rect2, selectionRectangle } from '@/views/select/basic/rect.ts';
import { stageEvent } from '@/views/select/basic/stageEvent.ts';
import { drawLine } from '@/views/select/basic/line.ts';
import { Stage } from 'konva/lib/Stage';
import { Layer } from 'konva/lib/Layer';
const { width, height } = useWindowSize(); const { width, height } = useWindowSize();
// let stage, layer;
const stage = ref<Stage>();
const layer = ref<Layer>();
const tr = ref();
const initial = () => { const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value }); stage.value = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer(); layer.value = new Konva.Layer();
stage.value.add(layer.value);
const rect1 = new Konva.Rect({ drawLine(stage.value, layer.value);
x: 60,
y: 60,
width: 100,
height: 90,
fill: 'red',
name: 'rect',
draggable: true,
});
layer.add(rect1);
const rect2 = new Konva.Rect({ rect1(layer.value);
x: 180, rect2(layer.value);
y: 200,
width: 100,
height: 200,
fill: 'green',
name: 'rect',
draggable: true,
});
layer.add(rect2);
// //
const tr = new Konva.Transformer(); tr.value = new Konva.Transformer();
layer.add(tr); layer.value.add(tr.value);
tr.nodes([rect1, rect2]);
const selectionRectangle = new Konva.Rect({ stageEvent(stage.value, selectionRectangle(layer.value), tr.value);
fill: 'rgba(0,0,255,0.5)',
visible: false,
// disable events to not interrupt with events
listening: false,
});
layer.add(selectionRectangle);
let x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0;
let selecting = false;
stage.on('mousedown touchstart', e => {
// do nothing if we mousedown on any shape
if (e.target !== stage) {
return;
}
e.evt.preventDefault();
x1 = stage.getPointerPosition()!.x;
y1 = stage.getPointerPosition()!.y;
x2 = stage.getPointerPosition()!.x;
y2 = stage.getPointerPosition()!.y;
selectionRectangle.width(0);
selectionRectangle.height(0);
selecting = true;
});
stage.on('mousemove touchmove', e => {
// do nothing if we didn't start selection
if (!selecting) {
return;
}
e.evt.preventDefault();
x2 = stage.getPointerPosition()!.x;
y2 = stage.getPointerPosition()!.y;
selectionRectangle.setAttrs({
visible: true,
x: Math.min(x1, x2),
y: Math.min(y1, y2),
width: Math.abs(x2 - x1),
height: Math.abs(y2 - y1),
});
});
stage.on('mouseup touchend', e => {
// do nothing if we didn't start selection
selecting = false;
if (!selectionRectangle.visible()) {
return;
}
e.evt.preventDefault();
// update visibility in timeout, so we can check it in click event
selectionRectangle.visible(false);
let shapes = stage.find('.rect');
let box = selectionRectangle.getClientRect();
let selected = shapes.filter(shape => Konva.Util.haveIntersection(box, shape.getClientRect()));
tr.nodes(selected);
});
// clicks should select/deselect shapes
stage.on('click tap', function (e) {
// if we are selecting with rect, do nothing
if (selectionRectangle.visible()) {
return;
}
// if click on empty area - remove all selections
if (e.target === stage) {
tr.nodes([]);
return;
}
// do nothing if clicked NOT on our rectangles
if (!e.target.hasName('rect')) {
return;
}
// do we pressed shift or ctrl?
const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
const isSelected = tr.nodes().indexOf(e.target) >= 0;
if (!metaPressed && !isSelected) {
// if no key pressed and the node is not selected
// select just one
tr.nodes([e.target]);
} else if (metaPressed && isSelected) {
// if we pressed keys and node was selected
// we need to remove it from selection:
const nodes = tr.nodes().slice(); // use slice to have new copy of array
// remove node from array
nodes.splice(nodes.indexOf(e.target), 1);
tr.nodes(nodes);
} else if (metaPressed && !isSelected) {
// add the node into selection
const nodes = tr.nodes().concat([e.target]);
tr.nodes(nodes);
}
});
stage.add(layer);
}; };
onMounted(() => { onMounted(() => {
initial(); initial();
useEventListener(window, 'resize', function () {
stage.value?.width(width.value);
stage.value?.height(height.value);
// tr.value.forceUpdate();
});
}); });
</script> </script>
<template> <template>
<div id="container"></div> <div id="container"></div>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,33 @@
import { Stage } from 'konva/lib/Stage';
import { Layer } from 'konva/lib/Layer';
import Konva from 'konva/lib';
export const drawLine = (stage: Stage, layer: Layer) => {
const xSnaps = Math.round(stage.width() / 50);
const ySnaps = Math.round(stage.height() / 50);
const cellWidth = stage.width() / xSnaps;
const cellHeight = stage.height() / ySnaps;
for (let i = 0; i < xSnaps; i++) {
const xLine = new Konva.Line({
x: i * cellWidth,
points: [0, 0, 0, stage.height()],
stroke: '#96e04d',
strokeWidth: 1,
id: 'line',
});
layer.add(xLine);
}
for (let i = 0; i < ySnaps; i++) {
layer.add(
new Konva.Line({
y: i * cellHeight,
points: [0, 0, stage.width(), 0],
stroke: '#96e04d',
strokeWidth: 1,
id: 'line',
}),
);
}
};

View File

@ -0,0 +1,41 @@
import { Layer } from 'konva/lib/Layer';
import Konva from 'konva/lib';
export const rect1 = (parent: Layer) => {
const rect = new Konva.Rect({
x: 60,
y: 60,
width: 100,
height: 90,
fill: 'red',
name: 'rect',
draggable: true,
});
parent.add(rect);
return rect;
};
export const rect2 = (parent: Layer) => {
const rect = new Konva.Rect({
x: 180,
y: 200,
width: 100,
height: 200,
fill: 'green',
name: 'rect',
draggable: true,
});
parent.add(rect);
return rect;
};
export const selectionRectangle = (layer: Layer) => {
const selectionRectangle = new Konva.Rect({
fill: 'rgba(0,0,255,0.5)',
visible: false,
listening: false,
});
layer.add(selectionRectangle);
return selectionRectangle;
};

View File

@ -0,0 +1,93 @@
import Konva from 'konva/lib';
import { Stage } from 'konva/lib/Stage';
import { Rect } from 'konva/lib/shapes/Rect';
import { Transformer } from 'konva/lib/shapes/Transformer';
export const stageEvent = (stage: Stage, selectionRectangle: Rect, tr: Transformer) => {
let x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0;
let selecting = false;
stage.on('mousedown touchstart', e => {
e.evt.preventDefault();
x1 = stage.getPointerPosition()!.x;
y1 = stage.getPointerPosition()!.y;
x2 = stage.getPointerPosition()!.x;
y2 = stage.getPointerPosition()!.y;
selectionRectangle.width(0);
selectionRectangle.height(0);
selecting = true;
});
stage.on('mousemove touchmove', e => {
if (!selecting) return;
e.evt.preventDefault();
x2 = stage.getPointerPosition()!.x;
y2 = stage.getPointerPosition()!.y;
selectionRectangle.setAttrs({
visible: true,
x: Math.min(x1, x2),
y: Math.min(y1, y2),
width: Math.abs(x2 - x1),
height: Math.abs(y2 - y1),
});
});
stage.on('mouseup touchend', e => {
selecting = false;
if (!selectionRectangle.visible()) return;
e.evt.preventDefault();
// update visibility in timeout, so we can check it in click event
selectionRectangle.visible(false);
let shapes = stage.find('.rect');
let box = selectionRectangle.getClientRect();
let selected = shapes.filter(shape => Konva.Util.haveIntersection(box, shape.getClientRect()));
tr.nodes(selected);
});
// clicks should select/deselect shapes
stage.on('click tap', function (e) {
// if we are selecting with rect, do nothing
if (selectionRectangle.visible()) {
return;
}
// if click on empty area - remove all selections
if (e.target === stage) {
tr.nodes([]);
return;
}
// do nothing if clicked NOT on our rectangles
if (!e.target.hasName('rect')) {
return;
}
// do we pressed shift or ctrl?
const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
const isSelected = tr.nodes().indexOf(e.target) >= 0;
if (!metaPressed && !isSelected) {
// if no key pressed and the node is not selected
// select just one
tr.nodes([e.target]);
} else if (metaPressed && isSelected) {
// if we pressed keys and node was selected
// we need to remove it from selection:
const nodes = tr.nodes().slice(); // use slice to have new copy of array
// remove node from array
nodes.splice(nodes.indexOf(e.target), 1);
tr.nodes(nodes);
} else if (metaPressed && !isSelected) {
// add the node into selection
const nodes = tr.nodes().concat([e.target]);
tr.nodes(nodes);
}
});
};

View File

@ -0,0 +1,54 @@
<script setup lang="ts">
import { onMounted } from 'vue';
import Konva from 'konva/lib';
import { useWindowSize } from '@vueuse/core';
const { width, height } = useWindowSize();
const MIN_WIDTH = 100;
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
const text = new Konva.Text({
x: 50,
y: 60,
fontSize: 20,
text: 'Hello from the Konva framework. Try to resize me.',
draggable: true,
});
layer.add(text);
const tr = new Konva.Transformer({
nodes: [text],
padding: 5,
flipEnabled: false,
enabledAnchors: ['middle-left', 'middle-right'],
boundBoxFunc(oldBox, newBox) {
if (Math.abs(newBox.width) < MIN_WIDTH) {
return oldBox;
}
return newBox;
},
});
layer.add(tr);
text.on('transform', () => {
text.setAttrs({
width: Math.max(text.width() * text.scaleX(), MIN_WIDTH),
scaleX: 1,
scaleY: 1,
});
});
};
onMounted(() => {
initial();
});
</script>
<template>
<div id="container"></div>
</template>

View File

@ -0,0 +1,103 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import { onMounted } from 'vue';
import Konva from 'konva/lib';
const { width, height } = useWindowSize();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
stage.draggable(true);
const layer = new Konva.Layer();
stage.add(layer);
const greenBox = new Konva.Rect({
x: 70,
y: stage.height() / 2,
width: 100,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
offset: {
x: 50,
y: 25,
},
});
const blueBox = new Konva.Rect({
x: 190,
y: stage.height() / 2,
width: 100,
height: 50,
fill: 'blue',
stroke: 'black',
strokeWidth: 4,
offset: {
x: 50,
y: 25,
},
});
const redBox = new Konva.Rect({
x: 310,
y: stage.height() / 2,
width: 100,
height: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
offset: {
x: 50,
y: 25,
},
});
layer.add(greenBox);
layer.add(blueBox);
layer.add(redBox);
// the tween has to be created after the node has been added to the layer
greenBox.tween = new Konva.Tween({
node: greenBox,
scaleX: 2,
scaleY: 1.5,
easing: Konva.Easings.EaseIn,
duration: 1,
});
blueBox.tween = new Konva.Tween({
node: blueBox,
scaleX: 2,
scaleY: 1.5,
easing: Konva.Easings.EaseInOut,
duration: 1,
});
redBox.tween = new Konva.Tween({
node: redBox,
scaleX: 2,
scaleY: 1.5,
easing: Konva.Easings.EaseOut,
duration: 1,
});
// use event delegation
layer.on('mouseover touchstart', function (evt) {
evt.target.tween.play();
});
layer.on('mouseout touchend', function (evt) {
evt.target.tween.reverse();
});
};
onMounted(() => {
initial();
});
</script>
<template>
<div id="container"></div>
</template>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,51 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import { onMounted } from 'vue';
import Konva from 'konva/lib';
const { width, height } = useWindowSize();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
const rect = new Konva.Rect({
x: 50,
y: 20,
width: 120,
height: 50,
fill: 'green',
stroke: 'black',
strokeWidth: 2,
opacity: 0.2,
});
layer.add(rect);
const tween = new Konva.Tween({
node: rect,
duration: 1,
x: 140,
y: 90,
fill: 'red',
rotation: Math.PI * 2,
opacity: 1,
strokeWidth: 6,
scaleX: 1.5,
});
setTimeout(() => {
tween.play();
}, 2000);
};
onMounted(() => {
initial();
});
</script>
<template>
<div id="container"></div>
</template>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,59 @@
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import { onMounted } from 'vue';
import Konva from 'konva/lib';
const { width, height } = useWindowSize();
const initial = () => {
const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
const layer = new Konva.Layer();
stage.add(layer);
const image = new Image();
const lion = new Konva.Image({
x: 80,
y: 30,
width: 50,
height: 50,
draggable: true,
image,
});
layer.add(lion);
image.crossOrigin = 'Anonymous';
image.src = 'https://konvajs.org/assets/darth-vader.jpg';
image.onload = function () {
lion.image(image);
lion.cache();
lion.filters([Konva.Filters.Blur]);
lion.blurRadius(100);
const tween = new Konva.Tween({
node: lion,
duration: 0.6,
blurRadius: 0,
easing: Konva.Easings.EaseInOut,
});
lion.on('mouseover', function () {
tween.play();
});
lion.on('mouseout', function () {
tween.reverse();
});
};
};
onMounted(() => {
initial();
});
</script>
<template>
<div id="container"></div>
</template>
<style scoped lang="scss"></style>