马黑黑 发表于 2022-11-12 08:18

用offset-path实现N多子元素静态布局

本帖最后由 马黑黑 于 2022-11-12 08:36 编辑

此前介绍过offset-path,借助该CSS属性,通过svg路径(无需svg标签)实现各种路线的关键帧动画。本帖,则简单探讨一下使用 offset-path 实现子元素沿svg路径(同样无需svg标签)的静态布局(即摆放成什么样子)。

我们先来复习一下 offset-pass 这个 CSS 属性,它的语句一般是酱紫:

offset-path: path('svg路径');

offset-path 是属性名称,其后用冒号引出值。值的构成用 path 关键字引导,svg 路径放在小角引号内,并整体置于小角小括号内。

关于路径,要求符合 svg 路径表达规则,即,只要是合法的 svg 路径均可使用。路径可以自己制作,也可以通过工具生成。
配套 offset-path 属性使用的另一个重要的CSS属性,offset-distance,则能将子元素布置到路径上的指定位置,例如,我们把子元素放置在路径上的50%处:

offset-distance: 50%;

下面开始实现子元素的静态布局——

子元素的静态布局需要载体,所以,我们先得创建一个父盒子:

#papa {
      margin: auto;
      width: 1024px;
      height: 640px;
      background: snow;
      box-shadow: 3px 3px 20px #000;
      display: grid;
      place-items: center;
      position: relative;
}


接着设定子元素的样式。本帖示范的,是帖子 《只爱我自己》 里的心形效果(注意观察 offset-path 属性和它的设定值):

.heart {
      position: absolute;
      left: 0;
      top: 0;
      width: 40px;
      height: 40px;
      display: grid;
      place-items: center;
      font: normal 40px sans-serif;
      color: pink;
      offset-path: path('m271.44526,175.38086c65.55493,-161.83822 322.4013,0 0,208.07771c-322.4013,-208.07771 -65.55493,-369.91593 0,-208.07771z');
}


这两个CSS盒子,都用到 grid 布局,其作用是快速定位子元素绝对居中(.heart也将拥有文本,文本是其子元素)。

记得写上HTML代码:

<div id="papa"></div>

在HTML代码里,我们没有写上任何一个 .heart 的子元素,它们将由 JS 生成,因为量大:

<script>
let total = 25;
Array.from({length: total}).forEach((item,key) => {
      item = document.createElement('span');
      item.className = 'heart';
      item.innerText = '♥';
      item.style.offsetDistance = 100/total *key + '%';
      papa.appendChild(item);
});
</script>


JS代码里,total 变量是 ♥ 的总数,可根据实际场景决定赋值。

然后遍历长度为 total 个子项目的数组,每一个数组元素都遍历(forEach)一次,遍历中对每一个数组元素进行处理:

① 将 forEach() 的参数 item 赋值为待添加的子元素 span;
② item 的CSS类名为 heart;
③ item 的文本内容为 ♥(本论坛需要使用Unicode编码表示心形:\u2764);
④ 重要!设置偏移距离(offsetDistance),实现按路径分散摆放效果。offsetDistance可以使用百分比表示偏移量,所以有这个算式 100/total *key ,后面再加上字串 '%';
⑤ 最后将子元素 item 追加到 papa 父框,papa.appendChild(item);

偏移路径起始点、分散摆放子元素的实现,核心是CSS属性 offset-distance,偏移距离,在JS里写为 offsetDistance 。子元素偏移量的计算,以自身的索引(forEach参数中的key)参与计算,从而实现路径上的均衡布局。

效果请查看下楼。

马黑黑 发表于 2022-11-12 08:20

<style>
#papa {
        margin: 0 0 0 calc(50% - 593px);
        width: 1024px;
        height: 640px;
        background: snow;
        box-shadow: 3px 3px 20px #000;
        display: grid;
        place-items: center;
        position: relative;
}
.heart {
        position: absolute;
        left: 0;
        top: 0;
        width: 40px;
        height: 40px;
        display: grid;
        place-items: center;
        font: normal 40px sans-serif;
        color: pink;
        offset-path: path('m271.44526,175.38086c65.55493,-161.83822 322.4013,0 0,208.07771c-322.4013,-208.07771 -65.55493,-369.91593 0,-208.07771z');
}
</style>

<div id="papa">
</div>

