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>