亚伦影音工作室 发表于 3 天前

岁月如笔写春秋(女版)

本帖最后由 亚伦影音工作室 于 2026-6-6 12:23 编辑 <br /><br /><style>
@import url("https://fonts.googleapis.com/css2?family=Liu+Jian+Mao+Cao&family=Long+Cang&family=Ma+Shan+Zheng&family=ZCOOL+KuaiLe&family=ZCOOL+QingKe+HuangYou&display=swap");
    #papa { margin: 0 0 0 calc(50% - 680px); width: 1186px; height:620px; background: #000000; overflow: hidden; display: grid; place-items: center; box-shadow: 0px 0px 0px gray; position: relative; z-index: 1; --state: paused; }

#dh{ width: 100%; height: 100%; position: absolute;
z-index: 1;
top:0px; left:0px;animation: rod 8s linear infinite var(--state);}
@keyframes rod{0% {opacity: 0.3;filter:hue-rotate(60deg);}
50% {opacity:1 ;}
100% {opacity: 0.3;}
}
#source{width: 100% ;}
main {z-index: 2;
position: relative;
overflow: hidden;
width: 100%;
min-height: 100%;
perspective: 340px;
}


/* star field */
#stars {
position: absolute;
top: 50%;
left: 50%;
width: 2px;
height: 2px;border-radius: 50%;
box-shadow: -238px 108px #f7f7f7, 193px -376px #f7f7f7, -1264px -60px #fff,
    145px -443px #c9c9c9, -1440px 37px #f7f7f7, 262px -136px #cfcfcf,
    212px 219px #e3e3e3, 319px 223px #c7c7c7, 1246px -51px #c9c9c9,
    308px 126px #e0e0e0, 147px 229px #e6e6e6, -1041px 450px #d1d1d1,
    671px 86px white, -921px 234px #f0f0f0, -957px 242px #e8e8e8,
    1249px -285px #d1d1d1, 741px 434px #d9d9d9, -1030px 330px #ededed,
    311px -475px #fff, -413px -105px #d4d4d4, 868px -435px #f7f7f7,
    -790px 289px #dbdbdb, 202px 427px #fcfcfc, -22px -158px #c9c9c9,
    -1294px -297px #cccccc, -63px 200px #f0f0f0, -592px -86px #f7f7f7,
    -732px 366px white, -1426px -262px #e8e8e8, 475px -400px #c9c9c9,
    -1442px -153px #f7f7f7, 1124px -219px #ededed, 701px 257px #f0f0f0,
    36px -179px #ebebeb, -937px 480px #f7f7f7, -267px -418px #f2f2f2,
    1467px 127px #cfcfcf, -1128px 274px #d1d1d1, -180px 430px #e0e0e0,
    624px 275px #fafafa, -473px 150px #e6e6e6, -537px -348px #d4d4d4,
    410px 455px #ebebeb, 497px -129px #cccccc, 416px -370px whitesmoke,
    977px 82px #c2c2c2, 1209px -222px #f0f0f0, 637px 360px #fcfcfc,
    -1049px 409px white, 959px 407px #c9c9c9, -1153px -168px #dedede,
    -437px -216px #dbdbdb, -572px 420px #fcfcfc, -228px 78px #dbdbdb,
    -925px 452px #cccccc, 244px 30px #c4c4c4, 453px -336px #dedede,
    993px -63px #c2c2c2, 670px -343px #d9d9d9, -1088px 344px #fcfcfc,
    -170px -153px #c4c4c4, 987px -208px #d1d1d1, 596px 166px #fcfcfc,
    -1362px -28px #c4c4c4, 1291px -106px #e3e3e3, -1128px 169px #ededed,
    1056px 367px #ebebeb, 261px -128px #cccccc, 1017px 401px #cccccc,
    1381px 245px #e3e3e3, 536px -113px #fafafa, -92px -217px #e3e3e3,
    1481px 268px #d1d1d1, 832px -345px #cccccc, -863px 138px #f0f0f0,
    -997px -412px #e3e3e3, -330px -260px #d9d9d9, 691px -39px #fcfcfc,
    -468px -135px #d6d6d6, -535px 405px #e8e8e8, -1289px -284px #e3e3e3,
    823px -225px #cccccc, -1172px -348px white, 505px -319px #ededed,
    94px -45px #ededed, -687px -64px #c7c7c7, -1133px -456px #f2f2f2,
    1357px 135px #e0e0e0, -919px -249px whitesmoke, 206px 32px white,
    1453px -338px #cccccc, -764px 83px #e8e8e8, 726px 85px #fafafa,
    205px 103px #e3e3e3, 85px 116px #d1d1d1, 1104px -121px #f0f0f0,
    649px -304px #dbdbdb, -313px 313px whitesmoke, 491px -419px #c9c9c9,
    -1405px 397px #cfcfcf, 30px -81px #e6e6e6;
