马黑黑 发表于 2023-4-8 17:47

由点组成的圆盘

<style>
#wrap {
      margin: 30px auto;
      width: 200px;
      height: 200px;
      display: grid;
      place-items: center;
      position: relative;
}
#wrap >span {
      position: absolute;
      width: 10px;
      height: 10px;
      border-radius: 50%;
      border: 8px dotted black;
}
</style>

<p>先看效果:<br><br></p>
<div id="wrap"></div>

<script>

Array.from({length:10}).forEach((item,key) => {
      let sp = document.createElement('span');
      sp.style.cssText += `
                width: ${key*18}px;
                height: ${key*18}px;
                border-color: #${Math.random().toString(16).substr(-6)};
      `;
      wrap.appendChild(sp);
});

</script>
<p><br><br>然后我将在后续的回复中逐一讲解——</p>

马黑黑 发表于 2023-4-8 17:47

本帖最后由 马黑黑 于 2023-4-8 21:23 编辑

先说一下HTML结构:

<div id="wrap">
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
</div>

这是一个 div 父元素 wrap 带十个 span 子元素的简单结构。在实际实现一楼的效果中,我并没有这么写HTML代码,而是这样写:

    <div id="wrap"></div>

没有 span 元素。为什么?因为,这些 span 元素涉及到诸多的算法,如果全用 CSS+HTML 写出来代码会有些繁琐,可以使用JS来高效实现。不过结构如此,理解了结构有助于对后续实现原理的理解。下面就说说——

实现原理:

父元素 wrap 起到包裹和约束子元素的作用,#wrap 选择器将定义为 grip 布局并设置其子元素绝对居中(即横向纵向两个方向都居中),仅此而已。

10 个 span 子元素,宽高从里到外,依次设置为外比里大一定尺寸的像素值,而它们的边框(border)设置为统一的尺寸值,样式风格为 dotted(小圆点),设置任意的初始边框颜色(后面JS会覆盖掉它们的边框颜色)。


马黑黑 发表于 2023-4-8 17:48

本帖最后由 马黑黑 于 2023-4-8 18:50 编辑 <br /><br /><style>
.papa > p { margin: 10px 0; }
.wrap {
        margin: 30px auto;
        width: 200px;
        height: 200px;
        display: grid;
        place-items: center;
        border: 1px solid purple;
        position: relative;
}
.wrap >span {
        position: absolute;
        width: 10px;
        height: 10px;
        border-radius: 50%;
        border: 8px dotted black;
}
</style>

<div class="papa">
        <p><font color="#ff0000">实现步骤</font>(一):</p>
        <p>首先,先写好 #wrap 选择器的CSS代码和wrap元素的HTML代码:</p>
        <blockquote><pre>
&lt;style&gt;
#wrap {
        margin: 30px auto;
        width: 200px;
        height: 200px;
        display: grid;
        place-items: center;
        position: relative;
        border: 1px solid purple;
}
&lt;/style&gt;

&lt;div class="wrap"&gt;&lt;/div&gt;
        </pre></blockquote>
        <p>#wrap 选择器的最后一句设置了一个边框,用来协助观察,将来弄好了要删掉它。这样,父元素准备好了,效果如下:</p>
        <div class="wrap"></div>
        <p>一楼效果的那些点,将会呈现在上面这个方框里。</p>
</div>

马黑黑 发表于 2023-4-8 17:48

本帖最后由 马黑黑 于 2023-4-8 22:42 编辑 <br /><br /><style>
.wrap > span {
        position: absolute;
        width: 0;
        height: 0;
        border-radius: 50%;
        border: 8px dotted black;
}
.wrap > span:nth-of-type(2) {
        width: 18px;
        height: 18px;
        border-color: red;
}
</style>

<div class="papa">
        <p><font color="#ff0000">实现步骤</font>(二):</p>
        <p>这个步骤是尝试性质,主要是推演一下各个 span 子元素的宽高尺寸算法。当然,span 的基本CSS设置,最终效果会用到,所以应加入到CSS代码中。下面,我们就给 span 标签做一个基本设置,它隶属于 wrap,是 wrap 的子元素,所以我们可以这样写这些 span 标签的共性基本代码:</p>
        <blockquote><pre>&lt;style&gt;
#wrap {
        margin: 30px auto;
        width: 200px;
        height: 200px;
        display: grid;
        place-items: center;
        position: relative;
        border: 1px solid purple;
}
#wrap &gt; span {
        position: absolute;
        width: 0;
        height: 0;
        border-radius: 50%;
        border: 8px dotted black;
}
&lt;/style&gt;

&lt;div id="wrap"&gt;
        &lt;span&gt;&lt;/span&gt;
