本文介绍了deleteRule CSSKeyframesRule方法混淆IE11中的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我使用css @keyframes创建了一个圆圈的基本动画。 我正在使用javascript通过在圆圈内点击来触发动画开始/停止。I have created basic animation of a circle using css @keyframes.I'm using javascript to trigger animation start/stop by click inside the circle.动画本身可分为5个(循环)阶段: pause-expand-pause-shrink-pause (参见下面的@keyframes css部分)The animation itself could be divided into 5 (looped) phases:pause-expand-pause-shrink-pause (see @keyframes css section below)我想要的目标实现最终是能够设置动画持续时间并更改关键帧的值(例如,通过输入字段用于暂停和扩展/缩小持续时间 - 细节对于此问题的范围并不重要)。我已经整理了一个JavaScript函数来执行此任务,并将其设置为 onload 只是为了测试它是如何工作的。The goal I want to achieve is, eventually, to be able to set animation duration and change the values of keyframes (say by having input fields for pause and expand/shrink durations - details doesn't really matter for the scope of this question). I have put together a JavaScript function, to perform this task, and have set it to onload just to test how it works.我的HTML:<!doctype html><html> <head> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> <meta content="utf-8" http-equiv="encoding"> <link rel="stylesheet" href="style.css"> <script src = "animation.js"></script> </head> <body onload=setAnimationDuration(1,1)> <div id="circle" class='circle-paused' onclick=cssAnimation()></div> </body></html>我的CSS:#circle {position: absolute;top: 50%;left: 50%;transform: translateX(-50%) translateY(-50%);}.circle-paused {width: 9%;padding-top: 9%;border-radius: 50%;background-color: #800080;margin: auto;}.circle-animated {/* 2 sec pause 4 sec expand_shrink*/width: 9%;padding-top: 9%;-webkit-animation-name: my-circle; /* Safari 4.0 - 8.0 */-webkit-animation-duration: 12s; /* Safari 4.0 - 8.0 */animation-name: my-circle;animation-duration: 12s;animation-iteration-count: infinite;animation-timing-function: linear;border-radius: 50%;margin: auto;}@keyframes my-circle {0% {background-color: #800080; width: 9%; padding-top: 9%;}33.3% {background-color: #D8BFD8; width: 28%; padding-top: 28%;}50% {background-color: #D8BFD8; width: 28%; padding-top: 28%;}83.3% {background-color: #800080; width: 9%; padding-top: 9%;}100% {background-color: #800080; width: 9%; padding-top: 9%;}}我的JavaScript:My JavaScript:function cssAnimation() { if (document.getElementById('circle').className == 'circle-paused') { document.getElementById('circle').className = 'circle-animated' } else { document.getElementById('circle').className = 'circle-paused' }}function findKeyframes(animation_name) { // get list of current keyframe rules var style_sheet = document.styleSheets; for (var i = 0; i < style_sheet.length; ++i) { for (var j = 0; j < style_sheet[i].cssRules.length; ++j) { // type 7 correspond to CSSRule.KEYFRAMES_RULE, for more info see https://developer.mozilla.org/en-US/docs/Web/API/CSSRule if (style_sheet[i].cssRules[j].type == 7 && style_sheet[i].cssRules[j].name == animation_name) { return style_sheet[i].cssRules[j]; } } } // keyframe rules were not found for given animation_name return null;}function getPercentage(total, fraction) { // Returns what percentage the fraction is from total // The result is rounded to 1 decimal place return Math.round(((100 / total) * fraction) * 10) / 10;}function setAnimationDuration(pause, expand_shrink) { var total_animation_duration = (pause * 2) + (expand_shrink * 2) var pause_percentage = getPercentage(total_animation_duration, pause) var expand_shrink_percentage = getPercentage(total_animation_duration, expand_shrink) var pause1 = pause_percentage + expand_shrink_percentage; var shrink = pause1 + expand_shrink_percentage; var frame_percentage_list = [0, expand_shrink_percentage, pause1, shrink, 100] var key_frame_list = findKeyframes('my-circle') var new_rule_list = [] var to_be_removed_key_list = [] //create array of new rules to be inserted //collecting old keys of rules to be deleted for(var i = 0; i < key_frame_list.cssRules.length; i++) { var current_rule = key_frame_list.cssRules[i].cssText to_be_removed_key_list.push(key_frame_list.cssRules[i].keyText) new_rule_list.push(current_rule.replace(/[+-]?([0-9]*[.])?[0-9]+%/, frame_percentage_list[i] + '%')) } // delete old rules for(var i = 0; i < to_be_removed_key_list.length; i++) { key_frame_list.deleteRule(to_be_removed_key_list[i]) } // populate new ruels for(var i = 0; i < new_rule_list.length; i++) { key_frame_list.appendRule(new_rule_list[i]) } document.getElementById('circle').style.animationDuration = total_animation_duration + "s"} 上面的代码,JSFiddle 问题本身: 代码在FireFox(55.0.3),Chrome(61.0)和Safari(11.0)中按预期工作。虽然,当我开始在IE11中测试它时,我发现 key_frame_list.deleteRule('rule_key')抛出无效参数错误。在研究这个问题的同时,我发现了(并且已经过了一段时间)这个文章(虽然它没有解决IE问题,但它提高了我对css动画的整体理解)。在MSDN上,我找到两个引用,涉及 deleteRule :一个和两个。虽然我并不真正理解其含义,但在第二个,by:The problem itself:The code is working as expected in FireFox (55.0.3), Chrome (61.0) and Safari (11.0). Though, when I started testing it in IE11, I have found that key_frame_list.deleteRule('rule_key') throws an Invalid argument error. While researching the issue, I have found (and went trough) this article (though it does not tackle the IE problem, it improved my overall understanding of the css animations). On MSDN I have find two references, concerning deleteRule: one and two. Though I didn't really understood what was meant, in the second one, by: 密钥必须解析为0到1之间的数字,否则规则将被忽略。 The key must resolve to a number between 0 and 1, or the rule is ignored.我认为在IE中你必须将索引传递给 deleteRule 字符串键。所以我试图在IE控制台中检查我的假设。这是我发现的(鉴于我的js代码在onload中):I assumed that in IE you have to pass index to deleteRule instead of string key. So I've tried to check my assumption in IE console. Here is what I have found (given my js code is in onload):var key_frame_list = findKeyframes('my-circle')key_frame_list.cssRules.length => 5key_frame_list.deleteRule(0)key_frame_list.cssRules.length => 4key_frame_list.deleteRule(1)key_frame_list.cssRules.length => 3key_frame_list.deleteRule(0)key_frame_list.deleteRule(1)key_frame_list.deleteRule(2)...key_frame_list.cssRules.length => 3发生的事情是: key_frame_list.deleteRule(0) - 删除第一条规则(0%) key_frame_list.deleteRule (1 ) - 删除最后一条规则(100%) 之后无论我传递给哪个索引 key_frame_list.deleteRule() key_frame_list.cssRules.length 仍然是3. 我的期望是我能用 key_frame_list.deleteRule(0)并删除所有规则(因为我预计每个规则删除后索引都会移位)。What is happening is:key_frame_list.deleteRule(0) - removes first rule (which is 0%)key_frame_list.deleteRule(1) - removes the last rule (which is 100%)After that no matter which index I pass to key_frame_list.deleteRule() the key_frame_list.cssRules.length remains 3.My expectation was that I will be able to recur with key_frame_list.deleteRule(0) and remove all the rules (as I expected that the indexes will shift after each rule deletion).现在,我想了解: 使用的方法是什么(基本上,'我做错了什么?') IE中的 deleteRule (或者如果应该使用其他方法)? 为什么我无法删除两个以上的规则五个? 是否有适合此目的的方法可以使用关于Firefox,Chrome和IE11的相同论点,我不知道?What is the proper way (basically, 'Am I doing something wrong?') to use deleteRule in the IE (or if another method should be used)?Why am I not able to delete more than two rules out of five?Is there a method suitable for this purposes that will work with the same arguments on Firefox, Chrome and IE11, I am not aware of?推荐答案 什么是正确的方法(基本上,'我做错了什么?')在IE中使用deleteRule(或者如果应该使用其他方法)? What is the proper way (basically, 'Am I doing something wrong?') to use deleteRule in the IE (or if another method should be used)? 为什么我不能删除五个以上的两个规则? Why am I not able to delete more than two rules out of five?第一个MSDN链接不适用; deleteRule()方法适用于顶级规则,而不适用于关键帧规则。The first MSDN link does not apply; that deleteRule() method applies to top-level rules, not keyframe rules.文本密钥必须解析为0到1之间的数字,否则规则将被忽略。从第二个链接实际上取自 2013年的CSS动画,表示代替包含0%-100%关键帧选择器的字符串,Internet Explorer需要一个表示百分比的十进制数字。该参数不代表索引。The text "The key must resolve to a number between 0 and 1, or the rule is ignored." from the second link is actually taken from the 2013 WD of css-animations, and means that instead of a string containing the 0%-100% keyframe selector, Internet Explorer expects a decimal number representing the percentage. The argument does not represent an index.因此,对于0%关键帧规则,IE期望值为0;对于100%关键帧规则,IE期望值为1;对于33.3%的关键帧规则,IE期望浮点值0.333:So for a 0% keyframe rule, IE expects the value 0; for a 100% keyframe rule, IE expects the value 1; and for a 33.3% keyframe rule, IE expects the floating-point value 0.333:key_frame_list.deleteRule(0) // Deletes the 0% keyframe rulekey_frame_list.deleteRule(0.333) // Deletes the 33.3% keyframe rulekey_frame_list.deleteRule(1) // Deletes the 100% keyframe rule删除0%规则后,如果没有0%规则,则再次调用 deleteRule(0)什么都不做。Once a 0% rule has been deleted, if no 0% rules remain then additional calls to deleteRule(0) will do nothing.由于关键帧不能超过100%, deleteRule(2)没有意义,因为它意味着删除一个不存在的200%关键帧规则。And since keyframes cannot exceed 100%, deleteRule(2) is meaningless since it would mean deleting a 200% keyframe rule, which cannot exist. 是否有适用于此目的的方法在Firefox,Chrome和IE11上使用相同的参数,我不知道? Is there a method suitable for this purposes that will work with the same arguments on Firefox, Chrome and IE11, I am not aware of?否; Internet Explorer 11遵循2013 WD(自2012年至2013年在Internet Explorer 10发布后开发),这意味着其实现与当前标准不一致,其中 deleteRule()方法已被更改为接受字符串参数而不是数字参数。No; Internet Explorer 11 follows the 2013 WD (itself having been developed between 2012 and 2013 following the release of Internet Explorer 10), meaning its implementation is not consistent with the current standard, in which the deleteRule() method has been changed to accept a string argument instead of a numeric argument.这意味着API不兼容,因此没有干净的解决方法。你只需要尝试两个参数。我在你的小提琴中改变了以下陈述:This means the API is incompatible, and so there is no clean workaround. You'll just have to attempt both arguments. I changed the following statement in your fiddle:// delete old rulesfor(var i = 0; i < to_be_removed_key_list.length; i++) { key_frame_list.deleteRule(to_be_removed_key_list[i])}到:// delete old rulesfor(var i = 0; i < to_be_removed_key_list.length; i++) { try { key_frame_list.deleteRule(to_be_removed_key_list[i]) } catch (e) { key_frame_list.deleteRule(+(parseFloat(to_be_removed_key_list[i]) / 100).toFixed(3)) }} +(parseFloat(to_be_removed_key_list [i])/ 100 ).toFixed(3)位将百分比字符串转换为数字值,将舍入错误考虑在内。 IEEE-754浮点数固有的舍入误差是API首先被改变的原因(与 appendRule()方法的一致性始终如一预期一个字符串),除了因为它只是在 Internet Explorer 11发布之后更改了一段时间,并且因为 IE11将不再接收平台更新,这意味着IE11陷入困境旧的WD实现(我必须强调,它在开发时是最新的)。The +(parseFloat(to_be_removed_key_list[i]) / 100).toFixed(3) bit converts a percentage string to a numeric value taking rounding errors into account. The rounding errors inherent to IEEE-754 floating-point numbers is the reason the API was changed in the first place (that, and consistency with the appendRule() method which has always expected a string), except since it was only changed some time after Internet Explorer 11 was released, and since IE11 will no longer receive platform updates, this means IE11 is stuck with its old WD implementation (which, I must emphasize, was current at the time of its development). 这篇关于deleteRule CSSKeyframesRule方法混淆IE11中的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-13 14:07