<script>
let total = 25;
Array.from({length: total}).forEach((item,key) => {
        item = document.createElement('span');
        item.className = 'heart';
        item.innerText = '\u2764';
        item.style.offsetDistance = 100/total *key + '%';
        papa.appendChild(item);
});
</script>

马黑黑 发表于 2022-11-12 08:21

二楼效果的代码
<style>
#papa {
        margin: auto;
        width: 1024px;
        height: 640px;
        background: snow;
        box-shadow: 3px 3px 20px #000;
        display: grid;
        place-items: center;
        position: relative;
}
.heart {
        position: absolute;
        left: 0;
        top: 0;
        width: 40px;
        height: 40px;
        display: grid;
        place-items: center;
        font: normal 40px sans-serif;
        color: pink;
        offset-path: path('m271.44526,175.38086c65.55493,-161.83822 322.4013,0 0,208.07771c-322.4013,-208.07771 -65.55493,-369.91593 0,-208.07771z');
}
</style>

<div id="papa">
</div>

<script>
let total = 25;
Array.from({length: total}).forEach((item,key) => {
        item = document.createElement('span');
        item.className = 'heart';
        item.innerText = '\u2764';
        item.style.offsetDistance = 100/total *key + '%';
        papa.appendChild(item);
});
</script>

马黑黑 发表于 2022-11-12 08:22

如果需要移动心形在papa盒子中的位置,请酌情修改 .heart 选择器的 top 和 left 值

白开水 发表于 2022-11-12 08:55

好想学习一个。。

小辣椒 发表于 2022-11-12 11:39

这星星好漂亮,谢谢黑黑分享教程{:4_187:}

小辣椒 发表于 2022-11-12 11:40

水区的彩色星星也是很漂亮的{:4_178:}

马黑黑 发表于 2022-11-12 12:02

白开水 发表于 2022-11-12 08:55
好想学习一个。。

这个不是很复杂,慢慢看都能懂

马黑黑 发表于 2022-11-12 12:02

小辣椒 发表于 2022-11-12 11:40
水区的彩色星星也是很漂亮的

彩色的可能更丰富

马黑黑 发表于 2022-11-12 12:03

小辣椒 发表于 2022-11-12 11:39
这星星好漂亮,谢谢黑黑分享教程

喝水{:4_190:}

小辣椒 发表于 2022-11-12 13:40

马黑黑 发表于 2022-11-12 12:03
喝水

都学老头{:4_180:}

小辣椒 发表于 2022-11-12 13:40

马黑黑 发表于 2022-11-12 12:02
彩色的可能更丰富

是的,和淡色图图衬托会更加漂亮

马黑黑 发表于 2022-11-12 14:17

小辣椒 发表于 2022-11-12 13:40
是的,和淡色图图衬托会更加漂亮

一切看着办就好,你的帖子就应用的不错

马黑黑 发表于 2022-11-12 14:17

小辣椒 发表于 2022-11-12 13:40
都学老头

适当喝水挺好的

红影 发表于 2022-11-12 16:52

这个 100/total *key公式没看懂,为什么是这样的取值?

马黑黑 发表于 2022-11-12 17:40

红影 发表于 2022-11-12 16:52
这个 100/total *key公式没看懂,为什么是这样的取值?

offset-distance 偏移初始点的设置,这里使用百分比,total 是子元素总数量,子元素在100个单位里平均偏移量当然要用 100 除以 总数,然后,每个子元素都有自己的所以,从 0 开始,key 就是子元素的索引。

以第一个子元素为例,它的偏移量 100/total *0 = 0,它在原位置,也就是路径的初始位置,其它的子元素的偏移量计算依此类推。

白开水 发表于 2022-11-12 20:03

马黑黑 发表于 2022-11-12 12:02
这个不是很复杂,慢慢看都能懂

目前还是一脑蒙。。但是很想学会。

马黑黑 发表于 2022-11-12 20:04

白开水 发表于 2022-11-12 20:03
目前还是一脑蒙。。但是很想学会。

需要点基础,CSS,HTML,JS

白开水 发表于 2022-11-12 20:21

马黑黑 发表于 2022-11-12 20:04
需要点基础,CSS,HTML,JS

那完了。我都不会耶。

马黑黑 发表于 2022-11-12 20:43

白开水 发表于 2022-11-12 20:21
那完了。我都不会耶。

那很难理解和掌握
页: [1] 2 3
查看完整版本: 用offset-path实现N多子元素静态布局