animate.js 修复运动路径,使 svg 的边缘始终与其他 svg 处于边缘

animate.js Fix motion path so edge of svg is always on edge with other svg

我似乎无法解决以下问题。 我正在创建一个刽子手游戏并使用自绘的 svg(刽子手) 然后我尝试将铅笔 svg 从 bootstrap 图标调整为那个刽子手 svg,这样看起来刽子手是用铅笔画出来的。

我遇到的唯一问题是铅笔应该始终与我的 svg 成一定角度,这样笔尖看起来就像接触到 svg。

以下是我的代码。如您所见,铅笔尖并不总是在我要绘制的 svg 线上,因为它在四处移动。

有办法解决吗?如果不是,我将如何以其他方式完成该任务?

感谢大家!

function animateHangman(target)
{
    anime({
        targets: '#hangman-animation #svg5 ' + target,
        strokeDashoffset: [anime.setDashoffset, 0],
        easing: 'easeInOutSine',
        opacity: [0, 1],
        duration: 2000,
    });

    var path = anime.path('#hangman-animation #svg5 ' + target);
    anime({
        targets: '#pencil',
        translateX: path('x'),
        translateY: path('y'),
        rotate: path('angle'),
        easing: 'linear',
        duration: 1900,
        opacity: [0, 1]
    });
}

var elements = ['#startblock', '#pillar', '#crossbar', '#stabilizer', '#rope', '#stickhead', '#stickbody', '#rightarm', '#leftarm', '#rightleg', '#leftleg'];
function delay(time)
{
    return new Promise(resolve => setTimeout(resolve, time));
}

elements.forEach((el, index) => {
    setTimeout(() => {
        animateHangman(el);
    }, 1000 * index)
});
#hangman-animation {
  position: relative;
}

#startblock {
  opacity: 0;
}

#pillar {
  opacity: 0;
}

#crossbar {
  opacity: 0;
}

#stabilizer {
  opacity: 0;
}

/*#headrope {
  opacity: 0;
}*/

#stickhead {
  opacity: 0;
}

#rope {
  opacity: 0;
}

#stickbody {
  opacity: 0;
}

#rightarm {
  opacity: 0;
}

#leftarm {
  opacity: 0;
}

#rightleg {
  opacity: 0;
}

#leftleg {
  opacity: 0;
}

#svg5 {
  border: #000 dashed 1px;
  padding: 3rem;
}

.square {
  width: 5px;
  height: 5px;
  fill: darkgreen;
  opacity: 0;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.0/font/bootstrap-icons.css" integrity="sha384-ejwKkLla8gPP8t2u0eQyL0Q/4ItcnyveF505U0NIobD/SMsNyXrLti6CWaD0L52l" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>

<div id="hangman-animation" class="mt-4 mb-3">
            <svg
                    width="250px"
                    height="250px"
                    viewBox="0 0 132.40746 133.18132"
                    version="1.1"
                    id="svg5"
                    inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
                    sodipodi:docname="sp_hangman_4.svg"
                    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
                    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
                    xmlns="http://www.w3.org/2000/svg"
                    xmlns:svg="http://www.w3.org/2000/svg">
                <sodipodi:namedview
                        id="namedview7"
                        pagecolor="#505050"
                        bordercolor="#eeeeee"
                        borderopacity="1"
                        inkscape:pageshadow="0"
                        inkscape:pageopacity="0"
                        inkscape:pagecheckerboard="0"
                        inkscape:document-units="mm"
                        showgrid="false"
                        inkscape:zoom="0.5"
                        inkscape:cx="121"
                        inkscape:cy="230"
                        inkscape:window-width="1920"
                        inkscape:window-height="1017"
                        inkscape:window-x="-8"
                        inkscape:window-y="-8"
                        inkscape:window-maximized="1"
                        inkscape:current-layer="svg5"
                        fit-margin-top="0"
                        fit-margin-left="0"
                        fit-margin-right="0"
                        fit-margin-bottom="0" />
                <defs
                        id="defs2" />
                <g id="pencil">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16">
                            <path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/>
                        </svg>
                </g>
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.211347;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 0.285709,132.847 43.289791,0.228 0.1789,-10.821 -16.994,-5.809 H 14.4175 l -14.310675,5.581 z"
                        id="startblock" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 14.4252,116.467 H 26.7555 L 27.1129,12.1056 H 15.3187 Z"
                        id="pillar" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 0.843947,12.463 27.1129,12.1056 H 125.398 V 0.13273 L 0.665247,0.66883 Z"
                        id="crossbar" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 27.1129,27.6526 44.6255,11.927 59.6364,12.1057 26.7555,40.1616 Z"
                        id="stabilizer" />
                <g
                        id="headrope"
                        inkscape:label="headrope" />
                <path
                        id="rope"
                        style="fill:none;stroke:#000000;stroke-width:0.20767;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 116.996,12.1075 0.721,21.8865 z" />
                <ellipse
                        style="fill:#000000;stroke-width:0.264583"
                        id="stickhead"
                        cx="117.93734"
                        cy="39.625481"
                        rx="7.2373662"
                        ry="7.460743"
                        inkscape:label="stickhead" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.105,47.0091 0.347,22.6185"
                        id="stickbody" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.357,53.7378 13.995,-6.4759"
                        id="rightarm" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 118.357,53.7378 105.563,47.2619"
                        id="leftarm" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.452,69.6276 9.604,13.1415"
                        id="rightleg" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.452,69.6276 -9.35,12.1306"
                        id="leftleg" />
            </svg>
        </div>

如果你想让一个特定的点接触它正在追踪的路径,你需要确保该点在 SVG space 中位于 0,0。对于你的铅笔,看起来将它向上推 16 个单位就可以让它走上正轨。最重要的是,您需要确保路径动画和铅笔动画之间的持续时间和缓动匹配,否则它们将 运行 彼此不同步。

我唯一注意到的另一件事是你 space 动画只延迟了 1000 毫秒。因为你只有一支铅笔,所以你会有多个动画相互争夺对它的控制权。最新的动画将获胜,这就是为什么它在跳到下一行之前永远不会完成一行。如果这不是故意的,您可以为每个铅笔创建一个新铅笔,并在动画结束时使用 complete 回调将其销毁。

function animateHangman(target)
{
    anime({
        targets: '#hangman-animation #svg5 ' + target,
        strokeDashoffset: [anime.setDashoffset, 0],
        easing: 'easeInOutSine',
        opacity: {value: [0, 1], duration: 250},
        duration: 1900,
    });

    var path = anime.path('#hangman-animation #svg5 ' + target);
    anime({
        targets: '#pencil',
        translateX: path('x'),
        translateY: path('y'),
        rotate: path('angle'),
        easing: 'easeInOutSine',
        duration: 1900,
        opacity: {value: [0, 1], duration: 250},
    });
}

var elements = ['#startblock', '#pillar', '#crossbar', '#stabilizer', '#rope', '#stickhead', '#stickbody', '#rightarm', '#leftarm', '#rightleg', '#leftleg'];
function delay(time)
{
    return new Promise(resolve => setTimeout(resolve, time));
}

elements.forEach((el, index) => {
    setTimeout(() => {
        animateHangman(el);
    }, 1000 * index)
});
#hangman-animation {
  position: relative;
}