&lt;/div&gt;
        </pre></blockquote>
        <p>运行以上代码,效果如下:</p>
        <div class="wrap"><span></span></div>
        <p>如果我们有第二个 span 标签,它会覆盖在第一个标签之上,因而,我们需要为第二个 span 标签单独设置更大的尺寸以及其它属性:</p>
        <blockqute><pre>#wrap &gt; span:nth-of-type(2) {
        width: 18px;
        height: 18px;
        border-color: red;
}
        </pre></blockqute>
        <p>为什么宽高设置为18px呢?首先,这是为所有的 span 预设了一个规律:每一个 span 的宽高尺寸都按自己的索引乘以18,第一个 span 的索引是 0,0 乘以 18 等于 0,正是CSS里所设计的,第二个索引是1,乘以18就是18,其余依次类推;其次,18的依据是,span 的边框厚度是8,当 span 的宽高为 0 时,它实际占位是16个像素,我们给第二个 span 的宽高都加上 2 ,是希望它与第一个拉开 2px 的距离。</p>
        <p>现在,我们给HTML代码加一组 span 标签,看看效果:</p>
        <div class="wrap"><span></span><span></span></div>
</div>

马黑黑 发表于 2023-4-8 17:48

本帖最后由 马黑黑 于 2023-4-8 21:32 编辑

实现步骤(三):

前面,在尝试性的步骤二中,我们预设了 wrap 父元素的 span 子元素一些规则:最里边的 span 宽高为0,它由 border 边框构成一个 8 像素的圆点,它之外两个两个像素处是它的第一个兄弟,宽高为 10 像素,边框厚度同样是 4 个像素。接着,下一个兄弟,排行老三,索引号是2,它的宽高尺寸按照预设规则是 2*18 = 36 个像素,其余的依此类推。嗯,写 10个 #wrap > span:nth-of-type(x) 很繁琐,这个工作可以交给 JS 完成:

<script>

Array.from({length:10}).forEach((item,key) => {
      let sp = document.createElement('span');
      sp.style.cssText += `
                width: ${key*18}px;
                height: ${key*18}px;
                border-color: #${Math.random().toString(16).substr(-6)};
      `;
      wrap.appendChild(sp);
});


</script>


Array.from({length:10}) 构建了一个有 10 个数组元素的数组,如果想修改 span 子元素的个数,将 10 改为其他数字就好。

接着,使用 forEach 循环方法,为上述数组的每一个数组元素构建 span 标签并追加到 wrap 元素中。这些 span 标签,每一个都以自己的索引号 key 乘以 18,它的边框颜色(border-color)取16进制随机值。因为事先存在了 span 标签的CSS设定,因此 span 子标签变量 sp 的 style.cssText 采用 += 的方式追加,注意我们使用了反引号 `` ,因之我们可以将CSS语句分行写,里面涉及到JS变量和运算式子时,用 ${...} 表示,该语句的 ... 即为JS变量或运算式子。

一楼效果的完整代码放在下一层楼。

马黑黑 发表于 2023-4-8 18:17

本帖最后由 马黑黑 于 2023-4-8 21:00 编辑

一楼效果完整代码:
<style>
#wrap {
        margin: 30px auto;
        width: 200px;
        height: 200px;
        display: grid;
        place-items: center;
        position: relative;
}
#wrap > span {
        position: absolute;
        width: 0;
        height: 0;
        border-radius: 50%;
        border: 8px dotted black;
}
#wrap > span:nth-of-type(2) {
        width: 18px;
        height: 18px;
        border-color: red;
}
</style>

<div id="wrap"></div>

<script>

Array.from({length:10}).forEach((item,key) => {
        let sp = document.createElement('span');
        sp.style.cssText += `
                width: ${key*18}px;
                height: ${key*18}px;
                border-color: #${Math.random().toString(16).substr(-6)};
        `;
        wrap.appendChild(sp);
});

</script>

雨中悄然 发表于 2023-4-8 18:33

本帖最后由 马黑黑 于 2023-4-9 00:23 编辑

占位六:扩展应用
<style>

.wrap {
        margin: 30px auto;
        width: 200px;
        height: 200px;
        display: grid;
        place-items: center;
        position: relative;
        border: 1px solid tan;
        --deg: 0deg; --state: running; --time: 10s;
}

.wrap > span {
        position: absolute;
        width: 10px;
        height: 10px;
        border-radius: 50%;
        border: 8px dashed black;
        transform: rotate(var(--deg));
        animation: rot var(--time) infinite linear var(--state);
}

@keyframes rot {
        from { transform: rotate(var(--deg)); }
        to { transform: rotate(calc(var(--deg) + 360deg)); }
}

