Most eLearning courses built in Articulate Storyline 360 rely heavily on linear navigation, Next buttons, static clicks and predictable interactions. If you’re new to customization, start with our Storyline 360 JavaScript triggers guide to understand how scripting works inside Storyline.

While functional, these courses often lack the micro-interactions that drive real learner engagement.

Click Preview to watch the how to Add Mouse Cursor Animation in Articulate Storyline 360 Using JavaScript.

Preview

Mouse cursor animation using JavaScript becomes a powerful enhancement.

By integrating subtle cursor effects like trails, clicks or hover animations, you can:

  • Elevate learner engagement
  • Create immersive, UX-driven learning environments
  • Introduce gamification without heavy development (see eLearning gamification strategies)
  • Make your courses feel modern and premium

What Is Mouse Cursor Animation in eLearning?

Mouse cursor animation refers to interactive visual effects that respond to user movement or clicks inside a course. These effects are a key part of modern UX, learn more in our interactive eLearning design tips guide.

Common Types of Cursor Effects:

To overcome this limitation, we use JavaScript in Storyline 360 to add advanced features and customization.

  • Cursor trail effects (particles following movement)
  • Click animations (ripples, bubbles, sparks)
  • Hover glow effects (interactive highlights)
  • Dynamic particle systems

These can be implemented using JavaScript triggers, covered in detail in our Storyline 360 advanced customization tutorial.

What are the benefits of cursor animation in eLearning?

Course Development Benefits:

Engagement Benefits:

Business Impact:

Looking for advanced Storyline tips and techniques?

Explore our free Storyline 360 tutorials, including JavaScript solutions and eLearning strategies to enhance your course design.

Explore Now

Step-by-Step: Add Mouse Cursor Animation in Storyline 360 Course

Step 1: Open Your Storyline Project

Launch Storyline 360
Open your .story file
Navigate to the target slide

Step 2: Add a JavaScript Trigger

Select the slide
Open the Triggers panel
Click “Create New Trigger”
Set:

  • Action: Execute JavaScript
  • When: Timeline starts

If you’re unsure about triggers, revisit Storyline 360 JavaScript triggers guide before proceeding.

Step 3: Insert the Cursor Animation JavaScript Code into the JavaScript Editor

To implement effects efficiently, understanding scripting basics is helpful, see Storyline JavaScript best practices.

Type 1: Basic Cursor Effect

How It Works:
This effect changes how the cursor looks or behaves when moving across the slide.

Steps:
Add a trigger → Execute JavaScript
Paste the following JavaScript code

