【问题标题】:How to create a lollipop shape by stacking divs in a circular manner?如何通过以圆形方式堆叠div来创建棒棒糖形状?
【发布时间】:2019-08-05 03:06:04
【问题描述】:

如何以循环方式堆叠 div,其中最后一个 div 应位于第一个 div 下方但位于倒数第二个 div 上方。用css可以吗?任何帮助将不胜感激。

请查找Codepen。 给出示例代码sn -p

<div class="frame">
  <div class="lolly-pop__wrapper">
    <div class="lollypop-top">
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
    </div>
  </div>
</div>


.frame {
  position: absolute;
  display: flex;
  justify-content: center;
  top: 50%;
  left: 50%;
  width: 400px;
  height: 400px;
  margin-top: -200px;
  margin-left: -200px;
  border-radius: 2px;
  box-shadow: 4px 8px 16px 0 rgba(0,0,0,0.1);
  overflow: hidden;
  background: #F5CE51;
  color: #333;
  font-family: 'Open Sans', Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.lollypop-top {
    position: relative;
    height: 150px;
    width: 150px;
    background-color: #fff;
    border-radius: 100%;
    overflow: hidden;

    .lollypop-top__item {
        position: absolute;
        height: 150px;
        width: 150px;
        top: -50%;
        border-radius: 100%;
        transform-origin: bottom;
        background-color: #fff;

        &:nth-child(odd) {
            background-color: #D70606;
        }

        &:nth-child(1) {
            transform: rotate(30deg);
        }

        &:nth-child(2) {
            transform: rotate(60deg);
        }

        &:nth-child(3) {
            transform: rotate(90deg);
        }

        &:nth-child(4) {
            transform: rotate(120deg);
        }

        &:nth-child(5) {
            transform: rotate(150deg);
        }

        &:nth-child(6) {
            transform: rotate(180deg);
        }

        &:nth-child(7) {
            transform: rotate(210deg);
        }

        &:nth-child(8) {
            transform: rotate(240deg);
        }

        &:nth-child(9) {
            transform: rotate(270deg);
        }

        &:nth-child(10) {
            transform: rotate(300deg);
        }

        &:nth-child(11) {
            transform: rotate(330deg);
        }

        &:nth-child(12) {
            transform: rotate(360deg);
        }
      }
    }

.frame {
  position: absolute;
  display: flex;
  justify-content: center;
  top: 50%;
  left: 50%;
  width: 400px;
  height: 400px;
  margin-top: -200px;
  margin-left: -200px;
  border-radius: 2px;
  box-shadow: 4px 8px 16px 0 rgba(0, 0, 0, 0.1);
  overflow: hidden;
  background: #F5CE51;
  color: #333;
  font-family: 'Open Sans', Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.lollypop-top {
  position: relative;
  height: 150px;
  width: 150px;
  background-color: #fff;
  border-radius: 100%;
  overflow: hidden;
}

.lollypop-top .lollypop-top__item {
  position: absolute;
  height: 150px;
  width: 150px;
  top: -50%;
  border-radius: 100%;
  transform-origin: bottom;
  background-color: #fff;
}

.lollypop-top .lollypop-top__item:nth-child(odd) {
  background-color: #D70606;
}

.lollypop-top .lollypop-top__item:nth-child(1) {
  transform: rotate(30deg);
}

.lollypop-top .lollypop-top__item:nth-child(2) {
  transform: rotate(60deg);
}

.lollypop-top .lollypop-top__item:nth-child(3) {
  transform: rotate(90deg);
}

.lollypop-top .lollypop-top__item:nth-child(4) {
  transform: rotate(120deg);
}

.lollypop-top .lollypop-top__item:nth-child(5) {
  transform: rotate(150deg);
}

.lollypop-top .lollypop-top__item:nth-child(6) {
  transform: rotate(180deg);
}

.lollypop-top .lollypop-top__item:nth-child(7) {
  transform: rotate(210deg);
}

.lollypop-top .lollypop-top__item:nth-child(8) {
  transform: rotate(240deg);
}

.lollypop-top .lollypop-top__item:nth-child(9) {
  transform: rotate(270deg);
}

.lollypop-top .lollypop-top__item:nth-child(10) {
  transform: rotate(300deg);
}

.lollypop-top .lollypop-top__item:nth-child(11) {
  transform: rotate(330deg);
}

.lollypop-top .lollypop-top__item:nth-child(12) {
  transform: rotate(360deg);
}
<div class="frame">
  <div class="lolly-pop__wrapper">
    <div class="lollypop-top">
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
      <div class="lollypop-top__item"></div>
    </div>
  </div>
</div>

【问题讨论】:

  • 这只是关于最终的视觉效果?
  • 你需要给每个棒棒糖项目自己的定位......所以#1 top:0;左:0; #2 前:50;左:50;等等等等。目前,您将它们全部堆叠在一起
  • 为什么不直接创建.svg 图像并嵌入代码?
  • @TemaniAfif 我打算给它制作动画。
  • @Bertlucas 如果可以使用 css 那就太好了。

标签: css sass css-transforms css-shapes


【解决方案1】:

我会考虑两个元素(伪元素)和多个径向渐变来创建这个。您只需要创建两次形状的一半并旋转其中一个。

.box {
  width:150px;
  height:150px;
  border-radius:100%;
  border:1px solid;
  position:relative;
  overflow:hidden;
}
.box::before,
.box::after{
  content:"";
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:50%;
  background:
    /*we rotate by 30deg so will use :
       sin(30deg)*R = 0.5x75px   = 37.5px 
       cos(30deg)*R = 0.866x75px = 64.95px       
       10.05px = 75px - 64.95px;
       112.5px = 75px + 37.5px
       139.95px = 75px + 64.95px
       37.5px = 75px - 37.5px
       */
    radial-gradient(circle 75px at 139.95px 37.5px,red   98%,transparent 100%),
    radial-gradient(circle 75px at 112.5px 10.05px,white 98%,transparent 100%),
    radial-gradient(circle 75px at 75px    0,      red   98%,transparent 100%),
    radial-gradient(circle 75px at 37.5px  10.05px,white 98%,transparent 100%),
    radial-gradient(circle 75px at 10.05px 37.5px ,red   98%,transparent 100%),
    radial-gradient(circle 75px at 0       75px,   white 98%,transparent 100%),
    radial-gradient(circle 75px at 10.05px 112.5px,red   98%,transparent 100%);
}

.box::after {
 transform:rotate(180deg);
 transform-origin:right;
}
<div class="box">

</div>

为了让事情更有趣,我们可以添加 CSS 变量来轻松控制形状:

.box {
  --R:50px; /*Radius*/
  --c1:red; /*first color*/
  --c2:#fff; /*second color*/
  
  --g1:var(--c1) 98%, transparent 100%;
  --g2:var(--c2) 98%, transparent 100%;
  width:calc(2*var(--R));
  height:calc(2*var(--R));
  border-radius:100%;
  border:1px solid;
  position:relative;
  overflow:hidden;
  display:inline-block;
  vertical-align:middle;
}
.box::before,
.box::after{
  content:"";
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:50%;
  background:
     /*we rotate by 30deg so will use :
       sin(30deg)*R = 0.5xR   
       cos(30deg)*R = 0.866xR 
     */
    radial-gradient(circle var(--R) at calc(var(--R) + 0.866*var(--R)) calc(var(--R) - 0.5*var(--R))  ,var(--g1)),
    radial-gradient(circle var(--R) at calc(var(--R) + 0.5*var(--R))   calc(var(--R) - 0.866*var(--R)),var(--g2)),
    radial-gradient(circle var(--R) at var(--R)                        0                              ,var(--g1)),
    radial-gradient(circle var(--R) at calc(var(--R) - 0.5*var(--R))   calc(var(--R) - 0.866*var(--R)),var(--g2)),
    radial-gradient(circle var(--R) at calc(var(--R) - 0.866*var(--R)) calc(var(--R) - 0.5*var(--R))  ,var(--g1)),
    radial-gradient(circle var(--R) at 0                               var(--R)                        ,var(--g2)),
    radial-gradient(circle var(--R) at calc(var(--R) - 0.866*var(--R)) calc(var(--R) + 0.5*var(--R))  ,var(--g1));
}

/*the same shape rotated*/
.box::after {
 transform:rotate(180deg);
 transform-origin:right;
}
<div class="box"></div>

<div class="box" style="--R:80px;--c1:blue"></div>

<div class="box" style="--R:100px;--c1:green;--c2:yellow"></div>

<div class="box" style="--R:150px;--c1:white;--c2:pink"></div>

请注意,Safari 不支持 at 的语法(此处解释为 How to make radial gradients work in Safari?),所以这里是另一种语法:

.box {
  --R:50px; /*Radius*/
  --c1:red; /*first color*/
  --c2:#fff; /*second color*/
  
  --g1:var(--c1) 98%, transparent 100%;
  --g2:var(--c2) 98%, transparent 100%;
  width:calc(2*var(--R));
  height:calc(2*var(--R));
  border-radius:100%;
  border:1px solid;
  position:relative;
  overflow:hidden;
  display:inline-block;
  vertical-align:middle;
}
.box::before,
.box::after{
  content:"";
  position:absolute;
  top:0;
  bottom:0;
  left:0;
  right:50%;
  background:
     /*we rotate by 30deg so will use :
       sin(30deg)*R = 0.5xR   
       cos(30deg)*R = 0.866xR 
     */
    radial-gradient(farthest-side,var(--g1)) calc(var(--R) + 0.866*var(--R) - var(--R)) calc(var(--R) - 0.5*var(--R) - var(--R)),
     
    radial-gradient(farthest-side,var(--g1)) calc(var(--R) + 0.866*var(--R) - var(--R)) calc(var(--R) - 0.5*var(--R) - var(--R)),
    radial-gradient(farthest-side,var(--g2)) calc(var(--R) + 0.5*var(--R) - var(--R))   calc(var(--R) - 0.866*var(--R) - var(--R)),
    radial-gradient(farthest-side,var(--g1)) 0 calc(-1*var(--R)),
    radial-gradient(farthest-side,var(--g2)) calc(var(--R) - 0.5*var(--R) - var(--R))   calc(var(--R) - 0.866*var(--R) - var(--R)),
    radial-gradient(farthest-side,var(--g1)) calc(var(--R) - 0.866*var(--R) - var(--R)) calc(var(--R) - 0.5*var(--R) - var(--R)),
    radial-gradient(farthest-side,var(--g2)) calc(-1*var(--R))  0,
    radial-gradient(farthest-side,var(--g1)) calc(var(--R) - 0.866*var(--R) - var(--R)) calc(var(--R) + 0.5*var(--R) - var(--R));
   background-size:calc(2*var(--R)) calc(2*var(--R));
   background-repeat:no-repeat;
}

/*the same shape rotated*/
.box::after {
 transform:rotate(180deg);
 transform-origin:right center;
}
<div class="box"></div>

<div class="box" style="--R:80px;--c1:blue"></div>

<div class="box" style="--R:100px;--c1:green;--c2:yellow"></div>

<div class="box" style="--R:150px;--c1:white;--c2:pink"></div>

这里有一个Codepen 演示代码

【讨论】:

    【解决方案2】:

    我的方法是一个可重复使用的 SVG &lt;symbol&gt;,路径由 quadratic-bézier 曲线塑造:

    #svg-lollipop path { transform-origin: 50% 50%; }
    
    #svg-lollipop path:nth-child(2) {  transform: rotateZ(60deg); }
    #svg-lollipop path:nth-child(3) {  transform: rotateZ(120deg); }
    #svg-lollipop path:nth-child(4) {  transform: rotateZ(180deg); }
    #svg-lollipop path:nth-child(5) {  transform: rotateZ(240deg); }
    #svg-lollipop path:nth-child(6) {  transform: rotateZ(300deg); }
    
    .lollipop {
      width: 30%;
      display: inline-block;
      overflow: hidden;
      border-radius: 50%;
      position: relative;
      margin: 0 20px;
    }
    
    .lollipop::before {
      content: "";
      padding-bottom: 100%;
      display: block;
    }
    
    .lollipop svg {
      position: absolute;  
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      height: 100%;
      fill: currentColor;
    }
    
    .lollipop--animated {
      animation: rotate 10s linear 0s infinite;
    }
    
    @keyframes rotate {
      0% { transform: rotateZ(0) }
      100% { transform: rotateZ(1turn) }
    }
    <svg style="display: none;">
       <symbol id="svg-lollipop">
          <path d="M150,150 Q75,185 0,150 H0 V63.6 Q75,150 150,150 z" />
          <path d="M150,150 Q75,185 0,150 H0 V63.6 Q75,150 150,150 z" />
          <path d="M150,150 Q75,185 0,150 H0 V63.6 Q75,150 150,150 z" />
          <path d="M150,150 Q75,185 0,150 H0 V63.6 Q75,150 150,150 z" />
          <path d="M150,150 Q75,185 0,150 H0 V63.6 Q75,150 150,150 z" />
          <path d="M150,150 Q75,185 0,150 H0 V63.6 Q75,150 150,150 z" />
       </symbol>
    </svg>
    
    <div class="lollipop lollipop--animated" 
      style="background-color: #FFF; color:#E92120;">
      <svg viewBox="0 0 300 300"><use xlink:href="#svg-lollipop"></use></svg>
    </div>
    
    <div class="lollipop" 
      style="background-color: #004991; color:#007BC1;">
      <svg viewBox="0 0 300 300"><use xlink:href="#svg-lollipop"></use></svg>
    </div>

    工作原理

    相同的形状被克隆 6 次并旋转以填充整个 svg。在此示例中,每个彩色形状都有一个角度 α = 30deg

    然后从三角函数中我们可以找到曲线原点的坐标:在路径中 y 坐标 63.6 获得为150 - (150 * tan(α)),所以如果您需要更改形状和角度的数量,您可以轻松找到自己的原点(quadratic curves 真的很容易绘制)。

    最后,外包装有一个border-radius 和一个隐藏的overflow 以形成圆形。


    最终结果也是响应式的,因为外包装保持其1:1 纵横比。

    白色区域可以通过在容器上设置background-color 来更改,而彩色区域可以通过color 属性来更改(svg 元素的fill 属性设置为currentColor为了您的方便)。


    我后来注意到的一些事情

    如果您将box-shadow: inset 0 0 20px #aaa; 添加到包装器中,则图像看起来像充气沙滩气球而不是棒棒糖。

    机缘巧合。

    【讨论】:

      【解决方案3】:

      也检查一下这个答案。Codepen

      <div class="frame">
      <div class="lolly-pop__wrapper">
      <div class="lollypop-top">
          <div class="first__half">
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
          </div>
              <div class="second__half">
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
              <div class="lollypop-top__item"></div>
          </div>
      </div>
      </div>
      </div>
      
      
      .frame {
        position: absolute;
        display: flex;
        justify-content: center;
        top: 50%;
        left: 50%;
        width: 400px;
        height: 400px;
        margin-top: -200px;
        margin-left: -200px;
        border-radius: 2px;
        box-shadow: 4px 8px 16px 0 rgba(0,0,0,0.1);
        overflow: hidden;
        background: #F5CE51;
        color: #333;
        font-family: 'Open Sans', Helvetica, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
      }
      
      .lollypop-top {
          position: relative;
          height: 150px;
          width: 150px;
          background-color: #ccc;
          border-radius: 100%;
          overflow: hidden;
      
      .lollypop-top__item {
          position: absolute;
          height: 150px;
          width: 150px;
          top: -50%;
          border-radius: 100%;
          transform-origin: bottom;
          background-color: #fff;
      
          &:nth-child(odd) {
              background-color: #D70606;
          }
      
          &:nth-child(1) {
              transform: rotate(30deg);
          }
      
          &:nth-child(2) {
              transform: rotate(60deg);
          }
      
          &:nth-child(3) {
              transform: rotate(90deg);
          }
      
          &:nth-child(4) {
              transform: rotate(120deg);
          }
      
          &:nth-child(5) {
              transform: rotate(150deg);
          }
      
          &:nth-child(6) {
              transform: rotate(180deg);
          }
      
          &:nth-child(7) {
              transform: rotate(210deg);
          }
      
          &:nth-child(8) {
              transform: rotate(240deg);
          }
      
          &:nth-child(9) {
              transform: rotate(270deg);
          }
      
          &:nth-child(10) {
              transform: rotate(300deg);
          }
      
          &:nth-child(11) {
              transform: rotate(330deg);
          }
      
          &:nth-child(12) {
              transform: rotate(360deg);
          }
      
          &:nth-child(13) {
              transform: rotate(390deg);
          }
      
          &:nth-child(14) {
              transform: rotate(420deg);
          }
        }
      }
      
      .first__half,
      .second__half {
          position: absolute;
          left: 0;
          top: 0;
          height: 100%;
          overflow: hidden;
      }
      
      .first__half {
          width: 50%;
      }
      
      .second__half {
          right: 0;
          width: 50%;
          transform: rotate(180deg);
          transform-origin:right center;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-04-17
        • 2015-08-12
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 2015-11-01
        • 2017-07-28
        • 2015-02-19
        • 2015-08-25
        相关资源
        最近更新 更多