影子《最辛苦的是咱爸》- 学习马老师帖《ThreeJS 直管道》
本帖最后由 杨帆 于 2025-6-19 17:45 编辑 <br /><br /><style>#papa { --size: 15vw; margin: 30px 0; left: calc(50% - 110px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); min-height: 80vh; aspect-ratio: 16/9; background: #333 url('') 0 0/100% 105%; box-shadow: 3px 3px 6px 6px gray; user-select: none; position: relative; overflow: hidden; z-index: 1; }
#dt { position: absolute; width: 100%; height: 100%; top: 0%; left: 0%; mix-blend-mode: screen; z-index: -1; }
#dt img { width: 100%; height: 100%; }
#bt { position: absolute; width: 100%; height: 100%; top: 0%; left: 0%; mix-blend-mode: screen; z-index: -1; }
#bt img { width: 100%; height: 100%; }
#papa>canvas { position: absolute; left: 0; top: 0; right: 0; bottom: 0; display: block; }
#btnFs { left: 2%; bottom: 20px; color: #eee; }
#pa { position: absolute; top: 2%; left: 92%; width: 35%; height: auto; opacity: 0; cursor: pointer; overflow: hidden; z-index: 10; }
#papa:hover #pa { opacity: .8; color: #fff; font-size: 20px; font-family: 华文中宋; filter: drop-shadow(0 0 80px Gold); }
.lrc { position: absolute; top: 42%; left: 5%; width: 540px; height: 250px; overflow: hidden; }
.lrc #ul { width: 100%; padding: 0; list-style: none; transition: 0.3s all ease; margin: 0; }
.lrc #ul li { color: #fff; font-size: 35px; font-family: 华文行楷; transition: .3s all ease; list-style-type: none; text-align: center; display: block; padding: 0 10px; height: 50px; line-height: 50px; margin: 0 auto; text-shadow: 0 0 3px rgba(0, 0, 0, 0.7); }
.lrc #ul li.active { transform: scale(1.2); color: #FFD700; font-weight: 650; text-shadow: 0 0 10px #EE1111; }
#vid2 { width: 100%; height: 100%; position: absolute; top: 0%; left: 0%; object-fit: cover; z-index: -2; opacity: .98; pointer-events: none; }
#nhzer { color: #99ff00; position: absolute; left: 10%; top: 6%; font-size: 40px; font-family: 华文行楷; z-index: 1; animation: yd 20s linear infinite var(--state); filter: drop-shadow(#ffffff 1px 0 0) drop-shadow(#ffffff 0 1px 0) drop-shadow(#ffffff -1px 0 0) drop-shadow(#ffffff 0 -1px 0); }
#nhzer span { transition: color 0.3s ease, text-shadow 0.3s ease; text-shadow: 0 0 5px rgba(0, 255, 255, 0.5); }
@keyframes rot { to { transform: rotate(360deg); } }
@keyframes yd {
0% { opacity: 0.8; left: 10%; }
50% { opacity: 1; left: 60%; }
100% { opacity: 0.8; left: 10%; }
}
</style>
<div id="papa">
<div id="nhzer"></div>
<div id="dt"><img src="https://pic1.imgdb.cn/item/67564aedd0e0a243d4e015f5.gif" id="Img" style="mix-blend-mode: screen"
alt=" " /></div>
<div id="bt"><img src="https://pic1.imgdb.cn/item/684b6ce058cb8da5c848da8b.gif" id="IMG"
style="mix-blend-mode: screen" alt=" " /></div>
<video id="vid2" src="https://cccimg.com/view.php/c5ccfecbbe8ed24c5469ebb96883573c.mp4" loop muted autoplay="">
</video>
<div id="pa" title="播放/暂停">播放/暂停</div>
<div id="dhgc" class="lrc"><ul id="ul"></ul></div>
</div>
<audio id="audio" src="https://cccimg.com/view.php/ee2cec2853c8aa3f0f987e40c793673b.mp3" loop autoplay></audio>
<script type="module">
import * as THREE from 'https://638183.freep.cn/638183/3dev/build/three.module.min.js';
const papa = document.getElementById('papa');
const width = papa.offsetWidth;
const height = papa.offsetHeight;
const scene = new THREE.Scene();
const clock = new THREE.Clock(false);
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(width, height);
papa.appendChild(renderer.domElement);
// 直管道
const path = new THREE.LineCurve3(new THREE.Vector3(-0.35, 0, 0), new THREE.Vector3(0.35, 0, 0));
const geometry = new THREE.TubeGeometry(path, 36, 1.2, 6, false);
const material = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide });
const mesh = new THREE.Mesh(geometry, material);
mesh.rotateZ(Math.PI / 2.2);
mesh.rotateY(Math.PI / 1.01);
mesh.position.set(0, 1.3 ,0);
scene.add(mesh);
// 动画
const animate = () => {
if (clock.running) {
requestAnimationFrame(animate);
const delta = clock.getDelta();
mesh.rotation.y += delta;
renderer.render(scene, camera);
}
};
window.onresize = () => {
const width = papa.offsetWidth;
const height = papa.offsetHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
};
const audio = document.getElementById('audio');
const pa = document.getElementById('pa');
pa.addEventListener('click', () => {
if (audio.paused) {
audio.play();
clock.start();
animate();
} else {
audio.pause();
clock.stop();
}
const videos = document.querySelectorAll('video');
const Img = document.getElementById('Img');
const nhzer = document.getElementById('nhzer');
const IMG = document.getElementById('IMG');
if (audio.paused) {
videos.forEach(v => v.pause());
Img.style.opacity = '0';
IMG.style.opacity = '0';
nhzer.style.setProperty('--state', 'paused');
} else {
videos.forEach(v => v.play());
Img.style.opacity = '0.9';
IMG.style.opacity = '0.9';
nhzer.style.setProperty('--state', 'running');
}
});
audio.addEventListener('play', () => {
clock.start();
animate();
});
audio.addEventListener('pause', () => {
clock.stop();
});
audio.addEventListener('ended', () => {
clock.stop();
});
</script>
<script>
var lrc = `
`;
let lrcArr = lrc.split('\n');
let result = [];
doms = {
audio: document.querySelector("#audio"),
ul: document.querySelector("#ul"),
container: document.querySelector(".lrc")
}
for (let i = 0; i < lrcArr.length; i++) {
let line = lrcArr.trim();
if (!line) continue;
let separatorIndex = line.indexOf(']');
if (separatorIndex === -1) continue;
let timePart = line.substring(1, separatorIndex);
let lyric = line.substring(separatorIndex + 1) || '';
result.push({
time: parseTime(timePart),
word: lyric.trim() || ' '
});
}
function parseTime(lrcTime) {
lrcTimeArr = lrcTime.split(":")
return +lrcTimeArr * 60 + +lrcTimeArr;
}
function getIndex() {
let Time = doms.audio.currentTime;
for (let i = 0; i < result.length; i++) {
if (result.time > Time) {
return i - 1;
}
}
}
function createElements() {
let frag = document.createDocumentFragment();
for (let i = 0; i < result.length; i++) {
let li = document.createElement("li");
li.innerText = result.word;
frag.appendChild(li);
}
doms.ul.appendChild(frag);
}
createElements();
let containerHeight = doms.container.clientHeight;
let liHeight = doms.ul.children.clientHeight;
let minOffset = 0;
let maxOffset = doms.ul.clientHeight - containerHeight;
function setOffset() {
let index = getIndex();
let offset = liHeight * index - containerHeight / 2 + liHeight / 2;
if (offset < minOffset) {
offset = minOffset;
};
if (offset > maxOffset) {
offset = maxOffset;
};
doms.ul.style.transform = `translateY(-${offset}px)`;
let li = doms.ul.querySelector(".active")
if (li) {
li.classList.remove("active");
}
li = doms.ul.children;
if (li) {
li.classList.add("active");
}
};
doms.audio.addEventListener("timeupdate", setOffset);
function createElements() {
let frag = document.createDocumentFragment();
for (let i = 0; i < result.length; i++) {
let li = document.createElement("li");
li.innerText = result.word || ' ';
frag.appendChild(li);
}
doms.ul.appendChild(frag);
}
const audio = doms.audio;
const nhzer = document.getElementById('nhzer');
const message = "最辛苦的是咱爸 - 影子";
const flashSpeed = 150;
const baseColor = "#00ffff";
const highlightColor = "#00ff00";
let currentIndex = 0;
let flashingTimer = null;
const textSpans = [];
function initNeonText() {
nhzer.innerHTML = '';
textSpans.length = 0;
message.split('').forEach((char) => {
const span = document.createElement('span');
span.textContent = char;
span.style.color = baseColor;
textSpans.push(span);
nhzer.appendChild(span);
});
}
function animateNeon() {
textSpans.forEach(span => {
span.style.color = baseColor;
span.style.textShadow = `0 0 5px rgba(0, 255, 255, 0.5)`;
});
if (textSpans) {
textSpans.style.color = highlightColor;
textSpans.style.textShadow = `
0 0 10px ${highlightColor},
0 0 20px ${highlightColor},
0 0 30px ${highlightColor}
`;
}
currentIndex = (currentIndex + 1) % textSpans.length;
}
audio.addEventListener('play', () => {
if (!flashingTimer) {
currentIndex = 0;
animateNeon();
flashingTimer = setInterval(animateNeon, flashSpeed);
nhzer.style.setProperty('--state', 'running');
}
});
audio.addEventListener('pause', () => {
if (flashingTimer) {
clearInterval(flashingTimer);
flashingTimer = null;
}
textSpans.forEach(span => {
span.style.color = baseColor;
span.style.textShadow = `0 0 5px rgba(0, 255, 255, 0.5)`;
});
nhzer.style.setProperty('--state', 'paused');
});
audio.addEventListener('ended', () => {
if (flashingTimer) {
clearInterval(flashingTimer);
flashingTimer = null;
}
currentIndex = 0;
textSpans.forEach(span => {
span.style.color = baseColor;
span.style.textShadow = `0 0 5px rgba(0, 255, 255, 0.5)`;
});
nhzer.style.setProperty('--state', 'paused');
});
initNeonText();
</script>
</body>
</html>
早上问好,欣赏精彩制作,真厉害!{:4_178:} 视频轮播很漂亮,这直管道用得也好。这播放器按钮还是另外设的呢。{:4_187:} 欣赏杨帆好帖{:4_187:} 梦江南 发表于 2025-6-19 07:58
早上问好,欣赏精彩制作,真厉害!
问好江南,谢谢鼓励,祝开心{:4_204:} 本帖最后由 杨帆 于 2025-6-19 21:52 编辑
红影 发表于 2025-6-19 11:01
视频轮播很漂亮,这直管道用得也好。这播放器按钮还是另外设的呢。
呵呵,影子当然欣赏影子了
问好影子,谢谢鼓励,祝开心{:4_204:} 影子唱歌真好。我很早就想听影子唱歌了。 梦油 发表于 2025-6-19 21:21
影子唱歌真好。我很早就想听影子唱歌了。
好呀,欢迎梦油超版多听听,祝开心{:4_191:} 杨帆 发表于 2025-6-19 17:50
呵呵,影子当然欣赏影子了
问好影子,谢谢鼓励,祝开心
呵呵,居然还有这样的重名,也挺开心的{:4_173:} 红影 发表于 2025-6-19 22:05
呵呵,居然还有这样的重名,也挺开心的
对,开心天天是必须滴{:4_187:} 杨帆 发表于 2025-6-19 22:07
对,开心天天是必须滴
谢谢,也祝你时时开心快乐{:4_187:} 红影 发表于 2025-6-19 22:20
谢谢,也祝你时时开心快乐
谢谢!健康是第一,开心是目的{:4_204:} 杨帆 发表于 2025-6-19 22:37
谢谢!健康是第一,开心是目的
其实健康也包含心理健康,而开心就是心理健康的重要课题之一{:4_173:} 红影 发表于 2025-6-20 09:35
其实健康也包含心理健康,而开心就是心理健康的重要课题之一
对,身心健康,开心快乐,丰富体验,淬炼灵魂,光大人生{:4_204:} 杨帆 发表于 2025-6-20 12:11
对,身心健康,开心快乐,丰富体验,淬炼灵魂,光大人生
杨帆说的这些词汇都是正能量的呢{:4_187:}
页:
[1]