马黑黑 发表于 2022-2-27 08:36

纯CSS简单实现牛顿摆

<style>

#faDiv {
        margin: 10px auto;
        width: 300px;
        height: 240px;
        padding: 0;
        border-top: 2px solid #000;
        position: relative;
}

#faDiv div {
        width: 1px;
        height: 220px;
        position: absolute;
        top: 0;
        background: #000;
        transform-origin: 0 0;
}

#faDiv div::before {
        content: "";
        width: 20px;
        height: 20px;
        border-radius: 10px;
        position: absolute;
        left: -10px;
        top: 220px;
        background: #000;
}

#faDiv div:nth-child(1){
        left: 110px;
        animation: zuobai 2s 0s ease-in infinite;
}

#faDiv div:nth-child(2){
        left: 130px;
}

#faDiv div:nth-child(3){
        left: 150px;
}

#faDiv div:nth-child(4){
        left: 170px;
}

#faDiv div:nth-child(5){
        left: 190px;
        animation: youbai 2s 1s ease-in infinite;
}

@keyframes zuobai {
        0% { transform: rotate(0deg); }
        25% { transform: rotate(20deg); }
        50% { transform: rotate(0deg); }
        100% {}
}

@keyframes youbai {
        0% { transform: rotate(0deg); }
        25% { transform: rotate(-20deg); }
        50% { transform: rotate(0deg); }
        100% {}
}

</style>

<div id="faDiv">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
</div>

马黑黑 发表于 2022-2-27 08:36

上代码:

<style>

#faDiv {
        margin: 10px auto;
        width: 300px;
        height: 240px;
        padding: 0;
        border-top: 2px solid #000;
        position: relative;
}

#faDiv div {
        width: 1px;
        height: 220px;
        position: absolute;
        top: 0;
        background: #000;
        transform-origin: 0 0;
}

#faDiv div::before {
        content: "";
        width: 20px;
        height: 20px;
        border-radius: 10px;
        position: absolute;
        left: -10px;
        top: 220px;
        background: #000;
}

#faDiv div:nth-child(1){
        left: 110px;
        animation: zuobai 2s 0s ease-in infinite;
}

#faDiv div:nth-child(2){
        left: 130px;
}

#faDiv div:nth-child(3){
        left: 150px;
}

#faDiv div:nth-child(4){
        left: 170px;
}

#faDiv div:nth-child(5){
        left: 190px;
        animation: youbai 2s 1s ease-in infinite;
}

@keyframes zuobai {
        0% { transform: rotate(0deg); }
        25% { transform: rotate(20deg); }
        50% { transform: rotate(0deg); }
        100% {}
}

@keyframes youbai {
        0% { transform: rotate(0deg); }
        25% { transform: rotate(-20deg); }
        50% { transform: rotate(0deg); }
        100% {}
}

</style>

<div id="faDiv">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
</div>

马黑黑 发表于 2022-2-27 08:44


结合一楼效果从HTML代码解析思路:

<div id="faDiv">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
</div>


一个父div带五个子div,父div以border-top(上边框)模拟横向挂线,五个子div模拟牛顿摆的五个紧挨着的小球,小球用细线悬挂在横线上。这是牛顿摆的基本结构,下面的任务就是让两边的小球动起来,这需要用到CSS3的@keyframes和animation方法,我们将在CSS部分详细介绍。

马黑黑 发表于 2022-2-27 08:45

本帖最后由 马黑黑 于 2022-2-27 10:25 编辑

CSS代码解释:
一、父盒子

#faDiv {
        margin: 10px auto;
        width: 300px;
        height: 240px;
        padding: 0;
        border-top: 2px solid #000;
        position: relative;
}


定位必须。高宽提供空间场景给子元素。padding设置为0必须,如此才能确保线头不脱节。border-top用以模拟挂线,小球将悬挂其上。

二、父盒子下所有的div

#faDiv div {
        width: 1px;
        height: 220px;
        position: absolute;
        top: 0;
        background: #000;
        transform-origin: 0 0;
}


用以模拟悬挂小球的细线,宽度为横向挂线的一半,高度为220px。绝对定位,必须。top都是0,这样刚好挂在横线上。变换(运动)半径均以自己的xy坐标起始位置(0 0)处为圆心点。

三、父盒子下所有div的伪元素共性样式

#faDiv div::before {
        content: "";
        width: 20px;
        height: 20px;
        border-radius: 10px;
        position: absolute;
        left: -10px;
        top: 220px;
        background: #000;
}


伪元素用以模拟小球,以上是伪元素的共性样式表,值得解释的是left值,-10px是其宽度的一半,恰好能在小球顶部的正中央与子元素模拟的细线衔接。

四、各伪元素的独立样式

#faDiv div:nth-child(1){
        left: 110px;
        animation: zuobai 2s 0s ease-in infinite;
}

#faDiv div:nth-child(2){
        left: 130px;
}

#faDiv div:nth-child(3){
        left: 150px;
}

#faDiv div:nth-child(4){
        left: 170px;
}

