transform从基础到高级到数据驱动

先来看一个例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    * {
       padding: 0;
       margin: 0; 
    }
    .con {
        width: 100px;
        height: 100px;
        border: 1px solid green;
        margin-bottom: 10px;
        display: flex;
        justify-content: center;
        align-items: center;
        perspective: 100px;
    }
    .rotate, .skew, .scale {
        width: 50px;
        height: 50px;
        border: 1px solid red;
        background: yellow;
        transition: all .5s;
    }
</style>
<body>
    <h1>transform3D</h1>
    <h3>旋转</h3>
    <div class="con">
        <div class="rotate">
            旋转
        </div>
    </div>
    <h3>斜切</h3>
    <div class="con">
        <div class="skew">
            斜切
        </div>
    </div>
    <h3>缩放</h3>
    <div class="con">
        <div class="scale">
            斜切
        </div>
    </div>
</body>
<!-- <script src="v3.js"></script> -->
<script>
    window.onload = function() {
        // 执行顺序,先写的后执行
        var rotate = document.querySelector('.rotate');
       
        rotate.addEventListener('touchstart', function() {
            rotate.style.transform = 'scale(2)'
        })
        var skew = document.querySelector('.skew');
        skew.addEventListener('touchstart', function() {
            skew.style.transform = 'skewX(30deg) skewY(60deg)'
        })
        
        var scale = document.querySelector('.scale');
        scale.addEventListener('touchstart', function() {
            scale.style.WebkitTransform = 'translateZ(-100px)'
        })
    } 
</script>
</html>

大家应该都能看的明白,这是用最原始的方法来实现动画。

简单易懂,但是这样的话我们会写很多重复的代码,rotate.style.transform = 'scale(2)',这样的代码每个事件内部我们都要写一遍。

一般遇到重复代码的时候,就可以考虑下是否可以封装函数了,我们先从最简单的参数出发,这个函数大概需要3个参数,ele元素,prop动画的动作,value,动画的值。

所以我们可以先封装这样一个带有3个参数的函数。

v1.js

/**
 * 
 * @param {*} element // 要操作的元素
 * @param {*} prop // 运动属性
 * @param {*} value // 具体值
 */

function cssTransform(element, prop, value) {
    var transform,
        transformValue = ''
        if(element.transform === undefined) {
            element.transform = transform = Object.create(null); // 纯净的对象 没有原型
        }
        if(value !== undefined){
            element.transform[prop] = value;
            transform = element.transform;
            for(let name in transform) {
                switch(name) {
                    case 'scale':
                    case 'scaleX':
                    case 'scaleY':
                        transformValue += " " + name + '(' + transform[name] + ")";
                        break;
                    case 'rotate':
                    case 'rotateX':
                    case 'rotateX':
                    case 'rotateZ':
                    case 'skewX':
                    case 'skewY':
                        transformValue += " " + name + '(' + transform[name] + "deg)";
                        break;
                    default:
                        transformValue += " " + name + '(' + transform[name] + "px)";
                        break;
                        
                }
                element.style.WebkitTransform = element.style.transform = transformValue;
            }
        } else {
            element.transform[prop]
        }
}
   rotate.addEventListener('touchstart', function() {
     cssTransform(rotate, 'scale', 2);
   })

每次使用的时候直接调用这样的一个函数,传入相应的值就可以了,是不是看起来简单了很多。

但是这样的写法还是有点繁琐,每次都需要传递3个参数。那能不能再简化一个,只传递两个参数呢?

我们给原型加上一个方法,看会怎样?

 HTMLElement.prototype.start = function() {
            console.log(this)
        }

        var rotate = document.querySelector('.rotate');
        var skew = document.querySelector('.skew');

        rotate.addEventListener('touchstart', function() {
            rotate.start()
            skew.start()
        })

可以看到任何一个元素都会有一个start方法,并且内部的this,就是调用者本身。所以我们可以用这种方式来封装

HTMLElement.prototype.cssTransform = function (prop, value) {
    this.transform = Object.create(null);
    var transformValue = ''
    if(value !== undefined){
        this.transform[prop] = value;
        for(let name in this.transform) {
            switch(name) {
                case 'scale':
                case 'scaleX':
                case 'scaleY':
                    transformValue += " " + name + '(' + this.transform[name] + ")";
                    break;
                case 'rotate':
                case 'rotateX':
                case 'rotateX':
                case 'rotateZ':
                case 'skewX':
                case 'skewY':
                    transformValue += " " + name + '(' + this.transform[name] + "deg)";
                    break;
                default:
                    transformValue += " " + name + '(' + this.transform[name] + "px)";
                    break;
            }
        }
        this.style.WebkitTransform = this.style.transform = transformValue;

    } else {
        return this.transform[prop]
    }
}
  rotate.addEventListener('touchstart', function() {
      console.log(1)
      rotate.cssTransform('scale', 2)
  })

这样调用,也可以实现需求,是不是又简单了一步。

那还能不能再优化呢?我们能不能只传递一个参数呢?

能不能这样 ele.scale(2);就能达到我们想要的效果呢?下面我们来实现一下

function Transform(ele) {
    var transform = Object.create(null);
    var transformValue = ''
    var props = ['scale', 'scaleX', 'scaleY', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY']

    props.forEach(function(prop) {
        Object.defineProperty(ele, prop, {
            get: function () {
                return ele[prop]
            },
            set: function (value) {
                transform[prop] = value;
                transformValue = '';
                for (var name in transform) {
                    switch(name) {
                        case 'scale':
                        case 'scaleX':
                        case 'scaleY':
                            transformValue += " " + name + '(' + transform[name] + ")";
                            break;
                        case 'rotate':
                        case 'rotateX':
                        case 'rotateX':
                        case 'rotateZ':
                        case 'skewX':
                        case 'skewY':
                            transformValue += " " + name + '(' + transform[name] + "deg)";
                            break;
                        default:
                            transformValue += " " + name + '(' + transform[name] + "px)";
                            break;
                            
                    }
                }
                ele.style.WebkitTransform = ele.style.transform = transformValue;
            }

        })
    })
    return ele;
}

 

 var ele = Transform(rotate);
    ele.addEventListener('touchstart', function() {
    console.log(1)
    ele.scale = 2
 })

亲测一下发现,功能实现了,很神奇,这就是我们的数据驱动思想,我只管发指令,具体怎么实现,内部去做处理。这样是不是比最初的那种封装看上去高大上了许多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值