第二次点击时 SVG 动画反转
SVG animate reverse on second click
我是一个尝试制作交互式 SVG 的新手 - 最好没有任何外部脚本。我想要的效果是让一个 SVG 元素充当一个交互式开关,使另一个元素出现和消失。
请在下面找到一个简单版本,其中文本“Toggle”用作切换。单击时,这将使矩形的不透明度属性从 0 变为 1,使其出现。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext.click" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
任何后续点击现在只会重复相同的动画。但我想要任何第二个(第四个、第六个等)点击来反转动画(即让矩形消失)。换句话说,真正充当切换器。
任何有关如何使用尽可能少的代码 and/or 不可见元素实现此效果的建议,我们将不胜感激。
谢谢!
添加第二个矩形渐变动画
<animate id="hide" attributeName="opacity" fill="freeze"
from="1" to="0" dur="2s" begin="indefinite" />
并添加一个切换矩形出现和消失动画的JS触发器
var svg_1 = document.getElementById("svg8"),
hide = document.getElementById("hide"),
visable = document.getElementById("visable");
let flag = true;
svg_1.addEventListener('click', function() {
if (flag == true) {
visable.beginElement();
flag = false;
} else {
hide.beginElement();
flag = true;
}
});
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate id="visable" attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="indefinite" />
<animate id="hide" attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="indefinite" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
这就是我的做法:我使用了 2 个重叠的文本元素,并将指针事件设置为全部或 none 单击:这样您将在一个文本上单击一次接下来是另一个。
矩形有 2 个动画元素:第一个动画将在您单击第一个文本时开始,第二个动画将在您单击第二个文本时开始。
text{font-size:8.46667px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;}
<svg width="300" viewBox="0 0 47.652294 10.096307" id="svg8">
<g id="layer1" transform="translate(-29.085516,-61.315985)">
<rect fill="#ff0000" opacity="0" id="rect" width="9.8317242" height="9.8317242" x="66.773796" y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext1.click" />
<animate attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="toggletext2.click" />
</rect>
<text x="29.085516" y="68.002762" id="toggletext2">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext1.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
<text x="29.085516" y="68.002762" id="toggletext1">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext2.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
</g>
</svg>
虽然我喜欢No-JavaScript pointer-events
方法;我会这样做:
当 OP 说:最好没有任何外部脚本。
我认为他的意思是没有第 3 方库。
所以我会使用自定义元素 <svg-toggle>
(所有现代浏览器都支持)
为您想要的任意数量的切换创建 SVG
切换动画:
- 每次点击切换
from
和 to
参数
- 重启动画
<style>
svg {
display: inline-block; width: 30%; vertical-align: top;
cursor: pointer; background: teal; color: white;
}
</style>
<svg-toggle></svg-toggle>
<svg-toggle color="yellow"></svg-toggle>
<svg-toggle color="blue" label="Blue" duration=".5"></svg-toggle>
<script>
customElements.define('svg-toggle', class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">
${this.getAttribute("label")||'Toggle'}</text>
<rect fill="${this.getAttribute("color")||'red'}" x='33' y="3" width="12" height="12">
<animate attributeName="opacity" dur="${this.getAttribute("duration")||2}s" from="0" to="1" fill="freeze" begin="indefinite"/>
</rect></svg>`;
this.animate = this.querySelector("animate");
this.onclick = (evt) => this.toggle();
}
toggle( // method, so can be called from Javascript
from = this.animate.getAttribute("from"), // optional from/to parameters
to = this.animate.getAttribute("to"),
) {
this.animate.setAttribute( "from", to );
this.animate.setAttribute( "to" , from );
this.animate.beginElement();
}
});
</script>
我不想要现代 W3C 标准 Web Components 胡言乱语...
然后将 JavaScript 贴在 每个 SVG 上:
<svg
onclick="{
let a = this.querySelector('animate');
let from = a.getAttribute('from');
a.setAttribute('from',a.getAttribute('to'));
a.setAttribute('to',from);
a.beginElement();
}"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">Gold</text>
<rect fill="gold" x="33" y="3" width="12" height="12">
<animate attributeName="opacity" dur=".3s" from="0" to="1"
fill="freeze" begin="indefinite"></animate>
</rect>
</svg>
我不要JavaScript
查看 Enxaneta 的 pointer-events
回答
我是一个尝试制作交互式 SVG 的新手 - 最好没有任何外部脚本。我想要的效果是让一个 SVG 元素充当一个交互式开关,使另一个元素出现和消失。
请在下面找到一个简单版本,其中文本“Toggle”用作切换。单击时,这将使矩形的不透明度属性从 0 变为 1,使其出现。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext.click" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
任何后续点击现在只会重复相同的动画。但我想要任何第二个(第四个、第六个等)点击来反转动画(即让矩形消失)。换句话说,真正充当切换器。
任何有关如何使用尽可能少的代码 and/or 不可见元素实现此效果的建议,我们将不胜感激。 谢谢!
添加第二个矩形渐变动画
<animate id="hide" attributeName="opacity" fill="freeze"
from="1" to="0" dur="2s" begin="indefinite" />
并添加一个切换矩形出现和消失动画的JS触发器
var svg_1 = document.getElementById("svg8"),
hide = document.getElementById("hide"),
visable = document.getElementById("visable");
let flag = true;
svg_1.addEventListener('click', function() {
if (flag == true) {
visable.beginElement();
flag = false;
} else {
hide.beginElement();
flag = true;
}
});
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate id="visable" attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="indefinite" />
<animate id="hide" attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="indefinite" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
这就是我的做法:我使用了 2 个重叠的文本元素,并将指针事件设置为全部或 none 单击:这样您将在一个文本上单击一次接下来是另一个。
矩形有 2 个动画元素:第一个动画将在您单击第一个文本时开始,第二个动画将在您单击第二个文本时开始。
text{font-size:8.46667px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;}
<svg width="300" viewBox="0 0 47.652294 10.096307" id="svg8">
<g id="layer1" transform="translate(-29.085516,-61.315985)">
<rect fill="#ff0000" opacity="0" id="rect" width="9.8317242" height="9.8317242" x="66.773796" y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext1.click" />
<animate attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="toggletext2.click" />
</rect>
<text x="29.085516" y="68.002762" id="toggletext2">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext1.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
<text x="29.085516" y="68.002762" id="toggletext1">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext2.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
</g>
</svg>
虽然我喜欢No-JavaScript pointer-events
方法;我会这样做:
当 OP 说:最好没有任何外部脚本。
我认为他的意思是没有第 3 方库。
所以我会使用自定义元素 <svg-toggle>
(所有现代浏览器都支持)
为您想要的任意数量的切换创建 SVG
切换动画:
- 每次点击切换
from
和to
参数 - 重启动画
<style>
svg {
display: inline-block; width: 30%; vertical-align: top;
cursor: pointer; background: teal; color: white;
}
</style>
<svg-toggle></svg-toggle>
<svg-toggle color="yellow"></svg-toggle>
<svg-toggle color="blue" label="Blue" duration=".5"></svg-toggle>
<script>
customElements.define('svg-toggle', class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">
${this.getAttribute("label")||'Toggle'}</text>
<rect fill="${this.getAttribute("color")||'red'}" x='33' y="3" width="12" height="12">
<animate attributeName="opacity" dur="${this.getAttribute("duration")||2}s" from="0" to="1" fill="freeze" begin="indefinite"/>
</rect></svg>`;
this.animate = this.querySelector("animate");
this.onclick = (evt) => this.toggle();
}
toggle( // method, so can be called from Javascript
from = this.animate.getAttribute("from"), // optional from/to parameters
to = this.animate.getAttribute("to"),
) {
this.animate.setAttribute( "from", to );
this.animate.setAttribute( "to" , from );
this.animate.beginElement();
}
});
</script>
我不想要现代 W3C 标准 Web Components 胡言乱语...
然后将 JavaScript 贴在 每个 SVG 上:
<svg
onclick="{
let a = this.querySelector('animate');
let from = a.getAttribute('from');
a.setAttribute('from',a.getAttribute('to'));
a.setAttribute('to',from);
a.beginElement();
}"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">Gold</text>
<rect fill="gold" x="33" y="3" width="12" height="12">
<animate attributeName="opacity" dur=".3s" from="0" to="1"
fill="freeze" begin="indefinite"></animate>
</rect>
</svg>
我不要JavaScript
查看 Enxaneta 的 pointer-events
回答