animation: fly 3s linear infinite var(--state);
transform-style: preserve-3d;
}
#stars:before,
#stars:after {
content: "";
position: absolute;
width: inherit;
height: inherit;
box-shadow: inherit;
}
#stars:before {
transform: translateZ(-300px);
animation: fade1 3s linear infinite var(--state);
}
#stars:after {
transform: translateZ(-600px);
animation: fade2 3s linear infinite var(--state);
}
@keyframes fly {
from {
    transform: translateZ(0px);
}
to {
    transform: translateZ(300px);
}
}
@keyframes fade1 {
from {
    opacity: 0.5;
}
to {
    opacity: 1;
}
}
@keyframes fade2 {
from {
    opacity: 0;
}
to {
    opacity: 0.5;
}
}

.mplayer { position: absolute; width: 300px; height: fit-content; display: flex; flex-direction: column; align-items: center; gap: 10px; color: #eee; margin: auto; top: 90%; left:64%;z-index: 20; }
    .mplayer::before { position: absolute; content: attr(data-time); width: 100%; text-align-last: justify; pointer-events: none; }
    .btnPlay { width: 20px; height: 20px; cursor: pointer; position: relative; }
    .btnPlay::after { position: absolute; content: ''; width: 100%; height: 100%; background: #eee; clip-path: var(--clip); }
    .progress { --prg: 0%; position: relative; width: 100%; height: 20px; display: grid; place-items: center start; background: linear-gradient(90deg, red var(--prg), gray var(--prg), gray 0) no-repeat center/100% 2px; padding: 0; margin: 0; }
    .thumb { position: absolute; left: calc(var(--prg) - 10px); width: 10px; height: 10px; background: red; border: 1px solid #FF0000; border-radius: 50%; cursor: pointer; box-sizing: border-box; }
    .play { --clip: polygon(10% 0,100% 50%,10% 100%); }
    .pause { --clip: polygon(35% 0,15% 0,15% 100%, 35% 100%,35% 0,75% 0,75% 100%,55% 100%,55% 0); }

.lrc {position:absolute;width: 600px; height: 400px;
   z-index: 3; left:3%;
   border: 0px solid white;
    overflow: hidden;margin: 6px;
}

.lrc #ul {width: 100%;filter:drop-shadow(#000 1px 0 0)drop-shadow(#000 0 1px 0)drop-shadow(#000 -1px 0 0) drop-shadow(#000 0 -1px0);
padding: 0;list-style: none;transition: 0.3s all ease;
    margin: 0}
.lrc #ul li {
   cursor: pointer;
font-family: "ZCOOL QingKe HuangYou","华文行楷","SimHei", "Arial", "sans-serif";
    font-size: 25px;
    color: #fff;
    font-weight: 100;
    transition: .3s all ease;
    list-style-type: none;
    text-align: center;display: block;
    width: 100%;
    margin: 0 auto;
    height: 50px;
    line-height: 35px;
}
.lrc #ulli.active{   font-size: 35px;
    color: #ff0000;
text-align: center;text-align: center; animation: fadeIn 0.5sforwards linear infinite var(--state);   }