</style>

<div class="wrap"></div>

<script>

let wrap = document.querySelector('.wrap'), root = document.querySelector(':root');
Array.from({length:10}).forEach((item,key) => {
        let sp = document.createElement('span');
        sp.style.cssText += `
                --deg: ${Math.random()*(key+10)}deg;
                --time: ${Math.random()*10+10}s;
                width: ${key*18}px;
                height: ${key*18}px;
                border-color: #${Math.random().toString(16).substr(-6)};
                border-width: ${key+4}px;
        `;
        wrap.appendChild(sp);
});

</script>

小辣椒 发表于 2023-4-8 21:37

现在可以回帖了

小辣椒 发表于 2023-4-8 21:38

黑黑这个圆盘是为后面做播放器组排准备吧

马黑黑 发表于 2023-4-8 21:42

小辣椒 发表于 2023-4-8 21:38
黑黑这个圆盘是为后面做播放器组排准备吧

也未必吧,主要是觉得它好看。类似的结构,doodle 框架有一个非常漂亮的示例,我研究了一下,决定用原生 JS 做一个相近的(二者并不一样)。

马黑黑 发表于 2023-4-8 21:43

小辣椒 发表于 2023-4-8 21:37
现在可以回帖了

早就可以会了,该站位的俺都占了{:5_106:}

小辣椒 发表于 2023-4-8 21:59

马黑黑 发表于 2023-4-8 21:42
也未必吧,主要是觉得它好看。类似的结构,doodle 框架有一个非常漂亮的示例,我研究了一下,决定用原生...

反正小辣椒就套用学习的{:4_170:}

小辣椒 发表于 2023-4-8 22:00

马黑黑 发表于 2023-4-8 21:43
早就可以会了,该站位的俺都占了

我特意等一下的,怕占了楼

马黑黑 发表于 2023-4-8 22:37

小辣椒 发表于 2023-4-8 22:00
我特意等一下的,怕占了楼

我早占了额

马黑黑 发表于 2023-4-8 22:37

小辣椒 发表于 2023-4-8 21:59
反正小辣椒就套用学习的

基础知识不懂还是不行的

红影 发表于 2023-4-8 22:38

马黑黑 发表于 2023-4-8 17:48
本帖最后由 马黑黑 于 2023-4-8 21:27 编辑
.wrap > span {
        position: absolute;


到这步已经不懂了,为什么“span 的边框厚度是4“?不是设置了8px么?

马黑黑 发表于 2023-4-8 22:44

红影 发表于 2023-4-8 22:38
到这步已经不懂了,为什么“span 的边框厚度是4“?不是设置了8px么?

额,那是我描述错误。应该是酱紫:

第一个span,宽高为0,边框厚度是8,实际占位是16,加上两个像素的差距,所以第二个span的宽高是18,其他的依此类推。

红影 发表于 2023-4-8 23:10

马黑黑 发表于 2023-4-8 22:44
额,那是我描述错误。应该是酱紫:

第一个span,宽高为0,边框厚度是8,实际占位是16,加上两个像素的 ...

这样说好像能懂点,可是,第二个也有厚度,若是16,再加上第二个的厚度,那么2个像素出不来啊。实际上却出来了,我就是没弄明白怎么出来的。
我拿像素尺去量了一下,那个黑点是8不是16
如果第一和第二个都是8,那么用18的宽高,剩下的间隙是1个像素,不是2个。只是从第二个开始,看着都小了一半啊。今天跑出忙一天,脑袋有点晕,黑黑勿怪{:5_109:}

马黑黑 发表于 2023-4-8 23:39

红影 发表于 2023-4-8 23:10
这样说好像能懂点,可是,第二个也有厚度,若是16,再加上第二个的厚度,那么2个像素出不来啊。实际上却 ...

黑点绝对是 16px,你再量一量。

第一个span实际占位16px;第二个18px宽高,肯定于前一个 16px实际占位拉开2px的距离,再加上8px边框,实际占位 18+8*2 = 34px;第三个span,2*18=36px,离第二个也拉开2px,加上 2*8=16的边框,它实际占位 2*18 + 2*8 = 52 ……

这里面的算法是没有问题的

红影 发表于 2023-4-9 11:55

马黑黑 发表于 2023-4-8 23:39
黑点绝对是 16px,你再量一量。

第一个span实际占位16px;第二个18px宽高,肯定于前一个 16px实际占位 ...

对对,边框是向外的,我又弄错了,以为是骑在线上的,哈哈,弄错第二次了都,下回坚决要记住了{:4_170:}
页: [1] 2 3 4
查看完整版本: 由点组成的圆盘