Filling water animation

前端 未结 6 874
小蘑菇
小蘑菇 2020-11-30 21:06

I am trying to get a wipe up animation to make a circle look like it\'s filling with water. I\'ve run into two errors, and haven\'t been able to even tackle

6条回答
  •  青春惊慌失措
    2020-11-30 21:58

    Here are four different versions to supplement @misterManSam's brilliant answer.

    1. With Easing


    Explanation

    If you filled up a circular bowl full of liquid, it would fill faster at the bottom and top than it would in the middle (because there is more area to cover in the wider middle section). So, with that crude explanation in mind, the animation needs to: start fast, slow in the middle, and then finish fast when the bowl narrows again at the top.

    To do this we can use a CSS3 easing function: cubic-bezier(.2,.6,.8,.4).

    Have a look at the example below.

    (If you want to tweak the easing here is a great resource: http://cubic-bezier.com/#.2,.6,.8,.4)

    Example:

    #banner {
      width: 150px;
      height: 150px;
      position: relative;
      background: #000;
      border-radius: 50%;
      overflow: hidden;
    }
    #banner::before {
      content: '';
      position: absolute;
      background: #04ACFF;
      width: 100%;
      bottom: 0;
      animation: wipe 5s cubic-bezier(.2,.6,.8,.4) forwards;
    }
    @keyframes wipe {
      0% {
        height: 0;
      }
      100% {
        height: 100%;
      }
    }

    2. SVG Deliciousness

    Let's take this one step further? What if we wanted to add a wavy surface on the "water" using CSS? We can do this using the amazing SVG. I created a wavy SVG image in Adobe Illustrator and then animated that to travel from left to right on a loop with a separate CSS animation and voila:

    Example

    #banner {
        border-radius: 50%;
        width: 150px;
        height: 150px;
        background: #000;
        overflow: hidden;
        backface-visibility: hidden;
        transform: translate3d(0, 0, 0);
    }
    #banner .fill {
        animation-name: fillAction;
        animation-iteration-count: 1;
        animation-timing-function: cubic-bezier(.2, .6, .8, .4);
        animation-duration: 4s;
        animation-fill-mode: forwards;
    }
    #banner #waveShape {
        animation-name: waveAction;
        animation-iteration-count: infinite;
        animation-timing-function: linear;
        animation-duration: 0.5s;
        width:300px;
        height: 150px;
        fill: #04ACFF;
    }
    @keyframes fillAction {
        0% {
            transform: translate(0, 150px);
        }
        100% {
            transform: translate(0, -5px);
        }
    }
    @keyframes waveAction {
        0% {
            transform: translate(-150px, 0);
        }
        100% {
            transform: translate(0, 0);
        }
    }

    3. With pour line


    This example includes a pour line (most bowls fill from the top, not the bottom). The pour line first animates from top to bottom while an animation-delay property prevents the fill animation from happening until the pour has finished.

    #banner {
      border-radius: 50%;
      width: 150px;
      height: 150px;
      background: #000;
      overflow: hidden;
      backface-visibility: hidden;
      transform: translate3d(0, 0, 0);
      position: relative;
    }
    
    #banner .fill {
      transform: translateY(150px);
      animation-name: fillAction;
      animation-iteration-count: 1;
      animation-timing-function: cubic-bezier(.2, .6, .8, .4);
      animation-duration: 4s;
      animation-fill-mode: forwards;
      animation-delay: 0.25s;
    }
    
    #banner .pour {
      width: 6px;
      position: absolute;
      left: 50%;
      margin-left: -3px;
      bottom: 0;
      top: 0;
      background: #009ae6;
      animation-name: pourAction;
      animation-timing-function: linear;
      animation-duration: 0.25s;
    }
    
    #banner #waveShape {
      animation-name: waveAction;
      animation-iteration-count: infinite;
      animation-timing-function: linear;
      animation-duration: 0.5s;
      width: 300px;
      height: 150px;
      fill: #04ACFF;
    }
    
    @keyframes pourAction {
      0% {
        transform: translateY(-100%);
      }
      100% {
        transform: translateY(0);
      }
    }
    
    @keyframes fillAction {
      0% {
        transform: translateY(150px);
      }
      100% {
        transform: translateY(-5px);
      }
    }
    
    @keyframes waveAction {
      0% {
        transform: translate(-150px, 0);
      }
      100% {
        transform: translate(0, 0);
      }
    }

    4. With Serious Bling (with beautiful aesthetics)


    This example adds a few more properties to the CSS to make it look a little more realistic.

    .bowl {
      position: relative;
      border-radius: 50%;
      width: 150px;
      height: 150px;
      box-shadow: inset 0 -5px 0 0 rgba(0, 0, 0, 0.5), inset 0 -20px 5px 0 rgba(0, 0, 0, 0.2), inset -15px 0 5px 0 rgba(0, 0, 0, 0.1), inset 15px 0 5px 0 rgba(0, 0, 0, 0.1);
      background: -moz-radial-gradient(center, ellipse cover, transparent 0%, transparent 76%, rgba(0, 0, 0, 0.65) 100%);
      background: -webkit-radial-gradient(center, ellipse cover, transparent 0%, transparent 76%, rgba(0, 0, 0, 0.65) 100%);
      background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0.65) 100%);
      margin: 20px;
    }
    .bowl:before {
      overflow: hidden;
      border-radius: 50%;
      content: "";
      box-shadow: inset 0 -5px 0 0 rgba(0, 0, 0, 0.5), inset 0 -20px 5px 0 rgba(0, 0, 0, 0.2), inset -15px 0 5px 0 rgba(0, 0, 0, 0.1), inset 15px 0 5px 0 rgba(0, 0, 0, 0.1);
      background: -moz-radial-gradient(center, ellipse cover, transparent 0%, transparent 60%, rgba(0, 0, 0, 0.65) 81%, black 100%);
      background: -webkit-radial-gradient(center, ellipse cover, transparent 0%, transparent 60%, rgba(0, 0, 0, 0.65) 81%, black 100%);
      background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 0.65) 81%, #000000 100%);
      position: absolute;
      width: 150px;
      height: 150px;
      z-index: 2;
    }
    .bowl:after {
      content: "";
      width: 60px;
      border-radius: 50%;
      height: 5px;
      background: #039be4;
      box-shadow: inset 0 0 10px 0 #000;
      position: absolute;
      left: 50%;
      margin-left: -30px;
      bottom: 0;
      z-index: 2;
    }
    .bowl .inner {
      border-radius: 50%;
      width: 150px;
      height: 150px;
      background: -moz-radial-gradient(center, ellipse cover, transparent 0%, transparent 76%, rgba(0, 0, 0, 0.65) 100%);
      background: -webkit-radial-gradient(center, ellipse cover, transparent 0%, transparent 76%, rgba(0, 0, 0, 0.65) 100%);
      background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 76%, rgba(0, 0, 0, 0.65) 100%);
      overflow: hidden;
      -webkit-backface-visibility: hidden;
      -webkit-transform: translate3d(0, 0, 0);
    }
    .bowl .inner:before {
      content: "";
      width: 20px;
      height: 20px;
      background: rgba(255, 255, 255, 0.2);
      border-radius: 50%;
      position: absolute;
      right: 40%;
      top: 60%;
      z-index: 2;
    }
    .bowl .inner:after {
      content: "";
      width: 20px;
      height: 40px;
      background: rgba(255, 255, 255, 0.2);
      border-radius: 50%;
      position: absolute;
      right: 30%;
      top: 15%;
      transform: rotate(-20deg);
      z-index: 2;
    }
    .bowl .fill {
      -webkit-animation-name: fillAction;
      -webkit-animation-iteration-count: 1;
      -webkit-animation-timing-function: cubic-bezier(0.2, 0.6, 0.8, 0.4);
      -webkit-animation-duration: 4s;
      -webkit-animation-fill-mode: forwards;
    }
    .bowl .waveShape {
      -webkit-animation-name: waveAction;
      -webkit-animation-iteration-count: infinite;
      -webkit-animation-timing-function: linear;
      -webkit-animation-duration: 0.5s;
      width: 300px;
      height: 150px;
      fill: #039be4;
    }
    
    @-webkit-keyframes fillAction {
      0% {
        -webkit-transform: translate(0, 150px);
      }
      100% {
        -webkit-transform: translate(0, 10px);
      }
    }
    @-webkit-keyframes waveAction {
      0% {
        -webkit-transform: translate(-150px, 0);
      }
      100% {
        -webkit-transform: translate(0, 0);
      }
    }
    /* For aesthetics only ------------------------------------------*/
    body {
      margin: 0;
      font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
    }
    
    h1 {
      font: 200 1.2em "Segoe UI Light", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
      font-weight: 200;
      color: #fff;
      background: #039be4;
      padding: 20px;
      margin: 0;
      border-bottom: 10px solid #ccc;
    }
    h1 strong {
      font-family: "Segoe UI Black";
      font-weight: normal;
    }
    
    .explanation {
      padding: 20px 40px;
      float: right;
      background: #e64a19;
      -webkit-box-shadow: inset 0 30px 3px 0 rgba(0, 0, 0, 0.5);
      box-shadow: inset 0 3px 5px 0 rgba(0, 0, 0, 0.2);
      border-bottom: 10px solid #ccc;
      max-width: 300px;
    }
    .explanation p {
      color: #fff;
      font-size: 0.8rem;
    }

提交回复
热议问题