美文网首页CSS
CSS3 中的动画之 transition 和 transfor

CSS3 中的动画之 transition 和 transfor

作者: 柏丘君 | 来源:发表于2017-05-25 15:58 被阅读0次

CSS3 使运动变得更加简单了,我们只需用少量的代码,就可以写出数行甚至更多 JavaScript 代码的效果,并且 CSS3 处理诸如旋转、倾斜、3D 等效果的能力是远强于 JavaScript 的。你能用 JavaScript 让一个 div 渲染任意角度吗?也许能,但复杂度肯定超乎想象,而这个效果可以使用 CSS3 一个函数轻松搞定。
有了 CSS3 写动画,就可以完全抛弃 JavaScript 了吗?当然不是。CSS3 强在表现,JavaScript 强在逻辑,二者结合可以发挥最大的威力。
CSS3 中实现动画效果可能会用到这几个属性:

  • transition
  • transform
  • animation

这几个属性构成了 CSS3 丰富多彩的动画世界。

transition

这是 CSS3 的一个属性,意为过渡。该属性用在某个元素上,用来定义该元素的属性发生变化时,呈现出的过渡效果
transition 有几个属性值:

  • transition-property:需要应用过渡效果的属性名称
  • transition-duration:完成该过渡效果所需的时间
  • transition-timing-function:过渡效果
  • transition-delay:延迟时间(默认为 0)

transition-timing-function 有下列可选值:

  • linear:匀速过渡
  • ease:先慢后快再慢过渡
  • ease-in:先慢后快过渡
  • ease-out:先快后慢过渡
  • ease-in-out:先慢后快再慢过渡
  • cubic-bezier:根据贝赛尔曲线过渡

这系列规则可以合写为:

transiton:<transition-property> <transition-duration> <transition-timing-function> <transition-delay>

如果想根据属性定义不同的过渡,可以这样写(以宽高为例):

transition:width 1s ease-in,height 0.5s ease-out 1s;

贝赛尔曲线用来定义更加复杂的过渡,如果我们想要一个自定义的过渡效果,就可以使用贝塞尔曲线,这个网站可以将贝塞尔曲线转换为相应的 CSS3 函数,推荐使用。

关于这些属性的记忆,这里给出了一个羞羞的方式。

transitionend 事件

transitionend 事件是在过渡效果完成后触发

ele.addEventListener("transitionend",fun);

注:元素的每个属性过渡完成后都会触发一次 transitionend 事件

transform

transform 用来对元素进行 2D/3D 上的属性转换。简单说来,使用该属性,可以对物体上进行形状上的变化,如倾斜,旋转。可以让物体在 2D 或者 3D 空间下展示,让物体在空间中进行位移等。常用的有这么些属性:

  • scale:对元素进行缩放
  • rotate:对元素进行旋转
  • skew:对元素进行倾斜变换
  • translate:对元素进行位移
  • scale3d:3D 场景下缩放
  • rotate3d:3D 场景下旋转
  • skew3d:3D 场景下倾斜
  • translate3d:3D 场景下位移

详细的用法可以参考这里
下面是一个动态时钟的例子。

动态时钟

先来看下布局:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>取个什么名字好呢</title>
    <style>
        /* 外层容器 */
        #box{
            width: 460px;
            height: 460px;
            margin: 100px auto;
            position: relative;
            border-radius: 50%;
        }
        /* 指针容器 */
        .pointers{
            width: 20px;
            height: 20px;
            position: absolute;
            left: calc(50% - 10px);
            top: calc(50% - 10px);
            background: #000;
            border-radius: 50%;
        }
        /* 时针 */
        #hour{
            width: 10px;
            height: 70px;
            background: #000;
            position: absolute;
            left: calc(50% - 5px);
            top: -60px;
            transform-origin: center 70px;
            transform: rotate(-45deg);
            z-index: -1;
        }

        /* 分针 */
        #min{
            width: 6px;
            height: 100px;
            background: #ccc;
            position: absolute;
            left: calc(50% - 3px);
            top: -90px;
            transform: rotate(45deg);
            transform-origin: center 100px;
            z-index: -1;

        }

        /* 秒针 */
        #sec{
            width: 4px;
            height: 140px;
            background: red;
            position: absolute;
            left: calc(50% - 2px);
            top: -130px;
            transform: rotate(90deg);
            transform-origin: center 140px;
            z-index: -1;
        }
        #dial{
            width: 460px;
            height: 460px;
            background: rgba(0,0,0,0.2);
            margin: 0;
            padding: 0;
            list-style: none;
            position: relative;
            display: flex;
            justify-content: center;
        }

        #dial li{
            width: 4px;
            height: 10px;
            background: #000;
            position: absolute;
            transform-origin: center 230px;
        }


        #dial li{
            width: 4px;
            height: 10px;
            background: #000;
            position: absolute;
            transform-origin: center 230px;
        }

        #dial li:nth-of-type(1){
            height: 20px;
            width: 10px;
        }

        #dial li:nth-of-type(2){
            transform: rotate(6deg);
        }

        #dial li:nth-of-type(3){
            transform: rotate(12deg);
        }

        #dial li:nth-of-type(4){
            transform: rotate(18deg);
        }

        #dial li:nth-of-type(5){
            transform: rotate(24deg);
        }
    </style>
</head>
<body>
    <div id="box">
        <!-- 刻度 -->
        <ul id="dial">
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
        <!-- 指针 -->
        <div class = "pointers">
            <div id = "hour"></div>
            <div id="min"></div>
            <div id="sec"></div>
        </div>

    </div>