@keyframes fadeIn {0% {filter: hue-rotate(360deg)brightness(580%)contrast(200%); }}

</style>
<div id="papa">
<div id="dh"><img   id="source" src="https://pic1.imgdb.cn/item/6a224c386cb4776548547bc8.gif"></div>
<main>
<div id="stars"></div>
</main>
    <div class="mplayer" data-time="00:00 00:00">
        <div class="btnPlay play"></div>
        <div class="progress">
                <div class="thumb"></div>
        </div>
</div>
<div class="lrc">
      <ul id="ul">
      </ul>
    </div>

    <audio id="audio"autoplay loop controlslist="nodownload">
            <source src="https://upfile.mp3.wf/view.php/15d364a8adc087b75fd725aab7249c5e.mp3" type="audio/mpeg">
         </audio>

</div>
<script>
//获取需要操作的元素标识
const mplayer = document.querySelector('.mplayer');
const btnPlay = document.querySelector('.btnPlay');
const progress = document.querySelector('.progress');
const thumb = document.querySelector('.thumb');
const audio = document.querySelector('audio');
// 拖曳操作状态(初始值为假)
let isDraggable = false;

//时间格式化工具函数 :秒转分秒 mm:ss 格式
const formatTime = (seconds) => {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
};

// 联动函数 mState :处理按钮形状
const mState = () => {
        btnPlay.className = `btnPlay ${['pause', 'play'][+audio.paused]}`;
};

// 获取设备指针所在点在进度条上的距离(百分比)
const getPercent = (e) => {
        const rect = progress.getBoundingClientRect();
        const left = rect.left;
        const width = rect.width;
        let x = e.clientX ?? e.touches?.?.clientX ?? e.changedTouches?.?.clientX;
        x = Math.min(width, Math.max(0, x - left));
        return x / width * 100;
};

// 滑块鼠标按下、触屏设备手指或触笔按下
thumb.onmousedown = thumb.ontouchstart = (e) => {
        isDraggable = true; // 拖曳状态进行中
        e.preventDefault(); // 阻止默认行为
};

// 文档指针松开、触屏设备手指或触笔弹开
document.onmouseup = document.ontouchend = (e) => {
    // 松开时若拖曳状态为真,驱动 audio 改变播放进度
        if (isDraggable) audio.currentTime = `${getPercent(e) * audio.duration / 100}`;
        isDraggable = false; //然后拖曳状态为假
};

// 文档上指针或手指、触笔移动时
document.onmousemove = document.ontouchmove = (e) => {
        if (!isDraggable) return; // 若不是拖曳状态则忽略之
        // 反之,若处于拖曳状态,给CSS变量 --prg 赋值
        progress.style.setProperty('--prg', `${getPercent(e)}%`);
        // 给时间文本信息即mplayer伪元素 attr(data-time) 函数赋值
        mplayer.dataset.time = `${formatTime(audio.duration * getPercent(e) / 100)} ${formatTime(audio.duration)}`;
};

// 进度条点击事件
progress.onclick = (e) => audio.currentTime = `${getPercent(e) * audio.duration / 100}`;

// 音频标签开始播放和暂停时执行联动函数
audio.onplaying = audio.onpause = () => mState();

// 音频时间更新事件 :驱动文本时间信息及进度条进度变更
audio.ontimeupdate = () => {
        if (isDraggable) return; // 拖曳操作发生时忽略
        mplayer.dataset.time = `${formatTime(audio.currentTime)} ${formatTime(audio.duration)}`;
        progress.style.setProperty('--prg', `${audio.currentTime / audio.duration * 100}%`);
};

// 按钮单击 :播放、暂停状态切换
btnPlay.onclick = () => audio.paused ? audio.play() : audio.pause();

