zoukankan      html  css  js  c++  java
  • $.cssHooks 扩展 jquery 的属性操作

    最近在研究 $.transit 然后发现了 $.cssHooks 这个方法,试了一下官方的 demo 表示好像并不是那么回事,所以决定深入的测试一下。

    $.cssHooks 的作用在于拓展属性(自己意淫的),比如用 "rotate" 代替 "transform: rotate()" 之类的,酱紫,$(".box1").css({"rotate":"10"});

    而且还可以用 "rotate" 代替 "transform:rotate()" 和 "-webkit-transform:rotate()",这样是不是很爽呢...

    那么,我们就分三个阶段好了,一获取当前浏览器支持的属性,二拆分成特殊属性,三添加到属性拓展。

    获取兼容的属性这个很容易找到啦,但对我这种懒人来说,代码优美最重要咯,行数越少越好了。

    var div = document.createElement('div');
    var support = {};
    function getVendorPropertyName(prop) {
        if (prop in div.style) return prop;
        var prefixes = ['Moz', 'Webkit', 'O', 'ms'];
        var prop_ = prop.charAt(0).toUpperCase() + prop.substr(1);
        for (var i=0; i<prefixes.length; ++i) {
            var vendorProp = prefixes[i] + prop_;
            if (vendorProp in div.style) { return vendorProp; }
        }
    }
    function checkTransition3dSupport() {
        div.style[support.transform] = '';
        div.style[support.transform] = 'rotateY(90deg)';
        return div.style[support.transform] !== '';
    }
    support.perspective = getVendorPropertyName('perspective');
    support.transition = getVendorPropertyName('transition');
    support.transitionDelay = getVendorPropertyName('transitionDelay');
    support.transform = getVendorPropertyName('transform');
    support.transformOrigin = getVendorPropertyName('transformOrigin');
    support.filter = getVendorPropertyName('Filter');
    

    这也是看了多家源码后总结出来最简短的了,不要嫌弃。

    拆分特殊属性这块,其实没有太多时间重写,先写上 $.transit 的代码好了,之后我会再写一个关于 filter 特殊属性的拆分。

    var Transform = function( str ) {
        if (typeof str === 'string') { this.parse(str); }
        return this;
    };
    // 将属性的值(如 rotate())转换为数字
    Transform.prototype.parse = function( str ) {
        var self = this;
        str.replace(/([a-zA-Z0-9]+)((.*?))/g, function(x, prop, val) {
            self.divideString(prop, val);
        });
    }
    // 将多值字符串拆分
    Transform.prototype.divideString = function( prop, val ) {
        var args =
            (typeof val === 'string')  ? 
            val.split(',') :
            (val.constructor === Array) ? val : [ val ];
        args.unshift(prop);
        Transform.prototype.set.apply(this, args);
    }
    // 设置 transform 的值,用于 $.cssHooks 方法
    Transform.prototype.set = function( prop ) {
        var args = Array.prototype.slice.apply(arguments, [1]);
        if (this.setter[prop]) {
            this.setter[prop].apply(this, args);
        } else {
            this[prop] = args.join(',');
        }
    }
    // transform 拆分值设置
    Transform.prototype.setter = {
        rotate: function(theta) {
            this.rotate = unit(theta, 'deg');
        },
        rotateX: function(theta) {
            this.rotateX = unit(theta, 'deg');
        },
        rotateY: function(theta) {
            this.rotateY = unit(theta, 'deg');
        },
        scale: function(x, y) {
            if (y === undefined) { y = x; }
            this.scale = x + "," + y;
        },
        skewX: function(x) {
            this.skewX = unit(x, 'deg');
        },
        skewY: function(y) {
            this.skewY = unit(y, 'deg');
        },
        perspective: function(dist) {
            this.perspective = unit(dist, 'px');
        },
        x: function(x) {
            this.set('translate', x, null);
        },
        y: function(y) {
            this.set('translate', null, y);
        },
        translate: function(x, y) {
            if (this._translateX === undefined) { this._translateX = 0; }
            if (this._translateY === undefined) { this._translateY = 0; }
            if (x !== null && x !== undefined) { this._translateX = unit(x, 'px'); }
            if (y !== null && y !== undefined) { this._translateY = unit(y, 'px'); }
            this.translate = this._translateX + "," + this._translateY;
        },
    }
    // 获取已有属性及其值,用于 $.cssHooks 的方法
    Transform.prototype.get = function( prop ) {
        if (this.getter[prop]) {
            return this.getter[prop].apply(this);
        } else {
            return this[prop] || 0;
        }
    }
    // 获取
    Transform.prototype.getter = {
        x: function() {
            return this._translateX || 0;
        },
        y: function() {
            return this._translateY || 0;
        },
        scale: function() {
            var s = (this.scale || "1,1").split(',');
            if (s[0]) { s[0] = parseFloat(s[0]); }
            if (s[1]) { s[1] = parseFloat(s[1]); }
            return (s[0] === s[1]) ? s[0] : s;
        },
        rotate3d: function() {
            var s = (this.rotate3d || "0,0,0,0deg").split(',');
            for (var i=0; i<=3; ++i) {
                if (s[i]) { s[i] = parseFloat(s[i]); }
            }
            if (s[3]) { s[3] = unit(s[3], 'deg'); }
            return s;
        }
    }
    // 将多值合并为 3d 状态
    Transform.prototype.toString = function( use3d ) {
        var re = [];
        for (var i in this) {
            if (this.hasOwnProperty(i)) {
                var sure = (!support.transform3d) && (
                    (i === 'rotateX') ||
                    (i === 'rotateY') ||
                    (i === 'perspective') ||
                    (i === 'transformOrigin'))
                if (sure) { continue; }
                if (i[0] !== '_') {
                    if (use3d && (i === 'scale')) {
                        re.push(i + "3d(" + this[i] + ",1)");
                    } else if (use3d && (i === 'translate')) {
                        re.push(i + "3d(" + this[i] + ",0)");
                    } else {
                        re.push(i + "(" + this[i] + ")");
                    }
                }
            }
        }
        return re.join(" ");
    }
    

      

    最后一步,添加到 $.cssHooks 中,具体 $.cssHooks 怎么用,搜文档比看我写过程其实要更精确

    // 添加特殊兼容性
    $.cssHooks['transit:transform'] = {
        get: function(elem) {
            return $(elem).data('transform') || new Transform();
        },
        set: function(elem, value) {
            if (!(value instanceof Transform)) {
                value = new Transform(value);
            }
            elem.style[support.transform] = value.toString();
            $(elem).data('transform', value);
        }
    };
    // 兼容 transform 属性
    $.cssHooks.transform = {
        set: $.cssHooks['transit:transform'].set
    };
    
    // 让特殊值可拥有过渡效果
    function registerCssHook(prop, isPixels) {
        if (!isPixels) { $.cssNumber[prop] = true; }
        // $.transit.propertyMap[prop] = support.transform;
        $.cssHooks[prop] = {
            get: function(elem) {
                var t = $(elem).css('transit:transform');
                return t.get(prop);
            },
            set: function(elem, value) {
                var t = $(elem).css('transit:transform');
                t.divideString(prop, value);
                $(elem).css({ 'transit:transform': t });
            }
        };
    }
    registerCssHook('scale');
    registerCssHook('scaleX');
    registerCssHook('scaleY');
    registerCssHook('translate');
    registerCssHook('rotate');
    registerCssHook('rotateX');
    registerCssHook('rotateY');
    registerCssHook('rotate3d');
    registerCssHook('perspective');
    registerCssHook('skewX');
    registerCssHook('skewY');
    registerCssHook('x', true);
    registerCssHook('y', true);
    

      

    ok,加上了上面这三串之后,你会发觉,$(".box1").css({"rotate":"10"}); 成为了现实,当初还要用插件和写多个 transform 已经不需要了。而且 $.animate 也可以哟。

    然而,$.cssHook 并不完善,所以会出现 rotateX  / perspective 等无效的情况,

    而 css 本身也有不足,比如 scaleX 的默认值为 0,本身没有 translate 那么添加 translate 动画也是无效的。

    还有一个问题在于,未用自己设的特殊属性赋值的话,当然也是取不到它的值的,也就是说你用 css 写的 translateX 并不能用 $.fn.css("x") 来获取到。

    家里电脑坏了,不开森,不开森,不开森...

  • 相关阅读:
    Java中的24种设计模式与7大原则
    Red Hat Enterprise Linux 6安装步骤
    jquery之获取当前时间和月份加1
    新手看过来:随车千斤顶怎么用?
    空挡滑行和带挡滑行究竟谁省油 误区要知道
    怎么开手动档轿车?这么开让你再也不想开自动档
    FindBugs插件的安装与使用
    图解Eclipse中安装和使用FindBugs
    新手开车上高速 不懂这些安全细节非常危险
    酒桌游戏
  • 原文地址:https://www.cnblogs.com/foreverZ/p/jquery-cssHooks.html
Copyright © 2011-2022 走看看