I can't seem to fix the following problem. I am creating a hangman game and use a self drawn svg (the hangman) Then I try to adjust a pencil svg from bootstrap icons to that hangman svg so that it looks like the hangman is drawn from the pencil.
The only problem I have is that the pencil should always be in an angle to my svg so that it looks like the tip is touching the svg.
Following is my code. As you can see the pencil tip is not always on the svg line I'm trying to draw since it is moving around.
Is there a way to fix it? If not how would I accomplish that task in an other way?
Thanks to all!
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/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/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" >
<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" 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>
CodePudding user response:
If you want a specific point to touch the path it's tracing, you need to make sure that point is positioned at 0,0 in SVG space. For your pencil, looks like nudging it up 16 units gets it on track. On top of that, you need to make sure duration and easing match between the path and pencil animations or they'll run out of sync with each other.
Only other thing I notice is that you space the animations out by only 1000ms. Since you only have one pencil you'll have multiple animations fighting each other over control of it. The newest animation will win which is why it never finishes a line before hopping to the next. If that's not intentional, you can create a new pencil for each one and destroy it when the animation finishes using the complete
callback.
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/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/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" >
<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" 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>