CSS 变换、过渡、动画实现案例

MarcCrane 8年前
   <p>以下所有效果的实现方式均为个人见解,如有不对的地方还请一一指出。</p>    <h3>目录</h3>    <ul>     <li>方块“Z”字形运动</li>     <li>线段围绕盒子运动</li>     <li>饼图[动图, 固定比例,如20%]</li>     <li>移动端录音旋转小按钮效果实现[渐变色][初始原型]</li>    </ul>    <h3>方块“Z”字形运动</h3>    <p>要求:5s钟循环五次;每次的执行时间为2s;每一次执行到底部后反方向执行;最后停留在最后一帧</p>    <p>考察:animation基本属性值</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/3168d9cad35a554a7e98610fce3eb0c8.png"></p>    <p><a href="/misc/goto?guid=4959742536046999237" rel="nofollow,noindex">点击查看效果</a></p>    <p>重点代码说明:</p>    <pre>  <code class="language-css">animation: move 2s linear 0s 5 alternate forwards;</code></pre>    <table>     <thead>      <tr>       <th>参数</th>       <th>含义</th>      </tr>     </thead>     <tbody>      <tr>       <td>move</td>       <td>animation-name 动画名称</td>      </tr>      <tr>       <td>2s</td>       <td>animation-duration 动画持续时间, 注意加上单位</td>      </tr>      <tr>       <td>linear</td>       <td>animation-timing-function 动画过渡类型,linear:线性过渡</td>      </tr>      <tr>       <td>0s</td>       <td>animation-delay 动画延迟时间,注意加上单位</td>      </tr>      <tr>       <td>5</td>       <td>animation-iteration-count 动画循环次数, infinite表示无限循环</td>      </tr>      <tr>       <td>alternate</td>       <td>animation-direction 动画是否有反向运动, normal:正向运行; reverse:反向运行; alternate:先正向后反向; alternate-reverse:先反向后正向</td>      </tr>      <tr>       <td>forwards</td>       <td>animation-fill-mode 动画时间之外的状态, none: 不设置; forwards:设置为结束时的状态; backwords:设置为开始时的状态; both:动画结束或开始的状态</td>      </tr>     </tbody>    </table>    <p>详细代码示例:</p>    <pre>  <code class="language-css">dom结构:    <div class="box">      <div class="square"></div>    </div>        基本样式:    .box{      position: relative;      width: 200px;      height: 200px;      background-color: #fb3;    }    .box .square{      position: absolute;      width: 30px;      height: 30px;      background-color: #58a;       animation: move 2s linear 0s 5 alternate forwards; //动画,这里要注意,时间必须带上单位    }        move动画定义    @keyframes move {      0% {        transform: translateX(0);      }      33% {        transform: translateX(170px);      }      66% {        transform: translate(0, 170px);      }      100% {        transform: translate(170px, 170px);      }    }</code></pre>    <h3>线段围绕盒子运动</h3>    <p>要求:线段围绕盒子运动</p>    <p>考察:clip的用法</p>    <p>这个动画效果使用animation并不能很好的实现,最终实现方法是使用了 clip 属性,该属性用来剪裁对象。动画实现的原理是用line-box盒子覆盖住box盒子,line-box无背景只设置边框,然后使用clip进行剪裁。</p>    <p>clip语法:rect(number number number number),依据上-右-下-左的顺序剪裁,如设置为auto则该边不剪裁。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/9769238035525d9851695fe702160ebb.png"></p>    <p><a href="/misc/goto?guid=4959742536129416031" rel="nofollow,noindex">点击查看效果</a></p>    <p>代码示例:</p>    <pre>  <code class="language-css">dom结构:    <div class="box">      <div class="line-box"></div>    </div>        基本样式:    .box{      position: relative;      width: 200px;      height: 200px;      background-color: #fb3;    }    .box .line-box{      position: absolute;      width: 220px; //多出来的20像素为线段到盒子的边距      height: 220px;      left: 0;      top: 0;      margin-left: -10px;      margin-top: -10px;      border: 2px solid #58a;      background-color: #58a;       box-sizing: border-box;      animation: move 5s linear infinite;    }        move动画定义    @keyframes move {      0% {        clip: rect(0 220px 2px 0); //依据上-右-下-左的顺序剪裁      }      25% {        clip: rect(0 0 220px 2px);      }      50% {        clip: rect(2px 220px 0 0);      }      75% {        clip: rect(0 2px 220px 0);      }    }</code></pre>    <h3>饼图</h3>    <p>动态饼图</p>    <p><a href="/misc/goto?guid=4959742536202909245" rel="nofollow,noindex">点击查看效果</a></p>    <p>实现方法:</p>    <ul>     <li>首先绘制饼图基本形状,使用使用渐变色生成背景 代码:</li>    </ul>    <pre>  <code class="language-css">.box {        border-radius: 50%;        background: linear-gradient(to right, #58a 50%, #fb3 0);      }</code></pre>    <p>效果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/12cec60c8bad758927595d303edb488b.png"></p>    <ul>     <li>借助伪元素盖住右侧背景,且需要设置 <strong>圆角</strong> ( <a href="/misc/goto?guid=4959742536285947303" rel="nofollow,noindex">Border详解</a> )。</li>     <li>更改旋转中心</li>     <li>设置动画,动画在旋转到50%时,需更改伪元素的背景由蓝色变成黄色。</li>    </ul>    <p>代码示例:</p>    <pre>  <code class="language-css">.box:before {        content: '';        position: absolute;        width: 50%;        height: 100%;        background-color: #58a;        right: 0;        border-radius: 0 100% 100% 0 / 50%;        transform-origin: left center;        animation: rotate 6s linear infinite, changeColor 12s step-end infinite;      }        @keyframes rotate{        to{          transform: rotate(180deg);        }      }      @keyframes changeColor{        50%{          background-color: #fb3;        }      }</code></pre>    <p>任意大小饼图</p>    <p><a href="/misc/goto?guid=4959742536363343248" rel="nofollow,noindex">预览效果</a></p>    <p>如果知道animation-delay一个比较神奇的用法,那这个效果就很容易实现了。</p>    <p>注意:一个负值的延时值是合法的,与0s的延迟类似,它意味着动画会立即开始播放,但会自动前进到延时值的绝对值处,就好像动画在过去已经播放了指定的时间一样。因此实际效果就是动画跳过指定时间而从中间开始播放了。</p>    <p>所以我们只需增加伪元素的代码:</p>    <pre>  <code class="language-css">.box:before {        ...          animation-delay: -3s;        animation-play-state: paused;      }</code></pre>    <p>最终代码如下:</p>    <pre>  <code class="language-css">.box {        position: relative;        width: 200px;        height: 200px;        margin: 0 auto;        margin-top: 50px;        border-radius: 50%;        background: linear-gradient(to right, #58a 50%, #fb3 0);        animation-delay: -7.5s;      }        .box:before {        content: '';        position: absolute;        width: 50%;        height: 100%;        background-color: #58a;        right: 0;        border-radius: 0 100% 100% 0 / 50%;        transform-origin: left center;        animation: rotate 6s linear infinite, change 12s step-end infinite;        animation-delay: inherit;        animation-play-state: paused;      }        @keyframes rotate{        to{          transform: rotate(180deg);        }      }      @keyframes change{        50%{          background-color: #fb3;        }      }</code></pre>    <h3>移动端录音旋转小按钮效果实现[渐变色]</h3>    <p>类似移动端的点击录音按钮的效果,或者是loading的原始效果,[初始原型,有待优化]。</p>    <p>效果图:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/1f2b4523128983ed460d0ee7cb976c93.png"></p>    <p><a href="/misc/goto?guid=4959742536447816106" rel="nofollow,noindex">预览效果</a></p>    <p>实现方法[个人见解]:左侧与右侧分别控制,分别旋转。</p>    <p>dom结构:</p>    <pre>  <code class="language-css"><div class="box">    <div class="item-left"></div>    <div class="item-right"></div>    <div class="item-center">60s</div>   </div></code></pre>    <ul>     <li>item-right, 右侧需设置渐变色背景且为半圆形,选择一个灰色作为渐变色的中间点,这里选择的是#666,效果图如下:</li>    </ul>    <p style="text-align:center"><img src="https://simg.open-open.com/show/d014cf8b38da0d230d8a68ab023e76c5.png"></p>    <p>代码:</p>    <pre>  <code class="language-css">.box .item-right {        position: absolute;        width: 50%;        height: 100%;        top: 0;        right: 0;        border-radius: 0 100% 100% 0/50%;  /*设置圆角以实现半圆效果*/        background: linear-gradient(#fff, #666); /*渐变色背景*/      }</code></pre>    <ul>     <li>item-right, 使用伪元素覆盖住原本的颜色,这里需要注意的是,为了使伪元素更好的覆盖住item-right的颜色,可使用等比放大或者加阴影等方法,这里选择的是阴影。</li>    </ul>    <pre>  <code class="language-css">.box .item-right:before{        content: '';        position: absolute;        width: 100%;        height: 100%;        top: 0;        left: 0;        border-radius: inherit;        background-color: #fff;        box-shadow: 3px 0 2px 2px #fff;      }</code></pre>    <ul>     <li>左侧同理,但是要注意圆角和颜色需更改:</li>    </ul>    <pre>  <code class="language-css">border-radius: 100% 0 0 100%/50%;        background: linear-gradient(#000, #666);</code></pre>    <ul>     <li>item-center主要是实现中间的小圆,可在这个圆上进行多种操作:</li>    </ul>    <pre>  <code class="language-css">.box .item-center{        position: absolute;        width: 190px;        height: 190px;        border-radius: 50%;        background-color: #fff;        top: 5px;        left: 5px;        line-height: 190px;      }</code></pre>    <ul>     <li>下面开始实现旋转。</li>     <li>右侧选中中心在左侧中间,而左侧的旋转中心在右侧中间,所以需要分别设置 transform-origin 属性。</li>     <li>右侧先开始旋转,第一个动画设置旋转动画,第二个动画则设置当旋转结束时,右侧伪元素的颜色为透明色,以便左侧旋转。</li>    </ul>    <pre>  <code class="language-css">animation: rotate 30s linear infinite, changeColor 60s step-end infinite;</code></pre>    <ul>     <li>左侧旋转需设置延迟时间,右侧旋转结束方可开始。</li>    </ul>    <pre>  <code class="language-css">animation: rotate 30s 30s linear infinite;</code></pre>    <p>两个动画的代码:</p>    <pre>  <code class="language-css">@keyframes rotate {        to {          transform: rotate(180deg);        }      }      @keyframes changeColor{        50%{          background-color: transparent;        }      }</code></pre>    <p> </p>    <p>来自:https://github.com/junruchen/junruchen.github.io/wiki/CSS-变换-过渡-动画使用案例</p>    <p> </p>