单图片背景循环移动精简版
<div class="hEdiv" data-prev="1"><pre class="hEpre"><style>
/* 容器元素 */
#mydiv {
margin: 20px 0 20px calc(50% - 720px); /* 水平方向居中 */
width: 1440px;
height: 810px;
background: skyblue;
box-shadow: 4px 4px 8px #000;
position: relative;
z-index: 1; /* 这个不要缺 */
}
/* 容器元素伪元素 */
#mydiv::before, #mydiv::after {
position: absolute;
content: '';
inset: 0; /* 定位,等同于 top、right、bottom、left 都为 0 */
/* 如果容器和图片尺寸不一致,下句分号前加空格再加 0 0 / 100% 100% */
background: url('https://638183.freep.cn/638183/t24/7/t24.jpg') no-repeat;
}
#mydiv::before {
background-position: var(--begin1) 0; /* 背景位置(值将由JS生成)*/
}
#mydiv::after {
transform: scale(-1, 1); /* 水平方向倒转 */
background-position: var(--begin2) 0; /* 背景位置(值将由JS生成)*/
z-index: -1; /* 重要,避免 :after 覆盖其它元素 */
}
/* 文本居中选择器 */
.tMid { text-align: center; }
</style>
<div id="mydiv"></div>
<p class="tMid"><button id="btnAni">播放/暂停动画</button></p>
<script>
// stop :动画开关;begin1 :移动背景初始值;raf :请求关键帧动画标识
let stop = true, begin1 = 0, raf = null;
// 移动背景函数 :elm - 容器元素,speed - 移动速度(缺省默认 0.5)
function bgMove(elm, speed = 0.5) {
const ww = elm.offsetWidth; // 取容器宽度
// 内嵌移动函数
function moving() {
cancelAnimationFrame(raf); // 注销动画标识(防止速度变快)
begin1 += speed; // ::before 伪元素移动值按速度递增
if (speed > 0 && begin1 >= ww) begin1 = -ww; // 自左向右移动衔接算法
if(speed < 0 && begin1 <= -ww) begin1 = ww; // 自右向左移动衔接算法
// ::after 伪元素移动值算法 :依据 begin1 当前值动态计算
const begin2 = begin1 >= 0 ? -1 * (begin1 - ww + 1) : -1 * (begin1 + ww - 1);
// 处理伪元素所需 CSS 变量值
elm.style.setProperty('--begin1', begin1 + 'px');
elm.style.setProperty('--begin2', begin2 + 'px');
// 依据外部 stop 变量注销或递归运行动画
stop ? cancelAnimationFrame(raf) : raf = requestAnimationFrame(moving);
}
moving(); // 运行 moving 函数
}
// 若需要立即运行请设置 stop = false 同时解开下行代码注释
// bgMove(mydiv, 0.6);
// 动画控制(按钮点击事件)
btnAni.onclick = () => {
stop = !stop; // stop 值取反
bgMove(mydiv, 0.6); // 运行动画
};
</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> 代码更简洁,效果更完美,演示更直观,谢谢马老师精彩示范{:4_180:} 黑黑老师,这代码能直接用吗? {:4_204:} 梦江南 发表于 2026-8-4 19:13
黑黑老师,这代码能直接用吗?
基本上是酱紫。但是要根据应用场景做一些设置,例如,你可能希望 stop 变量应该是其它依赖(比如音频播放或暂停),这种情况,核心函数的外部条件要改一改。 杨帆 发表于 2026-8-4 18:42
代码更简洁,效果更完美,演示更直观,谢谢马老师精彩示范
感谢支持 马老师晚上好!
这个我留存,更喜欢带小播的那个。各有用途,感谢分享,祝安好~~{:4_204:}{:4_190:}
这个讲解真清楚。“如果容器和图片尺寸不一致,下句分号前加空格再加 0 0 / 100% 100%” 这样也能让图片填满容器,只是图片和容器一样最好呢,不会失真{:4_204:} 本帖最后由 杨帆 于 2026-8-4 23:58 编辑
马黑黑 发表于 2026-8-4 19:35
基本上是酱紫。但是要根据应用场景做一些设置,例如,你可能希望 stop 变量应该是其它依赖(比如音频播放 ...
谢谢老师,刚试了一下,是要根据应用场景做一些设置呢 杨帆 发表于 2026-8-4 22:18
谢谢老师,刚试了一下,是要根据应用场景做一些设置呢
一些东东需要配套 红影 发表于 2026-8-4 21:58
这个讲解真清楚。“如果容器和图片尺寸不一致,下句分号前加空格再加 0 0 / 100% 100%” 这样也能让图片填 ...
这个自然 马黑黑 发表于 2026-8-5 12:50
一些东东需要配套
是,发现在全屏切换过渡中,背景移动动画的衔接还是有问题,不知其因 杨帆 发表于 2026-8-5 14:42
是,发现在全屏切换过渡中,背景移动动画的衔接还是有问题,不知其因
单图背景无限循环滚动本来就要求帖子容器宽高与图片尺寸保持一致。若非如此,需要精心设计其他方面。 马黑黑 发表于 2026-8-5 18:37
单图背景无限循环滚动本来就要求帖子容器宽高与图片尺寸保持一致。若非如此,需要精心设计其他方面。
用的是这个:“如果容器和图片尺寸不一致,下句分号前加空格再加 0 0 / 100% 100%” 杨帆 发表于 2026-8-5 19:41
用的是这个:“如果容器和图片尺寸不一致,下句分号前加空格再加 0 0 / 100% 100%”
这个是必须的,同时还需要其它的配套措施。这个需要慢慢领会,你可以参考我的相关帖子 马黑黑 发表于 2026-8-5 12:50
这个自然
即使不一样,也不能差得太多。 马黑黑 发表于 2026-8-5 20:24
这个是必须的,同时还需要其它的配套措施。这个需要慢慢领会,你可以参考我的相关帖子
好的,谢谢老师{:4_190:}
页:
[1]