马黑黑 发表于 2024-5-21 12:38

CSS关键帧动画:元素绕椭圆圆周运动的实现(一)

<style>
.art p { font-size: 18px; margin: 12px 0; }
.tMid { text-align: center; }
.eBox { margin: 20px auto; width: 400px; height: 240px; border: 1px solid gray; border-radius: 50%; }

li-zi { position: absolute; width: 30px; height: 30px; background: plum; offset-path: path('M0 120 A200 120 0 1 1 400 120 A200 120 0 1 1 0 120'); }
.ani { animation: move 10s linear infinite; }

.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }

@keyframes move { from { offset-distance: 0; } to { offset-distance: 100%; } }
</style>

<div class="art">
        <p>当一个元素的宽高尺寸不同,比如宽度大于高度,我们只需要设置好 border 和 border-radius 属性,即边框和边框角半径,就可以做出一个椭圆形的形状。看效果和代码:</p>
        <div class="eBox"></div>
        <div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">style</span>&gt;&nbsp; &nbsp; </cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; .eBox {</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">margin:</span> auto;</cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">width:</span> 400px;</cl-cd>
<cl-cd data-idx="5">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">height:</span> 240px;</cl-cd>
<cl-cd data-idx="6">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">border:</span> 1px solid gray;</cl-cd>
<cl-cd data-idx="7">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">border-radius:</span> 50%;</cl-cd>
<cl-cd data-idx="8">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">position:</span> relative;</cl-cd>
<cl-cd data-idx="9">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="10">&lt;<span class="tDarkRed">/style</span>&gt;</cl-cd>
<cl-cd data-idx="11">&nbsp;</cl-cd>
<cl-cd data-idx="12">&lt;<span class="tDarkRed">div</span> class=<span class="tMagenta">"eBox"</span>&gt;&lt;<span class="tDarkRed">/div</span>&gt;</cl-cd>
        </div>
        <p>400*240的宽高,1像素的实线边框,50%的边框角半径,椭圆形的框架就出来了。不过非常遗憾,它连跑道都不是,它只是一个场所——即一个父元素,我们的预期是它的子元素在这个椭圆上奔跑。好吧,我们需要在它上面安个真正的跑道,跑道就和这个框架一样并且相贴合。跑道的承建商是 svg,svg将 path 路径赋予子元素一个 offset-path 属性,字面意思是偏移路径,实际意义是创建一个路径,然后运动员身份的子元素在这条路径上以不同的 offset-distance 即偏移距离出现就产生了位置的转换即奔跑的效果。先来看看 li-zi 元素的CSS代码:</p>
        <div class='mum'>
<cl-cd data-idx="1">&nbsp; &nbsp; li-zi {</cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">position:</span> absolute;</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">width:</span> 30px;</cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">height:</span> 30px;</cl-cd>
<cl-cd data-idx="5">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">background:</span> plum;</cl-cd>
<cl-cd data-idx="6">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">offset-path:</span> path(<span class="tMagenta">'M0 120 A200 120 0 1 1 400 120 A200 120 0 1 1 0 120'</span>);</cl-cd>
<cl-cd data-idx="7">&nbsp; &nbsp; }</cl-cd>
        </div>
        <p>li-zi是我们自定义的一个元素名称,上面的代码是它的CSS样式:绝对定位、30*30的尺寸、梅红的背景色,第6行是关键,属性 offset-path 创建了一条无形的 svg 路径 path,路径的具体内容使用 svg 路径描述语言描述,在小括号里用小角引号包裹起来,大致意思是:这条路径,移动到 (0,120),从这个地方开始画一条弧线,再画一条弧线,两条弧线合起来就形成了椭圆形跑道。手绘这样的路径相对麻烦,可以使用工具,我这里做有一个,<a href="http://mhh.52qingyin.cn/api/svg/svg2path.html" target="_blank">SVG基本图形转路径</a>,选择svg基本图形中的椭圆即 ellipse 后设置好红色的数字,width、height 是父元素宽高,cx、cy是父元素椭圆圆心坐标,rx 是大圆半径,ry 是小圆半径,确定后如果满意,复制后变提供的路径数据就妥了。</p>
        <p>将上面的 li-zi 代码加入到我们的路径工程,看看怎么样?完整代码:</p>
        <div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">style</span>&gt;&nbsp; &nbsp; </cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; .eBox {</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">margin:</span> auto;</cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">width:</span> 400px;</cl-cd>
