先看效果
已有的css样式 动画效果是2s时间由透明变为不透明;
修改后的动画效果
styleSheets对象
Document.styleSheets 只读属性,
返回一个由 StyleSheet 对象组成的 StyleSheetList,
每个 StyleSheet 对象都是一个文档中链接或嵌入的样式表。
let styleSheetList = document.styleSheets;
它是一个 StyleSheet 对象的有序集合。
styleSheetList.item(index) 或 styleSheetList[index]
根据它的索引(索引基于0)返回一个单独的样式表对象。
CSSRule 对象
cssRule接口表示一个CSS规则。规则存在若干种类型。
CSSStyleRule // CSSRule.STYLE_RULE ==1
// CSSRule.CHARSET_RULE ==2
CSSImportRule //CSSRule.IMPORT_RULE ==3
CSSMediaRule // @media 规则 CSSRule.MEDIA_RULE==4
CSSFontFaceRule //CSSRule.FONT_FACE_RULE ==5
CSSPageRule //CSSRule.PAGE_RULE==6
CSSKeyframesRule // CSSRule.KEYFRAMES_RULE ==7 对应于@keyframes at-rule的完整的关键帧
CSSKeyframeRule // CSSRule.KEYFRAME_RULE==8 对应于@keyframes at-rule的单个关键帧
CSSNamespaceRule //CSSRule.NAMESPACE_RULE==10
CSSCounterStyleRule
CSSDocumentRule
CSSSupportsRule //CSSRule.SUPPORTS_RULE ==12
CSSFontFeatureValuesRule
CSSViewportRule
其中 CSSKeyframesRule 规则 定义了 @keyframes 动画的完整的关键帧;
查找动画关键帧样式位置
通过遍历 找到 document.styleSheets
下的cssRules
获取属性表对象
//例如
document.styleSheets[0].cssRules
//返回 CSSRuleList
其中type代表cssRule
规则类型的值,而type 等于7 代表完整的动画帧的规则CSSKeyframesRule
;
所以我们要修改动画样式 需要先找到 type==7
的列表;
修改动画关键帧样式
方法
//样式表中插入一条规则。
appendRule(rule, index) //Chrome IE9及以上 FireFox
insertRule(rule, index) // 暂未找到那个版本支持
addRule(selector, rules, [index])// IE 特有(以下,以上被删除了)
//样式表中插入删除条规则。
removeRule([index]) IE // IE 特有( ie9 以下,以上被删除了)
deleteRule(index) //Chrome IE9及以上 FireFox
注意
:修改时一定要找到所有的样式表修改;如下图存在两个同名的样式表,
两个同名的样式表都要修改,否则样式不生效;
如下图修改是只修改了最后一列样式表
f12查看样式修改成功!
但是会出现复用当前组件时,复用两次以上的动画不生效!
注意
:由于vue需要打包,vue会把css生成的样式打包成link引入的方式,当使用link引入方式时无法通过cssRules
进行查找
所以这里我们需要使用appendRule
或者insertRule
插入一条规则;
vue 代码参考 (细节请自行修改)
data
animationName: "",
sheetsIndex: "",
keyframeIndex: "",
// 动画总耗时 (毫秒)
animationDuration: "350",
// 动画关键帧数组
animationArr: [],
methods
// 改变窗口动画
changeAnimation() {
// 动画加载一定程度后再加载视图,否则性能差,出现掉帧情况
this.viewShow = false;
setTimeout(() => {
this.viewShow = true;
}, (this.animationDuration / 100) * 75);
// 设置动画
this.animationArr = [
`0% {
left: ${
String(window.$clientX) ? window.$clientX + "px" : "0%"};
top: ${
String(window.$clientY) ? window.$clientY + "px" : "100%"};
width: 0px;
height: 0px;
opacity: 0.5;
}`,
`100% {
left: ${
this.left};
top: ${
this.top};
width: ${
this.width};
height: ${
this.height};
opacity: 1;
}`,
];
let selector = ".no_router_popup_animation";
this.changeKeyframes(selector, "noRouterPopup", this.animationArr);
},
// 寻找 css不是link引入的
findNoLinkSheet() {
var styleSheets = document.styleSheets;
console.log("进入了findNoLinkSheet",styleSheets);
let ssLength = styleSheets.length;
for (var i = 0; i < ssLength; i++) {
try {
// 谷歌、火狐浏览器空时返回错误; uc浏览器 空为null;
styleSheets[i].cssRules || styleSheets[i].rules;
if (!styleSheets[i].cssRules && !styleSheets[i].rules) {
continue;
}
} catch {
continue;
}
this.sheetsIndex = i;
console.log("this.sheetsIndex", this.sheetsIndex);
break;
}
},
// 添加新动画
addKeyframes(selector, animName, AnimationArr) {
var styleSheets = document.styleSheets;
let animationString = "";
AnimationArr.forEach((item) => {
// keyframesArr[k].insertRule(item);
animationString += item;
});
let Keyframes = `@keyframes ${
animName}{
${
animationString}}`;
console.log("Keyframes");
if (styleSheets[this.sheetsIndex].appendRule) {
styleSheets[this.sheetsIndex].insertRule =
styleSheets[this.sheetsIndex].appendRule;
}
styleSheets[this.sheetsIndex].insertRule(Keyframes);
console.log(
"styleSheets[this.sheetsIndex]",
styleSheets[this.sheetsIndex]
);
this.animationName = animName;
// 动画总耗时设置
let selectorDom = document.querySelectorAll(selector);
selectorDom[selectorDom.length - 1].style.animationDuration =
this.animationDuration + "ms";
// 重新指定动画名字使之生效
selectorDom[
selectorDom.length - 1
].style.animationName = this.animationName;
},
// 查找动画keyframe
findKeyframesRule(animName) {
var styleSheets = document.styleSheets;
// console.log("styleSheets", styleSheets);
let ssLength = styleSheets.length;
for (var i = 0; i < ssLength; i++) {
try {
// 谷歌、火狐浏览器空时返回错误; uc浏览器 空为null;
styleSheets[i].cssRules || styleSheets[i].rules;
if (!styleSheets[i].cssRules && !styleSheets[i].rules) {
continue;
}
} catch {
continue;
}
var oRules = styleSheets[i].cssRules
? styleSheets[i].cssRules
: styleSheets[i].rules;
let oRulesLength = oRules.length;
for (var x = 0; x < oRulesLength; x++) {
// 跳过name为 undefined
if (!oRules[x].name) {
continue;
}
let rule = oRules[x];
if (
String(rule.name).indexOf(animName) != -1 &&
(rule.type == CSSRule.KEYFRAMES_RULE ||
rule.type == CSSRule.WEBKIT_KEYFRAMES_RULE)
) {
// console.log("rule.name", rule.name);
// console.log("oRules", oRules);
// 递归查找keyframes
return this.findKeyframesCallBack(oRules, animName, x);
}
}
}
},
/**
* @name: 递归查找keyframes
* @test: test font
* @msg:
* @param {*} oRules document.styleSheets[i].cssRules||document.styleSheets[i].rules
* @param {*} animName 修改的动画名称
* @param {*} index cssRules或rules数组下标
* @param {*} ruleArr 保存具有与animName的keyframes数组
* @return {*} ruleArr
*/
findKeyframesCallBack(oRules, animName, index, ruleArr = []) {
let ruleItem = oRules[index];
if (
String(ruleItem.name).indexOf(animName) != -1 &&
(ruleItem.type == CSSRule.KEYFRAMES_RULE ||
ruleItem.type == CSSRule.WEBKIT_KEYFRAMES_RULE)
) {
this.animationName = ruleItem.name;
this.keyframeIndex = index;
ruleArr.push(ruleItem);
return this.findKeyframesCallBack(oRules, animName, index + 1, ruleArr);
} else {
return ruleArr;
}
},
// 改变已有动画
changeKeyframes(selector, animName, AnimationArr) {
var keyframesArr = [];
try {
keyframesArr = this.findKeyframesRule(animName);
} catch {
return;
}
// 如果找不到则添加一个动画
if (!keyframesArr) {
console.log("!keyframesArr", !keyframesArr);
this.findNoLinkSheet();
this.addKeyframes(selector, animName, AnimationArr);
return;
}
const keyframesArrLength = keyframesArr.length;
// 遍历修改所有的keyframes 不全部修改会出现动画不生效 或者只生效一次
for (var k = 0; k < keyframesArrLength; k++) {
// 兼容ie (暂未验证)
if (!keyframesArr[k].deleteRule) {
keyframesArr[k].deleteRule = keyframesArr[k].removeRule;
}
// 删除已经存在的开始和结束帧
keyframesArr[k].deleteRule("0%");
keyframesArr[k].deleteRule("100%");
// 兼容谷歌与火狐
if (keyframesArr[k].appendRule) {
keyframesArr[k].insertRule = keyframesArr[k].appendRule;
}
// // 兼容ie (暂未验证)
// else if (keyframesArr[k].addRule) {
// keyframesArr[k].insertRule = function (rule, index = 0) {
// let selector = rule.split("{")[0];
// let selectorLength = selector.length;
// let style = rule.slice(selectorLength);
// return keyframesArr[k].addRule(selector, style, index);
// };
// }
// 添加动画
AnimationArr.forEach((item) => {
keyframesArr[k].insertRule(item);
});
}
var styleSheets = document.styleSheets;
// this.animationName = animName;
// 动画总耗时设置
let selectorDom = document.querySelectorAll(selector);
selectorDom[selectorDom.length - 1].style.animationDuration =
this.animationDuration + "ms";
// 重新指定动画名字使之生效
selectorDom[
selectorDom.length - 1
].style.animationName = this.animationName;
},