形状工具提示
HTML5 Canvas 形状工具提示与 Konva
此演示展示了如何创建在形状上悬停时跟随鼠标光标的工具提示。它演示了:
- 使用 sceneFunc 创建自定义形状
- 处理鼠标事件(mousemove, mouseout)
- 使用多个图层以便更好地组织
- 创建跟随光标的动态工具提示
- Vanilla
- 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>
说明:将鼠标移动到形状上以查看工具提示。工具提示将跟随光标并显示有关每个形状的信息。