中心点靠近动画解析

前端名狮

共 3175字,需浏览 7分钟

 ·

2022-06-19 16:10

背景

今天要解析的是一种常见动画效果,特点是:一排横行排列的卡片,被激活的卡片尽可能移动到中间位置。我给它命名为【中心点靠近动画】,先看下动画效果:

解析

要实现动画效果,个人总结有下面两个核心点:

  1. 运动动画基于什么实现?
  2. 每个卡片的运动到中心点的距离怎么计算?

1、运动动画基于什么实现?

针对第一个问题比较好解决,大致可以分为两种,一种是基于scrollLeft来控制卡片位置,一种是基于css3动画属性transform实现。两种方式各有优劣,具体如下:

scrollLeft

优点:在实现点击移动的效果下,能够利用div的滚动特性,快速实现横向滑动效果。

缺点:动画性能较低。

transform

优点:基于CSS3实现,动画性能高。

缺点:横向滚动效果需要单独实现。

这次是选用的transform实现的

html代码

<div class="container">
    <div class="list" 
        ref="listRef"
        style={{transform: `translateX(${translateX}px)` }}
    >
        <div class="cardItem">1</div>
        <div class="cardItem">2</div>
        <div class="cardItem">3</div>
        <div class="cardItem">4</div>
        <div class="cardItem">5</div>
        <div class="cardItem">6</div>
        <div class="cardItem active">7</div>
        <div class="cardItem">8</div>
    </div>
</div>

.container {
    position: relative;
    overflow: hidden;

    .list {
        display: flex;
        transition: 0.3s ease-in-out;
    }
}

2、每个卡片的运动到中心点的距离怎么计算

这个问题是今天讲的重点内容,画了一个简洁的示意图

每个卡片向中心点靠近时,list偏移的距离都是固定的。所以可以将list以中心点为分界线,分成两个部分。

active卡片中心点距离list左边距的距离为offsetLeft

  1. 如果offsetLeft < w/2,也就是中心点的左侧部分卡片,偏移距离translateX = 0;
  2. 如果offsetLeft > w/2,也就是中心点右侧部分卡片,运动到中心点需要偏移dis=offsetLeft-w/2,但是需要检查右边隐藏部分内容的宽度scrollRight,偏移距离需要为两者之间的最小值Math.min(dis, scrollRight)

注意点:当L < w时,也就是列表长度小于容器长度时,偏移距离都是0;

代码如下:

// 其中cardW为卡片宽度
useEffect(() => {
    const cardDomList = listRef.current?.children;
    if (cardDomList) {
      const leftDis = cardDomList[videoIndex].offsetLeft + cardW / 2;
      const scrollRight = L > w ? L - w : 0;
      if (leftDis < w / 2) {
        setTranslateX(0);
      } else {
        const dis = leftDis - w / 2;
        setTranslateX(-Math.min(dis, scrollRight));
      }
    }
  }, [videoIndex]);

总结

解决方案整体是一个距离计算的算法,相对于之前计算方案,感觉这个计算方式更简洁,具有通用性。

浏览 32
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报