关于css:纯htmlcss实现一个炫酷的无限滚动动效

42次阅读

共计 4389 个字符,预计需要花费 11 分钟才能阅读完成。

1. 先看成品

codepen 体验

(因为图片大小问题,只截取了一部分。实际效果是始终滚动,不会有动画复位的割裂感。)

2. 问题拆分

首先看到这个需要的时候,感觉比拟难做,次要是上面的起因:须要斜着滚动,且须要有限,再就是 icon 错位排列的问题。

起初思考了下,对这个问题进行了拆分:

  1. 编写容器及 icon 等的 css
  2. 排列好 icon 并且丢到一个 wrapper 中
  3. 将整个 wrapper 歪斜 30 度
  4. 为 wrapper 增加有限的横向滚动动画

话不多说,开始写代码

3. 开始口头

为了不便看边界,对于一些 dom 增加了边框~

3.1 创立容器

容器是一个固定大小的比拟好写

.box {
    height: 666px;
    width: 1182px;
    border-radius: 36px;
    border: 1px solid;
    overflow: hidden;
    text-align: center;
    font-size: 30px;
}

3.2 而后撸个 icon 进去

这里就不应用图片来做了,对立用这个 mock 一下~

.icon {
    width: 267px;
    height: 267px;
    border-radius: calc(267px * 0.23);
    background-image: conic-gradient(hsl(360, 100%, 50%),
        hsl(315, 100%, 50%),
        hsl(270, 100%, 50%),
        hsl(225, 100%, 50%),
        hsl(180, 100%, 50%),
        hsl(135, 100%, 50%),
        hsl(90, 100%, 50%),
        hsl(45, 100%, 50%),
        hsl(0, 100%, 50%)
    );
}

3.3 排列 icon 到 wrapper 中

咱们把脖子沿逆时针方向旋转 30 度发现,实际上就是错落有致的摆放着两排 icon。

咱们依照图示动态的摆放一下:

<div class="box">
    <div class="lean-box">
        <div class="wrapper">
            <div class="icon-pair">
                <div class="icon">1</div>
                <div class="icon">2</div>
            </div>
            <div class="icon-pair">
                <div class="icon">3</div>
                <div class="icon">4</div>
            </div>
            <div class="icon-pair">
                <div class="icon">5</div>
                <div class="icon">6</div>
            </div>
            <div class="icon-pair">
                <div class="icon">7</div>
                <div class="icon">8</div>
            </div>
        </div>
    </div>
</div>
.lean-box {
    display: flex;
    transform: rotate(-30deg);
}

.wrapper {
    margin-top: 180px;
    display: flex;
    flex-wrap: nowrap;
}

.wrapper .icon:nth-child(even) {
    margin-top: 45px;
    transform: translate(155px);
}

.icon-pair {margin-left: 45px;}

.icon {
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 66px;
    font-weight: bold;
}

这样看起来就很有精力了,接下来咱们须要让它动起来

3.4 增加动画

这里动起来应用的是 animation,于是,编写下列代码并且增加到 wrapper 上:

@keyframes rowup {
    from {transform: translateX(0%);
    }

    to {transform: translateX(-500px);
    }
}
.wrapper {
    margin-top: 180px;
    display: flex;
    flex-wrap: nowrap;
    animation: rowup 5s linear infinite;
}

这时候动是动起来了,接下来的问题是,怎么有限的进行滚动呢?

有限到是动静增加 dom,销毁 dom,就是在这一组 wrapper 后创立一组截然不同的 wrapper,等本组齐全隐没后销毁。

可是,这个老本会很高不是吗,而且这种实现形式势必须要随工夫去更新 icon 的地位,肯定有更好的办法

3.5 无缝滚动

animation 动画完结后会回归第一帧,假如咱们让第一帧的动画和最初一帧重合,那么是不是就看起来是无缝的了?

于是我将 wrapper 外面的元素从新拷贝一份放在前面(以后组称为 A,拷贝组称为 B),当动画完结时,B 刚好挪动到 A 的初始地位。

