为canvas绘制的图形设置点击事件
效果:

原理:
给canvas设置点击事件,点击时获取点击位置的信息,通过判断点击位置是否包含在图形中来执行对应的效果。
详解:
1.通过getBoundingClientRect方法获取canvas相对于可视区域的偏移量
2.canvas点击事件触发时使用clientX、clientY方法获取点击位置,计算可得到点击位置在canvas中的坐标
3.清空画布
4.重绘画布,在绘制完每个图形的时候都执行一次isPointInPath方法判断点击位置是否在该图形中,决定是否要执行onClick事件
代码:(react hook语法)
index.js
1 import React, { useEffect, useRef, useState } from 'react'; 2 import { DrawImg } from './draw'; 3 import { MenuInfo } from './config'; 4 import styles from './index.less'; 5 6 const Home = () => { 7 // canvas 8 const meCanvas = useRef(); 9 // 画布 10 const ctx = useRef(); 11 // canvas位置 12 const [cInfo, setCInfo] = useState({ top: 0, left: 0 }); 13 14 /* 获取canvas位置 */ 15 useEffect(() => { 16 //使canvas铺满可视区域 17 meCanvas.current.width = document.documentElement.clientWidth; 18 meCanvas.current.height = document.documentElement.clientHeight; 19 //更新canvas位置 20 setCInfo(meCanvas.current.getBoundingClientRect()) 21 }, []) 22 23 /* 绘制图形 */ 24 useEffect(() => { 25 ctx.current = meCanvas.current.getContext('2d'); 26 const qbb = ctx.current; 27 qbb.strokeStyle = "#fff"; 28 qbb.fillStyle = "#fff"; 29 MenuInfo.forEach(i => { 30 DrawImg({ 31 ctx: qbb, ...i, onClick: () => { 32 console.log(i.msg) 33 } 34 }) 35 }) 36 }, []) 37 38 /* 画布点击事件 */ 39 const CanvasOnClick = (e) => { 40 ctx.current.clearRect(0, 0, meCanvas.current.width, meCanvas.current.height); 41 MenuInfo.forEach(i => { 42 DrawImg({ 43 ctx: ctx.current, ...i, onClick: () => { 44 console.log(i.msg) 45 } 46 }, { x: e.clientX - cInfo.left, y: e.clientY - cInfo.top }) 47 }) 48 } 49 50 return <div> 51 <canvas onClick={CanvasOnClick} ref={meCanvas} className={styles.meCanvas} width={1000} height={1000}></canvas> 52 </div> 53 } 54 55 export default Home;
draw.js
/* 绘制六边形 */
export const DrawImg = (ctxMsg, position) => {
const { ctx, x = 50, y = 50, length = 50, onClick = () => { } } = ctxMsg;
const meLength = Math.sqrt(Math.pow(length, 2) / 2);
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + meLength, y - meLength);
ctx.lineTo(x + 2 * meLength, y);
ctx.lineTo(x + 2 * meLength, y + length);
ctx.lineTo(x + meLength, y + length + meLength);
ctx.lineTo(x, y + length);
ctx.lineTo(x, y);
if (position && ctx.isPointInPath(position.x, position.y)) {
ctx.fill();
ctx.stroke();
onClick();
} else {
ctx.stroke();
}
}
config.js
/* 菜单信息 */
export const MenuInfo = [
{ x: 100, y: 100, msg: 1 },
{ x: 200, y: 100, msg: 2 },
{ x: 300, y: 100, msg: 3 },
{ x: 400, y: 100, msg: 4 },
]
index.less
.meCanvas{
background-color: black;
}
浙公网安备 33010602011771号