(function () {
// �� Run only once
if (window.__cursorInitialized) return;
window.__cursorInitialized = true;
const container = document.body;
let mouseX = 0, mouseY = 0;
let currentX = 0, currentY = 0;
let prevMouseX = 0, prevMouseY = 0;
let dpr = window.devicePixelRatio || 1;
/* =========================
CURSOR
========================= */
let cursor = document.querySelector(“.global-cursor”);
if (!cursor) {
cursor = document.createElement(“div”);
cursor.classList.add(“global-cursor”);
Object.assign(cursor.style, {
position: “fixed”,
width: “30px”,
height: “30px”,
borderRadius: “50%”,
pointerEvents: “none”,
zIndex: “9999”,
filter: “blur(5px)”
});
document.body.appendChild(cursor);
}
/* =========================
CANVAS
========================= */
let canvas = document.querySelector(“.global-trail”);
if (!canvas) {
canvas = document.createElement(“canvas”);
canvas.classList.add(“global-trail”);
Object.assign(canvas.style, {
position: “fixed”,
top: “0”,
left: “0”,
pointerEvents: “none”,
zIndex: “9998”
});
document.body.appendChild(canvas);
}
const ctx = canvas.getContext(“2d”);
/* =========================
RESIZE
========================= */
function resizeCanvas() {
dpr = window.devicePixelRatio || 1;
canvas.width = window.innerWidth * dpr;
canvas.height = window.innerHeight * dpr;
canvas.style.width = window.innerWidth + “px”;
canvas.style.height = window.innerHeight + “px”;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
resizeCanvas();
window.addEventListener(“resize”, resizeCanvas);
/* =========================
MOUSE TRACK
========================= */
document.addEventListener(“mousemove”, (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
});
/* =========================
ANIMATION
========================= */
function animate() {
const dx = mouseX – prevMouseX;
const dy = mouseY – prevMouseY;
const speed = Math.sqrt(dx * dx + dy * dy);
const lag = Math.min(speed / 50, 0.2);
currentX += (mouseX – currentX) * (0.1 + lag);
currentY += (mouseY – currentY) * (0.1 + lag);
const hue = (Date.now() / 8) % 360;
// cursor
cursor.style.transform =
`translate(${currentX – 15}px, ${currentY – 15}px)`;
cursor.style.background =
`hsla(${hue}, 100%, 60%, 0.7)`;
prevMouseX = mouseX;
prevMouseY = mouseY;
/* ===== TRAIL ===== */
ctx.globalCompositeOperation = “destination-out”;
ctx.fillStyle = “rgba(0,0,0,0.2)”;
ctx.fillRect(0, 0, canvas.width / dpr, canvas.height / dpr);
ctx.globalCompositeOperation = “lighter”;
ctx.beginPath();
ctx.arc(currentX, currentY, 12, 0, Math.PI * 2);
ctx.fillStyle = `hsla(${hue}, 100%, 60%, 0.2)`;
ctx.shadowBlur = 20;
ctx.shadowColor = `hsla(${hue}, 100%, 60%, 0.8)`;
ctx.fill();
ctx.shadowBlur = 0;
requestAnimationFrame(animate);
}
animate();
/* =========================
CLICK PULSE (FIXED)
========================= */
document.addEventListener(“click”, (e) => {
const x = e.clientX;
const y = e.clientY;
const pulse = document.createElement(“div”);
Object.assign(pulse.style, {
position: “fixed”,
left: (x – 20) + “px”,
top: (y – 20) + “px”,
width: “40px”,
height: “40px”,
borderRadius: “50%”,
border: “2px solid white”,
pointerEvents: “none”,
zIndex: “10000”,
animation: “pulseAnim 0.6s ease-out”
});
document.body.appendChild(pulse);
setTimeout(() => pulse.remove(), 600);
});
/* =========================
CSS (ADD ONLY ONCE)
========================= */
if (!document.querySelector(“#cursor-style”)) {
const style = document.createElement(“style”);
style.id = “cursor-style”;
style.innerHTML = `
@keyframes pulseAnim {
0% { transform: scale(0.5); opacity: 1; }
100% { transform: scale(2); opacity: 0; }
}
`;
document.head.appendChild(style);
}
})();

Click OK

Result:
Once the trigger executes:
The mouse cursor transforms visually
Effects appear dynamically while moving across the slide

Best for: Use this in UI-heavy slides, paired with interactive eLearning design tips.

Type 2: Click-Based Bubble Effect

How It Works:
This effect creates bubbles or particles when the user clicks.

Repeat the same process:
Create trigger → Execute JavaScript
Paste the following JavaScript code


(function () {
// �� Prevent duplicate run
if (window.__trailEffectInit) return;
window.__trailEffectInit = true;
const container = document.body;
/* =========================
MOUSE MOVE TRAIL
========================= */
document.addEventListener(“mousemove”, function (e) {
let x = e.clientX;
let y = e.clientY;
let trail = document.createElement(“div”);
Object.assign(trail.style, {
position: “fixed”,
left: (x – 10) + “px”,
top: (y – 10) + “px”,
width: “20px”,
height: “20px”,
borderRadius: “50%”,
background: “rgba(0,150,255,0.2)”,
pointerEvents: “none”,
zIndex: “9999”,
animation: “fadeTrail 0.6s linear”
});
container.appendChild(trail);
setTimeout(() => trail.remove(), 600);
});
/* =========================
CLICK BURST EFFECT
========================= */
document.addEventListener(“click”, function (e) {
let x = e.clientX;
let y = e.clientY;
for (let i = 0; i < 6; i++) { let burst = document.createElement("div"); Object.assign(burst.style, { position: "fixed", left: x + "px", top: y + "px", width: "8px", height: "8px", background: "#00aaff", borderRadius: "50%", pointerEvents: "none", zIndex: "10000", animation: "burstAnim 0.6s ease-out forwards" }); let angle = (i * 60) * (Math.PI / 180); let distance = 60; burst.style.setProperty('--x', Math.cos(angle) * distance + 'px'); burst.style.setProperty('--y', Math.sin(angle) * distance + 'px'); container.appendChild(burst); setTimeout(() => burst.remove(), 600);
}
});
/* =========================
CSS (ONLY ONCE)
========================= */
if (!document.querySelector(“#trail-style”)) {
const style = document.createElement(“style”);
style.id = “trail-style”;
style.innerHTML = `
@keyframes fadeTrail {
0% { transform: scale(1); opacity: 0.4; }
100% { transform: scale(2); opacity: 0; }
}
@keyframes burstAnim {
0% { transform: translate(0,0); opacity: 1; }
100% { transform: translate(var(–x), var(–y)); opacity: 0; }
}
`;
document.head.appendChild(style);
}
})();

Click OK

Result:
Once the trigger executes:
Cursor interaction becomes playful
Bubbles appear on every click

Best for: Perfect for gamified modules, combine with eLearning gamification strategies.

Type 3: Advanced Cursor Interaction

How It Works:
A more dynamic or animated cursor effect (e.g., trailing particles, glow effects).

Steps:
Create trigger → Execute JavaScript
Paste the following JavaScript code

(function () {
if (window.__cursorFX) return;
window.__cursorFX = true;
const container = document.body;
/* =========================
�� CURSOR
========================= */
let cursor = document.createElement(“div”);
Object.assign(cursor.style, {
position: “fixed”,
width: “40px”,
height: “40px”,
borderRadius: “50%”,
background: “rgba(0,150,255,0.2)”,
pointerEvents: “none”,
transition: “transform 0.08s ease-out”,
zIndex: “999999”
});
container.appendChild(cursor);
/* =========================
�� MOUSE MOVE
========================= */
document.addEventListener(“mousemove”, function (e) {
let x = e.clientX;
let y = e.clientY;
cursor.style.transform = `translate(${x – 20}px, ${y – 20}px)`;
// Trail
let trail = document.createElement(“div”);
Object.assign(trail.style, {
position: “fixed”,
left: (x – 5) + “px”,
top: (y – 5) + “px”,
width: “10px”,
height: “10px”,
borderRadius: “50%”,
background: “rgba(0,150,255,0.3)”,
pointerEvents: “none”,
zIndex: “999998”,
animation: “fadeTrail 0.5s linear”
});
container.appendChild(trail);
setTimeout(() => trail.remove(), 500);
});
/* =========================
�� CLICK BURST
========================= */
document.addEventListener(“click”, function (e) {
let x = e.clientX;
let y = e.clientY;
for (let i = 0; i < 8; i++) { let burst = document.createElement("div"); Object.assign(burst.style, { position: "fixed", left: x + "px", top: y + "px", width: "6px", height: "6px", background: "#00aaff", borderRadius: "50%", pointerEvents: "none", zIndex: "1000000", animation: "burstAnim 0.6s ease-out forwards" }); let angle = (i * 45) * (Math.PI / 180); let distance = 80; burst.style.setProperty('--x', Math.cos(angle) * distance + 'px'); burst.style.setProperty('--y', Math.sin(angle) * distance + 'px'); container.appendChild(burst); setTimeout(() => burst.remove(), 600);
}
});
/* =========================
�� MAGNETIC (SAFE VERSION)
========================= */
function applyMagnet() {
const slide = document.querySelector(“#slide”);
if (!slide) return;
let magnets = slide.querySelectorAll(“button, .magnetic”);
magnets.forEach(el => {
if (el.__magnetApplied) return;
el.__magnetApplied = true;
el.addEventListener(“mousemove”, function (e) {
let rect = el.getBoundingClientRect();
let x = e.clientX – rect.left – rect.width / 2;
let y = e.clientY – rect.top – rect.height / 2;
el.style.transform =
`translate(${x * 0.15}px, ${y * 0.15}px)`;
});
el.addEventListener(“mouseleave”, function () {
el.style.transform = “translate(0,0)”;
});
});
}
applyMagnet();
// Reapply on slide change
const observer = new MutationObserver(() => {
applyMagnet();
});
observer.observe(document.body, {
childList: true,
subtree: true
});
/* =========================
�� CSS
========================= */
if (!document.querySelector(“#cursor-fx-style”)) {
const style = document.createElement(“style”);
style.id = “cursor-fx-style”;
style.innerHTML = `
@keyframes fadeTrail {
0% { transform: scale(1); opacity: 0.5; }
100% { transform: scale(2); opacity: 0; }
}
@keyframes burstAnim {
0% { transform: translate(0,0); opacity: 1; }
100% { transform: translate(var(–x), var(–y)); opacity: 0; }
}
`;
document.head.appendChild(style);
}
})();

Click OK

Result:
Once the trigger executes:
Enhanced visual feedback
Smooth animation tied to cursor movement

Best for: Best for high-end learning, see Storyline 360 advanced customization.

Step 4: Preview and Test

After adding your triggers:

Click Preview → This Slide
Move and click your mouse
Observe how each effect behaves

Tip: For accurate results, test published output to learn more in Storyline publishing best practices.

Best Practices for JavaScript Cursor Animations in Storyline 360 Courses

Performance Optimization

UX Considerations

Compatibility

Looking for advanced Storyline tips and techniques?

Explore our free Storyline 360 tutorials, including JavaScript solutions and eLearning strategies to enhance your course design.

Explore Now

Summary

Mouse cursor animation in Articulate Storyline 360 is a small enhancement with a massive impact.

When used strategically, it can:

  • Turn passive content into interactive experiences
  • Increase learner engagement and retention
  • Give your courses a polished, modern feel

The key is balance enhance, don’t distract.

Frequently Asked Questions (FAQs)

Cursor animation involves dynamic visuals that follow or respond to cursor movement, while hover effects are triggered when the cursor stays over a specific object. Both can be combined in Storyline 360 to create richer interactions.

To add JavaScript in Storyline 360:

  • Select a slide
  • Open the Triggers panel
  • Click Create New Trigger
  • Choose Execute JavaScript
  • Paste your script
  • Click OK to save

This method allows you to extend Storyline functionality beyond built-in features, including cursor animations.

No, native cursor animation is not directly supported in Articulate Storyline 360. To create advanced cursor effects like particle trails or click animations, you must use JavaScript triggers.

Yes, using JavaScript in Articulate Storyline 360 is safe when you use clean, tested code. Avoid untrusted external scripts and ensure compatibility across browsers.

Yes, cursor animations created with JavaScript work in HTML5 output, which is the default publishing format in Articulate Storyline 360. However, performance depends on script optimization and browser compatibility.

Looking for eLearning solutions for your training materials?

We design custom, interactive and easy-to-use training solutions for your business.

Contact Us Today