Подтвердить что ты не робот

Как получить атрибут стиля из класса CSS с помощью javascript/jQuery?

Как я могу получить доступ к свойству класса CSS с помощью jQuery? У меня есть класс CSS, например:

.highlight { 
    color: red; 
}

И мне нужно сделать цветную анимацию для объекта:

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

Так что я могу изменить от red до blue (в CSS), и моя анимация будет работать в соответствии с моим CSS.

Один из подходов - разместить невидимый элемент с классом highlight, а затем получить цвет элемента, который будет использоваться в анимации, но я думаю, что это очень и очень плохая практика.

Любые предложения?

4b9b3361

Ответ 1

Я написал небольшую функцию, которая пересекает таблицы стилей в документе, ища подходящий селектор, а затем стиль.

Существует одно предостережение, это будет работать только для таблиц стилей, определенных с тегом стиля, или внешних листов из того же домена.

Если лист известен, вы можете передать его и сохранить себя от необходимости искать в нескольких листах (быстрее, а если у вас есть правильные правила, то более точно).

Я тестировал только на 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) {

теперь он проверяет, соответствует ли какой-либо из селекторов в сгруппированных правилах.

Ответ 2

Поскольку вы уже используете jQuery, попробуйте использовать функцию jQuery-ui switchClass, которая позволит вам анимировать этот новый цвет.

Например:

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

Демо


Если вы не хотите включать библиотеку пользовательского интерфейса в целом, здесь используется код:

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/

Ответ 3

Единственное решение, которое приходит мне на ум, следующее:

//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>

Ответ 4

Как насчет этого?

$('<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], чтобы заставить это работать на скрипке из-за встроенного характера среды.

Ответ 5

Я только что написал эту функцию, чтобы получить все стили селектором. Примечание. Селектор должен быть таким же, как в 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;
                }
            }
        }

    }

Ответ 6

К сожалению, я не могу комментировать этот удивительный ответ, но нашел случай, который не обслуживается (когда класс CSS объявлен несколько раз, а первая декларация не имеет стиля, который вы ищете), сделал 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.indexOf(selector) !== -1 && rule.style[style] !== '') {
        return rule.style[style];
      }
    }
  }
  return null;
}

Также вынул раскол в условном, необязательном, и теперь он подтверждает, что стиль присутствует в проверяемом правиле.

Только для shigiggles создан jsFiddle для кэширования стилей с помощью селектора:

var styleCache = {};

function getStyleRuleValue(style, selector, sheet) {
  if (typeof styleCache[selector] !== 'undefined') {
    if (typeof styleCache[selector][style] !== 'undefined') {
        return styleCache[selector][style];
    }
  }
  else {
    styleCache[selector] = {};
  }

  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.indexOf(selector) !== -1 && rule.style[style] !== '') {
        return styleCache[selector][style] = rule.style[style];
      }
    }
  }
  return null;
}

Хотя, если вы это используете, я бы предложил поместить его в класс закрытия/класса. Еще раз спасибо rlemon за потрясающий оригинал.

Ответ 7

Здесь другой метод: добавьте скрытый div с применяемым классом. Используйте jQuery.css для поиска значения стиля. Затем удалите элемент.

http://plnkr.co/edit/Cu4lPbaJWHW42vgsk9ey

function getStyleValue(className, style) {
  var elementId = 'test-' + className,
    testElement = document.getElementById(elementId),
    val;

  if (testElement === null) {
    testElement = document.createElement('div');
    testElement.className = className;
    testElement.style.display = 'none';
    document.body.appendChild(testElement);
  }

  val = $(testElement).css(style);
  document.body.removeChild(testElement);
  return val;
}

console.log( 'The style value is ' + getStyleValue('dark-red', 'color') );

Ответ 8

Почему бы не добавить класс .highlighted, кешировать стиль color, чем удалить его и анимировать в кешированный цвет? То есть не добавляйте элементы и не разбирайте стили и петли.

Пример jsfiddle

var $element = $('.my-class').addClass('highlighted');
var colorToAnimate = $element.css('color');

$element.removeClass('highlighted');

alert(colorToAnimate);
.my-class {
  color: blue;
}
.highlighted {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="my-class">Animated color text</span>