马黑黑老师《这个图案以前用svgdr画过》
<div class="hEdiv" data-prev="1"><pre class="hEpre"><style>
/* svg id选择器可以定义使用的部分属性(fill、stroke-*等) */
#msvg { display: block; margin: auto; fill: none; stroke: steelblue; stroke-width: 6; stroke-linecap: round; stroke-linejoin: round; }
/* 外层图案(齿轮)样式 */
.path{ stroke-dasharray: var(--len); stroke-dashoffset: var(--len); animation: draw linear 6s var(--delay) forwards; --delay: 4s; }
/* 里层图案(圆)样式 */
.cc { animation: grow linear 4s forwards; }
/* 描边动画 */
@keyframes draw { to { stroke-dashoffset: 0; } }
/* 圆变大动画 */
@keyframes grow { to { r: 120; } }
</style>
<svg id="msvg" width="600" height="600" viewBox="-200 -200 400 400" xmlns="http://www.w3.org/2000/svg"></svg>
<script>
loadJs('https://638183.freep.cn/638183/svgdr/svgdr.min.js', tzRun);
function tzRun() {
var dr = _dr(msvg);
const vertex1 = dr.circlePoints(26, 200, 180); // 外切圆1点坐标
const vertex2 = dr.circlePoints(26, 200, 160); // 外切圆2点坐标
// 拼接路径
let path = 'M';
for (let i = 0; i < vertex1.length; i++) {
const v1 = vertex1.join(',');
const v2 = vertex2.join(',');
path += i % 2 === 0 ? v1 + ' ' + v2 + ' ' : v2 + ' ' + v1 + ' ';
};
path += 'Z'; // 路径闭环
dr.path(path).set('class', 'path'); // 绘制路径
dr.elm.style.setProperty('--len', dr.elm.getTotalLength()); // 设置--len变量
dr.circle(0, 0, 0).set('class', 'cc'); // 画圆
}
function loadJs(url, callback) {
var script = document.createElement('script');
script.charset = 'utf-8';
script.src = url;
script.onload = function() {
if (callback) callback();
};
document.head.appendChild(script);
}
</script>
</pre></div>
<script type="module">
import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
const divs = document.querySelectorAll('.hEdiv');
const pres = document.querySelectorAll('.hEpre');
divs.forEach((div,idx) => hl.hl(div, pres));
</script>
<div class="t_fsz">
<table cellspacing="0" cellpadding="0"><tr><td class="t_f" id="postmessage_2592315">
path 路径通过两个外切圆获取各 26 个圆周上的点坐标,这些点按照预设规则连线成为闭合路径,最终的路径数据如下:<br />
<div class="blockcode"><div id="code_oaA"><ol><li>M180.00,0.00 160.00,0.00 155.35,38.29 174.77,43.08 159.38,83.65 141.67,74.36 119.76,106.10 134.73,119.36 102.25,148.14 90.89,131.68 56.74,149.60 63.83,168.30 21.70,178.69 19.29,158.83 -19.29,158.83 -21.70,178.69 -63.83,168.30 -56.74,149.60 -90.89,131.68 -102.25,148.14 -134.73,119.36 -119.76,106.10 -141.67,74.36 -159.38,83.65 -174.77,43.08 -155.35,38.29 -160.00,0.00 -180.00,0.00 -174.77,-43.08 -155.35,-38.29 -141.67,-74.36 -159.38,-83.65 -134.73,-119.36 -119.76,-106.10 -90.89,-131.68 -102.25,-148.14 -63.83,-168.30 -56.74,-149.60 -19.29,-158.83 -21.70,-178.69 21.70,-178.69 19.29,-158.83 56.74,-149.60 63.83,-168.30 102.25,-148.14 90.89,-131.68 119.76,-106.10 134.73,-119.36 159.38,-83.65 141.67,-74.36 155.35,-38.29 174.77,-43.08 Z</ol></div><em onclick="copycode($('code_oaA'));">复制代码</em></div><br />
</td></tr></table>
<div class="t_fsz">
<table cellspacing="0" cellpadding="0"><tr><td class="t_f" id="postmessage_2592316">
图案中,圆从小到大的动画,是通过改变圆的半径而得,半径从 0 长到 120。<br />
<br />
在CSS中,圆的半径属性 r 得到原生支持,所以可以使用 @keyframes 关键帧动画选择器基于圆的半径设置动画<br />
</td></tr></table> <div class="blockcode"><div id="code_Cva"><ol><li><style>
<li> @import 'https://638183.freep.cn/638183/web/tz/tz.v4.css';
<li>
<li>
<li> .pa {
<li> --offsetX: 0px;
<li> --bg: url('https://ff.xiaoqiaodali.top:5401/i/2026/06/21/6a36d4571ca23.gif') no-repeat center/cover;
<li> --ma-size: 12%;
<li> width: 450px;
<li> height: 800px;
<li> position: relative;
<li> overflow: hidden;
<li> }
<li>
<li> .pa *, .pa *::before, .pa *::after {
<li> content: none !important;
<li> }
<li>
<li>
<li> #custom-lrc-container {
<li> position: absolute;
<li> top: 50px; /* 定位显示的位置*/
<li> right: 30px;
<li> width: 2em; /* 宽高与横排时反过来*/
<li> height: 80%;
<li> writing-mode: vertical-rl; /* 设为竖排 */
<li> z-index: 9999;
<li> pointer-events: none;
<li> }
<li>
<li>
<li> .lrc-line {
<li> position: absolute;
<li> left: 50%;
<li> transform: translateX(-50%);
<li> white-space: nowrap;
<li> color: #fefefe;
<li> color:darkgreen;
<li> font-size: 20px;
<li> font-family: "隶书", "LiSu", serif;
<li> font-weight: normal;
<li> text-shadow: 0 0 12px rgba(0,0,0,0.8);
<li> opacity: 0;
<li> transition: opacity 0.5s ease, transform 0.5s ease;
<li> margin: 0;
<li> top: 0;
<li> }
<li>
<li> .lrc-line.active {
<li> opacity: 1;
<li> transform: translateX(-50%) scale(1.15);
<li> z-index: 10;
<li> }
<li>
<li>
<li> @media (max-aspect-ratio: 9/16) {
<li> .pa {
<li> width: 100vw;
<li> height: calc(100vw * 16 / 9);
<li> }
<li> }
<li>
<li> @media (min-aspect-ratio: 9/16) {
<li> .pa {
<li> width: calc(100vh * 9 / 16);
<li> height: 100vh;
<li> }
<li> }
<li></style>
<li>
<li><div class="pa">
<li> <div id="custom-lrc-container"></div>
<li></div>
<li>
<li><script type="module">
<li> import TZ from 'https://638183.freep.cn/638183/web/tz/tz.v4.js';
<li>
<li> const tz = TZ.TZ('pa');
<li>
<li> tz.add('audio', '', '', { src: 'https://imgimg.qqdsw8.cn/view.php/915c88832e0049c6bd78acf0744ba633.mp3' });
<li> tz.add('video', '', 'pd-vid', {src: 'https://imgimg.qqdsw8.cn/view.php/2ec28ce2bc8f195e7a531771c6e8ff41.mp4'}).style('opacity: 0.5;');
<li>
<li> //
<li> tz.add('img', '', 'ma', {
<li> src: 'https://pic1.imgdb.cn/item/6a36c2802830ce602a508060.gif'
<li> })
<li> .style('right: 10px; bottom: 400px;')
<li> .playmp3();
<li>
<li> //
<li> tz.bgprog().style('bottom: 50%; color: #fefefe; width: 80%; ')
<li> tz.fs().style('left: 40px; top: 40px;');
<li> const lrcString = `
<li>曾醉
<li>作词:五子
<li>作曲:Winky诗
<li>演唱:HITA
<li>山深问桃花染过几度春
<li>哪一枝勾住过客衣上风尘
<li>有倦意三分
<li>要行路千程
<li>怎记这山水静默待离人
<li>轻舟邀斜月听岸上孤筝
<li>回旋处恰趁醉踏青石前门
<li>有余音两声
<li>共与你微醺
<li>融入这一夜长灯落满身
<li>曾画下山间桃花流水逐云
<li>跌破了一晌贪梦了无痕
<li>倚泉浣笔重逢或偶遇洗不净
<li>点墨片心留在归梦时分
<li>斟满浮生在酒中浮与沉
<li>哪一口填满岁月旧日余温
<li>有醉意三分
<li>都酿做前尘
<li>梦醒后又在何处扮离人
<li>红梅邀斜月听墙里孤筝
<li>回旋处不是你惯唱的游吟
<li>似乡音两声
<li>唱今雪纷纷
<li>错看成那年桃花落满身
<li>曾见你山间走马落日长云
<li>踏破了一声珍重无处闻
<li>敛花做酒
<li>相送或独酌都太冷清
<li>待到如今那池春水已平
<li>用醉眼看不清擦肩人
<li>酒醒后分不清假与真
<li>行遍天涯旧约难记存
<li>分岔太多归路不可寻
<li>曾画下山间桃花流水逐云
<li>跌破了一晌贪梦何处寻
<li>倚泉浣笔
<li>重逢或偶遇洗不净
<li>点墨片心留在归梦时分
<li>曾见你山间走马落日长云
<li>踏破了一声珍重了无痕
<li>敛花做酒
<li>相送或独酌都太冷清
<li>待到如今那池春水已平`;
<li>
<li> function initCustomLrc(lrcText) {
<li> const container = document.getElementById('custom-lrc-container');
<li> const lines = [];
<li>
<li> const lineRegex = /\[(\d{2}):(\d{2})\.(\d{2,3})\](.*)/;
<li> const rawLines = lrcText.split('\n');
<li>
<li> rawLines.forEach(text => {
<li> const match = text.match(lineRegex);
<li> if (match) {
<li> const minutes = parseInt(match);
<li> const seconds = parseInt(match);
<li> const milliseconds = parseInt(match);
<li> const time = minutes * 60 + seconds + milliseconds / 1000;
<li> let content = match.trim();
<li>
<li>
<li> content = content.replace(/&#\d+;/g, '').trim();
<li>
<li> if (content) {
<li> lines.push({ time, content, element: null });
<li> }
<li> }
<li> });
<li>
<li> lines.forEach((line) => {
<li> const div = document.createElement('div');
<li> div.className = 'lrc-line';
<li> div.textContent = line.content;
<li> container.appendChild(div);
<li> line.element = div;
<li> });
<li>
<li> const audio = document.querySelector('.pa audio');
<li>
<li> if (audio) {
<li> audio.addEventListener('timeupdate', () => {
<li> const currentTime = audio.currentTime;
<li> let activeIndex = -1;
<li>
<li> for (let i = 0; i < lines.length; i++) {
<li> if (currentTime >= lines.time) {
<li> activeIndex = i;
<li> } else {
<li> break;
<li> }
<li> }
<li>
<li> lines.forEach((line, idx) => {
<li> if (idx === activeIndex) {
<li> line.element.classList.add('active');
<li> } else {
<li> line.element.classList.remove('active');
<li> }
<li> });
<li> });
<li>
<li> audio.addEventListener('ended', () => {
<li> lines.forEach(line => line.element.classList.remove('active'));
<li> });
<li> }
<li> }
<li>
<li> setTimeout(() => {
<li> const audioEl = document.querySelector('.pa audio');
<li> if(audioEl) {
<li> initCustomLrc(lrcString);
<li> } else {
<li> const observer = new MutationObserver(() => {
<li> const aud = document.querySelector('.pa audio');
<li> if(aud) {
<li> initCustomLrc(lrcString);
<li> observer.disconnect();
<li> }
<li> });
<li> observer.observe(document.querySelector('.pa'), { childList: true, subtree: true });
<li> }
<li> }, 500);
<li> let prog = document.querySelector('.prog');
<li> prog.style.transform = 'rotate(-90deg)';
<li> prog.style.cssText += 'left:300px;top:250px;color:brown;';
<li>
<li></script></ol></div><em onclick="copycode($('code_Cva'));">复制代码</em></div>
-->
<div style="width:521px;height:921px;background:url(https://ff.xiaoqiaodali.top:5401/i/2026/06/21/6a36d4571ca23.gif);overflow:hidden;border-radius:24px;box-shadow:4px 4px 10px black;position:relative;margin:auto;">
<progress min='0' max='100' value='35'
style="width:80%;transform:rotate(-90deg);position:absolute;left:57%;top:25%" ></progress>
<div style="width:2em;height:80%;position:absolute;top:5%;writing-mode:vertical-rl;color:red;font-size:2em;left:83%">LRC歌词</div>
<img src="https://pic1.imgdb.cn/item/6a36c2802830ce602a508060.gif" style="width:75px;position:absolute;top:50%;right:5px;" />
</div></td></tr></table>
本帖最后由 klxf 于 2026-6-22 23:20 编辑 <br /><br />漂亮~谢谢分享,祝开心
klxf 发表于 2026-6-22 14:01
本帖最后由 klxf 于 2026-6-22 21:57 编辑 漂亮~谢谢分享,祝开心
谢谢友友光临!
页:
[1]