likes
comments
collection
share

记一次动画实现--左右滑动的盒子

作者站长头像
站长
· 阅读数 52

一个需求:一个盒子从中间开始,碰到最左边的边界往右移动,碰到最右边的边界往左移动,如此循环。

记一次动画实现--左右滑动的盒子

像这种动画实现,我们自然而然地想到使用 @keyframes 来定义动画,可以使用设置定位中的 left 或者 transform 中的 translate 来实现盒子移动。

使用定位中的 left 设置动画,css 代码如下所示:

body {position: relative;}

#box {width: 50px;height: 50px;border: 5px solid black;
position: absolute;left: 50%;
/* 为了实现水平居中,所以需要移动自身的50%宽度 */
transform: translateX(-50%);
animation: move linear 6s infinite; }
@keyframes move {
0% {left: 50%;}
25% {left: 0;
/* 必须覆盖上面的 translateX(-50%) */
transform: translateX(0);}
75% {left: 100%;
/* 如果不向左平移盒子的100%宽度,盒子就会超出屏幕 */
transform: translateX(-100%);}
100% {  left: 50%;}
}

需要注意的是当设置绝对定位时,因为盒子本身是有宽度的,所以需要使用 translate 来适量地平移一下,才能达到正常滑动的效果,否则盒子就不会正常地居中以及移动的过程中超出屏幕窗口。另外,使用 left 来进行移动的话性能不是特别好,因为 left 会引起 css 的重流和重绘,所以我们需要完全使用 translate 来进行移动。

使用 translate 移动,css 代码如下:

body {display: flex;justify-content: center;}
#box {width: 50px;height: 50px;border: 5px solid black;animation: move 6s infinite linear;}
@keyframes move {
  0% {transform: translateX(0);}
  25% {transform: translateX(calc(-50vw + 50%));}
  75% {transform: translateX(calc(50vw - 50%));}
  100% {transform: translateX(0);}
}

因为使用 translate 移动,所以我直接就用了 flex 布局将盒子水平居中,为了使其正常移动,不超出屏幕窗口,我使用了 calc 计算盒子实际移动值,这里值得注意的是 translate 的移动值是以自身的位置而定位的,比如 0% 的时候 translateX 的移动值为 0,当 25% 的时候需要移动屏幕宽度值的一半,向左的话就是 -50vw,当 75% 的时候要移动到屏幕窗口的最右侧,就需要将移动值设为 50vw,而不是 100 vw。

除了 css 以外,我们还可以使用 js 来实现这个动画,使用 window.requestAnimationFrame 这个 api,该 api 会要求浏览器在下次重绘之前调用指定的回调函数更新动画,要了解更多该 api 可以看这里:传送门

实现代码:

const element = document.getElementById("app");
const bodyWidth = document.body.clientWidth;
const boxWidth = element.getBoundingClientRect().width;
let distance = Math.floor((bodyWidth - boxWidth) / 2);
let moveValue = 0;
let moveFlag = false;
function step() {
if (moveValue === -distance) {
moveFlag = true;
}
if (moveValue === distance) {
moveFlag = false;
}
if (moveFlag) {
moveValue += 1;
} else {
moveValue -= 1;
}
element.style.transform = "translateX(" + moveValue + "px)";
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
转载自:https://juejin.cn/post/7080921980857221134
评论
请登录