div的凸出边,在CSS

时间:2015-10-04 09:49:01

标签: css css3 css-animations css-shapes

enter image description here

我希望在CSS中创建两个形状。第一个,左边的那个,我接近制作,但我的形状走得太远了。

第二种形状,我正在完全挣扎。

无论如何都要复制这些形状?反正有没有使用Psuedo元素/只作为一个div?

目标是使用CSS动画将第一个形状设为第二个,所以我不相信SVG是一个选项

div应从形状一开始,逐渐过渡到形状二。用我的方法来说,到目前为止我的问题还没有突出。

HTML

<div id="one"></div>
<div id="two"></div>

CSS

div {
    width: 80px;
    height: 80px;
    background: black;
    margin: 60px;
    position: relative;
}

#one:before {
  content: "";
  display: block;
  position: absolute;
  border-radius: 55%;
  width: 80px;
  height: 80px;
  background: black;
  left: 0;
  top: -34px;
}

JS Fiddle Link

3 个答案:

答案 0 :(得分:4)

你可以使用Raphael或SVG变形bezier路径,但我不知道该怎么做。这应该是最干净的解决方案

我认为这可能有用: -

  • 创建一个元素并将Overflow隐藏

  • 设置伪元素的时间,动画边框半径和高度

  • 使用伪元素的框阴影进行着色。

<强>&GT; Fiddle&lt;

&#13;
&#13;
body{
    background: url("http://www.placekitten.com/g/600/400");
    background-size: cover;
}

#rect {
    height: 300px;
    width: 100px;
    border-top-left-radius: 50px 40px;
    border-top-right-radius: 50px 40px;
    position: relative;
    overflow: hidden;
    -webkit-animation: morph 1s linear 1;
    -webkit-animation-fill-mode: forwards;
    
    animation: morph 1s linear 1;
    animation-fill-mode: forwards; 
}

#rect:before {
    position: absolute;
    content: "";
    width: 100px;
    box-shadow: 0px 0px 0px 400px #A34;
    -webkit-animation: morph2 1s linear 1;
    -webkit-animation-delay: 1s;
    -webkit-animation-fill-mode: forwards;
    
    animation: morph2 1s linear 1;
    animation-delay: 1s;
    animation-fill-mode: forwards;
    
}

@-webkit-keyframes morph {
    0%{
        border-top-left-radius: 50px 40px;
        border-top-right-radius: 50px 40px;
        top:0px;
        height: 300px;
    }
    100%{
        border-top-left-radius: 40px 0px;
        border-top-right-radius: 40px 0px;
        top: 40px;
        height: 260px;
    }
}

@-webkit-keyframes morph2 {
    0%{
        height: 0px;
        border-bottom-left-radius: 40px 0px;
        border-bottom-right-radius: 40px 0px;
    }
    100%{
        border-bottom-left-radius: 50px 40px;
        border-bottom-right-radius: 50px 40px;
        height: 40px;
    }
}

/*FOR OTHER BROWSERS*/

@keyframes morph {
    0%{
        border-top-left-radius: 50px 40px;
        border-top-right-radius: 50px 40px;
        top:0px;
        height: 300px;
    }
    100%{
        border-top-left-radius: 40px 0px;
        border-top-right-radius: 40px 0px;
        top: 40px;
        height: 260px;
    }
}

@keyframes morph2 {
    0%{
        height: 0px;
        border-bottom-left-radius: 40px 0px;
        border-bottom-right-radius: 40px 0px;
    }
    100%{
        border-bottom-left-radius: 50px 40px;
        border-bottom-right-radius: 50px 40px;
        height: 40px;
    }
}
&#13;
<div id="rect">
</div>
&#13;
&#13;
&#13;

注意抱歉代码有点太大了,我写了大约一年后写的CSS和HTML!我认为可以缩短很多这种混乱。

答案 1 :(得分:3)

据我所知,没有使用伪元素就无法实现动画效果。以下是使用多个渐变和伪元素的一种可能(但非常复杂的方法)。形状由以下部分组成:

  • 具有凹陷/凹陷形状的主div元素。它使用径向梯度和线性梯度的组合生成。父级的一半高度由径向渐变占据并产生透明切口,另一半(底部)半部由线性渐变占据并最终产生纯黑色。线性渐变实际上不产生任何渐变,而是仅产生纯色,因为纯色的颜色停止太靠近终点。这仍然是必需的,因为不使用渐变(作为图像),我们无法控制纯色占据的空间。
  • :before元素,它具有两个径向渐变,并产生两个半椭圆相互叠加的效果。顶部的一个是透明的半椭圆形(其余为黑色),而底部的一个是黑色半椭圆形(其余部分是透明的)。我们需要两个渐变,因为当我们为background-position设置动画时,这看起来好像凸出的区域正在崩溃。
  • :after元素有一个径向渐变,产生一个纯黑色椭圆。此元素位于父元素上方的一半以产生凸出效果。
  • 在动画的第一部分中,:after元素沿X轴旋转90度,这使得它看起来好像从视图中慢慢消失。在动画的第二部分期间,:before元素的background-position被动画化,使得黑色半椭圆偏离路径并且透明的半椭圆形到位。

