如何通过 javascript/jQuery 从 CSS 类中获取样式属性?

IT技术 javascript jquery css
2021-01-31 12:58:01

如何通过 jQuery 从 CSS 类访问属性?我有一个 CSS 类,如:

.highlight { 
    color: red; 
}

我需要在一个对象上做一个彩色动画:

$(this).animate({
    color: [color of highlight class]
}, 750);

这样我就可以从redblue(在 CSS 中)更改,并且我的动画将按照我的 CSS 工作。

一种方法是在highlight类中放置一个不可见的元素,然后获取要在动画中使用的元素的颜色,但我想这是一种非常非常糟糕的做法。

有什么建议?

6个回答

我写了一个小函数,它遍历文档上的样式表,寻找匹配的选择器,然后设置样式。

有一个警告,这仅适用于使用样式标签定义的样式表,或来自同一域的外部表。

如果工作表已知,您可以将其传入并避免自己查看多张工作表(更快,如果您有冲突规则,则更准确)。

我只用一些弱测试用例在 jsFiddle 上进行了测试,让我知道这是否适合你。

function getStyleRuleValue(style, selector, sheet) {
    var sheets = typeof sheet !== 'undefined' ? [sheet] : document.styleSheets;
    for (var i = 0, l = sheets.length; i < l; i++) {
        var sheet = sheets[i];
        if( !sheet.cssRules ) { continue; }
        for (var j = 0, k = sheet.cssRules.length; j < k; j++) {
            var rule = sheet.cssRules[j];
            if (rule.selectorText && rule.selectorText.split(',').indexOf(selector) !== -1) {
                return rule.style[style];
            }
        }
    }
    return null;
}

用法示例:

var color = getStyleRuleValue('color', '.foo'); // searches all sheets for the first .foo rule and returns the set color style.

var color = getStyleRuleValue('color', '.foo', document.styleSheets[2]); 

编辑:

我忽略了考虑分组规则。我将选择器检查更改为:

if (rule.selectorText.split(',').indexOf(selector) !== -1) {

现在它将检查分组规则中的任何选择器是否匹配。

测试的时候有一些问题,现在应该都修复了。如果你发现任何东西,请告诉我。
2021-03-17 12:58:01
@rlemon 在我的第四张纸上,sheet.cssRules 为空,因此“sheet.cssRules.length”会引发错误。我不知道为什么它为空,但是您可以在第二个“for”之前检查是否为空
2021-03-17 12:58:01
@robsonrosa 我有两个似乎有效的解决方案,让我测试它们并回复您。
2021-03-19 12:58:01
+1 非常好,自己做。另外,请注意这里没有 jQuery 依赖项,因此它可以在任何项目中使用!
2021-03-24 12:58:01
有用的功能。但由于空格,它仍然不适用于像 '.class, .class' 这样的选择器。测试:jsfiddle.net/C7BAB所以每个选择器都需要trim()。我试图编辑这个答案。
2021-04-03 12:58:01

由于您已经在使用 jQuery,请尝试使用 jQuery-ui 的函数switchClass,它可以让您为这种新颜色设置动画。

例如:

 $('div').switchClass( "", "highlight", 1000 );

演示


如果您不想包含整个UI 库,这里是他们使用的代码:

switchClass: function( remove, add, speed, easing, callback) {
    return $.effects.animateClass.call( this, {
        add: add,
        remove: remove
    }, speed, easing, callback );
}

和 animateClass fn:

var classAnimationActions = [ "add", "remove", "toggle" ],
    shorthandStyles = {
        border: 1,
        borderBottom: 1,
        borderColor: 1,
        borderLeft: 1,
        borderRight: 1,
        borderTop: 1,
        borderWidth: 1,
        margin: 1,
        padding: 1
    };
function styleDifference( oldStyle, newStyle ) {
    var diff = {},
        name, value;




    for ( name in newStyle ) {
        value = newStyle[ name ];
        if ( oldStyle[ name ] !== value ) {
            if ( !shorthandStyles[ name ] ) {
                if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
                    diff[ name ] = value;
                }
            }
        }
    }




    return diff;
}
function getElementStyles( elem ) {
    var key, len,
        style = elem.ownerDocument.defaultView ?
            elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
            elem.currentStyle,
        styles = {};




    if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
        len = style.length;
        while ( len-- ) {
            key = style[ len ];
            if ( typeof style[ key ] === "string" ) {
                styles[ $.camelCase( key ) ] = style[ key ];
            }
        }
    // support: Opera, IE <9
    } else {
        for ( key in style ) {
            if ( typeof style[ key ] === "string" ) {
                styles[ key ] = style[ key ];
            }
        }
    }




    return styles;
}
$.effects.animateClass = function( value, duration, easing, callback ) {
    var o = $.speed( duration, easing, callback );

    return this.queue( function() {
        var animated = $( this ),
            baseClass = animated.attr( "class" ) || "",
            applyClassChange,
            allAnimations = o.children ? animated.find( "*" ).addBack() : animated;

        // map the animated objects to store the original styles.
        allAnimations = allAnimations.map(function() {
            var el = $( this );
            return {
                el: el,
                start: getElementStyles( this )
            };
        });

        // apply class change
        applyClassChange = function() {
            $.each( classAnimationActions, function(i, action) {
                if ( value[ action ] ) {
                    animated[ action + "Class" ]( value[ action ] );
                }
            });
        };
        applyClassChange();

        // map all animated objects again - calculate new styles and diff
        allAnimations = allAnimations.map(function() {
            this.end = getElementStyles( this.el[ 0 ] );
            this.diff = styleDifference( this.start, this.end );
            return this;
        });

        // apply original class
        animated.attr( "class", baseClass );

        // map all animated objects again - this time collecting a promise
        allAnimations = allAnimations.map(function() {
            var styleInfo = this,
                dfd = $.Deferred(),
                opts = $.extend({}, o, {
                    queue: false,
                    complete: function() {
                        dfd.resolve( styleInfo );
                    }
                });

            this.el.animate( this.diff, opts );
            return dfd.promise();
        });

        // once all animations have completed:
        $.when.apply( $, allAnimations.get() ).done(function() {

            // set the final class
            applyClassChange();

            // for each animated element,
            // clear all css properties that were animated
            $.each( arguments, function() {
                var el = this.el;
                $.each( this.diff, function(key) {
                    el.css( key, "" );
                });
            });

            // this is guarnteed to be there if you use jQuery.speed()
            // it also handles dequeuing the next anim...
            o.complete.call( animated[ 0 ] );
        });
    });
};

