创建响应式云形状

22

我一直在尝试为一个项目创建一个响应式的云形CSS,但由于HTTP请求和响应要求,我试图不使用图片、CSS或内置SVG来完成。

所需的形状将是这个(但可以类似-略微变化/改进会很酷):

Cloud Shape

我发现了这两个问题,但它们似乎不适合我的确切需要:

我已经尝试过(失败了)用borderbox-shadow创建云朵,需要知道是否可以通过CSS或替代方案内联SVG实现。我也看到Canvas也是一个选项,但我更喜欢远离它,因为它可能会相当复杂。

这是我的差劲的尝试。

body {
  background: skyblue;
}

.cloud {
  width: 15%;
  height: 10vh;
  background: white;
  position: relative;
  margin: 100px 100px;
  border-radius: 65px;
  box-shadow: black 0 0 10px 10px;
}
.cloud:after {
  content: '';
  position: absolute;
  width: 150px;
  height: 150px;
  top: -60px;
  left: 100px;
  border-radius: 75px;
  background: white;
}
.cloud:before {
  content: '';
  position: absolute;
  width: 70px;
  height: 70px;
  background: white;
  left: 50px;
  top: -30px;
  border-radius: 35px;
}
<div class="cloud"></div>

如您所见,我在响应性方面遇到了一些问题,无法准确计算每个元素所需的高度/宽度。

我还尝试将HTML的数量保持到最少,并且更喜欢使用单个div或简短的SVG代码。

2个回答

30

使用单个path元素可以使用SVG创建云形状。由于SVG本质上是可缩放的且不会导致形状失真,因此浏览器对SVG的支持非常好,如果需要,可以使用VML提供IE8及以下版本的回退。

形状创建

绘制形状时使用的命令及其含义如下:

  • M 25,60 - 此命令将笔移动到X轴前进25px和Y轴前进60px的位置。(注意:该命令用大写字母书写,表示它是绝对移动而不是相对移动)。
  • a 20,20 1 0,0 0,40 - 此命令创建一个圆弧,其X和Y半径为20像素。弧起点在(25,60),终点在(25,100)(即,X轴上距离为0px,Y轴上距离为40px)。
  • h 50 - 此命令绘制一条水平线,距离起点向前50px。由于是相对的,因此终点将位于(75,100)。
  • a 20,20 1 0,0 0,-40 - 类似于第二个命令,创建另一个半径为20px的圆弧,在先前点的相对位置向前40px。因此,本质上会在(75,100)到(75,60)之间创建一条弧线。该命令与第二个命令一起形成云的两侧的弧线。
  • a 10,10 1 0,0 -15,-10 - 另一个圆弧命令,用于创建云的曲线顶部的一部分。半径为10px,弧线从(75,60)到(60,50)。
  • a 15,15 1 0,0 -35,10 - 最终弧线,以完成云的形状。半径为15px,弧线从(60,50)到(25,60)。(25,60)是原始起点,因此完成了整个形状。
  • z - 关闭路径。

svg {
  height: 50%;
  width: 50%;
}
path {
  fill: white;
  stroke: black;
  stroke-width: 2;
  stroke-linejoin: round;
}
path:hover {
  fill: aliceblue;
  stroke: lightskyblue;
}
<svg viewBox='0 0 105 105'>
  <path d='M 25,60 
           a 20,20 1 0,0 0,40 
           h 50 
           a 20,20 1 0,0 0,-40 
           a 10,10 1 0,0 -15,-10 
           a 15,15 1 0,0 -35,10  
           z' />
</svg>


使用SVG的优点

  • 易于创建和维护
  • 命令简单易懂,不需要复杂的定位或hack技巧
  • 默认情况下可缩放(响应式)
  • 只要SVG是内联的,就不需要额外的HTTP请求
  • 对弧线及其半径等有更好的控制
  • 悬停效果(如下方片段所示)可以限制在鼠标在形状边界内时才触发。
  • 可以轻松添加额外的效果。也就是说,您可以模仿形状在屏幕上绘制的行为等。

额外效果 - 云绘制动画

