袖舞江南(测试新模式单图循环滚动)
本帖最后由 马黑黑 于 2024-4-5 20:47 编辑 <br /><br /><style>#mydiv {
margin: 0 0 0 calc(50% - 563.5px);
width: 965px;
height: 500px;
background: #d3f0f5;
box-shadow: 4px 4px 8px gray;
overflow: hidden;
z-index: 1;
position: relative;
--begin1: 0px;
--begin2: 960px;
}
#mydiv::before , #mydiv::after {
position: absolute;
content: '';
inset: 0;
background: url('https://638183.freep.cn/638183/t24/webp/xwjn.webp') no-repeat;
z-index: -2;
}
#mydiv::before {
background-position: var(--begin1) 0;
}
#mydiv::after {
transform: scale(-1, 1);
background-position: var(--begin2) 0;
}
#play {
position: absolute;
left: calc(50% - 50px);
bottom: 10px;
width: 100px;
cursor: pointer;
animation: rotating 5s linear infinite var(--state);
}
@keyframes rotating { to { transform: rotate(360deg); } }
</style>
<div id="mydiv">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=472005796" autoplay></audio>
<img id="play" src="https://638183.freep.cn/638183/web/svg/clover4.svg" alt="" />
</div>
<script>
var ww = mydiv.offsetWidth;
var step = 1, begin1 = 0, begin2 = ww, raf = null;
play.onclick = () => aud.paused ? aud.play() : aud.pause();
aud.onpause = aud.onplaying = () => mState();
aud.onended = () => { aud.play(); cancelAnimationFrame(raf); }
aud.onseeked = () => cancelAnimationFrame(raf);
var moving = () => {
begin1 -= step;
if(begin1 <= -ww) begin1 = ww;
begin2 = begin1 >= 0 ? -1 * (begin1 - ww + 1) : begin2 = -1 * (begin1 + ww - 1) ;
mydiv.style.setProperty('--begin1', begin1 + 'px');
mydiv.style.setProperty('--begin2', begin2 + 'px');
aud.paused ? cancelAnimationFrame(raf) : raf = requestAnimationFrame(moving);
};
var mState = () => {
aud.paused
? (mydiv.style.setProperty('--state', 'paused'), cancelAnimationFrame(raf))
: (mydiv.style.setProperty('--state', 'running'), raf = requestAnimationFrame(moving));
};
</script>
<style>
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>
<h2>代码</h2>
<div class='mum'>
<cl-cd data-idx="1"><<span class="tDarkRed">style</span>></cl-cd>
<cl-cd data-idx="2">#mydiv {</cl-cd>
<cl-cd data-idx="3"> <span class="tBlue">margin:</span> 0 0 0 calc(50% - 563.5px);</cl-cd>
<cl-cd data-idx="4"> <span class="tBlue">width:</span> 965px;</cl-cd>
<cl-cd data-idx="5"> <span class="tBlue">height:</span> 500px;</cl-cd>
<cl-cd data-idx="6"> <span class="tBlue">background:</span> #d3f0f5;</cl-cd>
<cl-cd data-idx="7"> <span class="tBlue">box-shadow:</span> 4px 4px 8px gray;</cl-cd>
<cl-cd data-idx="8"> <span class="tBlue">overflow:</span> hidden;</cl-cd>
<cl-cd data-idx="9"> <span class="tBlue">z-index:</span> 1;</cl-cd>
<cl-cd data-idx="10"> <span class="tBlue">position:</span> relative;</cl-cd>
<cl-cd data-idx="11"> --begin1: 0px;</cl-cd>
<cl-cd data-idx="12"> --begin2: 960px;</cl-cd>
<cl-cd data-idx="13">}</cl-cd>
<cl-cd data-idx="14">#mydiv::before , #mydiv::after {</cl-cd>
<cl-cd data-idx="15"> <span class="tBlue">position:</span> absolute;</cl-cd>
<cl-cd data-idx="16"> <span class="tBlue">content:</span> <span class="tMagenta">''</span>;</cl-cd>
<cl-cd data-idx="17"> <span class="tBlue">inset:</span> 0;</cl-cd>
<cl-cd data-idx="18"> <span class="tBlue">background:</span> url(<span class="tMagenta">'https://638183.freep.cn/638183/t24/webp/xwjn.webp'</span>) no-repeat;</cl-cd>
<cl-cd data-idx="19"> <span class="tBlue">z-index:</span> -2;</cl-cd>
<cl-cd data-idx="20">}</cl-cd>
<cl-cd data-idx="21">#mydiv::before {</cl-cd>
<cl-cd data-idx="22"> <span class="tBlue">background-position:</span> <span class="tBlue">var</span>(--begin1) 0;</cl-cd>
<cl-cd data-idx="23">}</cl-cd>
<cl-cd data-idx="24"> </cl-cd>
<cl-cd data-idx="25">#mydiv::after {</cl-cd>
<cl-cd data-idx="26"> <span class="tBlue">transform:</span> scale(-1, 1);</cl-cd>
<cl-cd data-idx="27"> <span class="tGreen">/* begin2的值当为 -1*(begin1 + 960px) */</span></cl-cd>
<cl-cd data-idx="28"> <span class="tBlue">background-position:</span> <span class="tBlue">var</span>(--begin2) 0;</cl-cd>
<cl-cd data-idx="29">}</cl-cd>
<cl-cd data-idx="30">#play {</cl-cd>
<cl-cd data-idx="31"> <span class="tBlue">position:</span> absolute;</cl-cd>
<cl-cd data-idx="32"> <span class="tBlue">left:</span> calc(50% - 50px);</cl-cd>
<cl-cd data-idx="33"> <span class="tBlue">bottom:</span> 10px;</cl-cd>
<cl-cd data-idx="34"> <span class="tBlue">width:</span> 100px;</cl-cd>
<cl-cd data-idx="35"> <span class="tBlue">cursor:</span> pointer;</cl-cd>
<cl-cd data-idx="36"> <span class="tBlue">animation:</span> rotating 5s linear infinite <span class="tBlue">var</span>(--state);</cl-cd>
<cl-cd data-idx="37">}</cl-cd>
<cl-cd data-idx="38">@keyframes rotating { to { <span class="tBlue">transform:</span> rotate(360deg); } }</cl-cd>
<cl-cd data-idx="39"><<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="40"> </cl-cd>
<cl-cd data-idx="41"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"mydiv"</span>></cl-cd>
<cl-cd data-idx="42"> <<span class="tDarkRed">audio</span> <span class="tRed">id</span>=<span class="tMagenta">"aud"</span> src=<span class="tMagenta">"https://music.163.com/song/media/outer/url?<span class="tRed">id</span>=472005796"</span> autoplay><<span class="tDarkRed">/audio</span>></cl-cd>
<cl-cd data-idx="43"> <<span class="tDarkRed">img</span> <span class="tRed">id</span>=<span class="tMagenta">"play"</span> src=<span class="tMagenta">"https://638183.freep.cn/638183/web/svg/clover4.svg"</span> alt=<span class="tMagenta">""</span> /></cl-cd>
<cl-cd data-idx="44"><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="45"> </cl-cd>
<cl-cd data-idx="46"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="47"> </cl-cd>
<cl-cd data-idx="48"><span class="tBlue">var</span> ww = mydiv.offsetWidth;</cl-cd>
<cl-cd data-idx="49"><span class="tBlue">var</span> step = 1, begin1 = 0, begin2 = ww, raf = null;</cl-cd>
<cl-cd data-idx="50"> </cl-cd>
<cl-cd data-idx="51">play.onclick = () => aud.paused ? aud.play() : aud.pause();</cl-cd>
<cl-cd data-idx="52"> </cl-cd>
<cl-cd data-idx="53">aud.onpause = aud.onplaying = () => mState();</cl-cd>
<cl-cd data-idx="54">aud.onended = () => { aud.play(); cancelAnimationFrame(raf); }</cl-cd>
<cl-cd data-idx="55">aud.onseeked = () => cancelAnimationFrame(raf);</cl-cd>
<cl-cd data-idx="56"> </cl-cd>
<cl-cd data-idx="57"><span class="tBlue">var</span> moving = () => {</cl-cd>
<cl-cd data-idx="58"> begin1 -= step;</cl-cd>
<cl-cd data-idx="59"> <span class="tBlue">if</span>(begin1 <= -ww) begin1 = ww;</cl-cd>
<cl-cd data-idx="60"> <span class="tGreen">/* 处理背景衔接 移动设备衔接存在1像素问题 ±1 */</span></cl-cd>
<cl-cd data-idx="61"> begin2 = begin1 >= 0 ? -1 * (begin1 - ww + 1) : begin2 = -1 * (begin1 + ww - 1) ;</cl-cd>
<cl-cd data-idx="62"> mydiv.style.setProperty(<span class="tMagenta">'--begin1'</span>, begin1 + <span class="tMagenta">'px'</span>);</cl-cd>
<cl-cd data-idx="63"> mydiv.style.setProperty(<span class="tMagenta">'--begin2'</span>, begin2 + <span class="tMagenta">'px'</span>);</cl-cd>
<cl-cd data-idx="64"> aud.paused ? cancelAnimationFrame(raf) : raf = requestAnimationFrame(moving);</cl-cd>
<cl-cd data-idx="65">};</cl-cd>
<cl-cd data-idx="66"> </cl-cd>
<cl-cd data-idx="67"><span class="tBlue">var</span> mState = () => {</cl-cd>
<cl-cd data-idx="68"> aud.paused</cl-cd>
<cl-cd data-idx="69"> ? (mydiv.style.setProperty(<span class="tMagenta">'--state'</span>, <span class="tMagenta">'paused'</span>), cancelAnimationFrame(raf))</cl-cd>
<cl-cd data-idx="70"> : (mydiv.style.setProperty(<span class="tMagenta">'--state'</span>, <span class="tMagenta">'running'</span>), raf = requestAnimationFrame(moving));</cl-cd>
<cl-cd data-idx="71">};</cl-cd>
<cl-cd data-idx="72"> </cl-cd>
<cl-cd data-idx="73"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
像极全景片片。高档! 本帖最后由 马黑黑 于 2024-4-5 21:05 编辑
帖子测试目的:不同设备下浏览器的表现。我在编写代码时测试过基于Windows的Firefox、Chrome、Edge等几个浏览器,同时使用虚拟仿真环境测试过果机、安卓等设备。若帖子出现背景图片左右对接有缝线的或其他问题的,请反馈一下,谢谢。
css中,变量 --begin1、--begin2 的赋值不重要,这些值都将在JS中重新设定。
简单描述一下背景图片实现滚动原理:帖子容器下设两个伪元素 ::before 和 ::after,它们使用同一张背景图片,::after 水平方向翻转。二者理论上背景图片位置相衔接即可,::after 开始时背景图片位置在 0 0,:after 在 ww 0(ww为帖子宽度),然后通过JS不断同步改变背景图片位置,改变到一定位置时,前一个伪元素复位到 ww 位置,另一个伪元素继续按原速行进,如此反复交替。
计算机下,包括Windows平台和Linux平台,上述实现原理没问题。移动设备则不一定,所以代码中已经考虑了这个问题,故意在衔接处提前了一个像素。即便如此,可能仍然出现衔接处闪烁等问题,所以在此测试一下。 本帖所使用的图片URL:
https://638183.freep.cn/638183/t24/webp/xwjn.webp
樵歌 发表于 2024-4-5 21:01
像极全景片片。高档!
看五楼 注意一下:帖子尺寸和图片实际尺寸一致 俺这里看很平稳的 绿叶清舟 发表于 2024-4-5 21:19
俺这里看很平稳的
电脑看没啥大问题的 这个就一张图片出来无缝全景,黑黑太厉害了{:4_199:} 小辣椒 发表于 2024-4-5 21:32
这个就一张图片出来无缝全景,黑黑太厉害了
你有空时用手机看看效果 好,我现在上去 马黑黑 发表于 2024-4-5 21:22
电脑看没啥大问题的
手机也试了一下没问题了 华为手机,画面无缝链接,流畅{:4_199:} 小辣椒 发表于 2024-4-5 21:37
华为手机,画面无缝链接,流畅
太好了。俺是原生支持鸿蒙的。 绿叶清舟 发表于 2024-4-5 21:37
手机也试了一下没问题了
细看,有木有细细的接头缝线 小辣椒 发表于 2024-4-5 21:35
好,我现在上去
辛苦 非常顺畅的无缝连接图图,很漂亮。{:4_187:} 红影 发表于 2024-4-5 22:30
非常顺畅的无缝连接图图,很漂亮。
晚上嚎 马黑黑 发表于 2024-4-5 22:32
晚上嚎
黑黑研究了很多滚动连接方式,很赞{:4_187:}