处理所需的所有功能:http : //jsfiddle.net/maniator/3C5ZQ/

这意味着包含另一个巨大的外部库 (jQueryUI)。
2021-03-13 12:58:01
@Neal 对不起,我的英语。您的回答没有解释“如何通过 jquery 从 css 类获取样式属性”,但正是我所需要的。
2021-03-19 12:58:01
@robsonrosa 为什么它不回答问题?
2021-03-21 12:58:01
@Neal 这对我来说可能是一个很好的解决方案(也许是最好的解决方案)(我正在使用 jQueryUI),所以非常感谢,但我不会投票(或“接受”它),因为它没有回答问题.
2021-03-25 12:58:01
@BenjaminGruenbaum 您不必包含整个内容。您可以从 jQuery ui 的网站中包含此函数。
2021-04-09 12:58:01

这个怎么样?

$('<span class="highlight"></span>').appendTo('body');
$(this).animate({
    color: $('.highlight').css('color')
}, 750);
$('.highlight').remove();

这有点脏,但会给你一个(空)元素来引用以获得你正在寻找的 CSS 值。

更新这是来自CSS 解析器/抽象器的一个不错的解决方案如何将样式表转换为对象

function findColorProperty(selector) {
    rules = document.styleSheets[0].cssRules
    for(i in rules) {
        //if(rules[i].selectorText==selector) 
            //return rules[i].cssText; // Original
        if(rules[i].selectorText == selector) 
            return rules[i].style.color; // Get color property specifically
    }
    return false;
}

用法

$(this).animate({
    color: findColorProperty('.highlight')
}, 750);

这是一个小提琴http://jsfiddle.net/wzXDx/1/styleSheets[1]由于环境的嵌入特性,我不得不使用它来处理小提琴。

不要忘记删除添加的跨度:-P
2021-03-12 12:58:01
这是个坏主意,乔……然后您删除页面上的所有突出显示,而不仅仅是您创建的突出显示。
2021-04-02 12:58:01
@Neal 我认为这个想法是.highlight页面上存在。如果是这样,那么 OP 不会只是使用.css()所有这些样式表来疯狂解析吗?
2021-04-05 12:58:01
@BenjaminGruenbaum 更新以提供实际解决方案。:)
2021-04-10 12:58:01

我想到的唯一解决方案如下:

//create an element with this class and append it to the DOM
var eleToGetColor = $('<div class="highlight" style="display: none;">').appendTo('body');
//get the color of the element
var color = eleToGetColor.css('color');
//completly remove the element from the DOM
eleToGetColor.remove();


$("div").animate({
  //set the new color
  color: color,
}, 1000);
.highlight {
  color: red;
}
div {
  width: 200px;
  height: 100px;
  color: blue;
  font-size: 6em;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<div>TEST</div>

我刚刚编写了这个函数,通过选择器获取所有样式。注意:选择器必须与 CSS 中的选择器相同。

    /**
     * Gets styles by a classname
     * 
     * @notice The className must be 1:1 the same as in the CSS
     * @param string className_
     */
    function getStyle(className_) {

        var styleSheets = global_.document.styleSheets;
        var styleSheetsLength = styleSheets.length;
        for(var i = 0; i < styleSheetsLength; i++){
            var classes = styleSheets[i].rules || styleSheets[i].cssRules;
            var classesLength = classes.length;
            for (var x = 0; x < classesLength; x++) {
                if (classes[x].selectorText == className_) {
                    var ret;
                    if(classes[x].cssText){
                        ret = classes[x].cssText;
                    } else {
                        ret = classes[x].style.cssText;
                    }
                    if(ret.indexOf(classes[x].selectorText) == -1){
                        ret = classes[x].selectorText + "{" + ret + "}";
                    }
                    return ret;
                }
            }
        }

    }