Expand Image on Hover
This demo shows how to create an effect where images expand when the mouse hovers over them. The images are also draggable.
Instructions: Hover your mouse over the images to see them expand.
- 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(); stage.add(layer); // Create Darth Vader image const darthVaderImg = new Konva.Image({ x: 110, y: 88, width: 200, height: 137, offset: { x: 100, y: 68, }, draggable: true, }); layer.add(darthVaderImg); // Create Yoda image const yodaImg = new Konva.Image({ x: 290, y: 70, width: 93, height: 104, offset: { x: 46, y: 52, }, draggable: true, }); layer.add(yodaImg); // Load Darth Vader image const imageObj1 = new Image(); imageObj1.onload = function () { darthVaderImg.image(imageObj1); }; imageObj1.src = 'https://konvajs.org/assets/darth-vader.jpg'; // Load Yoda image const imageObj2 = new Image(); imageObj2.onload = function () { yodaImg.image(imageObj2); }; imageObj2.src = 'https://konvajs.org/assets/yoda.jpg'; // Use event delegation to update pointer style and apply scaling layer.on('mouseover', function (evt) { const shape = evt.target; document.body.style.cursor = 'pointer'; // Scale up the image on hover shape.to({ scaleX: 1.2, scaleY: 1.2, duration: 0.2, }); }); layer.on('mouseout', function (evt) { const shape = evt.target; document.body.style.cursor = 'default'; // Scale back to normal when mouse leaves shape.to({ scaleX: 1, scaleY: 1, duration: 0.2, }); });
import { useState, useEffect } from 'react'; import { Stage, Layer, Image } from 'react-konva'; import { useImage } from 'react-konva-utils'; const ImageWithHover = ({ src, x, y, width, height, offsetX, offsetY }) => { const [image] = useImage(src); const [isHovered, setIsHovered] = useState(false); const scale = isHovered ? 1.2 : 1; return ( <Image image={image} x={x} y={y} width={width} height={height} offsetX={offsetX} offsetY={offsetY} scaleX={scale} scaleY={scale} draggable onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} /> ); }; const App = () => { return ( <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> <ImageWithHover src="https://konvajs.org/assets/darth-vader.jpg" x={110} y={88} width={200} height={137} offsetX={100} offsetY={68} /> <ImageWithHover src="https://konvajs.org/assets/yoda.jpg" x={290} y={70} width={93} height={104} offsetX={46} offsetY={52} /> </Layer> </Stage> ); }; export default App;
<template> <v-stage :config="stageConfig"> <v-layer ref="layerRef"> <v-image v-for="(img, index) in images" :key="index" :config="getImageConfig(img, index)" @mouseenter="handleMouseEnter(index)" @mouseleave="handleMouseLeave(index)" /> </v-layer> </v-stage> </template> <script setup> import { ref, onMounted, computed } from 'vue'; const stageConfig = { width: window.innerWidth, height: window.innerHeight }; const layerRef = ref(null); const hoveredIndex = ref(null); const loadedImages = ref({}); // Define image data const images = ref([ { src: 'https://konvajs.org/assets/darth-vader.jpg', x: 110, y: 88, width: 200, height: 137, offsetX: 100, offsetY: 68, loaded: false }, { src: 'https://konvajs.org/assets/yoda.jpg', x: 290, y: 70, width: 93, height: 104, offsetX: 46, offsetY: 52, loaded: false } ]); // Load images onMounted(() => { images.value.forEach((img, index) => { const imageObj = new Image(); imageObj.onload = () => { loadedImages.value = { ...loadedImages.value, [index]: imageObj }; }; imageObj.src = img.src; }); }); // Get configuration for each image const getImageConfig = (img, index) => { const isHovered = hoveredIndex.value === index; const scale = isHovered ? 1.2 : 1; return { image: loadedImages.value[index], x: img.x, y: img.y, width: img.width, height: img.height, offsetX: img.offsetX, offsetY: img.offsetY, scaleX: scale, scaleY: scale, draggable: true }; }; // Mouse event handlers const handleMouseEnter = (index) => { hoveredIndex.value = index; document.body.style.cursor = 'pointer'; }; const handleMouseLeave = () => { hoveredIndex.value = null; document.body.style.cursor = 'default'; }; </script>