(function() {letmState = () => papa.style.setProperty('--state', audio.paused ? 'paused' : 'running');
audio.addEventListener('playing',mState,false);
audio.addEventListener('pause',mState,false);
})();
</script>
<script>
(function() {
var lrc = `爱上音画
岁月如笔写春秋(女版)
作词:日月同辉
作曲:欧阳尚尚
演唱:河南三妹
出品:亚伦影音工作室
岁月如笔写春秋
一生知己最难求
相逢本是百年修
缘聚今生不可丢
时光似酒酿温柔
心事诉与明月收
若问情根深几许
朝朝暮暮共白头
我珍惜一路 真心的相逢
感恩命运的温柔
愿余生常相伴不负这份宿命
我眷恋时光 沉淀的安宁
憧憬偕老的约定
若有来世重逢 再续未了情
岁月如笔写春秋
一生知己最难求
相逢本是百年修
缘聚今生不可丢
时光似酒酿温柔
心事诉与明月收
若问情根深几许
朝朝暮暮共白头
我珍惜一路 真心的相逢
感恩命运的温柔
愿余生常相伴不负这份宿命
我眷恋时光 沉淀的安宁
憧憬偕老的约定
若有来世重逢 再续未了情
我珍惜一路 真心的相逢
感恩命运的温柔
愿余生常相伴不负这份宿命
我眷恋时光 沉淀的安宁
憧憬偕老的约定
若有来世重逢 再续未了情
歌词整理:亚伦`;

let lrcArr = lrc.split('\n');
      let result = [];
      var audio = document.querySelector("#audio");
      var ul = document.querySelector("#ul");
      var container = document.querySelector(".lrc");

      for (let i = 0; i < lrcArr.length; i++) {
            var lrcData = lrcArr.split(']');
            if (lrcData.length < 2) continue;
            var lrcTime = lrcData.substring(1);
            var obj = {
                time: parseTime(lrcTime),
                word: lrcData.trim()
            }
            result.push(obj);
      }

      function parseTime(lrcTime) {
            let lrcTimeArr = lrcTime.split(":");
            return +lrcTimeArr * 60 + parseFloat(lrcTimeArr);
      }

      function getIndex() {
            let time = audio.currentTime;
            for (let i = 0; i < result.length; i++) {
                if (result.time > time) {
                  return i - 1;
                }
            }
            return result.length - 1;
      }

function randomColor(){
    const colors = ['#ff0000','#00ff00','#ff0000','#7fff00','#1e90ff','#ff8800','#fff000'];
    return colors;
}


   function createElements() {
            let fragment = document.createDocumentFragment();

            for (let i = 0; i < result.length; i++) {
                let li = document.createElement("li");
                li.innerText = result.word;
li.style.color = randomColor();
                li.addEventListener("click", function () {
                  audio.currentTime = result.time;
                  setOffset();
                });

                fragment.appendChild(li);
            }

            ul.appendChild(fragment);
      }
      createElements();
      let containerHeight = container.clientHeight;
      let liHeight = ul.children?.clientHeight || 50;
      let minOffset = 0;
      let maxOffset = ul.clientHeight - containerHeight;

      function setOffset() {
            const index = getIndex();
            if (index < 0) return;

            const liHeight = ul.children?.clientHeight || 50;
            let offset = liHeight * index - containerHeight / 3 + liHeight / 2;

            offset = Math.max(minOffset, Math.min(offset, maxOffset));

            ul.style.transform = `translateY(${-offset}px)`;

            ul.querySelectorAll('.active').forEach(li => li.classList.remove('active'));
            if (index < ul.children.length) {
                ul.children.classList.add('active');
            }
      }

      audio.addEventListener("timeupdate", setOffset);
})();
</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;
      }
    });
btnPlay.addEventListener('click', function () {
      if (paused) {
            paused = false;
            renderImage(canvas.nextResult);
      } else {
          paused = true;
      }
    });
};
   renderGif(source);
</script>



醉美水芙蓉 发表于 3 天前

欣赏亚伦老师精彩音画!

醉美水芙蓉 发表于 3 天前

谢谢老师精彩分享!

醉美水芙蓉 发表于 3 天前

老师这个动图做得漂亮!

klxf 发表于 前天 11:51

漂亮~谢谢亚伦老师精彩分享
页: [1]
查看完整版本: 岁月如笔写春秋(女版)