<cl-cd data-idx="5">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">height:</span> 240px;</cl-cd>
<cl-cd data-idx="6">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">border:</span> 1px solid gray;</cl-cd>
<cl-cd data-idx="7">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">border-radius:</span> 50%;</cl-cd>
<cl-cd data-idx="8">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">position:</span> relative;</cl-cd>
<cl-cd data-idx="9">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="10">&nbsp; &nbsp; li-zi {</cl-cd>
<cl-cd data-idx="11">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">position:</span> absolute;</cl-cd>
<cl-cd data-idx="12">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">width:</span> 30px;</cl-cd>
<cl-cd data-idx="13">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">height:</span> 30px;</cl-cd>
<cl-cd data-idx="14">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">background:</span> plum;</cl-cd>
<cl-cd data-idx="15">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">offset-path:</span> path(<span class="tMagenta">'M0 120 A200 120 0 1 1 400 120 A200 120 0 1 1 0 120'</span>);</cl-cd>
<cl-cd data-idx="16">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="17">&lt;<span class="tDarkRed">/style</span>&gt;</cl-cd>
<cl-cd data-idx="18">&nbsp;</cl-cd>
<cl-cd data-idx="19">&lt;<span class="tDarkRed">div</span> <span class="tRed">class</span>=<span class="tMagenta">"eBox"</span>&gt;</cl-cd>
<cl-cd data-idx="20">&nbsp; &nbsp; &lt;<span class="tDarkRed">li-zi</span>&gt;&lt;<span class="tDarkRed">/li-zi</span>&gt;</cl-cd>
<cl-cd data-idx="21">&lt;<span class="tDarkRed">/div</span>&gt;</cl-cd>
        </div>
        <p>效果:</p>
        <div class="eBox"><li-zi></li-zi></div>
        <p>从效果中大家应该能够发现:子元素一旦拥有 offset-path 属性,子元素的位置就会受到 offset-path 给出的 path 路径的影响,它已经去到了路径开始的地方 (0,120),但要特别注意,这需要一个前提:父元素相对定位 relative、子元素绝对定位 absolute。现在,我们要让 li-zi 小矩形移动起来,这需要用到 CSS关键帧动画 @keyframes 控制元素在偏移路径上的偏移距离 offset-distance,试看代码:</p>
        <div class='mum'>
<cl-cd data-idx="1">&nbsp; &nbsp; @keyframes move {</cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; &nbsp; &nbsp; from { <span class="tBlue">offset-distance:</span> 0; }</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; &nbsp; &nbsp; to { <span class="tBlue">offset-distance:</span> 100%; }</cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; }</cl-cd>
        </div>
        <p>然后我们在 li-zi CSS样式代码中加入 animation 属性就大功告成:</p>
        <div class="eBox"><li-zi class="ani"></li-zi></div>
        <p>上述 li-zi 元素做椭圆形运动的完整代码:</p>
        <div class='mum'>
<cl-cd data-idx="1">&lt;<span class="tDarkRed">style</span>&gt;&nbsp; &nbsp; </cl-cd>
<cl-cd data-idx="2">&nbsp; &nbsp; .eBox {</cl-cd>
<cl-cd data-idx="3">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">margin:</span> 20px auto;</cl-cd>
<cl-cd data-idx="4">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">width:</span> 400px;</cl-cd>
<cl-cd data-idx="5">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">height:</span> 240px;</cl-cd>
<cl-cd data-idx="6">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">border:</span> 1px solid gray;</cl-cd>
<cl-cd data-idx="7">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">border-radius:</span> 50%;</cl-cd>
<cl-cd data-idx="8">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">position:</span> relative;</cl-cd>
<cl-cd data-idx="9">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="10">&nbsp; &nbsp; li-zi {</cl-cd>
<cl-cd data-idx="11">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">position:</span> absolute;</cl-cd>
<cl-cd data-idx="12">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">width:</span> 30px;</cl-cd>
<cl-cd data-idx="13">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">height:</span> 30px;</cl-cd>
<cl-cd data-idx="14">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">background:</span> plum;</cl-cd>
<cl-cd data-idx="15">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">offset-path:</span> path(<span class="tMagenta">'M0 120 A200 120 0 1 1 400 120 A200 120 0 1 1 0 120'</span>);</cl-cd>
<cl-cd data-idx="16">&nbsp; &nbsp; &nbsp; &nbsp; <span class="tBlue">animation:</span> move 10s linear infinite;</cl-cd>
<cl-cd data-idx="17">&nbsp; &nbsp; }</cl-cd>
<cl-cd data-idx="18">    @keyframes move {</cl-cd>
<cl-cd data-idx="19">      from { <span class="tBlue">offset-distance:</span> 0; }</cl-cd>
<cl-cd data-idx="20">      to { <span class="tBlue">offset-distance:</span> 100%; }</cl-cd>
<cl-cd data-idx="21">    }</cl-cd>
<cl-cd data-idx="22">&lt;<span class="tDarkRed">/style</span>&gt;</cl-cd>
<cl-cd data-idx="23">&nbsp;</cl-cd>
<cl-cd data-idx="24">&lt;<span class="tDarkRed">div</span> class=<span class="tMagenta">"eBox"</span>&gt;</cl-cd>
<cl-cd data-idx="25">    &lt;<span class="tDarkRed">li-zi</span>&gt;&lt;<span class="tDarkRed">/li-zi</span>&gt;</cl-cd>
<cl-cd data-idx="26">&lt;<span class="tDarkRed">/div</span>&gt;</cl-cd>
        </div>
        <p>后续内容需要另开章节探讨,敬请期待。</p>
</div>

南无月 发表于 2024-5-21 12:53

新开的路径课程。。。{:4_199:}

基本图形转路径这个是新整的吗?
提供了好几种,不过大小要研究一下怎么变化

南无月 发表于 2024-5-21 12:53

粒子可随意变图片这个功能超级友好{:4_199:}

红影 发表于 2024-5-21 14:36

这个讲解特别详细,语言也风趣。学习了{:4_187:}

红影 发表于 2024-5-21 14:37

我记得svg也做过椭圆文字的转动呢,那个好像还需要设置文字一直朝上的{:4_204:}

小辣椒 发表于 2024-5-21 20:41

粒子的效果特别美也是喜欢,但小辣椒对路径的制作总是滞后。。。。

马黑黑 发表于 2024-5-21 21:41

小辣椒 发表于 2024-5-21 20:41
粒子的效果特别美也是喜欢,但小辣椒对路径的制作总是滞后。。。。

这个需要一点基础

马黑黑 发表于 2024-5-21 21:42

南无月 发表于 2024-5-21 12:53
新开的路径课程。。。

基本图形转路径这个是新整的吗?


这个严格来讲是旧课了,不过过去不是直接实现,现在这个是直接实现了椭圆运动

马黑黑 发表于 2024-5-21 21:43

红影 发表于 2024-5-21 14:37
我记得svg也做过椭圆文字的转动呢,那个好像还需要设置文字一直朝上的

这个不需要

马黑黑 发表于 2024-5-21 21:43

红影 发表于 2024-5-21 14:36
这个讲解特别详细,语言也风趣。学习了

这个简单的

马黑黑 发表于 2024-5-21 21:43

南无月 发表于 2024-5-21 12:53
粒子可随意变图片这个功能超级友好

CSS+HTML的可能熟悉一点

小辣椒 发表于 2024-5-21 21:46

马黑黑 发表于 2024-5-21 21:41
这个需要一点基础

这个基础我没有的,所以不会

马黑黑 发表于 2024-5-21 21:46

小辣椒 发表于 2024-5-21 21:46
这个基础我没有的,所以不会

不会就不学

红影 发表于 2024-5-21 23:09

马黑黑 发表于 2024-5-21 21:43
这个不需要

嗯嗯,这个设置好路径,方块就可以跟着走了{:4_204:}

红影 发表于 2024-5-21 23:20

马黑黑 发表于 2024-5-21 21:43
这个简单的

继续期待后续课程{:4_187:}

马黑黑 发表于 2024-5-22 07:42

红影 发表于 2024-5-21 23:09
嗯嗯,这个设置好路径,方块就可以跟着走了

并且自动转身

马黑黑 发表于 2024-5-22 07:42

红影 发表于 2024-5-21 23:20
继续期待后续课程

简单的

红影 发表于 2024-5-22 11:03

马黑黑 发表于 2024-5-22 07:42
并且自动转身

嗯嗯,这个厉害。

红影 发表于 2024-5-22 11:03

马黑黑 发表于 2024-5-22 07:42
简单的

看到今天的学习内容了,讲解得很详细{:4_199:}

马黑黑 发表于 2024-5-22 11:32

红影 发表于 2024-5-22 11:03
看到今天的学习内容了,讲解得很详细

{:4_190:}
页: [1] 2 3 4 5 6
查看完整版本: CSS关键帧动画:元素绕椭圆圆周运动的实现(一)