Forum Discussion
CAROUSEL in Storyline!
Ok over the last few weeks I've been learning to use JavaScript in Storyline modules and this is another great example of taking some of the functionality out of Rise and using it in Storyline. I've discovered how to create a really slick carousel.
https://360.articulate.com/review/content/b2224974-b080-41ad-aa47-f874da152b14/review
You can customize the code for size speed and motion. Just need to copy your object IDs into the code and you're good to go. Code should be able to be copied and pasted right into your project.
Let me know how you like it!!!!
// ------------------------------------
// STORYLINE CARD CAROUSEL
// ------------------------------------
const CARD_IDS = [
"CARD_1_OBJECT_ID",
"CARD_2_OBJECT_ID",
"CARD_3_OBJECT_ID",
"CARD_4_OBJECT_ID"
];
const PREVIOUS_BUTTON_ID = "PREVIOUS_BUTTON_OBJECT_ID";
const NEXT_BUTTON_ID = "NEXT_BUTTON_OBJECT_ID";
// ------------------------------------
// CUSTOMIZATION
// ------------------------------------
// Horizontal center of the carousel.
// Change these to match your slide.
const CENTER_X = slideWidth() / 2;
const CENTER_Y = slideHeight() / 2;
// Distance between card centers.
const CARD_SPACING = 330;
// Appearance of the centered card.
const ACTIVE_SCALE = 1;
const ACTIVE_OPACITY = 1;
// Appearance of cards beside the centered card.
const SIDE_SCALE = 0.78;
const SIDE_OPACITY = 0.45;
// Cards farther away can be hidden.
const HIDDEN_SCALE = 0.65;
// Animation responsiveness.
// Lower numbers are slower and smoother.
const SMOOTHING = 0.14;
// Whether Next from the last card returns to the first.
const LOOP_CAROUSEL = true;
// ------------------------------------
// SETUP
// ------------------------------------
const cards = CARD_IDS.map((id, index) => {
const item = object(id);
item.style.transformOrigin = "center center";
return {
item,
index,
currentX: item.x,
currentY: item.y,
currentScale: 1,
currentOpacity: 1
};
});
const previousButton = object(PREVIOUS_BUTTON_ID);
const nextButton = object(NEXT_BUTTON_ID);
let activeIndex = 0;
// ------------------------------------
// HELPERS
// ------------------------------------
function clamp(value, min, max) {
return Math.min(max, Math.max(min, value));
}
function changeCard(direction) {
activeIndex += direction;
if (LOOP_CAROUSEL) {
if (activeIndex < 0) {
activeIndex = cards.length - 1;
}
if (activeIndex >= cards.length) {
activeIndex = 0;
}
} else {
activeIndex = clamp(
activeIndex,
0,
cards.length - 1
);
}
// Optional Storyline number variable.
// Create CurrentCarouselCard if you want to use this.
// setVar("CurrentCarouselCard", activeIndex + 1);
}
// ------------------------------------
// BUTTON EVENTS
// ------------------------------------
previousButton.click(() => {
changeCard(-1);
});
nextButton.click(() => {
changeCard(1);
});
// ------------------------------------
// CARD CLICK EVENTS
// ------------------------------------
// Clicking a side card brings it to the center.
// Clicking the active card can trigger your
// normal Storyline action or open a layer.
cards.forEach((card) => {
card.item.click(() => {
activeIndex = card.index;
});
});
// ------------------------------------
// ANIMATION LOOP
// ------------------------------------
update(() => {
cards.forEach((card) => {
const offset = card.index - activeIndex;
const absoluteOffset = Math.abs(offset);
let targetX;
let targetY = CENTER_Y - card.item.height / 2;
let targetScale;
let targetOpacity;
if (absoluteOffset === 0) {
// Active center card.
targetX =
CENTER_X - card.item.width / 2;
targetScale = ACTIVE_SCALE;
targetOpacity = ACTIVE_OPACITY;
card.item.style.pointerEvents = "auto";
} else if (absoluteOffset === 1) {
// Immediate side cards.
targetX =
CENTER_X -
card.item.width / 2 +
offset * CARD_SPACING;
targetScale = SIDE_SCALE;
targetOpacity = SIDE_OPACITY;
card.item.style.pointerEvents = "auto";
} else {
// Cards farther away.
targetX =
CENTER_X -
card.item.width / 2 +
offset * CARD_SPACING;
targetScale = HIDDEN_SCALE;
targetOpacity = 0;
card.item.style.pointerEvents = "none";
}
// Smoothly ease toward the target values.
card.currentX +=
(targetX - card.currentX) * SMOOTHING;
card.currentY +=
(targetY - card.currentY) * SMOOTHING;
card.currentScale +=
(targetScale - card.currentScale) * SMOOTHING;
card.currentOpacity +=
(targetOpacity - card.currentOpacity) * SMOOTHING;
card.item.x = card.currentX;
card.item.y = card.currentY;
card.item.style.transform =
`scale(${card.currentScale})`;
card.item.style.opacity =
card.currentOpacity;
});
});
6 Replies
This is so neat BillyTheroux! Thanks for sharing it (with the code + instructions, especially!)
- BillyTherouxCommunity Member
I have another post up with flip cards and some cool button treatments. Pretty much everything that's in RISE you can use javascript to put into storyline.. it's soo rad because the functionality in Storyline much better than Rise but, Rise had those cool features... now we can make Storyline modules so rad.
Really cool, BillyTheroux! I feel like DavidShaw would be interested in this, too, based on some of the linear Rise courses he's been working on.
Awesome BillyTheroux, thanks for sharing! We are going to share this example in our
https://community.articulate.com/blog/articles/sign-up-for-the-e-learning-heroes-newsletter/1220424Weekly Newsletter.
- BillyTherouxCommunity Member
That's amazing!! Glad I can help advance Storyline development a little :-)
- MarianneDuch307Community Member
Hi! How can I set up the cards for this carousel? I tried your flipcards project and it worked like a charm, but I'm having trouble running this carousel project. What am I missing or doing wrong? Thanks!
Related Content
- 8 months ago
- 1 year ago
- 10 months ago