我如何避免在 svg 变形转换中出现损坏的 svg 路径?
How do i avoid the mangled svg path in the svg morph transition?
我在 inkscape 中创建了以下 svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="345.70975"
height="352.91309"
viewBox="0 0 91.469035 93.374923"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="double-square.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="226.41877"
inkscape:cy="36.880616"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="801"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-21.120772,-24.484056)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#800080;stroke-width:1.29393971;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z"
id="rect818"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:1.31637728;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 96.672725,103.80812 c -22.695046,9.46462 -52.584739,24.28389 -62.190302,0.78977 -9.605563,-23.494119 -20.853186,-57.321821 1.841865,-66.786436 22.695046,-9.464613 57.771554,-23.161339 67.377122,0.332775 9.60556,23.494112 15.66636,56.199275 -7.028685,65.663891 z"
id="path815"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssss" />
</g>
</svg>
现在,当我使用 anime.js 将此 svg 从正方形变形为圆角正方形时,我看到正方形被破坏了很多,向正方形的过渡不太正确。
let shapes = [
{
d: "m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z"
},
{
d: "m 96.672725,103.80812 c -22.695046,9.46462 -52.584739,24.28389 -62.190302,0.78977 -9.605563,-23.494119 -20.853186,-57.321821 1.841865,-66.786436 22.695046,-9.464613 57.771554,-23.161339 67.377122,0.332775 9.60556,23.494112 15.66636,56.199275 -7.028685,65.663891 z"
}
]
var morph1 = anime({
targets: '.square-path',
d: [
{value: shapes[0].d},
{value: shapes[1].d}
],
duration: 3000,
direction: 'alternate',
autoplay: true,
easing: 'linear',
elasticity: 100,
loop: true
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="345.70975"
height="352.91309"
viewBox="0 0 91.469035 93.374923"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="double-square.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="226.41877"
inkscape:cy="36.880616"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="801"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-21.120772,-24.484056)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#800080;stroke-width:1.29393971;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z"
id="rect818"
class="square-path"
inkscape:connector-curvature="0" />
</g>
</svg>
如何避免 svg 变形过渡中出现乱七八糟的正方形?
确保您的两个形状具有相同的段数和段类型。
这实际上是一个 SVG 规则,但我相信 anime.js 可以帮助您通过修改路径来解决这个规则,使它们起作用。但是最好自己控制它,而不是依靠程序来猜测你的意图。
您的起始路径有 8 或 9 个路径段:
m 22.242817,24.963907
h 89.459313
c 0.10307,0 0.18605,0.08678 0.18605,0.194558
v 92.051005
c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456
H 22.242817
c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456
V 25.158465
c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558
z
但是你的结束路径只有四个:
m 96.672725,103.80812
c -22.695046,9.46462 -52.584739,24.28389 -62.190302,0.78977
c -9.605563,-23.494119 -20.853186,-57.321821 1.841865,-66.786436
c 22.695046,-9.464613 57.771554,-23.161339 67.377122,0.332775
c 9.60556,23.494112 15.66636,56.199275 -7.028685,65.663891
z
两条路径都应该有匹配的路径命令。例如,两个路径都应该是 M H C V C H C V C Z
,或者都应该是 M C C C C Z
.
安排你的路径点,使它们的位置靠近你希望它们以另一种形状结束的位置。
例如,在圆到正方形的过渡中,使圆有四个点,并将这四个点定位在 NW、NE、SW 和 SE。
相反,如果它们相对于另一个形状处于随机位置,您将获得一个动画,看起来像是将自己绑定到一个 not 中,然后再进行解读。
在下面的示例中,两条路径正好有 四个 贝塞尔曲线路径命令 (c
)。并且它们的端点靠近另一个形状上的相应位置。请注意,即使是正方形的直线,我也使用了曲线路径命令 (C
)。你可以让曲线看起来笔直,但你不能让直线弯曲。
let shapes = [
{
d: "M 20, 20 c 100,0 200,0 300,0 c 0,100 0,200 0,300 c -100,0 -200,0 -300,0 c 0,-100 0,-200 0,-300 z"
},
{
d: "M 89.289322,89.289322 c 42.392448,-38.369033 104.952908,-35.372751 141.421358,0 39.05243,39.052428 39.05243,102.368928 0,141.421358 -39.05243,39.05243 -102.36893,39.05243 -141.421358,0 -39.05243,-39.05243 -39.052429,-102.36893 0,-141.421358 z"
}
]
var morph1 = anime({
targets: '.square-path',
d: [
{value: shapes[0].d},
{value: shapes[1].d}
],
duration: 3000,
direction: 'alternate',
autoplay: true,
easing: 'linear',
elasticity: 100,
loop: true
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg
width="345.70975"
height="352.91309"
viewBox="0 0 340 340"
id="svg8">
<g
id="layer1">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#800080;stroke-width:1.29393971;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 20, 20 c 100,0 200,0 300,0 c 0,100 0,200 0,300 c -100,0 -200,0 -300,0 c 0,-100 0,-200 0,-300 z"
id="rect818"
class="square-path" />
</g>
</svg>
我在 inkscape 中创建了以下 svg
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="345.70975"
height="352.91309"
viewBox="0 0 91.469035 93.374923"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="double-square.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="226.41877"
inkscape:cy="36.880616"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="801"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-21.120772,-24.484056)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#800080;stroke-width:1.29393971;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z"
id="rect818"
inkscape:connector-curvature="0" />
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:1.31637728;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 96.672725,103.80812 c -22.695046,9.46462 -52.584739,24.28389 -62.190302,0.78977 -9.605563,-23.494119 -20.853186,-57.321821 1.841865,-66.786436 22.695046,-9.464613 57.771554,-23.161339 67.377122,0.332775 9.60556,23.494112 15.66636,56.199275 -7.028685,65.663891 z"
id="path815"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssss" />
</g>
</svg>
现在,当我使用 anime.js 将此 svg 从正方形变形为圆角正方形时,我看到正方形被破坏了很多,向正方形的过渡不太正确。
let shapes = [
{
d: "m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z"
},
{
d: "m 96.672725,103.80812 c -22.695046,9.46462 -52.584739,24.28389 -62.190302,0.78977 -9.605563,-23.494119 -20.853186,-57.321821 1.841865,-66.786436 22.695046,-9.464613 57.771554,-23.161339 67.377122,0.332775 9.60556,23.494112 15.66636,56.199275 -7.028685,65.663891 z"
}
]
var morph1 = anime({
targets: '.square-path',
d: [
{value: shapes[0].d},
{value: shapes[1].d}
],
duration: 3000,
direction: 'alternate',
autoplay: true,
easing: 'linear',
elasticity: 100,
loop: true
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="345.70975"
height="352.91309"
viewBox="0 0 91.469035 93.374923"
version="1.1"
id="svg8"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="double-square.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="226.41877"
inkscape:cy="36.880616"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1440"
inkscape:window-height="801"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-21.120772,-24.484056)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#800080;stroke-width:1.29393971;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z"
id="rect818"
class="square-path"
inkscape:connector-curvature="0" />
</g>
</svg>
如何避免 svg 变形过渡中出现乱七八糟的正方形?
确保您的两个形状具有相同的段数和段类型。
这实际上是一个 SVG 规则,但我相信 anime.js 可以帮助您通过修改路径来解决这个规则,使它们起作用。但是最好自己控制它,而不是依靠程序来猜测你的意图。
您的起始路径有 8 或 9 个路径段:
m 22.242817,24.963907 h 89.459313 c 0.10307,0 0.18605,0.08678 0.18605,0.194558 v 92.051005 c 0,0.10779 -0.0829,0.19456 -0.18605,0.19456 H 22.242817 c -0.103073,0 -0.186053,-0.0867 -0.186053,-0.19456 V 25.158465 c 0,-0.107785 0.08299,-0.194558 0.186053,-0.194558 z
但是你的结束路径只有四个:
m 96.672725,103.80812 c -22.695046,9.46462 -52.584739,24.28389 -62.190302,0.78977 c -9.605563,-23.494119 -20.853186,-57.321821 1.841865,-66.786436 c 22.695046,-9.464613 57.771554,-23.161339 67.377122,0.332775 c 9.60556,23.494112 15.66636,56.199275 -7.028685,65.663891 z
两条路径都应该有匹配的路径命令。例如,两个路径都应该是
M H C V C H C V C Z
,或者都应该是M C C C C Z
.安排你的路径点,使它们的位置靠近你希望它们以另一种形状结束的位置。
例如,在圆到正方形的过渡中,使圆有四个点,并将这四个点定位在 NW、NE、SW 和 SE。
相反,如果它们相对于另一个形状处于随机位置,您将获得一个动画,看起来像是将自己绑定到一个 not 中,然后再进行解读。
在下面的示例中,两条路径正好有 四个 贝塞尔曲线路径命令 (c
)。并且它们的端点靠近另一个形状上的相应位置。请注意,即使是正方形的直线,我也使用了曲线路径命令 (C
)。你可以让曲线看起来笔直,但你不能让直线弯曲。
let shapes = [
{
d: "M 20, 20 c 100,0 200,0 300,0 c 0,100 0,200 0,300 c -100,0 -200,0 -300,0 c 0,-100 0,-200 0,-300 z"
},
{
d: "M 89.289322,89.289322 c 42.392448,-38.369033 104.952908,-35.372751 141.421358,0 39.05243,39.052428 39.05243,102.368928 0,141.421358 -39.05243,39.05243 -102.36893,39.05243 -141.421358,0 -39.05243,-39.05243 -39.052429,-102.36893 0,-141.421358 z"
}
]
var morph1 = anime({
targets: '.square-path',
d: [
{value: shapes[0].d},
{value: shapes[1].d}
],
duration: 3000,
direction: 'alternate',
autoplay: true,
easing: 'linear',
elasticity: 100,
loop: true
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg
width="345.70975"
height="352.91309"
viewBox="0 0 340 340"
id="svg8">
<g
id="layer1">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#800080;stroke-width:1.29393971;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 20, 20 c 100,0 200,0 300,0 c 0,100 0,200 0,300 c -100,0 -200,0 -300,0 c 0,-100 0,-200 0,-300 z"
id="rect818"
class="square-path" />
</g>
</svg>