1

I'm trying to generate a task timeline coded as SVG in a generic way, and managed to do it until this point:

https://jsfiddle.net/dx7uryob/

What remains to do is the following animation (on any task point):

From:

enter image description here:

To the "task" label rotating 90 deg until displayed perfectly horizontally and centered above the task point. I managed to do this by adding rotate(90, x+45, y) into the transform attribute of the according <text> tag, but this fails to rotate gradually when I use svg text { transition: transform 1s; }.

I would really like to know how to animate that (working also in IE, so I guess animateTransform is not an option..?).

Then, the final step would be to blend in a second label below the rotated "task" label, ideally by turning an opacity to 1 to gradually make it appear / disappear. For this, I could not even find out how to place a second text label below the first one in an SVG.

Concering solutions; I'd really prefer to stick to SVG, as my solution copied in the snippet can be generated in a generic way and then scaled as you please; it's just these last two pieces missing and I can't find them out.

.label-below-task-point {
    text-anchor: end;
}
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
    <line x1="11" x2="200" y1="11" y2="142.2" stroke="black" />
    <line x1="200" x2="400" y1="142.2" y2="121" stroke="black" />
    <line x1="400" x2="600" y1="121" y2="167.6" stroke="black" />
    <line x1="600" x2="989" y1="167.6" y2="11" stroke="black" />
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="11" transform="translate(-10,-10)" />
    <text x="11" y="11" transform="translate(6,20) rotate(-90,11,11)" class="label-below-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="200" y="142.2" transform="translate(-10,-10)" />
    <text x="200" y="142.2" transform="translate(6,-20) rotate(-90,200,142.2)" class="label-above-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="400" y="121" transform="translate(-10,-10)" />
    <text x="400" y="121" transform="translate(6,-20) rotate(-90,400,121)" class="label-above-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="600" y="167.6" transform="translate(-10,-10)" />
    <text x="600" y="167.6" transform="translate(6,-20) rotate(-90,600,167.6)" class="label-above-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="989" y="11" transform="translate(-10,-10)" />
    <text x="989" y="11" transform="translate(6,20) rotate(-90,989,11)" class="label-below-task-point">task</text>
</svg>

Am I maybe better off using a canvas here? I've no experience with it, but I wonder if it's the better choice for what I'm trying to do..

DevelJoe
  • 856
  • 1
  • 10
  • 24
  • 1
    use animateTransform and [fakesmile](https://leunen.me/fakesmile/) to support IE – Robert Longson Mar 29 '21 at 09:34
  • I'll check that, cheers. – DevelJoe Mar 29 '21 at 23:02
  • @RobertLongson do you know how to trigger animateTransform effects on click, e.g. via a js click event listener? Just add the animateTransform element on click ? – DevelJoe Apr 01 '21 at 21:29
  • 1
    use begin="click" – Robert Longson Apr 01 '21 at 21:40
  • Legend, thx mate – DevelJoe Apr 01 '21 at 23:05
  • And a last follow-up. When the element is clicked again, I wanna reverse the animation back to the original state. What I'm doing for the moment is reverse the values specified in the ```animateTransform``` element on click via js (e.g. if ```from="0" to="90"```, change these attribute values to ```from="90" to="0"``` and leave the rest as is). Is there a better approach than this; maybe some built-in SVG animation feature? – DevelJoe Apr 03 '21 at 10:34
  • so am I understanding you correctly; the only way to do this is creating a duplicate element for the one you want to animate on & off; ad work with ```display:block``` and ```display:none``` on these and ```begin ="click"```? (I'm assuming you closed https://stackoverflow.com/questions/66931710/trigger-reverse-svg-animation-triggered-with-button-click-on-subsequent-click)..? – DevelJoe Apr 03 '21 at 13:55
  • Couldn't you make things easier by let's say coding two ```animateTransform``` s; one for the forward and another for the backwards animation A) and B), and then use a js variable as ```var forward=true```; then trigger either A) or B) if ```forward``` is true or false, then change the value of ```forward``` to the opposite value..? For this you'd need to trigger an SVG animation via js; and the only way I've read is via ```beginElement()```, right? – DevelJoe Apr 03 '21 at 13:59
  • In case of anyone wondering about answers, check [this](https://stackoverflow.com/questions/32431156/toggle-svg-animation-effect-when-click-the-button) (thanks @Robert Longson) and [this](https://codepen.io/mikemjharris/post/svg-toggling) – DevelJoe Apr 03 '21 at 14:55

1 Answers1

0

I have solved it for the second text, task2, using transform-origin :

.label-below-task-point {
    transform: rotate(90deg);
    transition: transform 1s;
}

.label-below-task-point:hover {
    transform: rotate(0deg);
}
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
    <line x1="11" x2="200" y1="11" y2="142.2" stroke="black" />
    <line x1="200" x2="400" y1="142.2" y2="121" stroke="black" />
    <line x1="400" x2="600" y1="121" y2="167.6" stroke="black" />
    <line x1="600" x2="989" y1="167.6" y2="11" stroke="black" />
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="11" transform="translate(-10,-10)" />
    <text x="11" y="11" class="label-below-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="200" y="142.2" transform="translate(-10,-10)" />
    <text x="180" y="125" transform-origin="199px 120px" class="label-below-task-point">task2</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="400" y="121" transform="translate(-10,-10)" />
    <text x="400" y="121" transform="translate(6,-20) rotate(-90,400,121)" class="label-above-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="600" y="167.6" transform="translate(-10,-10)" />
    <text x="600" y="167.6" transform="translate(6,-20) rotate(-90,600,167.6)" class="label-above-task-point">task</text>
    <rect stroke="black" stroke-width="2" fill="white" width="20" height="20" x="989" y="11" transform="translate(-10,-10)" />
    <text x="989" y="11" transform="translate(6,20) rotate(-90,989,11)" class="label-below-task-point">task</text>
</svg>
vals
  • 61,425
  • 11
  • 89
  • 138