&#13;
&#13;
div {
  position: relative;
  height: 80px;
  width: 80px;
  margin-top: 60px; /* safe to have half of parent height */
  background: radial-gradient(ellipse at 50% 0%, transparent 70%, black 72%), linear-gradient(to bottom, black 99.9%, transparent 99.9%);
  background-size: 100% 50%, 100% 50%; /* the height of first image will be same as height of transparent cut, height of second image is the rest */
  background-position: 0% 0%, 0% 100%;
  background-repeat: no-repeat;
}
div:before,
div:after {
  position: absolute;
  content: '';
  width: 100%;
}
div:before {
  height: 100%; /* height of first image on parent * 2 */
  top: 0px;
  background-image: radial-gradient(ellipse at 50% 0%, black 70%, transparent 72%), radial-gradient(ellipse at 50% 0%, transparent 70%, black 72%);
  background-size: 100% 50%;
  background-position: 0% 2px, 0% -38px;
  background-repeat: no-repeat;
  animation: morph-shape 2s 2s linear forwards;
}
div:after {
  height: 50%; /* this should be same as height of first image on parent */
  top: -38px; /* this is height of pseudo-element in % * height of parent - 2px */
  background-image: radial-gradient(ellipse at 50% 50%, black 70%, transparent 72%);
  background-size: 100% 200%;
  background-repeat: no-repeat;
  transform-origin: bottom;
  animation: morph-shape2 2s linear forwards;
}
@keyframes morph-shape2 {
  from {
    transform: rotateX(0deg);
  }
  to {
    transform: rotateX(90deg);
  }
}
@keyframes morph-shape {
  from {
    background-position: 0% 2px, 0% -38px; /* the negative value is height of image - 2px = 50% of container height (which is 50% of 80px) - 2px*/
  }
  to {
    background-position: 0% 100%, 0% 0%;
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div></div>
&#13;
&#13;
&#13;

仅为了说明,这里是三个元素在没有放在另一个上面时的样子。我已经离开动画了,你仍然可以感受到它到底发生了什么。此外,即使更改了父级的维度(如果评论中提到的计算正确完成),它似乎也能正常工作。

&#13;
&#13;
div {
  position: relative;
  height: 160px;
  width: 120px;
  margin-top: 80px;
  background: radial-gradient(ellipse at 50% 0%, transparent 70%, black 72%), linear-gradient(to bottom, black 99.9%, transparent 99.9%);
  background-size: 100% 40%, 100% 60%;
  background-position: 0% 0%, 0% 100%;
  background-repeat: no-repeat;
}
div:before,
div:after {
  position: absolute;
  content: '';
  width: 100%;
}
div:before {
  height: 80%;
  top: 0px;
  left: 150px;
  background-image: radial-gradient(ellipse at 50% 0%, black 70%, transparent 72%), radial-gradient(ellipse at 50% 0%, transparent 70%, black 72%);
  background-size: 100% 50%;
  background-position: 0 2px, 0% -62px;
  background-repeat: no-repeat;
  animation: morph-shape 2s 2s linear forwards;
}
div:after {
  height: 40%;
  top: -62px;
  left: 300px;
  background-image: radial-gradient(ellipse at 50% 50%, black 70%, transparent 72%);
  background-size: 100% 200%;
  background-repeat: no-repeat;
  transform-origin: bottom;
  animation: morph-shape2 2s linear forwards;
}
@keyframes morph-shape2 {
  from {
    transform: rotateX(0deg);
  }
  to {
    transform: rotateX(90deg);
  }
}
@keyframes morph-shape {
  from {
    background-position: 0% 2px, 0% -62px;
  }
  to {
    background-position: 0% 100%, 0% 0%;
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div></div>
&#13;
&#13;
&#13;

下面是容器和透明切口的不同尺寸的版本。

&#13;
&#13;
div {
  position: relative;
  height: 200px;
  width: 150px;
  margin-top: 100px;
  background: radial-gradient(ellipse at 50% 0%, transparent 70%, black 72%), linear-gradient(to bottom, black 99.9%, transparent 99.9%);
  background-size: 100% 30%, 100% 70%;
  background-position: 0% 0%, 0% 100%;
  background-repeat: no-repeat;
}
div:before,
div:after {
  position: absolute;
  content: '';
  width: 100%;
}
div:before {
  height: 60%;
  top: 0px;
  background-image: radial-gradient(ellipse at 50% 0%, black 70%, transparent 72%), radial-gradient(ellipse at 50% 0%, transparent 70%, black 72%);
  background-size: 100% 50%;
  background-position: 0% 2px, 0% -58px;
  background-repeat: no-repeat;
  animation: morph-shape 2s 2s linear forwards;
}
div:after {
  height: 30%;
  top: -58px;
  background-image: radial-gradient(ellipse at 50% 50%, black 70%, transparent 72%);
  background-size: 100% 200%;
  background-repeat: no-repeat;
  transform-origin: bottom;
  animation: morph-shape2 2s linear forwards;
}
@keyframes morph-shape2 {
  from {
    transform: rotateX(0deg);
  }
  to {
    transform: rotateX(90deg);
  }
}
@keyframes morph-shape {
  from {
    background-position: 0% 2px, 0% -58px;
  }
  to {
    background-position: 0% 100%, 0% 0%;
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div></div>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以使用伪元素和溢出隐藏

&#13;
&#13;
*{box-sizing: border-box}

html{text-align: center;padding: 60px 10px}

.fig{
  margin: 20px auto;
  width: 100px;
  height: 200px;
  position: relative
}
.fig:before{
  content:'';
  position: absolute;
  top: -50px;
  left:0;
  width: 100px;
  height: 100px;
  border-radius: 50%
}
#one{background: black}
#two{overflow: hidden; box-shadow: inset 0 -150px black}
#one:before{background: black}
#two:before{box-shadow: 0 3em black}
&#13;
<div id=one class=fig></div>
<div id=two class=fig></div>
&#13;
&#13;
&#13;