HTML5 Canvas 图像事件与 Konva
为了仅检测 Konva 中图像中非透明像素的事件,我们可以使用 drawHitFromCache()
方法来生成更精确的图像命中区域。
默认情况下,事件可以在图像内任何像素上触发,即使是透明的。drawHitFromCache()
方法还接受一个可选的回调方法,用于在图像命中区域创建时执行。
注意:drawHitFromCache()
方法要求图像托管在与执行代码相同域的 Web 服务器上。
说明:将鼠标悬停在猴子和狮子上,观察鼠标悬停事件的绑定。请注意,当你将鼠标悬停在图像的任何部分(包括透明像素)上时,事件会在猴子上触发。由于我们为狮子创建了一个图像命中区域,因此透明像素会被忽略,这使得事件检测更为精确。
- Vanilla
- React
- Vue
import Konva from 'konva'; const stage = new Konva.Stage({ container: 'container', width: window.innerWidth, height: window.innerHeight, }); const layer = new Konva.Layer(); stage.add(layer); const text = new Konva.Text({ x: 10, y: 10, fontFamily: 'Calibri', fontSize: 24, text: '', fill: 'black', }); layer.add(text); function writeMessage(message) { text.text(message); } const imageObj1 = new Image(); imageObj1.onload = () => { const monkey = new Konva.Image({ x: 120, y: 50, image: imageObj1, width: 200, height: 200, }); monkey.on('mouseover', function () { writeMessage('mouseover monkey (regular image)'); }); monkey.on('mouseout', function () { writeMessage(''); }); layer.add(monkey); }; imageObj1.crossOrigin = 'Anonymous'; imageObj1.src = 'https://konvajs.org/assets/monkey.png'; const imageObj2 = new Image(); imageObj2.onload = () => { const lion = new Konva.Image({ x: 320, y: 50, image: imageObj2, width: 200, height: 200, }); // 覆盖颜色检测区域 lion.on('mouseover', function () { writeMessage('mouseover lion (with transparent pixels detection)'); }); lion.on('mouseout', function () { writeMessage(''); }); layer.add(lion); lion.cache(); lion.drawHitFromCache(); }; imageObj2.crossOrigin = 'Anonymous'; imageObj2.src = 'https://konvajs.org/assets/lion.png';
import { Stage, Layer, Image, Text } from 'react-konva'; import { useState, useEffect, useRef } from 'react'; import useImage from 'use-image'; const App = () => { const [message, setMessage] = useState(''); const lionRef = useRef(); const [monkeyImage] = useImage('https://konvajs.org/assets/monkey.png', 'anonymous'); const [lionImage] = useImage('https://konvajs.org/assets/lion.png', 'anonymous'); useEffect(() => { if (lionImage) { lionRef.current.cache(); lionRef.current.drawHitFromCache(); } }, [lionImage]); return ( <Stage width={window.innerWidth} height={window.innerHeight}> <Layer> <Text x={10} y={10} fontFamily="Calibri" fontSize={24} text={message} fill="black" /> {monkeyImage && ( <Image x={120} y={50} image={monkeyImage} width={200} height={200} onMouseover={() => setMessage('mouseover monkey (regular image)')} onMouseout={() => setMessage('')} /> )} {lionImage && ( <Image x={320} y={50} image={lionImage} width={200} height={200} ref={lionRef} onMouseover={() => setMessage('mouseover lion (with transparent pixels detection)') } onMouseout={() => setMessage('')} /> )} </Layer> </Stage> ); }; export default App;
<template> <v-stage :config="stageSize"> <v-layer> <v-text :config="textConfig" /> <v-image v-if="monkeyImage" :config="monkeyConfig" @mouseover="handleMonkeyOver" @mouseout="handleMouseOut" ref="monkeyRef" /> <v-image v-if="lionImage" :config="lionConfig" @mouseover="handleLionOver" @mouseout="handleMouseOut" ref="lionRef" /> </v-layer> </v-stage> </template> <script setup> import { ref, computed, nextTick, watch } from 'vue'; import { useImage } from 'vue-konva'; const message = ref(''); const lionRef = ref(null); const monkeyRef = ref(null); const [monkeyImage] = useImage('https://konvajs.org/assets/monkey.png', 'anonymous'); const [lionImage] = useImage('https://konvajs.org/assets/lion.png', 'anonymous'); const stageSize = { width: window.innerWidth, height: window.innerHeight }; const textConfig = computed(() => ({ x: 10, y: 10, fontFamily: 'Calibri', fontSize: 24, text: message.value, fill: 'black' })); const monkeyConfig = computed(() => ({ x: 120, y: 50, image: monkeyImage.value, width: 200, height: 200 })); const lionConfig = computed(() => ({ x: 320, y: 50, image: lionImage.value, width: 200, height: 200 })); // 观察图像加载以设置命中区域 watch([lionImage, monkeyImage], () => { console.log('watch', lionImage, monkeyImage); nextTick(() => { if (lionRef.value) { const node = lionRef.value.getNode(); node.cache(); node.drawHitFromCache(); } }); }); const handleMonkeyOver = () => { message.value = 'mouseover monkey (regular image)'; }; const handleLionOver = () => { message.value = 'mouseover lion (with transparent pixels detection)'; }; const handleMouseOut = () => { message.value = ''; }; </script>