添加CSS
通常情况CSS不论是内嵌还是外联,都是预先定义好的。其实利用JavaScript,我们也可以动态在页面中插入或删除CSS。
比较常见的场景是:CSS动画。由于我们在设计网页时不能预知动画的具体细节,所以需要在运行时进行定制。比如,我们想让一个元素从右侧飞出屏幕,如果用keyframe动画实现,我们必须知道屏幕的宽度,这个信息只有在运行才知道。
例如下面的1026px,是运行时浏览器窗口的宽度。
1
2
3
4
5
6
7
8
9
10
|
@-webkit-keyframes slide-
right
{
0%
{
-webkit-transform: translateX(
0px
) scale(
1
);
-webkit-transform-origin:
50%
50%
;
}
100%
{
-webkit-transform: translateX(
1026px
) scale(
1
);
-webkit-transform-origin:
50%
50%
;
}
}
|
如果要运行这个动画,我们需要将这个keyframe的css加入到页面的Style节点中。
我们可以在页面的document对象的styleSheets中查找第一个可用的style节点,如果当前页面没有style节点我们就需要新建一个:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/**
* Insert CSS keyframe rule
*/
insertCSS:
function
(rule) {
if
(document.styleSheets && document.styleSheets.length) {
try
{
document.styleSheets[0].insertRule(rule, 0);
}
catch
(ex) {
console.warn(ex.message, rule);
}
}
else
{
var
style = document.createElement(
"style"
);
style.innerHTML = rule;
document.head.appendChild(style);
}
return
;
}
|
参数rule就是要添加css文本。
如果我们想在一个元素上应用以上动画,我们可以动态定义一个css class:
1
2
3
4
5
6
7
8
9
10
11
|
.animateSlideRight {
-webkit-animation-name: slide-
right
;
-webkit-animation-delay:
0
ms;
-webkit-animation-duration:
1
s;
-webkit-animation-timing-function:linear;
-webkit-animation-iteration-count:
1
;
-webkit-animation-
direction
:
normal
;
-webkit-perspective:
1000px
;
-webkit-perspective-origin:
50%
50%
;
-webkit-backface-
visibility
:
visible
;
}
|
我们也可以用insertCSS方法将css插入到style节点中。这里要注意,以上函数每次只能加入一条css规则,如果rule中包含2条或2条以上规则,则以insertRule方法会出现异常。这也是为什么参数名叫rule而不是cssText的原因。
对于本例,我们需要执行2次insertCSS函数,第一次插入keyframe的CSS,第二次插入class的CSS。
然后我们可以用以下语句设置元素的class,播放元素的动画效果:
1
|
elem.className +=
' '
+ className;
|
删除CSS
如果动画是临时播放的,那么我们还需要在动画结束后将添加的keyframe的css和class的css删除,避免在页面中制造垃圾。
删除CSS还是需要访问document的styleSheets。由于之前我们一直将CSS添加到styleSheet[0]中,所以在删除的时候我们只访问styleSheets中的第一个CSSStyleSheet实例就可以了。
我们添加的css和原有的css都保存在CSSStyleSheet对象的cssrules列表中:
如果要删除keyframe的css,可以通过rule的name属性判断:
如果要删除的是class的css,则需要通过rule的selectorText来判断
我们通过以下deleteCSS函数实现这个功能:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/**
* Delete CSS keyframe rule
*/
deleteCSS:
function
(ruleName) {
var
cssrules = (document.all) ?
"rules"
:
"cssRules"
,
i;
for
(i = 0; i < document.styleSheets[0][cssrules].length; i += 1) {
var
rule = document.styleSheets[0][cssrules][i];
if
(rule.name === ruleName || rule.selectorText ===
'.'
+ruleName) {
document.styleSheets[0].deleteRule(i);
if
(
this
.debug) {
console.log(
"Deleted keyframe: "
+ ruleName);
}
break
;
}
}
return
;
},
|
这个函数中并没有考虑其他情况,比如 #elementCSS的情况。读者可以自行扩展该函数。