#startblock {
  opacity: 0;
}

#pillar {
  opacity: 0;
}

#crossbar {
  opacity: 0;
}

#stabilizer {
  opacity: 0;
}

/*#headrope {
  opacity: 0;
}*/

#stickhead {
  opacity: 0;
}

#rope {
  opacity: 0;
}

#stickbody {
  opacity: 0;
}

#rightarm {
  opacity: 0;
}

#leftarm {
  opacity: 0;
}

#rightleg {
  opacity: 0;
}

#leftleg {
  opacity: 0;
}

#svg5 {
  border: #000 dashed 1px;
  padding: 3rem;
}

.square {
  width: 5px;
  height: 5px;
  fill: darkgreen;
  opacity: 0;
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.0/font/bootstrap-icons.css" integrity="sha384-ejwKkLla8gPP8t2u0eQyL0Q/4ItcnyveF505U0NIobD/SMsNyXrLti6CWaD0L52l" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>

<div id="hangman-animation" class="mt-4 mb-3">
            <svg
                    width="250px"
                    height="250px"
                    viewBox="0 0 132.40746 133.18132"
                    version="1.1"
                    id="svg5"
                    inkscape:version="1.1.2 (b8e25be833, 2022-02-05)"
                    sodipodi:docname="sp_hangman_4.svg"
                    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
                    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
                    xmlns="http://www.w3.org/2000/svg"
                    xmlns:svg="http://www.w3.org/2000/svg">
                <sodipodi:namedview
                        id="namedview7"
                        pagecolor="#505050"
                        bordercolor="#eeeeee"
                        borderopacity="1"
                        inkscape:pageshadow="0"
                        inkscape:pageopacity="0"
                        inkscape:pagecheckerboard="0"
                        inkscape:document-units="mm"
                        showgrid="false"
                        inkscape:zoom="0.5"
                        inkscape:cx="121"
                        inkscape:cy="230"
                        inkscape:window-width="1920"
                        inkscape:window-height="1017"
                        inkscape:window-x="-8"
                        inkscape:window-y="-8"
                        inkscape:window-maximized="1"
                        inkscape:current-layer="svg5"
                        fit-margin-top="0"
                        fit-margin-left="0"
                        fit-margin-right="0"
                        fit-margin-bottom="0" />
                <defs
                        id="defs2" />
                <g id="pencil">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16" x="0" y="-16">
                            <path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" />
                        </svg>
                </g>
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.211347;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 0.285709,132.847 43.289791,0.228 0.1789,-10.821 -16.994,-5.809 H 14.4175 l -14.310675,5.581 z"
                        id="startblock" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 14.4252,116.467 H 26.7555 L 27.1129,12.1056 H 15.3187 Z"
                        id="pillar" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 0.843947,12.463 27.1129,12.1056 H 125.398 V 0.13273 L 0.665247,0.66883 Z"
                        id="crossbar" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 27.1129,27.6526 44.6255,11.927 59.6364,12.1057 26.7555,40.1616 Z"
                        id="stabilizer" />
                <g
                        id="headrope"
                        inkscape:label="headrope" />
                <path
                        id="rope"
                        style="fill:none;stroke:#000000;stroke-width:0.20767;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 116.996,12.1075 0.721,21.8865 z" />
                <ellipse
                        style="fill:#000000;stroke-width:0.264583"
                        id="stickhead"
                        cx="117.93734"
                        cy="39.625481"
                        rx="7.2373662"
                        ry="7.460743"
                        inkscape:label="stickhead" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.105,47.0091 0.347,22.6185"
                        id="stickbody" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.357,53.7378 13.995,-6.4759"
                        id="rightarm" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="M 118.357,53.7378 105.563,47.2619"
                        id="leftarm" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.452,69.6276 9.604,13.1415"
                        id="rightleg" />
                <path
                        style="fill:none;stroke:#000000;stroke-width:0.264583;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
                        d="m 118.452,69.6276 -9.35,12.1306"
                        id="leftleg" />
            </svg>
        </div>