Forum Discussion
Sliding Results Bar by Variable - impossible?
I've created a self assessment that maps a company's readiness level for adopting innovation. They score themselves on a range of metrics and end up somewhere on a 5 point scale showing their current readiness, and clearly displaying what they need to do to move themselves closer to full readiness, however it isn't as simple as 5 - there are graduations between the numbers. I want their result to fill up a meter in a smooth and visually appealing graphic which slides from the left to the right, and stops where they are in their readiness level, which might include 3.2, 3.25, 4.15 etc.
I'm having real difficulty making this animation based on the variable from their results. (I have the final variable by using triggers to add the results one by one to a new variable, then divide that result by 5, thus making the average which is their final score).
Motion paths can't be edited based on a variable (ie, motion path to stop 'variable' percent of the path); motion paths go from the center of the object, not the edge meaning imprecise ending of the motion across a range; layering and using states means I have to do something like 50 states to show the graduations between numbers which is a lot of work and still isn't going to show the graduations I want to show. Using a slider won't work as you can't change the colours of the slider track as the thumb moves.
Can anyone help me? Surely I'm not the only one who wants to show results by percentage, with accuracy in this way? Think of the ways to use it - filling up a jar to a percentage point... Superimposing a syringe image and decreasing a quantity by a percentage... Making a tug-of-war concept that changes by percentage to demonstrate equal and opposing concepts...
If you examine the JS ,I think you'll find that this does actually move the bar according to the value of the variable (0 to 100). The movement itself is triggered by the incremental changes to a variable (starting at 0 and progressing to the final value), but that all happens inside the script trigger to move the bar. The actual distance is set by the variable currently attached to the slider.
- Nathan_HilliardCommunity Member
While you can make a much more elegant progress bar using GSAP or even CSS animations through JavaScript, you can make a very basic progress bar using a motion path linked to a variable change trigger. This still uses JavaScript to update the variable via whatever process you desire, but it avoids a lot of the other issues created by modifying object positions outside of Storyline proper.
Basic demo of linking motion path: https://360.articulate.com/review/content/ad32b581-1869-417a-bdcb-c91399dbdcf4/review
This uses a motion path with a relative start position and no easing that moves a very small increment each time a variable changes. Update the variable to the desired endpoint in a JS trigger and the object will move along the motion path. The variable update process could be modified to accomodate your desired speed, easing, etc.
- AlvaroAldanaCommunity Member
Thanks so much for the reply, Nathan!
Unfortunately, I need this for a results bar, not a progress bar. The progress bar solution is great because yes, it can advance each time a variable changes. But I need the moving bar to move only based on the variable - not that the variable changes.
For example, on the assessment, say they end up with a 7.2 out of 10. I need a bar to move 72% of the length of the motion path and stop.
The assessment result is achievable through triggers to make a variable, no problem.
I can express that result as a percentage as a variable, no problem.Making an object move the percentage amount, the amount of the variable? Nope! I'm pulling my hair out! 🤪
Any help very much appreciated.- Nathan_HilliardCommunity Member
If you examine the JS ,I think you'll find that this does actually move the bar according to the value of the variable (0 to 100). The movement itself is triggered by the incremental changes to a variable (starting at 0 and progressing to the final value), but that all happens inside the script trigger to move the bar. The actual distance is set by the variable currently attached to the slider.
- AlvaroAldanaCommunity Member
That seems to be the answer, Nathan! Thanks so much for your help!
- NedimCommunity Member
I used this concept a while ago, which involves JavaScript and the GSAP library for the animation part. It's a single line shape with an animated property that adjusts its width based on a variable value. The rectangle beneath it represents the total width and acts as a marker. For example, if the variable value is 56, the line's width is calculated as 56% of the rectangle's width. Does that make sense? I'm not sure if it aligns with your requirements, but I thought it would be worth mentioning.
- AlvaroAldanaCommunity Member
Thanks, Nadim! That looks great and could also be a solution. Can you share the java script? How do you assign the variable to the line width?
- NedimCommunity Member
I've attached a .story file with a simple example demonstrating how to achieve this effect. In short, start by drawing a rectangle, for example, 400px wide, which will serve as the background for the fill. Then, draw a line on top of the rectangle and align it with the left edge of the rectangle. Once aligned, set the line's width to 1px and its height to 0px. Next, select the line, right-click to access 'Accessibility' and enter 'line' as 'Alternative Text', so that we can reference it in our scripts.
The main goal is to properly access the line 'x2' property and manipulate its value with the value of our variable.
Example:
Current x2 = 1;
Var = 72;
Base length: 400px
New x2 = 72 * (400 / 100) = 288px (72% of the length of the base rectangle)
Initially, I load this script to set the line's stroke-width to match the height of the base rectangle.const fill = document.querySelector('[data-acc-text="line"] line'); fill.style.setProperty('stroke-width', '15');
Main scriptconst fillWidthCurrent = document.querySelector('[data-acc-text="line"] [x2]'); const maxLength = 400; const myVar = getVar('Var1'); const fillWidthAfter = myVar * (maxLength / 100); gsap.to(fillWidthCurrent, { duration: 1, attr: { x2: fillWidthAfter }, ease: 'power2.out' });
Result