Canvas 绘制曲线并实现鼠标点击高亮效果
使用 Canvas 绘制的曲线也可以实现鼠标点击高亮显示效果。由于 Canvas 是基于像素的绘制方式不像 SVG 是基于矢量的我们需要手动检测鼠标点击位置是否在曲线上并重新绘制高亮效果。实现方案基本思路存储所有曲线的路径数据监听鼠标点击事件检测点击位置是否在某条曲线上使用点是否在路径上的检测算法重新绘制所有曲线将选中的曲线高亮显示完整代码示例!DOCTYPEhtmlhtmllangzh-CNheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0titleCanvas曲线点击高亮示例/titlestylebody{font-family:Arial,sans-serif;display:flex;flex-direction:column;align-items:center;padding:20px;}h1{color:#333;}.container{margin-top:20px;border:1px solid #ddd;padding:10px;border-radius:5px;background-color:#f9f9f9;}canvas{border:1px solid #ccc;background-color:white;}.info{margin-top:15px;font-style:italic;color:#666;}/style/headbodyh1Canvas曲线点击高亮示例/h1p点击任意一条曲线可以高亮显示它/pdivclasscontainercanvasidcurveCanvaswidth600height400/canvas/divdivclassinfoidcurveInfo点击一条曲线查看详细信息/divscriptdocument.addEventListener(DOMContentLoaded,function(){constcanvasdocument.getElementById(curveCanvas);constctxcanvas.getContext(2d);constcurveInfodocument.getElementById(curveInfo);// 存储所有曲线的信息constcurves[{name:曲线1: 蓝色正弦波,color:#3498db,highlightColor:#ff9900,path:createSineWavePath(ctx,50,200,500,150,2)},{name:曲线2: 绿色方波,color:#2ecc71,highlightColor:#27ae60,path:createSquareWavePath(ctx,50,100,500,200)},{name:曲线3: 红色三角波,color:#e74c3c,highlightColor:#c0392b,path:createTriangleWavePath(ctx,50,300,500,200)}];letselectedCurveIndex-1;// 当前选中的曲线索引// 绘制所有曲线functiondrawCurves(){// 清空画布ctx.clearRect(0,0,canvas.width,canvas.height);// 绘制背景网格drawGrid();// 绘制所有曲线curves.forEach((curve,index){if(indexselectedCurveIndex){// 高亮显示选中的曲线ctx.strokeStylecurve.highlightColor;ctx.lineWidth4;}else{// 普通显示其他曲线ctx.strokeStylecurve.color;ctx.lineWidth2;}ctx.beginPath();ctx.moveTo(curve.path[0].x,curve.path[0].y);for(leti1;icurve.path.length;i){ctx.lineTo(curve.path[i].x,curve.path[i].y);}ctx.stroke();});}// 绘制背景网格functiondrawGrid(){ctx.strokeStyle#eee;ctx.lineWidth1;// 垂直线for(letx50;x550;x100){ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,canvas.height);ctx.stroke();}// 水平线for(lety50;y350;y100){ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(canvas.width,y);ctx.stroke();}}// 创建正弦波路径functioncreateSineWavePath(ctx,startX,startY,width,height,cycles){constpath[];constpoints100;for(leti0;ipoints;i){constxstartX(width/points)*i;constystartYMath.sin((i/points)*cycles*Math.PI*2)*height/2;path.push({x,y});}returnpath;}// 创建方波路径functioncreateSquareWavePath(ctx,startX,startY,width,height){constpath[];constsegments10;constsegmentWidthwidth/segments;for(leti0;isegments;i){constxstartXi*segmentWidth;lety;if(i%20){ystartY-height/2;}else{ystartYheight/2;}path.push({x,y});}returnpath;}// 创建三角波路径functioncreateTriangleWavePath(ctx,startX,startY,width,height){constpath[];constsegments10;constsegmentWidthwidth/segments;for(leti0;isegments;i){constxstartXi*segmentWidth;constprogressi/segments;lety;if(progress0.5){ystartY(progress*2-0.5)*height;}else{ystartY(1.5-progress*2)*height;}path.push({x,y});}returnpath;}// 检测点是否在路径上简化版适用于连续曲线functionisPointOnPath(point,path,tolerance5){for(leti0;ipath.length-1;i){constp1path[i];constp2path[i1];// 计算点到线段的距离constdistancepointToSegmentDistance(point,p1,p2);if(distancetolerance){returntrue;}}returnfalse;}// 计算点到线段的距离functionpointToSegmentDistance(point,p1,p2){constApoint.x-p1.x;constBpoint.y-p1.y;constCp2.x-p1.x;constDp2.y-p1.y;constdotA*CB*D;constlen_sqC*CD*D;letparam-1;if(len_sq!0){paramdot/len_sq;}letxx,yy;if(param0){xxp1.x;yyp1.y;}elseif(param1){xxp2.x;yyp2.y;}else{xxp1.xparam*C;yyp1.yparam*D;}constdxpoint.x-xx;constdypoint.y-yy;returnMath.sqrt(dx*dxdy*dy);}// 初始化绘制drawCurves();// 鼠标点击事件处理canvas.addEventListener(click,function(e){constrectcanvas.getBoundingClientRect();constmouseXe.clientX-rect.left;constmouseYe.clientY-rect.top;letfoundfalse;// 检查是否点击了某条曲线for(leti0;icurves.length;i){constpoint{x:mouseX,y:mouseY};if(isPointOnPath(point,curves[i].path)){selectedCurveIndexi;curveInfo.textContent已选择:${curves[i].name};foundtrue;break;}}// 如果没有点击任何曲线取消选择if(!found){selectedCurveIndex-1;curveInfo.textContent点击一条曲线查看详细信息;}// 重新绘制drawCurves();});});/script/body/html代码说明曲线存储:使用数组存储所有曲线信息包括名称、颜色、高亮颜色和路径点每种曲线类型有对应的路径生成函数绘制函数:drawCurves()负责绘制所有曲线根据选中状态应用不同样式drawGrid()绘制背景网格作为参考路径检测:isPointOnPath()检测点是否在路径上简化版适用于连续曲线pointToSegmentDistance()计算点到线段的最短距离交互处理:监听 canvas 的点击事件检测点击位置是否在某条曲线上更新选中状态并重新绘制优化建议性能优化:对于复杂曲线可以减少路径点数量或使用更高效的检测算法可以使用requestAnimationFrame优化重绘功能扩展:添加鼠标悬停效果支持多选曲线添加图例说明支持曲线动态修改精确检测:对于更精确的检测可以考虑使用 Canvas 的isPointInPath()方法但需要为每条曲线重新创建路径对象或者使用第三方库如paper.js或fabric.js提供更高级的交互功能这个实现展示了 Canvas 实现曲线点击高亮的基本方法你可以根据实际需求进一步优化和完善。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2588886.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!