Forum Discussion
Controlling Illustrated Characters via JS?
- 16 days ago
You can use the object().state property to set slide objects to either the "Normal" state or a custom state. When you add characters to the slide, they adopt the Normal state and whatever pose/expression you selected is assigned to that state. Under the States tab, you can edit and add additional states for a slide object. You can select the character state you desire from the list of possible states, and add that to the state list. The names will match the list, so something like "Surprised", or "Disappointed", etc.
When adjusting states in JavaScript, use Normal to set the normal state, or use one of the custom state names you added (matching the case of the name). You have to explicitly add the state to the list for it to be available from JavaScript.
Note: When testing from the developer panel, if an invalid state was assigned to the object, for example object("####").state = "Default", then all later state assignments also failed, even if correct. I don't know if this issue persists within Storyline project triggers, but it may be a bug and should be kept in mind. If you accidentally assign an invalid state via JavaScript, then they may stop working altogether.
Also, you can assign a Disabled or _disabled state, but I'm not sure what that does since it does not actually become disabled. You can also assign a Hidden state, but if you do you can't unassign it via JavaScript. It just stays hidden.
Hi Andrew,
Part 1
All custom states should be written exactly as they appear in the Object States panel—no underscores are needed. For example, in your case, the custom state is "Happy".
Underscores are only required for default states such as Selected, Hover, Visited, and Down. These must be written with the "default" prefix, like so:
- _default_Selected
- _default_Hover
- _default_Visited
- _default_Down
This also applies when combining multiple default states during interactions, assuming all relevant states are activated in the Object States panel.
Note:
- The Normal state remains simply "Normal" (no prefix or underscores).
- The Disabled state is written as "Disabled".
I used a simple script executed when the timeline starts, as well as for enabling and disabling a button.
const button1 = object('5pyrnxdTyGJ');
setInterval(() => {
setVar('currState', button1.state);
}, 100);
I also used a separate trigger attached to another button to enable and disable the target button.
const button1 = object('5pyrnxdTyGJ');
button1.state = 'Disabled';
// when a disable/enable button is Selected
// else
const button1 = object('5pyrnxdTyGJ');
button1.state = 'Normal';
Part 2
I'm not entirely sure what you meant by dynamically changing expressions. The JavaScript API for Storyline only exposes the current state of an object, not the full list of available states.
To cycle through all states, you need to dig deeper into Storyline’s internal structure. I used a custom recursive function to locate the object by its ID and extract its states from nested properties. Then, I created a simplified version containing only the properties I needed, resulting in an array of all available states. This function is reusable—the only change you need to make is updating the object ID (e.g., '6fO7ipghgcH') to retrieve the available states for your next target object.
In the example below, the first button retrieves all available expression states for my character, and the second button cycles through them every second by setting object('id').state = stateName.
If you'd like to dig deeper, I can attach my Storyline file for you to review and test.
Part 3
To avoid writing complex code while achieving the same result, you might consider renaming your states using simple numbers—for example, from "1" to "8". Then, you can use a simple function to iterate through these states by setting the object's state to a number that increases at a regular interval (e.g., every second). The numeric value should match the name of each state, allowing the function to dynamically set the object’s state based on that number. You might even be able to squeeze in some form of GSAP or web animation between the intervals to create smoother transitions between states.
const rectangle = object('6cn5CQM1j6n');
let num = 1;
setInterval(() => {
if (num <= 8) {
rectangle.state = `${num}`;
} else {
rectangle.state = 'Normal';
num = 0;
}
num++;
}, 1000);
Related Content
- 8 months ago
- 10 months ago