下面是一个带有云绘制动画的示例片段,其中通过重复递减路径的stroke-dashoffset属性来绘制路径,直到它变为0。初始偏移值等于使用getTotalLength()方法计算的路径总长度。云形状还添加了模糊阴影。

使用window.requestAnimationFrame方法实现动画。

window.onload = function() {
  var offset;
  var path = document.getElementsByTagName('path')[0];
  var len = path.getTotalLength();

  function paint() {
    path.style.strokeDashoffset = len;
    path.style.strokeDasharray = len + ',' + len;
    animate();
  }

  function animate() {
    if (!offset) offset = len;
    offset -= 0.5;
    path.style.strokeDashoffset = offset;
    if (offset < 0)
      window.cancelAnimationFrame(anim);
    else anim = window.requestAnimationFrame(function() {
      animate();
    });
  }

  paint();
};
svg {
  height: 40%;
  width: 40%;
}
path {
  fill: white;
  stroke: black;
  stroke-width: 2;
  stroke-linejoin: round;
}
path:hover {
  fill: aliceblue;
  stroke: lightskyblue;
}
<svg viewBox='0 0 105 105'>
  <filter id='shadow'>
    <feGaussianBlur in='SourceAlpha' stdDeviation='2' />
    <feOffset dx='2' dy='0' result='blur' />
    <feMerge>
      <feMergeNode in='blur' />
      <feMergeNode in='SourceGraphic' />
    </feMerge>
  </filter>
  <path d='M 25,60 
           a 20,20 1 0,0 0,40 
           h 50 
           a 20,20 1 0,0 0,-40 
           a 10,10 1 0,0 -15,-10 
           a 15,15 1 0,0 -36,10  
           z' filter='url(#shadow)' />
</svg>


14

蓬松的云和彩虹。

免责声明:这里没有彩虹

不过,下面是一个基本的“云”,由单个元素创建,并且它使用了vw单位,因此也相当具有响应性。

它使用两个伪元素作为圆形,以在顶部创建云的“烟囱”。这还可以允许使用边框,因为您可以旋转圆圈并将边框颜色应用于其中两个边。

.cloud {
  height: 30vw;
  width: 90vw;
  background: lightgray;
  border-radius: 40vw;
  border: 5px solid black;
  position: relative;
  margin-top: 20vw;
}
.cloud:before {
  content: "";
  position: absolute;
  top: -10vw;
  box-sizing: border-box;
  height: 20vw;
  width: 20vw;
  left: 15vw;
  border-radius: 50%;
  border: 5px solid black;
  border-bottom-color: transparent;
  border-right-color: transparent;
  background: lightgray;
  transform: rotate(40deg);
}
.cloud:after {
  content: "";
  position: absolute;
  height: 40vw;
  width: 40vw;
  top: -20vw;
  left: 32vw;
  border-radius: 50%;
  box-sizing: border-box;
  border: 5px solid black;
  border-bottom-color: transparent;
  background: lightgray;
  border-right-color: transparent;
  transform: rotate(55deg);
}
<div class="cloud"></div>

尽管本答案使用了CSS,但如果您需要更多地控制云形状的输出,则使用SVG可能更有利。


另外,SVG也可以使用

<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
  <g>
    <path d="M320,128c52,0,95,42,96,94c-0,1-0,3-0.5,5l-0.812,23l22,7
  C462,268,480,293,480,320c0,35-28,64-64,64H96c-35,0-64-28-64-64c0-34,28-63,63-64
  c1,0,3,0,4,0l24,1l8-22C140,209,165,192,192,192c3,0,6,0,11,1
  l22,4.031l11-19C253.875,146,285,128,320,128 M320,96c-47,0-89,26-111,65
  C203,160.719,197,160,192,160c-41,0-77.219,27-90.281,64.563C99.813,224.438,97.969,224,96,224c-53,0-96,43-96,96
  s43,96,96,96h320c53,0,96-43,96-96c0-41-27-77-64-90C447.5,227.75,448,225.938,448,224
  C448,153,390,96,320,96L320,96z" />
  </g>
</svg>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接