#faDiv div:nth-child(5){
        left: 190px;
        animation: youbai 2s 1s ease-in infinite;
}


这里,我们采用伪标签 nth-child() 属性定义各伪元素的样式,从 1 至 5 逐一定义,其中,第一个为标签 div:nth-child(1) 左边值为110px,这是考虑了父div宽度和子元素div的宽度、结构而定,以确保五个小球挂在横线的正中央。根据牛顿摆质点传输动能原理,第一个小球和第五个小球摆动,所以这两个小球均加入 animation 属性,运行摆动动画。各个伪标签均依次设置left值,令其紧挨着摆放。

五、两个动画:左摆动和右摆动

@keyframes zuobai {
        0% { transform: rotate(0deg); }
        25% { transform: rotate(20deg); }
        50% { transform: rotate(0deg); }
        100% {}
}

@keyframes youbai {
        0% { transform: rotate(0deg); }
        25% { transform: rotate(-20deg); }
        50% { transform: rotate(0deg); }
        100% {}
}


这两个动画高度相似,唯rotate角度相反。这按理不符合牛顿摆原理,牛顿摆应是一摆一停。我们实现牛顿摆的关键是在为标签独立样式的 animation 引用之上,看这两句代码:

animation: youbai 2s 1s ease-in infinite;
animation: zuobai 2s 0s ease-in infinite;

右摆动和左摆动周期都是 2s,但右摆动延时 1s,左摆动未有延时(0s)。动画延时仅在启动动画时有效,如此,当左摆动运行一半,右摆动启动,就可以通过步进相同的两个动画达成对牛顿摆完美模拟的目的。

加林森 发表于 2022-2-27 11:29

惯性定律,对不对?

马黑黑 发表于 2022-2-27 13:18

加林森 发表于 2022-2-27 11:29
惯性定律,对不对?

非也。这背后的物理原理是能量守恒定律,是能量与动量在质子中的传输。

樵歌 发表于 2022-2-27 14:15

CSS是不是一种计算机语言呀?

小辣椒 发表于 2022-2-27 14:42

每次看见黑黑的东西我就在想我帖里面可以不可以玩{:4_170:}

红影 发表于 2022-2-27 15:58

这个有意思。延时1秒,就正好让2秒的运动错位开来。
试了一下,如果让child(1)延时1秒,child(5)延时两秒,得到的结果差不多。
但是如果反过来,让child(5)延时0,child(1)延时1秒,就会出现child(1)走2词,child(5)走一次的现象。

红影 发表于 2022-2-27 16:00

要让父元素两遍剩的量相等,小球的数量只能是奇数呢。

延时能早晨过一次运动的效果,这个有意思。延迟的时间设定和设置在哪个上面也很有讲究的。{:4_187:}

红影 发表于 2022-2-27 16:00

学习了,感谢黑黑分享的好帖{:4_187:}

加林森 发表于 2022-2-27 16:19

马黑黑 发表于 2022-2-27 13:18
非也。这背后的物理原理是能量守恒定律,是能量与动量在质子中的传输。

哦,是四大定律之一啊。

马黑黑 发表于 2022-2-27 19:03

加林森 发表于 2022-2-27 16:19
哦,是四大定律之一啊。

这个你也知道

马黑黑 发表于 2022-2-27 19:08

小辣椒 发表于 2022-2-27 14:42
每次看见黑黑的东西我就在想我帖里面可以不可以玩

牛顿摆的可玩性是极高的,很多富豪家里都有摆设,你帖子里放一个的话,你也是富豪{:4_170:}

马黑黑 发表于 2022-2-27 19:09

樵歌 发表于 2022-2-27 14:15
CSS是不是一种计算机语言呀?

也算,只是它的方向是基于web页的

马黑黑 发表于 2022-2-27 19:11

红影 发表于 2022-2-27 15:58
这个有意思。延时1秒,就正好让2秒的运动错位开来。
试了一下,如果让child(1)延时1秒,child(5)延时两秒 ...

我在写这个时没有你想的那么多,还是你的思路宽阔

马黑黑 发表于 2022-2-27 19:12

红影 发表于 2022-2-27 16:00
要让父元素两遍剩的量相等,小球的数量只能是奇数呢。

延时能早晨过一次运动的效果,这个有意思。延迟的 ...

依据动画的设计考虑吧。动画设计的好,不用延时也行,延时可以减少了动画设计的繁琐程度

马黑黑 发表于 2022-2-27 19:14

红影 发表于 2022-2-27 16:00
学习了,感谢黑黑分享的好帖

这个东东其实很有意思的,尤其是对文科生应是一个不小的挑战

加林森 发表于 2022-2-27 19:32

马黑黑 发表于 2022-2-27 19:03
这个你也知道

当然知道啊

马黑黑 发表于 2022-2-27 20:02

加林森 发表于 2022-2-27 19:32
当然知道啊

嗯,你是老师
页: [1] 2 3 4 5
查看完整版本: 纯CSS简单实现牛顿摆