无需登录 数据私有 本地保存

鼠标轨迹特效生成 - 跟随粒子或星星

19
0
0
0
移动鼠标查看特效
粒子: 0
圆形
星星
爱心
钻石
雪花
气泡
📚 常见问题与知识点
鼠标轨迹特效(Mouse Trail Effect)是一种网页交互动效,当用户移动鼠标时,在光标经过的路径上生成跟随的粒子、星星或其他图形元素。这些粒子会逐渐消散,创造出绚丽的视觉尾迹。它常用于个人博客、创意网站、游戏界面等场景,能显著提升用户体验和页面趣味性。核心原理是通过JavaScript监听鼠标事件,在Canvas画布上实时绘制并更新粒子状态。
非常简单!点击"生成代码"按钮,复制生成的HTML代码,保存为一个独立的.html文件,或将其中的<canvas>元素和<script>脚本粘贴到您的网页中即可。代码包含完整的粒子系统,无需额外依赖。确保canvas元素覆盖在需要特效的区域上方,并设置合适的z-index。您还可以根据需求调整粒子数量、大小、颜色等参数来匹配网站风格。
合理配置下影响极小。本工具使用Canvas + requestAnimationFrame进行高效渲染,粒子数量上限自动控制在300个以内,且鼠标静止时不产生新粒子(除非开启持续生成)。在移动端建议将粒子数量控制在10以内、大小不超过15px。如果页面本身已经很复杂,可适当降低参数。Canvas的GPU加速特性使其比DOM动画高效得多,是现代浏览器中实现粒子效果的最佳选择。
完全支持!本工具同时监听了mousemove和touchmove事件,在手机和平板等触屏设备上也能正常使用。手指滑动时同样会产生粒子轨迹。移动端还做了特别优化:触摸画布时不会触发页面滚动(使用touch-action:none),确保交互流畅。建议在移动端使用较小的粒子参数以获得最佳体验。
圆形使用Canvas的arc()方法;五角星通过计算5个外顶点和5个内顶点的坐标连线绘制;爱心使用贝塞尔曲线(bezierCurveTo)模拟心形轮廓;钻石使用4个顶点绘制菱形并填充;雪花通过3条交叉直线加分支线条模拟;气泡则是圆形加偏移的高光点。所有形状都支持旋转、缩放和透明度渐变,创造出丰富的视觉效果。
扩散角度控制粒子从鼠标位置飞散的方向范围。360°表示向四面八方散开;180°则只向前方半圆扩散;0°时所有粒子朝同一方向飞出。重力模拟重力加速度对粒子的影响。正值使粒子下落(类似真实物理),负值使粒子上浮(适合气泡效果),0则粒子保持直线运动。这两个参数配合使用可以创造出完全不同的视觉风格。
对于粒子轨迹特效,Canvas是明显更优的选择。Canvas直接操作像素缓冲区,由GPU加速渲染,可轻松处理数百个粒子。而CSS动画每个粒子需要一个DOM元素,大量粒子会导致DOM节点过多、重排重绘开销巨大。此外Canvas支持更复杂的绘制(如渐变、阴影、自定义形状),且粒子状态管理更灵活。本工具生成的代码使用Canvas实现,性能优异。
您可以通过多种方式自定义颜色:①点击预设颜色圆点快速选择;②使用颜色选择器精确调节;③选择"彩虹"模式让每个粒子随机呈现不同色相。在生成的代码中,颜色以十六进制格式(如#fbbf24)存储,您可以修改color变量来更改。彩虹模式使用HSL颜色空间,通过随机色相值实现,代码中对应Math.random()*360的hue值。
发光效果通过Canvas的shadowBlur和shadowColor属性实现。在绘制粒子前设置ctx.shadowBlur = size*3(模糊半径为粒子大小的3倍)和ctx.shadowColor = 粒子颜色,绘制后粒子周围就会出现柔和的光晕。这个技巧利用了Canvas内置的阴影渲染,性能消耗很小但视觉效果显著提升。关闭发光效果可以获得更清爽的扁平风格。
`; return code; } // 事件绑定 wrapper.addEventListener('mousemove', function(e) { const rect = wrapper.getBoundingClientRect(); mouseX = e.clientX - rect.left; mouseY = e.clientY - rect.top; mouseOnCanvas = true; if (hintVisible) { hint.style.opacity = '0'; setTimeout(() => { if (hintVisible) hint.style.display = 'none'; }, 500); hintVisible = false; } spawnParticle(mouseX, mouseY); }); wrapper.addEventListener('mouseenter', function() { mouseOnCanvas = true; }); wrapper.addEventListener('mouseleave', function() { mouseOnCanvas = false; mouseX = -100; mouseY = -100; continuousTimer = 0; }); wrapper.addEventListener('touchmove', function(e) { e.preventDefault(); const rect = wrapper.getBoundingClientRect(); const touch = e.touches[0]; mouseX = touch.clientX - rect.left; mouseY = touch.clientY - rect.top; mouseOnCanvas = true; if (hintVisible) { hint.style.opacity = '0'; setTimeout(() => { if (hintVisible) hint.style.display = 'none'; }, 500); hintVisible = false; } spawnParticle(mouseX, mouseY); }, { passive: false }); wrapper.addEventListener('touchend', function() { mouseOnCanvas = false; continuousTimer = 0; }); wrapper.addEventListener('click', function(e) { if (config.clickBurst) { const rect = wrapper.getBoundingClientRect(); const cx = e.clientX - rect.left; const cy = e.clientY - rect.top; burstParticles(cx, cy); } }); // 形状选择 tool.find('.shape-btn').on('click', function() { tool.find('.shape-btn').removeClass('active-shape'); $(this).addClass('active-shape'); config.shape = $(this).data('shape'); tool.find('.preset-btns .btn').removeClass('active-preset'); }); // 颜色点选择 tool.find('.color-dot').on('click', function() { tool.find('.color-dot').removeClass('active-color'); $(this).addClass('active-color'); const c = $(this).data('color'); if (c === 'rainbow') { config.colorMode = 'rainbow'; } else { config.colorMode = 'single'; config.color = c; $('#customColor').val(c); } tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#customColor').on('input', function() { config.colorMode = 'single'; config.color = $(this).val(); tool.find('.color-dot').removeClass('active-color'); tool.find('.preset-btns .btn').removeClass('active-preset'); }); // 预设按钮 tool.find('.preset-btns .btn').on('click', function() { const preset = $(this).data('preset'); applyPreset(preset); }); // 参数滑块 $('#particleCount').on('input', function() { config.particleCount = parseInt($(this).val()); updateValLabels(); tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#particleSize').on('input', function() { config.particleSize = parseInt($(this).val()); updateValLabels(); tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#particleSpeed').on('input', function() { config.speed = parseFloat($(this).val()); updateValLabels(); tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#particleLife').on('input', function() { config.life = parseFloat($(this).val()); updateValLabels(); tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#gravity').on('input', function() { config.gravity = parseFloat($(this).val()); updateValLabels(); tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#spreadAngle').on('input', function() { config.spreadAngle = parseInt($(this).val()); updateValLabels(); tool.find('.preset-btns .btn').removeClass('active-preset'); }); $('#clickBurst').on('change', function() { config.clickBurst = $(this).is(':checked'); }); $('#continuousGen').on('change', function() { config.continuousGen = $(this).is(':checked'); continuousTimer = 0; }); $('#glowEffect').on('change', function() { config.glowEffect = $(this).is(':checked'); tool.find('.preset-btns .btn').removeClass('active-preset'); }); // 按钮 $('#btnReset').on('click', function() { applyPreset('starry'); $('#codeArea').slideUp(250); }); $('#btnGenerateCode').on('click', function() { const code = generateCode(); $('#codeBlock').text(code); $('#codeArea').slideDown(300); $('html, body').animate({ scrollTop: $('#codeArea').offset().top - 80 }, 400); }); $('#btnCopyCode').on('click', function() { const code = $('#codeBlock').text(); if (navigator.clipboard) { navigator.clipboard.writeText(code).then(() => { const btn = $('#btnCopyCode'); btn.html('已复制!'); btn.removeClass('btn-success').addClass('btn-info'); setTimeout(() => { btn.html('一键复制'); btn.removeClass('btn-info').addClass('btn-success'); }, 1800); }); } else { const ta = document.createElement('textarea'); ta.value = code; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); document.body.removeChild(ta); const btn = $('#btnCopyCode'); btn.html('已复制!'); btn.removeClass('btn-success').addClass('btn-info'); setTimeout(() => { btn.html('一键复制'); btn.removeClass('btn-info').addClass('btn-success'); }, 1800); } }); $('#btnClearCanvas').on('click', function() { particles = []; ctx.clearRect(0, 0, canvas.width, canvas.height); counter.textContent = '粒子: 0'; hint.style.display = 'block'; hint.style.opacity = '1'; hintVisible = true; }); // 窗口大小调整 $(window).on('resize', function() { resizeCanvas(); }); // FAQ折叠 - 使用bootstrap自带collapse,无需额外代码 // 初始化 resizeCanvas(); updateValLabels(); animId = requestAnimationFrame(loop); // 初始显示提示 hint.style.opacity = '1'; hint.style.display = 'block'; });