</body>
</html>

transform-orgin 属性指定元素 transform 时的基准点,默认为元素的中心(center center),我们可以将 transform-origin 指定为页面上的任意一个点。
布局效果如图:

时钟布局效果.png

接下来画出剩余的其他刻度:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>取个什么名字好呢</title>
    <style>
        /* 外层容器 */
        #box{
            width: 460px;
            height: 460px;
            margin: 100px auto;
            position: relative;
            border-radius: 50%;
        }
        /* 指针容器 */
        .pointers{
            width: 20px;
            height: 20px;
            position: absolute;
            left: calc(50% - 10px);
            top: calc(50% - 10px);
            background: #000;
            border-radius: 50%;
        }
        /* 时针 */
        #hour{
            width: 10px;
            height: 70px;
            background: #000;
            position: absolute;
            left: calc(50% - 5px);
            top: -60px;
            transform-origin: center 70px;
            transform: rotate(-45deg);
            z-index: -1;
        }

        /* 分针 */
        #min{
            width: 6px;
            height: 100px;
            background: #ccc;
            position: absolute;
            left: calc(50% - 3px);
            top: -90px;
            transform: rotate(45deg);
            transform-origin: center 100px;
            z-index: -1;

        }

        /* 秒针 */
        #sec{
            width: 4px;
            height: 140px;
            background: red;
            position: absolute;
            left: calc(50% - 2px);
            top: -130px;
            transform: rotate(90deg);
            transform-origin: center 140px;
            z-index: -1;
        }
        #dial{
            width: 460px;
            height: 460px;
            background: rgba(0,0,0,0.2);
            margin: 0;
            padding: 0;
            list-style: none;
            position: relative;
            display: flex;
            justify-content: center;
        }

        #dial li{
            width: 4px;
            height: 10px;
            background: #000;
            position: absolute;
            transform-origin: center 230px;
        }


        #dial li{
            width: 4px;
            height: 10px;
            background: #000;
            position: absolute;
            transform-origin: center 230px;
        }
    </style>
</head>
<body>
    <div id="box">
        <!-- 刻度 -->
        <ul id="dial"></ul>
        <!-- 指针 -->
        <div class = "pointers">
            <div id = "hour"></div>
            <div id="min"></div>
            <div id="sec"></div>
        </div>

    </div>
</body>
<script>
    (function (){
        const dial = document.getElementById("dial"); 
        let dials = "";
        for(let i = 0; i < 60; i++){
            let tmp = "";
            if(i % 5 === 0){
                tmp = `<li style = " width:10px;height:20px;transform:rotate(${6 * i}deg)"></li>`;
            }else{
                tmp = `<li style = "transform:rotate(${6 * i}deg)"></li>`;
            }
            dials += tmp;
        }
        dial.innerHTML = dials;
    })();
</script>
</html>

看下效果:


js批量生成布局.png

获取当前的时、分、秒数值:

const hourEle = document.getElementById("hour");
const minEle = document.getElementById("min");
const secEle = document.getElementById("sec");
(function (){
    const dial = document.getElementById("dial"); 
    let dials = "";
    for(let i = 0; i < 60; i++){
        let tmp = "";
        if(i % 5 === 0){
            tmp = `<li style = " width:10px;height:20px;transform:rotate(${6 * i}deg)"></li>`;
        }else{
            tmp = `<li style = "transform:rotate(${6 * i}deg)"></li>`;
        }
        dials += tmp;
    }
    dial.innerHTML = dials;
    getTime()
})();

function getTime(){
    clearInterval(getTime.timer);
    let date = new Date();
    let sec = date.getSeconds();
    let min = date.getMinutes();
    let hour = date.getHours();
    // 秒针每秒走6deg
    // 分针分钟走6deg
    // 时针每小时走30deg
    secEle.style.transform = `rotate(${sec * 6}deg)`;
    minEle.style.transform = `rotate(${min * 6}deg)`;
    hourEle.style.transform = `rotate(${hour * 6}deg)`;
    getTime.timer = setInterval(getTime,1000);
}

看下效果:

时钟效果01.gif

现在时钟已经动起来了,并可以显示当前的时间。还有一个小问题,就是时钟的分针和时针总是正对着当前分钟的刻度,而实际情况下分针和时针应该是有一些偏移角度的。这是因为我们在计算旋转度数的时候,只单纯计算了当前的分钟或者小时数,正确的做法应该是:

  • 计算分针度数时加上当前的秒数(需将秒换算为分)
  • 计算时针度数时加上当前的分钟数(需将分换算为时)

对 getTime 函数稍作修改:

...
function getTime(){
    clearInterval(getTime.timer);
    let date = new Date();
    let sec = date.getSeconds();
    let min = date.getMinutes();
    let hour = date.getHours();
    // 秒针每秒走6deg
    // 分针分钟走6deg
    // 时针每小时走30deg
    secEle.style.transform = `rotate(${sec * 6}deg)`;
    minEle.style.transform = `rotate(${min * 6 + sec / 60}deg)`;
    hourEle.style.transform = `rotate(${hour * 6 + min / 60}deg)`;
    getTime.timer = setInterval(getTime,1000);
}
...

看下最终效果:


时钟效果02.gif

完。

相关文章

网友评论

    本文标题:CSS3 中的动画之 transition 和 transfor

    本文链接:https://www.haomeiwen.com/subject/tbgaxxtx.html