Tween Blur Filter Tutorial
To tween a filter using Konva, we can simply tween the properties associated with the filter.
In this tutorial, we'll tween the blurRadius property, which controls the amount of blur applied to the image.
Instructions: Mouseover or touch the image to focus it (reduce blur).
- Vanilla
- React
- Vue
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();
// create image
const imageObj = new Image();
imageObj.onload = () => {
const lion = new Konva.Image({
x: 50,
y: 50,
image: imageObj,
draggable: true,
});
layer.add(lion);
// add blur filter
lion.cache();
lion.filters([Konva.Filters.Blur]);
lion.blurRadius(10);
// create blur tween
const tween = new Konva.Tween({
node: lion,
duration: 0.5,
blurRadius: 0,
easing: Konva.Easings.EaseInOut,
});
// bind events
lion.on('mouseenter touchstart', () => {
tween.play();
});
lion.on('mouseleave touchend', () => {
tween.reverse();
});
};
imageObj.src = '/assets/lion.png';
imageObj.crossOrigin = 'anonymous';
stage.add(layer);
import Konva from 'konva';
import { Stage, Layer, Image } from 'react-konva';
import { useEffect, useRef, useState } from 'react';
import useImage from 'use-image';
const App = () => {
const imageRef = useRef();
const [image] = useImage('/assets/lion.png');
const tweenRef = useRef();
const [position, setPosition] = useState({ x: 50, y: 50 });
useEffect(() => {
if (!image || !imageRef.current) return;
const node = imageRef.current;
node.cache();
node.filters([Konva.Filters.Blur]);
node.blurRadius(10);
const tween = new Konva.Tween({
node: node,
duration: 0.5,
blurRadius: 0,
easing: Konva.Easings.EaseInOut,
});
tweenRef.current = tween;
return () => {
tween.destroy();
if (tweenRef.current === tween) tweenRef.current = null;
};
}, [image]);
const handleMouseEnter = () => {
tweenRef.current?.play();
};
const handleMouseLeave = () => {
tweenRef.current?.reverse();
};
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Image
ref={imageRef}
x={position.x}
y={position.y}
image={image}
draggable
onDragEnd={(e) => {
setPosition({ x: e.target.x(), y: e.target.y() });
}}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onTouchStart={handleMouseEnter}
onTouchEnd={handleMouseLeave}
/>
</Layer>
</Stage>
);
};
export default App;
<template>
<v-stage :config="stageSize">
<v-layer>
<v-image
v-if="image"
:config="imageConfig"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
@touchstart="handleMouseEnter"
@touchend="handleMouseLeave"
ref="imageRef"
/>
</v-layer>
</v-stage>
</template>
<script setup>
import { computed, nextTick, onUnmounted, ref, watch } from 'vue';
import Konva from 'konva';
const stageSize = {
width: window.innerWidth,
height: window.innerHeight
};
const image = ref(null);
const imageRef = ref(null);
let tween = null;
// Load image
const img = new Image();
img.onload = () => {
image.value = img;
};
img.src = '/assets/lion.png';
const imageConfig = computed(() => ({
x: 50,
y: 50,
image: image.value,
draggable: true
}));
watch(image, async (loadedImage) => {
if (!loadedImage) return;
await nextTick();
const node = imageRef.value.getNode();
node.cache();
node.filters([Konva.Filters.Blur]);
node.blurRadius(10);
tween = new Konva.Tween({
node: node,
duration: 0.5,
blurRadius: 0,
easing: Konva.Easings.EaseInOut,
});
});
const handleMouseEnter = () => {
tween?.play();
};
const handleMouseLeave = () => {
tween?.reverse();
};
onUnmounted(() => tween?.destroy());
</script>