Forum Discussion
Interactive Dynamic Shadows Script
This JavaScript code automatically generates a realistic drop shadow that reacts to mouse movements, simulating a moving light source.
How it works:
- Paste the code into an "Execute JavaScript" trigger.
- Add the Accessibility Text (Alt Text) Mybtnshad to any object or button.
- The shadow applies instantly and moves opposite to the cursor to simulate depth.
Key Features: Fully customizable settings (intensity, blur, opacity) located right at the top of the script.
5 Replies
Thanks for sharing this Seb_Daubert! A shadow that dynamically reacts to cursor movement is a great way to add depth, especially in moments where learners benefit from subtle visual cues. I love that you’ve made it easy to implement, too.
We are going to share this is an upcoming ELH Weekly Newsletter, make sure you are subscribed if you want to see this in your inbox! 🎉
- KnutCollettJrgeCommunity Member
Loving it!
When is Articulate going to provide us with something other than the alt-text to get a hold of objects in javascripts?- Seb_DaubertCommunity Member
Hi, You can target the object ID directly instead...
- KnutCollettJrgeCommunity Member
Yes, but then that exact ID needs to be added to the JS, and you have no control of the ID.
The best thing is to be able to have a prefix to the name of the object (For instance: blurMe_ObjectName). Then you can have the script find all the objects where the name begins with "blurMe", add them to an array/nodelist and loop through them, adding the effect.
The alt text will be picked up by screen readers etc. and is not ment to locate objects in a js :)
- Seb_DaubertCommunity Member
Try this...
/* -----------------------------------------------------------
* Ombre dynamique plein-écran + facteur d'accentuation
* Version Ciblée sur l'ID : 5ZAZJ8sOw9l
* --------------------------------------------------------- */
(function () {
/* Réglages */
const MAX_OFFSET = 18; // décalage max. de base (px)
const MIN_BLUR = 1; // flou mini (px)
const MAX_BLUR = 8; // flou maxi (px)
const OPACITY = 0.35; // opacité
const INTENSITY = 1.6; // facteur d'accentuation (1 = normal)
/* --- MODIFICATION ICI : CIBLAGE PAR ID --- */
const targetID = '5ZAZJ8sOw9l';
// On récupère l'élément du DOM qui correspond à cet ID Storyline
const rectangle1 = document.querySelector(`[data-model-id="${targetID}"]`);
// Sécurité : si l'objet n'est pas sur la diapo, on arrête le script
if (!rectangle1) return;
// On place l'élément dans un tableau pour garder la logique du script original
// (au cas où tu voudrais ajouter d'autres IDs plus tard)
const elements = [rectangle1];
/* Fonction pour appliquer l'ombre à un élément spécifique */
function applyShadowToElement(element, clientX, clientY) {
const rect = element.getBoundingClientRect();
const cx = rect.left + rect.width / 2;
const cy = rect.top + rect.height / 2;
/* Normalisés sur toute la largeur / hauteur de la fenêtre */
const dxNorm = Math.max(-1, Math.min(1, (clientX - cx) / (window.innerWidth / 2)));
const dyNorm = Math.max(-1, Math.min(1, (clientY - cy) / (window.innerHeight / 2)));
/* Décalage opposé au curseur, amplifié par INTENSITY */
const offsetX = -dxNorm * MAX_OFFSET * INTENSITY;
const offsetY = -dyNorm * MAX_OFFSET * INTENSITY;
/* Flou : on amplifie la partie variable (MAX_BLUR-MIN_BLUR) */
const distance = Math.min(1, Math.hypot(dxNorm, dyNorm));
const blur = MIN_BLUR + distance * (MAX_BLUR - MIN_BLUR) * INTENSITY;
// Application du style CSS
element.style.filter = `drop-shadow(${offsetX.toFixed(1)}px ${offsetY.toFixed(1)}px ${blur.toFixed(1)}px rgba(0,0,0,${OPACITY}))`;
}
/* Fonction pour appliquer l'ombre à tous les éléments de la liste */
function applyGlobalShadow(clientX, clientY) {
elements.forEach(element => {
applyShadowToElement(element, clientX, clientY);
});
}
/* Affichage immédiat de l'ombre par défaut (simulation curseur en haut à gauche) */
elements.forEach(element => {
const rect = element.getBoundingClientRect();
const btnCenterX = rect.left + rect.width / 2;
const btnCenterY = rect.top + rect.height / 2;
const offsetCursorX = btnCenterX - 50;
const offsetCursorY = btnCenterY - 50;
applyShadowToElement(element, offsetCursorX, offsetCursorY);
});
/* Mise à jour lors du mouvement de la souris */
document.addEventListener('mousemove', (e) => {
applyGlobalShadow(e.clientX, e.clientY);
});
/* Capture initiale */
document.addEventListener('mouseenter', (e) => {
applyGlobalShadow(e.clientX, e.clientY);
});
/* Réinitialisation lors de la sortie de la fenêtre */
window.addEventListener('mouseleave', () => {
applyGlobalShadow(window.innerWidth / 2, window.innerHeight / 2);
});
})();