形状工具提示
HTML5 Canvas 形状工具提示与 Konva
此演示展示了如何创建在形状上悬停时跟随鼠标光标的工具提示。它演示了:
- 使用 sceneFunc 创建自定义形状
- 处理鼠标事件(mousemove, mouseout)
- 使用多个图层以便更好地组织
- 创建跟随光标的动态工具提示
- 原生
- React
- Vue
import Konva from 'konva';
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
const shapesLayer = new Konva.Layer();
const tooltipLayer = new Konva.Layer();
// 创建自定义三角形形状
const triangle = new Konva.Shape({
stroke: 'black',
fill: '#00D2FF',
strokeWidth: 1,
sceneFunc: function (context) {
context.beginPath();
context.moveTo(120, 50);
context.lineTo(250, 80);
context.lineTo(150, 170);
context.closePath();
context.fillStrokeShape(this);
},
});
// 创建圆形
const circle = new Konva.Circle({
x: 250,
y: stage.height() / 2,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
radius: 70,
});
// 创建工具提示
const tooltip = new Konva.Text({
text: '',
fontFamily: 'Calibri',
fontSize: 12,
padding: 5,
textFill: 'white',
fill: 'black',
alpha: 0.75,
visible: false,
});
// 为三角形添加事件监听器
triangle.on('mousemove', () => {
const mousePos = stage.getPointerPosition();
tooltip.position({
x: mousePos.x + 5,
y: mousePos.y + 5,
});
tooltip.text('青色三角形');
tooltip.show();
});
triangle.on('mouseout', () => {
tooltip.hide();
});
// 为圆形添加事件监听器
circle.on('mousemove', () => {
const mousePos = stage.getPointerPosition();
tooltip.position({
x: mousePos.x + 5,
y: mousePos.y + 5,
});
tooltip.text('红色圆形');
tooltip.show();
});
circle.on('mouseout', () => {
tooltip.hide();
});
// 添加形状和工具提示到图层
shapesLayer.add(triangle);
shapesLayer.add(circle);
tooltipLayer.add(tooltip);
// 添加图层到舞台
stage.add(shapesLayer);
stage.add(tooltipLayer);
import React from 'react';
import { Stage, Layer, Shape, Circle, Text } from 'react-konva';
const CustomShape = ({ onMouseMove, onMouseOut }) => {
return (
<Shape
stroke="black"
fill="#00D2FF"
strokeWidth={1}
sceneFunc={(context, shape) => {
context.beginPath();
context.moveTo(120, 50);
context.lineTo(250, 80);
context.lineTo(150, 170);
context.closePath();
context.fillStrokeShape(shape);
}}
onMouseMove={onMouseMove}
onMouseOut={onMouseOut}
/>
);
};
const App = () => {
const [tooltipPos, setTooltipPos] = React.useState({ x: 0, y: 0 });
const [tooltipText, setTooltipText] = React.useState('');
const [isTooltipVisible, setTooltipVisible] = React.useState(false);
const handleMouseMove = (e, text) => {
const stage = e.target.getStage();
const pos = stage.getPointerPosition();
setTooltipPos({
x: pos.x + 5,
y: pos.y + 5,
});
setTooltipText(text);
setTooltipVisible(true);
};
const handleMouseOut = () => {
setTooltipVisible(false);
};
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<CustomShape
onMouseMove={(e) => handleMouseMove(e, '青色三角形')}
onMouseOut={handleMouseOut}
/>
<Circle
x={250}
y={window.innerHeight / 2}
radius={70}
fill="red"
stroke="black"
strokeWidth={4}
onMouseMove={(e) => handleMouseMove(e, '红色圆形')}
onMouseOut={handleMouseOut}
/>
</Layer>
<Layer>
<Text
x={tooltipPos.x}
y={tooltipPos.y}
text={tooltipText}
fontFamily="Calibri"
fontSize={12}
padding={5}
textFill="white"
fill="black"
alpha={0.75}
visible={isTooltipVisible}
/>
</Layer>
</Stage>
);
};
export default App;
<template>
<v-stage :config="stageConfig">
<v-layer>
<v-shape
:config="{
stroke: 'black',
fill: '#00D2FF',
strokeWidth: 1,
sceneFunc: drawTriangle,
}"
@mousemove="(e) => handleMouseMove(e, '青色三角形')"
@mouseout="handleMouseOut"
/>
<v-circle
:config="{
x: 250,
y: stageConfig.height / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
}"
@mousemove="(e) => handleMouseMove(e, '红色圆形')"
@mouseout="handleMouseOut"
/>
</v-layer>
<v-layer>
<v-text
:config="{
...tooltipConfig,
visible: isTooltipVisible,
}"
/>
</v-layer>
</v-stage>
</template>
<script setup>
import { ref, computed } from 'vue';
const stageConfig = {
width: window.innerWidth,
height: window.innerHeight,
};
const tooltipPos = ref({ x: 0, y: 0 });
const tooltipText = ref('');
const isTooltipVisible = ref(false);
const tooltipConfig = computed(() => ({
x: tooltipPos.value.x,
y: tooltipPos.value.y,
text: tooltipText.value,
fontFamily: 'Calibri',
fontSize: 12,
padding: 5,
textFill: 'white',
fill: 'black',
alpha: 0.75,
}));
const drawTriangle = (context, shape) => {
context.beginPath();
context.moveTo(120, 50);
context.lineTo(250, 80);
context.lineTo(150, 170);
context.closePath();
context.fillStrokeShape(shape);
};
const handleMouseMove = (e, text) => {
const stage = e.target.getStage();
const pos = stage.getPointerPosition();
tooltipPos.value = {
x: pos.x + 5,
y: pos.y + 5,
};
tooltipText.value = text;
isTooltipVisible.value = true;
};
const handleMouseOut = () => {
isTooltipVisible.value = false;
};
</script>
说明:将鼠标移动到形状上以查看工具提示。工具提示将跟随光标并显示有关每个形状的信息。