如何实现SVG中单个岩石元素的随机淡入淡出闪烁动画?
实现单个岩石元素随机淡入淡出的闪烁效果
首先得提醒你:如果你的SVG是作为background-image引用的,浏览器通常不会运行其内部的动画逻辑。所以要实现单个岩石的独立闪烁,我们需要调整SVG的使用方式,结合CSS或JavaScript来实现。下面给你两种可行的方案:
方案1:内联SVG + CSS动画(原始SVG内的岩石单独随机)
这个方案适合让你原始SVG里的每个岩石分组独立闪烁,平铺后同一组的岩石会同步动画。
步骤1:重构SVG结构,给每个岩石分组
把SVG中属于同一个岩石的所有<path>包裹到单独的<g>标签里,添加统一类名(比如.rock-shard),并给每个分组设置随机延迟的CSS变量:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="384px" height="384px" viewBox="0 0 200 200" xml:space="preserve"> <!-- 第一个岩石分组 --> <g class="rock-shard" style="--random-delay: 0.2s;"> <path d="M61.639,162.195c0.483-0.863,0.887-1.493,1.114-1.659l-0.859,0.215C61.757,161.203,61.694,161.695,61.639,162.195z"/> <path d="M62.753,160.536l0.141-0.035C62.86,160.477,62.812,160.493,62.753,160.536z"/> </g> <!-- 第二个岩石分组 --> <g class="rock-shard" style="--random-delay: 1.5s;"> <path d="M53.959,179.342c-2.256,3.034-3.331,7.56-4.521,10.83C50.734,186.206,53.188,183.417,53.959,179.342z"/> <path d="M53.959,179.342c0.363-0.488,0.754-0.942,1.184-1.342l-1,0.25C54.104,178.631,54.027,178.984,53.959,179.342z"/> </g> <!-- 剩余岩石分组同理,每个设置不同的--random-delay值 --> <g class="rock-shard" style="--random-delay: 0.7s;"> <path d="M159.644,110l2-4c-2.467,3.473-4.598,7.94-5.592,11.998C157.587,115.744,158.907,112.613,159.644,110z"/> </g> </svg>
步骤2:用SVG Pattern实现平铺,添加动画CSS
我们可以把上述SVG定义为一个Pattern,让它自动平铺到整个容器,同时保留每个岩石的动画:
<div class="rock"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"> <defs> <pattern id="rock-pattern" x="0" y="0" width="384" height="384" patternUnits="userSpaceOnUse"> <!-- 放入上面的所有.rock-shard分组 --> <g class="rock-shard" style="--random-delay: 0.2s;">...</g> <g class="rock-shard" style="--random-delay: 1.5s;">...</g> </pattern> </defs> <rect width="100%" height="100%" fill="url(#rock-pattern)" /> </svg> </div>
然后添加CSS动画:
.rock { width: 100%; height: 200vh; position: relative; } .rock svg { position: absolute; z-index: -1; top: 0; left: 0; width: 100%; height: 100%; /* 保留你原来的mask效果 */ -webkit-mask-image: linear-gradient(transparent 0%, #fff 10%, #fff 90%, transparent 100%); mask-image: linear-gradient(transparent 0%, #fff 10%, #fff 90%, transparent 100%); } .rock-shard { animation: flicker 2.5s ease-in-out infinite; animation-delay: var(--random-delay); /* 给每个岩石设置不同的动画时长,增加随机性 */ animation-duration: calc(2s + var(--random-duration)); } /* 手动给每个分组设置随机时长变量 */ .rock-shard:nth-child(1) { --random-duration: 0.5s; } .rock-shard:nth-child(2) { --random-duration: 1.2s; } .rock-shard:nth-child(3) { --random-duration: 0.8s; } @keyframes flicker { 0%, 100% { opacity: 1; } 30%, 70% { opacity: 0.4; } /* 可以调整淡入淡出的幅度和时机 */ }
方案2:JavaScript动态生成独立岩石(完全随机闪烁)
如果希望每个平铺的岩石实例都完全独立闪烁(而非重复组同步),可以用JS动态生成多个岩石元素,每个设置随机的位置和动画参数:
步骤1:准备单个岩石的模板
<template id="rock-template"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="192px" height="192px"> <!-- 单个岩石的path --> <path d="M61.639,162.195c0.483-0.863,0.887-1.493,1.114-1.659l-0.859,0.215C61.757,161.203,61.694,161.695,61.639,162.195z"/> <path d="M62.753,160.536l0.141-0.035C62.86,160.477,62.812,160.493,62.753,160.536z"/> </svg> </template> <div class="rock"></div>
步骤2:用JS生成随机岩石
const rockContainer = document.querySelector('.rock'); const rockTemplate = document.querySelector('#rock-template'); const containerWidth = rockContainer.offsetWidth; const containerHeight = rockContainer.offsetHeight; const rockSize = 192; // 单个岩石的尺寸 // 计算需要生成的岩石数量 const rows = Math.ceil(containerHeight / rockSize); const cols = Math.ceil(containerWidth / rockSize); for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { const rockClone = document.importNode(rockTemplate.content, true); const rockEl = rockClone.querySelector('svg'); // 设置随机位置(轻微偏移避免完全对齐) const x = j * rockSize + Math.random() * 20 - 10; const y = i * rockSize + Math.random() * 20 - 10; rockEl.style.position = 'absolute'; rockEl.style.top = `${y}px`; rockEl.style.left = `${x}px`; // 设置随机动画参数 const randomDelay = Math.random() * 3; const randomDuration = 2 + Math.random() * 2; const randomOpacity = 0.3 + Math.random() * 0.5; rockEl.style.animation = `flicker ${randomDuration}s ease-in-out infinite`; rockEl.style.animationDelay = `${randomDelay}s`; rockEl.style.setProperty('--flicker-opacity', randomOpacity); rockContainer.appendChild(rockEl); } }
步骤3:添加对应的CSS
.rock { width: 100%; height: 200vh; position: relative; overflow: hidden; -webkit-mask-image: linear-gradient(transparent 0%, #fff 10%, #fff 90%, transparent 100%); mask-image: linear-gradient(transparent 0%, #fff 10%, #fff 90%, transparent 100%); } @keyframes flicker { 0%, 100% { opacity: 1; } 50% { opacity: var(--flicker-opacity); } }
这种方案下,每个岩石都是独立的DOM元素,拥有完全随机的动画延迟、时长和淡入程度,视觉效果更自然随机。
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

