Javascript 如何在IE11中设置SVG过滤器的动画?
我专门使用IE11(不问),因此解决方案不必在任何其他浏览器中工作。我有一个包含多个图像的SVG,我在上面应用了几个过滤器。其中之一是一个滤镜,可以使给定的图像变暗。我可以很好地打开和关闭它,并改变过滤器变暗的程度,但我似乎无法使其动画化;相反,在最后指定的过滤器值(在这种情况下,斜率为0.5,一半变暗)处,应用过滤器时没有任何时间延迟 以下是svg的简化版本:Javascript 如何在IE11中设置SVG过滤器的动画?,javascript,svg,internet-explorer-11,svg-filters,Javascript,Svg,Internet Explorer 11,Svg Filters,我专门使用IE11(不问),因此解决方案不必在任何其他浏览器中工作。我有一个包含多个图像的SVG,我在上面应用了几个过滤器。其中之一是一个滤镜,可以使给定的图像变暗。我可以很好地打开和关闭它,并改变过滤器变暗的程度,但我似乎无法使其动画化;相反,在最后指定的过滤器值(在这种情况下,斜率为0.5,一半变暗)处,应用过滤器时没有任何时间延迟 以下是svg的简化版本: <svg id="svgcanvas" width="200" height="200" xmlns="http://www.w
<svg id="svgcanvas" width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<filter id="darkenMe">
<feComponentTransfer>
<feFuncR id="FR" type="linear" slope="1.0"></feFuncR>
<feFuncG id="FG" type="linear" slope="1.0"></feFuncG>
<feFuncB id="FB" type="linear" slope="1.0"></feFuncB>
</feComponentTransfer>
</filter>
<image id="whatever" href="./images/whatever.png" y="0" x="0" width="200" height="200"></image>
</svg>
以下是相关的JS功能:
function applySelectiveDarken(el) {
var elementsToDarken = Array.prototype.slice.call(document.getElementsByClassName("elements-to-darken"),0);
for (i = 0; i < elementsToDarken.length; i++) {
if (elementsToDarken[i].id == el) {
//skip, we just need to darken everything but this
} else {
elementsToDarken[i].setAttribute("filter","url('#darkenMe')");
}
}
animateDarkenDown();
}
function DarkenDown(slopeR, slopeB, slopeG, slope) {
slopeR.setAttribute("slope",slope);
slopeG.setAttribute("slope",slope);
slopeB.setAttribute("slope",slope);
}
var timeoutID, timeout1, timeout2, timeout3, timeout4, timeout5;
function animateDarkenDown() {
var slopeR = document.getElementById("FR");
var slopeG = document.getElementById("FG");
var slopeB = document.getElementById("FB");
var slope = 1.0;
// my first attempt
/*for (i = 0; i < 5; i++) {
timeout = window.setTimeout(DarkenDown(slopeR, slopeG, slopeB, slope), 100);
slope = slope - 0.1;
}*/
//second attempt, also not working, behaves the same as above
timeout1 = window.setTimeout(DarkenDown(slopeR, slopeG, slopeB, 0.9), 100);
timeout2 = window.setTimeout(DarkenDown(slopeR, slopeG, slopeB, 0.8), 200);
timeout3 = window.setTimeout(DarkenDown(slopeR, slopeG, slopeB, 0.7), 300);
timeout4 = window.setTimeout(DarkenDown(slopeR, slopeG, slopeB, 0.6), 400);
timeout5 = window.setTimeout(DarkenDown(slopeR, slopeG, slopeB, 0.5), 500);
}
document.getElementById("whatever").addEventListener("mouseover", function(e) {
applySelectiveDarken("whatever");
});
函数applySelectiveDarken(el){
var elementsToDarken=Array.prototype.slice.call(document.getElementsByClassName(“要变暗的元素”),0;
对于(i=0;i
我希望超时有问题(如果有更好的方法,我很感兴趣。我可以使用jquery和其他库,但我更喜欢原生JS,因为客户端对传递PageSpeed洞察很挑剔)。所以部分问题是setTimeout的语法,但它也不接受元素作为参数(不知道为什么)。因此,我稍微改变了逻辑,创建了5个不同的过滤器,每个过滤器具有不同的斜率,并将遍历所有需要更改过滤器的图像的循环移动到一个助手函数中,该函数在超时时被调用。然后我执行了5个不同的超时(因此不会被覆盖).以下是修订后的SVG:
<svg id="svgcanvas" width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<filter id="darkenMe">
<feComponentTransfer>
<feFuncR id="FR" type="linear" slope="1.0"></feFuncR>
<feFuncG id="FG" type="linear" slope="1.0"></feFuncG>
<feFuncB id="FB" type="linear" slope="1.0"></feFuncB>
</feComponentTransfer>
</filter>
<filter id="darkenMe2">
<feComponentTransfer>
<feFuncR type="linear" slope="0.9"></feFuncR>
<feFuncG type="linear" slope="0.9"></feFuncG>
<feFuncB type="linear" slope="0.9"></feFuncB>
</feComponentTransfer>
</filter>
<filter id="darkenMe3">
<feComponentTransfer>
<feFuncR type="linear" slope="0.8"></feFuncR>
<feFuncG type="linear" slope="0.8"></feFuncG>
<feFuncB type="linear" slope="0.8"></feFuncB>
</feComponentTransfer>
</filter>
<filter id="darkenMe4">
<feComponentTransfer>
<feFuncR type="linear" slope="0.7"></feFuncR>
<feFuncG type="linear" slope="0.7"></feFuncG>
<feFuncB type="linear" slope="0.7"></feFuncB>
</feComponentTransfer>
</filter>
<filter id="darkenMe5">
<feComponentTransfer>
<feFuncR type="linear" slope="0.6"></feFuncR>
<feFuncG type="linear" slope="0.6"></feFuncG>
<feFuncB type="linear" slope="0.6"></feFuncB>
</feComponentTransfer>
</filter>
<image id="whatever" href="./images/whatever.png" y="0" x="0" width="200" height="200"></image>
</svg>
以下是相关的JS:
function filterHelper(el,filter) {
var elementsToChange = Array.prototype.slice.call(document.getElementsByClassName("apple-table"),0);
for (i = 0; i < elementsToChange.length; i++) {
if (elementsToChange[i].id == el) {
//skip
} else {
elementsToChange[i].setAttribute("filter",filter);
}
}
}
var timeoutID, timeout1, timeout2, timeout3, timeout4, timeout5;
function applySelectiveDarken(el) {
timeout1 = window.setTimeout(function() {
filterHelper(el,"url('#darkenMe)");
}, 50);
timeout2 = window.setTimeout(function() {
filterHelper(el,"url('#darkenMe2)");
}, 100);
timeout3 = window.setTimeout(function() {
filterHelper(el,"url('#darkenMe3)");
}, 150);
timeout4 = window.setTimeout(function() {
filterHelper(el,"url('#darkenMe4)");
}, 200);
timeout5 = window.setTimeout(function() {
filterHelper(el,"url('#darkenMe5)");
}, 250);
}
功能过滤器帮助器(el,过滤器){
var elementsToChange=Array.prototype.slice.call(document.getElementsByClassName(“苹果表”),0);
对于(i=0;i
然而,虽然这是我想要的,但它是脆弱的。例如,如果我想更改转换中的步骤数,我就要设置更多的超时和过滤器。有没有更有效、更不脆弱的方法?编写
window.setTimeout(变暗(slopeR,slopeG,slopeB,0.9),100);
类似于编写:
var result = DarkenDown(slopeR, slopeG, slopeB, 0.9);
window.setTimeout(result, 100);
您正在调用DarkenDown
,然后创建一个不会调用任何内容的超时
这里至少有两种解决方案。您可以创建一个调用DarkenDown
的函数,或使用bind定义参数值:
window.setTimeout(function() { DarkenDown(slopeR, slopeG, slopeB, 0.9) }, 100);
或
我发现超时立即触发,因为语法错误。在上面的表单中,DarkenDown(…),100不起作用,但DarkenDown,100起作用。但是我需要传入参数。另一种方法是timeout1=window.setTimeout(函数(){DarkenDown(arguments);},2000);但是,我在获取元素时遇到了问题,因此这不是一个完整的解决方案。我认为问题在于您正在将SVG片段的名称空间设置为“SVG”。如果您只保留“xmlns=”“,元素将保留在HTML5名称空间(默认)中,您应该能够使用正常的jquery。
window.setTimeout(DarkenDown.bind(slopeR, slopeG, slopeB, 0.9), 100);