独家动图切换且控制每帧【欢迎提供高清gif动图】
本帖最后由 亚伦影音工作室 于 2026-5-9 16:05 编辑 <br /><br /><style>@import url("https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap");#mydiv {
margin: 0px -300px;
display: grid;
width: 1186px;
height: 640px;
background-color: #333;
overflow: hidden;
position: relative;
z-index: 1;--state: running;
}
.slide {z-index: 1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 1;
}
.slide img{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;object-fit: cover; pointer-events: none;
display: block;
}
#overlay {
position: absolute;
top: -60px;
left: 0;
width: 100%;
height: calc(100% + 80px);
object-fit: cover;
mix-blend-mode: overlay;
opacity: 0.0;
z-index: 50;
pointer-events: none;
}
.block-effect-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
display: grid;
transition: opacity 0.3s linear ;
}
.dissolve-wrapper {
grid-template-columns: repeat(30, 1fr);
grid-template-rows: repeat(20, 1fr);
}
.pixelate-wrapper {
grid-template-columns: repeat(40, 1fr);
grid-template-rows: repeat(30, 1fr);
}
.mosaic-wrapper {
grid-template-columns: repeat(15, 1fr);
grid-template-rows: repeat(10, 1fr);
}
.block-piece {
background-color: #006400;
transition: all 1.2s cubic-bezier(0.2, 0.8, 0.2, 1);
opacity: 0.6; border-radius: 2%;
transform: scale(1);box-shadow: 0px 0px 0px 2px #ffffff;
}
.shatter-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
perspective: 1500px;
}
.shatter-piece {
position: absolute;
background: url(https://pic1.imgdb.cn/item/67f11e350ba3d5a1d7edcf6e.png) no-repeat center/200% 250%;
transition: transform 14s cubic-bezier(0.1, 0.9, 0.3, 1.2), opacity 10s ease ;
opacity: 1;
transform-origin: center center;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#xiaobo {z-index: 100;
width: 350px;
height: 220px;cursor: pointer;
margin: 120px 20px;
position: absolute;
overflow: hidden;
}
.hexahedron {width: 210px;border: 2px solid #555;
height: 210px;
margin: 0px 0px;
position: relative;
background:url(https://pic1.imgdb.cn/item/69f6d4a598d7db9e97813aeb.png)no-repeat -120px 0px/cover;
border-radius: 12px;mask: radial-gradient(circle at 98% 50%,transparent 40px,#red 0%);-webkit-mask: radial-gradient(circle at 98% 50%,transparent 40px,red 0%); }
#cp { position: relative; top: 0px; left: 0px;width: 200px; height: 200px;transition: 6s;animation:opentop 0.5s linear 1s ;background:repeating-radial-gradient(#000, #000 8px, #444 9px);border-radius: 50%;box-shadow:0px 0px 0px 1px #aaa,0px 0px 0px 4px #555;}
.overlay {z-index: 1;
content: '';
left: 0px;
top: 0px;
position: absolute;
width: 200px;
height: 200px;
background: linear-gradient(-45deg, transparent, 35%, rgba(224,255,255,0.35),65%,transparent);
border-radius: 50%;
}
.inner {z-index: 2;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 70px;
height: 70px;
box-shadow:0px 0px 0px 1px #333,0px 0px 0px 2px #aaa;
background:#5a4532 url()no-repeat center/cover;
border-radius: 50%;
}
.inner::after {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 6px;
height: 6px;
background: #aa2;
border-radius: 50%;
}
#all {position: absolute;width:200px; height:200px;top: 7px; left: 110px;z-index: -1; transition: 2s; animation:tion3s linear 1.5s infinite}
@keyframes opentop { 0% {transform: translatex(-50px);} 100% { transform:rotateX(0px);}}
@keyframes tion { 0% {} 100% { transform:rotate(360deg) } }
#smsvg{ z-index: 10;position: relative;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
#lrc {z-index: 12;
--state: paused;
--motion: cover2;
--tt: 2s;
--bg: linear-gradient(90deg,#e56420, #c22525, #3d9c31, #37bbde, #000080,#ff0000) ;
position: absolute;z-index: 6;
left: 50%;
transform: translate(-50%);
top: 86%;
font:normal 3em "Ma Shan Zheng","SimHei", "Arial", "sans-serif";
color: #000;
filter:drop-shadow(#FFFFFF 1px 0 0)drop-shadow(#FFFFFF 0 1px 0)drop-shadow(#FFFFFF -1px 0 0) drop-shadow(#FFFFFF 0 -1px0);
}
#lrc::before {
position: absolute;
content: attr(data-lrc);
width: 20%;
height: 100%;
color: transparent;
overflow: hidden;
white-space: pre;
background: var(--bg);
-webkit-background-clip: text;
animation: var(--motion) var(--tt) linear forwards;
animation-play-state: var(--state);
}
@keyframes cover1{0% { width: 0%;}100% { width: 100%;}}
@keyframes cover2 { 0% { width: 0%;}100% { width: 100%;}}
</style>
<div id="mydiv">
<div class="slide">
<img id="source1" src="https://pic1.imgdb.cn/item/6829aba658cb8da5c8fb0908.gif">
</div>
<div class="slide">
<img id="source2" src="https://pic1.imgdb.cn/item/69e5a07201316fbabf2ca12b.gif">
</div>
<div class="slide">
<img id="source3" src="https://pic1.imgdb.cn/item/69e5906a01316fbabf2c8137.gif">
</div>
<div class="slide">
<img id="source4" src="https://pic1.imgdb.cn/item/69e58edb01316fbabf2c80a0.gif">
</div>
<div class="slide">
<img id="source5" src="https://pic1.imgdb.cn/item/69dc42dcd93192251ec66328.gif">
</div>
<div class="slide">
<img id="source6" src="https://pic1.imgdb.cn/item/69f82ce1b681ce9bfd1dce63.gif">
</div>
<audio id="aud" src="https://s2.cldisk.com/sv-w9/audio/a3/bc/69/def4138af0f53fc9bb3e774c4fc083e3/audio.mp3"loopautoplay ></audio>
<div id="xiaobo">
<div class="hexahedron"></div>
<div id="all">
<divid="cp" ><div class="inner"><svgid="smsvg"width="200px" height="200px">
<defs>
<path id="path" d="M0 100 A100 100 0 1 1 200 100 A100 100 0 1 1 0 100"/>
</defs>
<text dx="77" dy="77" font-size="12" fill="#00ff00"font-family="'楷体'">
<textPath href="#path" textLength="535"> 花潮论坛 亚伦影音工作室 </textPath>
</text>
</svg>
</div> <div class="overlay"></div>
</div>
</div>
</div>
<div id="lrc" data-lrc=""></div>
</div>
<script>
let mState = () => {xiaobo.style.setProperty('--state', aud.paused ?'paused' : 'running');};
xiaobo.onclick = () =>aud.paused ? (all.style.left = '110px',all.style.animationPlayState = 'running'):(all.style.left = '30px',all.style.animationPlayState = 'paused');
</script>
<script>
let currentIndex = 0;
const slides = document.querySelectorAll('.slide');
const totalSlides = slides.length;
let timer;
let effectIndex = 0;
const effects = [
{func: applyDissolveEffect},
{func: applyMosaicEffect},
{func: applyShatterEffect},
{func: applyPixelateEffect}
];
function createWrapper(className) {
const wrapper = document.createElement('div');
wrapper.className = className;
return wrapper;
}
function createBlockPiece() {
const piece = document.createElement('div');
piece.className = 'block-piece';
return piece;
}
function init() {
const firstSlide = slides;
effects.func(firstSlide);
effectIndex = (effectIndex + 1) % effects.length;
startTimer();
}
function clearEffects() {
const containers = document.querySelectorAll(
'.block-effect-wrapper, .shatter-wrapper'
);
containers.forEach(container => container.remove());
slides.forEach(slide => {
slide.style.opacity = '0';
});
}
function showNext() {if(!aud.paused){
clearEffects();
currentIndex = (currentIndex + 1) % totalSlides;
const currentEffect = effects;
effectIndex = (effectIndex + 1) % effects.length;
const targetSlide = slides;
currentEffect.func(targetSlide);
resetTimer();
}
}
function applyDissolveEffect(slide) {
slide.style.opacity = '1';
const wrapper = createWrapper('block-effect-wrapper dissolve-wrapper');
slide.appendChild(wrapper);
const totalPieces = 30 * 20;
for(let i = 0; i < totalPieces; i++) {
const piece = createBlockPiece();
piece.style.transitionDelay = `${0.1 + Math.random() * 0.9}s`;
wrapper.appendChild(piece);
}
setTimeout(() => {
wrapper.querySelectorAll('.block-piece').forEach(piece => {
piece.style.opacity = '0';
piece.style.transform = 'scale(0.8)';
});
}, 100);
}
function applyMosaicEffect(slide) {
slide.style.opacity = '1';
const wrapper = createWrapper('block-effect-wrapper mosaic-wrapper');
slide.appendChild(wrapper);
const totalPieces = 15 * 10;
for(let i = 0; i < totalPieces; i++) {
const piece = createBlockPiece();
const row = Math.floor(i / 15);
const col = i % 15;
piece.style.transitionDelay = `${(row + col) * 0.05}s`;
wrapper.appendChild(piece);
}
setTimeout(() => {
wrapper.querySelectorAll('.block-piece').forEach(piece => {
piece.style.transform = 'scale(0)';
piece.style.opacity = '0';
});
}, 100);
}
function applyShatterEffect(slide) {
slide.style.opacity = '1';
const wrapper = createWrapper('shatter-wrapper');
slide.appendChild(wrapper);
const pieceCount = 80;
const containerWidth = 1186;
const containerHeight = 680;
for(let i = 0; i < pieceCount; i++) {
const piece = document.createElement('div');
piece.className = 'shatter-piece';
const pieceWidth = 40 + Math.random() * 130;
const pieceHeight = 40 + Math.random() * 130;
const x = Math.min(Math.random() * containerWidth, containerWidth - pieceWidth);
const y = Math.min(Math.random() * containerHeight, containerHeight - pieceHeight);
piece.style.width = `${pieceWidth}px`;
piece.style.height = `${pieceHeight}px`;
piece.style.left = `${x}px`;
piece.style.top = `${y}px`;
piece.style.transitionDelay = `${Math.random() * 0.8}s`;
wrapper.appendChild(piece);
}
setTimeout(() => {
wrapper.querySelectorAll('.shatter-piece').forEach(piece => {
const angle = Math.random() * Math.PI * 2;
const distance = 500 + Math.random() * 500;
const x = Math.cos(angle) * distance;
const y = Math.sin(angle) * distance;
const rotateZ = Math.random() * 720 - 360;
piece.style.transform = `translate3d(${x}px, ${y}px, 300px) rotateZ(${rotateZ}deg)`;
piece.style.opacity = '0';
});
}, 100);
}
function applyPixelateEffect(slide) {
slide.style.opacity = '1';
const wrapper = createWrapper('block-effect-wrapper pixelate-wrapper');
slide.appendChild(wrapper);
const totalPieces = 40 * 30;
for(let i = 0; i < totalPieces; i++) {
const piece = createBlockPiece();
const row = Math.floor(i / 40);
const col = i % 40;
piece.style.transitionDelay = `${(row * 0.02) + (col * 0.01)}s`;
wrapper.appendChild(piece);
}
setTimeout(() => {
wrapper.querySelectorAll('.block-piece').forEach(piece => {
const dirs = ['translateX(-50%)', 'translateX(50%)', 'translateY(-50%)', 'translateY(50%)'];
piece.style.transform = dirs;
piece.style.opacity = '0';
});
}, 100);
}
function startTimer() {
timer = setInterval(showNext, 4000);
}
function resetTimer() {
clearInterval(timer);
startTimer();
}
window.onload = init;
</script>
<script >
(function() {
letlrcStr=`放慢脚步 听一听耳边的风
制作人:亚伦
词:吴忧 曲:吴忧
出品方:亚伦影音
出品人:亚伦
代码独家设计:亚伦
【未经著作权人许可不得翻唱翻录或使用】
放慢脚步 听一听耳边的风
半生光阴 轻的就像一场梦
不争不求 也不问人海匆匆
只想贪恋 此刻眼底的晴空
推开门窗 迎一抹夕阳的红
就让喧嚣 都留在烟雨之中
几分淡泊 换来一路的从容
烟火人间 且行且望且随风
就让岁月开成一朵花
人生啊又何处不芳华
任凭光阴流转
年轮又添笔画
爱在时光中轻轻发芽
就让岁月开成一朵花
等一场春风温柔抵达
带着知足上路
带着晚霞回家
爱在时光中轻轻发芽
推开门窗 迎一抹夕阳的红
就让喧嚣 都留在烟雨之中
几分淡泊 换来一路的从容
烟火人间 且行且望且随风
就让岁月开成一朵花
人生啊又何处不芳华
任凭光阴流转
年轮又添笔画
爱在时光中轻轻发芽
就让岁月开成一朵花
等一场春风温柔抵达
带着知足上路
带着晚霞回家
爱在时光中轻轻发芽
爱在时光中轻轻发芽
`;
/*变量 :mKey - 当前歌词索引;mFlag :调用关键帧动画索引;averAdd :平均值补偿*/
let mKey = 0, mFlag = true, averAdd = 0.3;
/*函数 :获取每句歌词用时,歌词用时若超过平均值则取平均值,最后一句歌词则取平均值*/
let lrcTime = (ar) => {
let tmpAr = [];
for(j = 0; j <ar.length - 1; j ++) {
if(j !== ar.length - 1) tmpAr = parseFloat((ar - ar).toFixed(1));
}
let aver = parseInt(tmpAr.reduce((a,b) => a + b) / (tmpAr.length - 1)) + averAdd;
tmpAr.push(aver);
tmpAr.forEach((item,key) => {
ar = item > aver ? aver : item;
});
return ar;
};
/*函数 :从原始lrc歌词获取信息并存入 n*3 数组*/
let getLrcAr = (text) => {
let lrcAr = [];
let calcRule = ;
for(x of text.split('\n')) {
let ar = [];
let re = /\d+[\.:]\d+([\.:]\d+)?/g;
let geci = x.replace(re,'');
if(geci) {
geci = geci.replace(/[\[\]\'\"\t,]s?/g,'');
let time = x.match(re);
if(time != null) {
for(y of time) {
let tmp = y.match(/\d+/g);
let sec = 0;
for(z in tmp) sec += tmp * calcRule;
ar = ;
lrcAr.push(ar);
}
}
}
}
lrcAr.sort((a,b)=> a - b);
return(lrcTime(lrcAr));
};
/*函数 :模拟显示同步歌词*/
let showLrc = (time) => {
let name = mFlag ? 'cover1' : 'cover2';
lrc.innerHTML = lrcAr;
lrc.dataset.lrc = lrcAr;
lrc.style.setProperty('--motion', name);
lrc.style.setProperty('--tt', time + 's');
lrc.style.setProperty('--state', 'running');
mKey += 1;
mFlag = !mFlag;
};
/*函数 :处理当前歌词索引 mKey*/
let calcKey = () => {
for (j = 0; j < lrcAr.length; j++) {
if (aud.currentTime <= lrcAr) {
mKey = j - 1;
break;
}
}
if (mKey < 0) mKey = 0;
if (mKey > lrcAr.length - 1) mKey = lrcAr.length - 1;
let time = lrcAr - (aud.currentTime - lrcAr);
showLrc(time);
};
/*格式化时间信息*/
let toMin = (val) => {
if (!val) return '00:00';
val = Math.floor(val);
let min = parseInt(val / 60),
sec = parseFloat(val % 60);
if (min < 10) min = '0' + min;
if (sec < 10) sec = '0' + sec;
return min + ':' + sec;
}
/*函数 :关键帧动画状态切换*/
let mState = () => aud.paused ? (lrc.style.setProperty('--state','paused')) : (lrc.style.setProperty('--state','running'));
/*监听播放进度*/
aud.addEventListener('timeupdate', () => {
for (j = 0; j < lrcAr.length; j++) {
if (aud.currentTime >= lrcAr) {
cKey = j;
if (mKey === j) showLrc(lrcAr);
else continue;
}
}
});
aud.addEventListener('pause', () => mState());/*监听暂停事件*/
aud.addEventListener('play', () => mState());/*监听播放事件*/
aud.addEventListener('seeked', () => calcKey());/*监听查询事件*/
let lrcAr = getLrcAr(lrcStr); /*获得歌词数组*/
})();
</script>
<script>
const renderGif = function (dom) {
if (!dom || !dom.src) {
return;
}
// gif图片的url地址
const src = dom.src;
// 创建的用来播放gif的canvas元素
const canvas = document.createElement('canvas');
const context = canvas.getContext("2d");
// 一些与GIF播放有关的变量
let imageDecoder = null;
let imageIndex = 0;
let paused = false;
// 绘制方法
const renderImage = function (result) {
context.drawImage(result.image, 0, 0);
const track = imageDecoder.tracks.selectedTrack;
// 如果播放结束,从头开始循环
if (imageDecoder.complete) {
if (track.frameCount === 1) {
return;
}
if (imageIndex + 1 >= track.frameCount) {
imageIndex = 0;
}
}
// 绘制下一帧内容
imageDecoder
.decode({ frameIndex: ++imageIndex })
.then((nextResult) => {
if (paused === false) {
setTimeout(() => {
renderImage(nextResult);
}, result.image.duration / 1200.0);
} else {
canvas.nextResult = nextResult;
}
})
.catch((e) => {
// imageIndex可能超出的容错处理
if (e instanceof RangeError) {
imageIndex = 0;
imageDecoder.decode({ frameIndex: imageIndex }).then(renderImage);
} else {
throw e;
}
});
};
// 判断地址能够请求
fetch(src).then((response) => {
// 可以请求,进行样式处理
// 设置canvas尺寸
canvas.width = dom.naturalWidth;
canvas.height = dom.naturalHeight;
// 实际显示尺寸
canvas.style.width = dom.clientWidth + 'px';
canvas.style.height = dom.clientHeight + 'px';
// 隐藏图片,显示画布
dom.after(canvas);
dom.style.position = 'absolute';
dom.style.opacity = '0';
// 将GIF绘制在canvas上
imageDecoder = new ImageDecoder({
data: response.body,
type: "image/gif"
});
// 解析第一帧并绘制
imageDecoder.decode({
frameIndex: imageIndex
}).then(renderImage);
});
// 事件绑定处理
dom.addEventListener('ended',function () {
if (paused) {
paused = false;
renderImage(canvas.nextResult);
} else {aud.pause();
paused = true;
}
});
canvas.addEventListener('ended',function () {
if (paused) {
paused = false;
renderImage(canvas.nextResult);
} else {
paused = true;
}
});
xiaobo.addEventListener('click', function () {
if (paused) {aud.play();
paused = false;
renderImage(canvas.nextResult);
} else {aud.pause();
paused = true;
}
});
};
renderGif(source1);renderGif(source2);renderGif(source3);renderGif(source4);renderGif(source5);renderGif(source6);
</script>
经典探索,精彩示范,精致效果,祝亚伦老师节日快乐{:4_176:} 的确是可以逐帧控制动图呢,还能切换动图。
欣赏亚伦老师好帖{:4_199:} 欣赏佳作,问候亚伦。
页:
[1]