如何通过jQuery从CSS类访问属性? 我有一个CSS类,如:
.highlight {
color: red;
}
我需要在对象上做一个颜色动画:
$(this).animate({
color: [color of highlight class]
}, 750);
这样我就可以从red
更改为blue
(在CSS中),我的动画将按照我的CSS工作。
一种方法是使用highlight
类放置一个不可见的元素,然后获取要在动画中使用的元素的颜色,但我想这是一种非常非常糟糕的做法。
有什么建议吗?
答案 0 :(得分:66)
我编写了一个小函数,遍历文档中的样式表,寻找匹配的选择器,然后是样式。
有一点需要注意,这只适用于使用样式标记定义的样式表或来自同一域的外部工作表。
如果表单已知,您可以将其传入,并且不必查看多张表格(更快,如果您有冲突规则则更准确)。
我只在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) {
现在它将检查分组规则中的任何选择器是否匹配。
答案 1 :(得分:3)
由于您已经在使用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/
答案 2 :(得分:2)
这个怎么样?
$('<span class="highlight"></span>').appendTo('body');
$(this).animate({
color: $('.highlight').css('color')
}, 750);
$('.highlight').remove();
它有点脏,但会给你一个(空)元素来引用你得到的CSS值。
更新以下是来自CSS parser/abstracter? How to convert stylesheet into object
的合适解决方案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]
来使这个在小提琴中起作用。
答案 3 :(得分:2)
我想到的唯一解决方案如下:
//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 :(得分:1)
我刚刚编写了这个函数,通过选择器获取所有样式。注意:选择器必须与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;
}
}
}
}
答案 5 :(得分:1)
不幸的是我不能评论这个真棒answer,但发现了一个没有照顾的情况(当CSS类被多次声明并且第一个声明没有你正在寻找的样式时for),提出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获得了令人敬畏的原创作品。
答案 6 :(得分:0)
这是另一种方法:在应用类的情况下添加隐藏的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') );
答案 7 :(得分:0)
为什么不添加.highlighted
类,缓存color
样式,而不是将其删除并设置为缓存颜色的动画?即不要添加元素,不要解析和解析。循环样式。
var $element = $('.my-class').addClass('highlighted');
var colorToAnimate = $element.css('color');
$element.removeClass('highlighted');
alert(colorToAnimate);
&#13;
.my-class {
color: blue;
}
.highlighted {
color: red;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<span class="my-class">Animated color text</span>
&#13;