如何用CSS/Svelte实现SVG <line>元素坐标属性的过渡动画?
SVG线条坐标平滑过渡解决方案
问题根源
你当前用{#if}条件渲染切换<line>元素,这会导致旧线条被销毁、新线条被创建,而非同一元素的属性值变化——CSS过渡只对同一元素的属性变更生效,所以直接跳变无动画。
方案一:原生CSS过渡(优先推荐)
保留所有<line>元素,通过动态绑定属性值实现状态切换,让CSS能捕获属性变化并触发过渡。
修改后的Svelte组件代码
<button aria-pressed={active} on:click={toggleActive} {...$$restProps}> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"> <!-- 第一条线:从水平中线变对角线 --> <line x1={active ? 10 : 5} y1={active ? 10 : 10} x2={active ? 20 : 35} y2={active ? 20 : 10} /> <!-- 第二条线:从水平中线变交叉对角线 --> <line x1={active ? 10 : 5} y1={active ? 30 : 20} x2={active ? 30 : 35} y2={active ? 10 : 20} /> <!-- 第三条线:从水平中线变对角线 --> <line x1={active ? 20 : 5} y1={active ? 20 : 30} x2={active ? 30 : 35} y2={active ? 30 : 30} /> </svg> </button>
CSS代码
svg line { stroke: black; stroke-width: 5; /* 精准指定过渡属性,也可用all简化 */ transition: x1 0.5s, x2 0.5s, y1 0.5s, y2 0.5s; }
说明
- 移除
{#if}条件渲染,让每个<line>始终存在于DOM中 - 用Svelte属性绑定语法
{active ? A : B}动态切换坐标值 - CSS过渡会捕获同一元素的属性变化,实现平滑动画
方案二:Svelte过渡+元素复用(备选)
如果一定要用条件渲染,可以结合Svelte的{#key}指令复用元素,同时配合过渡效果:
组件代码
<script> import { fade } from 'svelte/transition'; let active = false; function toggleActive() { active = !active; } </script> <button aria-pressed={active} on:click={toggleActive} {...$$restProps}> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"> {#key active} <g in:fade={{duration: 500}} out:fade={{duration: 500}}> {#if active} <line x1="10" y1="10" x2="20" y2="20" /> <line x1="10" y1="30" x2="30" y2="10" /> <line x1="20" y1="20" x2="30" y2="30" /> {:else} <line x1="5" y1="10" x2="35" y2="10" /> <line x1="5" y1="20" x2="35" y2="20" /> <line x1="5" y1="30" x2="35" y2="30" /> {/if} </g> {/key} </svg> </button> <style> svg line { stroke: black; stroke-width: 5; } </style>
说明
{#key active}会在active变化时复用<g>元素容器,避免完全销毁重建- 用
fade过渡实现切换时的淡入淡出效果,适合不需要坐标平滑过渡的场景
注意:此方案是元素切换的过渡,而非坐标属性的连续平滑动画,若需要线条坐标的渐变效果,优先选方案一。
内容的提问来源于stack exchange,提问作者code913
相关产品推荐
相关产品推荐

