如何使用jQuery实现鼠标悬停时连接Div的Stroke从0到100%的绘制动画
实现Div连接线条的悬停绘制动画
要实现鼠标悬停元素时,连接线条从0%逐步绘制到100%的效果,我们可以通过两种方案来实现:一种基于你现有的div线条结构调整,另一种是改用SVG线条(更适合任意方向的线条动画)。
方案1:基于现有Div线条的动画实现
如果希望保留当前的div线条结构,可以通过伪元素和CSS过渡来模拟绘制效果:
1. 调整CSS样式
先给线条设置基础样式,用伪元素作为动画载体:
.line { position: absolute; background: transparent; /* 移除原有背景,用伪元素实现线条 */ overflow: hidden; } /* 水平线条动画 */ .line::before { content: ''; position: absolute; top: 0; left: 0; width: 0; height: 100%; background: #000; /* 线条颜色 */ transition: width 0.6s ease; /* 动画时长和缓动效果 */ } /* 垂直线条动画 */ .line.vertical::before { width: 100%; height: 0; transition: height 0.6s ease; } /* 悬停触发动画 */ .line.hovered::before { width: 100%; } .line.vertical.hovered::before { height: 100%; }
2. 完善JS逻辑
在adjustLine函数中,判断线条方向并添加对应类,同时绑定悬停事件:
function adjustLine(from, to, line) { if (from.length === 0 || to.length === 0 || line.length === 0) { return; } const fromRect = from[0].getBoundingClientRect(); const toRect = to[0].getBoundingClientRect(); // 计算线条位置、尺寸,判断方向 let top, left, width, height, isVertical = false; if (Math.abs(toRect.left - fromRect.left) > Math.abs(toRect.top - fromRect.top)) { // 水平线条 left = fromRect.right; width = toRect.left - fromRect.right; top = fromRect.top + fromRect.height / 2; height = 2; line.removeClass('vertical'); } else { // 垂直线条 top = fromRect.bottom; height = toRect.top - fromRect.bottom; left = fromRect.left + fromRect.width / 2; width = 2; line.addClass('vertical'); isVertical = true; } line.css({ top: `${top}px`, left: `${left}px`, width: `${width}px`, height: `${height}px` }); } // 绑定悬停事件 $('.mydiv').hover(function() { const lineId = $(this).find('.indeximg').data('line'); $('#' + lineId).addClass('hovered'); }, function() { const lineId = $(this).find('.indeximg').data('line'); $('#' + lineId).removeClass('hovered'); }); // 初始化线条 function loop() { adjustLine($('#div1'), $('.canvas-box'), $('#line1')); adjustLine($('#div2'), $('.canvas-box'), $('#line2')); adjustLine($('#div3'), $('.canvas-box'), $('#line3')); adjustLine($('#div4'), $('.canvas-box'), $('#line4')); adjustLine($('#div5'), $('.canvas-box'), $('#line5')); adjustLine($('#div6'), $('.canvas-box'), $('#line6')); } loop(); window.addEventListener('resize', loop);
方案2:改用SVG线条(推荐,支持任意方向)
SVG的stroke-dasharray和stroke-dashoffset属性是实现路径绘制动画的标准方案,能完美支持斜向线条:
1. 替换HTML中的Div线条为SVG
<div id="content"> <!-- 保留你的div1-div6结构不变 --> </div> <svg class="lines-container" viewBox="0 0 1200 800" preserveAspectRatio="none"> <line id="lineArticle08" stroke="#000" stroke-width="2" /> <line id="lineArticle02" stroke="#000" stroke-width="2" /> <line id="lineArticle03" stroke="#000" stroke-width="2" /> <line id="lineArticle09" stroke="#000" stroke-width="2" /> <line id="lineArticle10" stroke="#000" stroke-width="2" /> <line id="lineArticle01" stroke="#000" stroke-width="2" /> </svg>
2. 设置SVG动画CSS
.lines-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; /* 不干扰下方元素的交互 */ } .lines-container line { fill: none; stroke-dasharray: 0; stroke-dashoffset: 0; transition: stroke-dashoffset 0.6s ease; } .lines-container line.hovered { stroke-dashoffset: 0; }
3. 调整JS逻辑计算线条路径
function adjustLine(from, to, line) { if (from.length === 0 || to.length === 0 || line.length === 0) { return; } const fromRect = from[0].getBoundingClientRect(); const svgRect = document.querySelector('.lines-container').getBoundingClientRect(); // 转换坐标到SVG坐标系 const x1 = fromRect.left - svgRect.left + fromRect.width / 2; const y1 = fromRect.top - svgRect.top + fromRect.height / 2; const x2 = to[0].getBoundingClientRect().left - svgRect.left + to[0].getBoundingClientRect().width / 2; const y2 = to[0].getBoundingClientRect().top - svgRect.top + to[0].getBoundingClientRect().height / 2; // 设置线条端点 line.attr({ x1: x1, y1: y1, x2: x2, y2: y2 }); // 计算线条长度,设置dash参数 const lineLength = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); line.attr({ 'stroke-dasharray': lineLength, 'stroke-dashoffset': lineLength }); } // 绑定悬停事件 $('.mydiv').hover(function() { const lineId = $(this).find('.indeximg').data('line'); $('#' + lineId).addClass('hovered'); }, function() { const lineId = $(this).find('.indeximg').data('line'); $('#' + lineId).removeClass('hovered'); }); // 初始化和窗口resize时更新线条 function loop() { adjustLine($('#div1'), $('.canvas-box'), $('#lineArticle08')); adjustLine($('#div2'), $('.canvas-box'), $('#lineArticle02')); adjustLine($('#div3'), $('.canvas-box'), $('#lineArticle03')); adjustLine($('#div4'), $('.canvas-box'), $('#lineArticle09')); adjustLine($('#div5'), $('.canvas-box'), $('#lineArticle10')); adjustLine($('#div6'), $('.canvas-box'), $('#lineArticle01')); } loop(); window.addEventListener('resize', loop);
关键提示
- 方案2的SVG方式更灵活,支持任意角度的线条动画,推荐使用;方案1适合仅水平/垂直线条的场景。
- 可以通过修改CSS中的
0.6s调整动画时长,ease可以换成linear实现匀速动画。 - 确保SVG或div线条的
z-index设置正确,避免被其他元素遮挡。
内容的提问来源于stack exchange,提问作者ambaamba
相关产品推荐
相关产品推荐