咱们来计算一下:

这里一组 8 个 icon 排两排状况,挪动的宽度应该为 4 个 icon 宽度 + 4 个 margin,(267 4) + (45 4) = 1248px,这样 B 就能够刚好挪动到 A 了

更新下动画:

@keyframes rowup {
    from {transform: translateX(0%);
    }

    to {transform: translateX(-1248px);
    }
}

html 也相应更新下:

<div class="box">
    <div class="lean-box">
        <div class="wrapper">
            <div class="icon-pair">
                <div class="icon">1</div>
                <div class="icon">2</div>
            </div>
            <div class="icon-pair">
                <div class="icon">3</div>
                <div class="icon">4</div>
            </div>
            <div class="icon-pair">
                <div class="icon">5</div>
                <div class="icon">6</div>
            </div>
            <div class="icon-pair">
                <div class="icon">7</div>
                <div class="icon">8</div>
            </div>
            <div class="icon-pair">
                <div class="icon">1</div>
                <div class="icon">2</div>
            </div>
            <div class="icon-pair">
                <div class="icon">3</div>
                <div class="icon">4</div>
            </div>
            <div class="icon-pair">
                <div class="icon">5</div>
                <div class="icon">6</div>
            </div>
            <div class="icon-pair">
                <div class="icon">7</div>
                <div class="icon">8</div>
            </div>
        </div>
    </div>
</div>

3.6 欠缺一下

如果每次都要依据组件个数去计算的话,的确有点 low 了,其实会搁置两个截然不同的 icons,所以 translateX 的间隔不须要计算,设置为 -50% 就好了,最终代码如下(能够在 codepen 上体验):

<div class="box">
    <div class="lean-box">
        <div class="wrapper">
            <div class="icon-pair">
                <div class="icon">1</div>
                <div class="icon">2</div>
            </div>
            <div class="icon-pair">
                <div class="icon">3</div>
                <div class="icon">4</div>
            </div>
            <div class="icon-pair">
                <div class="icon">5</div>
                <div class="icon">6</div>
            </div>
            <div class="icon-pair">
                <div class="icon">7</div>
                <div class="icon">8</div>
            </div>
            <div class="icon-pair">
                <div class="icon">1</div>
                <div class="icon">2</div>
            </div>
            <div class="icon-pair">
                <div class="icon">3</div>
                <div class="icon">4</div>
            </div>
            <div class="icon-pair">
                <div class="icon">5</div>
                <div class="icon">6</div>
            </div>
            <div class="icon-pair">
                <div class="icon">7</div>
                <div class="icon">8</div>
            </div>
        </div>
    </div>
</div>
@keyframes rowup {
    from {transform: translateX(0%);
    }

    to {transform: translateX(-50%);
    }
}
.box {
    height: 666px;
    width: 1182px;
    border-radius: 36px;
    border: 1px solid;
    overflow: hidden;
    text-align: center;
    font-size: 30px;
}

.icon {
    width: 267px;
    height: 267px;
    border-radius: calc(267px * 0.23);
    background-image: conic-gradient(hsl(360, 100%, 50%),
        hsl(315, 100%, 50%),
        hsl(270, 100%, 50%),
        hsl(225, 100%, 50%),
        hsl(180, 100%, 50%),
        hsl(135, 100%, 50%),
        hsl(90, 100%, 50%),
        hsl(45, 100%, 50%),
        hsl(0, 100%, 50%)
    );
}

.lean-box {
    display: flex;
    transform: rotate(-30deg);
}

.wrapper {
    margin-top: 180px;
    display: flex;
    flex-wrap: nowrap;
    animation: rowup 5s linear infinite;
}

.wrapper .icon:nth-child(even) {
    margin-top: 45px;
    transform: translate(155px);
}

.icon-pair {margin-left: 45px;}

.icon {
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 66px;
    font-weight: bold;
}

正文完
 0