top of page

Working Example

Angle

90

Decay

0

Spread

90

Element Count

50

Start Velocity

45
Show Debug
Show Settings
Reset Settings

Confetti
Working Example

Page Script

// For full API documentation, including code examples, visit http://wix.to/94BuAAs

 

let confettiSettings;

let readyTimer = null;

let timeoutCounter = 0;

let ready = false;

let htmlDebugging = false;

 

$w.onReady(function () {

    initConfettiSettings();

    clearMessage();

    

    $w('#confettiComponent').onMessage((event) => {

        if (event.data && event.data.to === 'Page') {

            // Message received

            processMessage(event.data.message);

        } else {

             showMessage("Unknown event "+JSON.stringify(event));

        }

    });

 

    // Delay ready test

    setTimeout(() => {

        startReadyTimer();

    }, 1000);

});

 

function startReadyTimer() {

    

    if (timeoutCounter === 0) {

        showMessage("Starting Up...");

    } else {

        showMessage("Timer restart number: "+timeoutCounter);

    }

    sendConfettiMessage({'action':'ready'});

    readyTimer = setTimeout(() => {

        timeoutCounter++;

        startReadyTimer();

    }, 1000);

}

 

function showMessage(message) {

    $w('#messages').text = message;

}

 

function clearMessage() {

    showMessage("");

}

 

function processMessage(message) {

    switch (message.action) {

        case 'ready':

            clearTimeout(readyTimer);

            ready = true;

            showMessage("Ready!");

            // Disable debugButton_click

            sendConfettiMessage({'action':'debugOff'});

            //load component settings_click

            sendConfettiMessage({'action':'getSettings'});

        break;

 

        case 'settings':

            {

                // We should have a pay load

                if (message.payload) {

                    let settings = message.payload;

                    // Merge the settings received with the

                    // local confetti settings

                    Object.assign(getConfettiSettings(), settings);

                    updateSettingsSliders();

                }

            }

        break;

 

        default:

         showMessage("Unknown Event: "+message.action);

            break;

    }

}

 

function sendConfettiMessage(message, to) {

    let messageObject = {

        'to' : (to?to:'Confetti'),

        'from': 'Page',

        'message':message

    };

    $w('#confettiComponent').postMessage(messageObject);

}

 

function initConfettiSettings() {

    confettiSettings = {};

}

 

function getConfettiSettings() {

    if (!confettiSettings) {

        initConfettiSettings();

    }

    return confettiSettings;

}

 

function updateSettingsSliders() {

    let settings = getConfettiSettings();

    $w('#angle').value = settings.angle;

    $w('#decay').value = settings.decay;

    $w('#spread').value = settings.spread;

    $w('#elementCount').value = settings.elementCount;

    $w('#startVelocity').value = settings.startVelocity;

}

 

export function settings_click(event) {

    if ($w('#settingsBox').isVisible) {

        $w('#settingsBox').hide();

        $w('#settings').label = "Show Settings";

        // Send changed settings

        sendConfettiMessage({'action':'setSettings', 'payload':getConfettiSettings()});

    } else {

        $w('#settingsBox').show();

        $w('#settings').label = "Hide Settings";

    }

}

 

export function confetti_click(event) {

    sendConfettiMessage({'action':'confetti'});

}

 

export function angle_change(event) {

    getConfettiSettings().angle = $w('#angle').value;

}

 

export function decay_change(event) {

    getConfettiSettings().decay = $w('#decay').value;

}

 

export function spread_change(event) {

    getConfettiSettings().spread = $w('#spread').value;

}

 

export function elementCount_change(event) {

    getConfettiSettings().elementCount = $w('#elementCount').value;

}

 

export function startVelocity_change(event) {

    getConfettiSettings().startVelocity = $w('#startVelocity').value;

}

 

export function debugButton_click(event) {

    if (htmlDebugging) {

        sendConfettiMessage({'action':'debugOff'});

        $w('#debugButton').label = "Show Debug";

    } else {

        sendConfettiMessage({'action':'debugOn'});

        $w('#debugButton').label = "Hide Debug";

    }

    htmlDebugging = !htmlDebugging;

}

 

export function resetSettings_click(event) {

    sendConfettiMessage({'action':'resetSettings'});

}

Page Script
Page onReady
startReadyTimer
showMessage
clearMessage
processMessage
sendConfettiMessage
initConfettiSettings
getConfettiSettings
updateSettingsSliders
settings_click
confetti_click
angle_change
decay_change
spread_change
elementCount_change
startVelocity_change
debugButton_click
resetSettings_click

This example shows how to use third party javascript on a Wix page.

 

The javascript is called confetti and was used as is from its author's, Daniel Lundin, github page here

https://github.com/daniel-lundin/dom-confetti/blob/master/src/main.js

 

This page has somewhat replicated the example page for this code available here:

https://daniel-lundin.github.io/react-dom-confetti/

 

The page is structured into three sections:

  • Section 1:        This section is the working example of the code used on a Wix page. The code runs in a Wix HTML

component block which is colored grey below this introduction. The buttons perform as follows:

Confetti: Sends a message to the html component which activates the confetti function and will display confetti in the grey box.

Show(Hide) Debug: Sends a message to the html component telling it to show or not show log data. The log data shows how messages received from the page are processed.

Show(Hide) Settings: Reveals a set of sliders that allow confetti configuration to be changed. This is similar to the example page referenced above. When the settings are hidden a message is sent to the html component to update the settings that confetti uses.

Reset Settings: Sends a message to the html component telling it to update to the default start up settings used by the confetti function.

  • Section 2:         This section shows the javascript used on the Wix Code Page that drives the interaction with onscreen

controls and communication with the html component. Each function is linked to an on screen menu ( will not be shown on mobile device).

  • Section 3:         This section shows the html code used by the Wix html component that drives the interaction with

page code to respond to messages from the wix Page code. It also has the full javascript module (without nodeJs packaging) for confetti described above. Each function is linked to an on screen menu ( will not be shown on mobile device).

Close

HTML Component Code

<!DOCTYPE html>

<html>

<head>

<style>

body {

    background-color: transparent;

}

 

#log {

    background-color: white;

}

</style>

<script>

let pageURL = window.location.href;

let startTimer = null;

let timeoutCounter = 0;

let ready = false;

let initConfettiSettings = {​

    angle : 90,

    decay : 0.9,

    spread : 45,

    startVelocity : 45,

    elementCount : 50,

};

​

let confettiSettings = Object.assign({}, initConfettiSettings);

 

window.onmessage = (event) => {

    if (event.data &&

        event.data.to &&

        event.data.from &&

        event.data.message) {

        log(`HTML Component received a message: ${JSON.stringify(event.data)}`);

        // relay message to event lister

        if (event.data.to === 'Confetti') {

            processMessage(event.data.message);

        } else {

            log("Message not for me!: " +event.data.message+" to: "+event.data.to+" from: "+event.data.from);

        }

    } else {

        log("Badly formed Message! "+JSON.stringify(event.data));

    }

}

 

function processMessage(message) {

    log('processMessage('+JSON.stringify(message)+')');

​

    switch (message.action) {

        case 'ready':

        {

            if (!ready) {

                // Disable timeout

                clearTimeout(startTimer);

                ready = true;

                log('ready!');

            }

            // If we receive a ready we will send an ack to close the loop

            sendPageMessage({'action':'ready'});

        }

        break;

 

        case 'setSettings':

            updateSettings(message.payload);

        break;

 

        case 'getSettings':

            getSettings();

        break;

 

        case 'resetSettings':

            confettiSettings = Object.assign({}, initConfettiSettings);

            getSettings();

        break;

 

        case 'confetti':

            let root = document.getElementById('confettiLauch');

            activateConfetti(root);

        break;

 

        case 'debugOn':

            enableLog();

        break;

​

        case 'debugOff':

            disableLog();

            clearLog();

        break;

​

        default:

            log('Unknown Action ['+JSON.stringify(message)+']');

        break;

    }

}

 

// send message to the page code

function sendPageMessage(msg, to) { 

    let messageObject = {

        'to' : (to?to:'Page'),

        'from': 'Confetti',

        'message':msg

    };

    log("sending message ["+JSON.stringify(messageObject)+"]");

    window.parent.postMessage(messageObject, "*");

}

 

function startup() {

    log("Page URL: "+pageURL);

    if (timeoutCounter === 0) {

        log("Starting Up...");

    } else {

        log("Timer restart number: "+timeoutCounter);

    }

    sendPageMessage({'action':'ready'});

    startTimer = setTimeout(() => {

        timeoutCounter++;

        startup();

    }, 1000);

}

 

function log(params) {

    document.getElementById('logMessages').innerHTML += '<BR>'+'<B>'+params+'</B>';

}

 

function enableLog() {

    document.getElementById('log').style.visibility = 'visible';

}

 

function disableLog() {

    document.getElementById('log').style.visibility = 'hidden';

}

 

function clearLog() {

    document.getElementById('logMessages').innerHTML = '<H1>Debug Output</H1>';

}

 

function updateSettings(settings) {

    log('updateSettings('+JSON.stringify(settings)+')');

    if (settings.hasOwnProperty('angle')) {

        setAngle(settings.angle);

    }

    if (settings.hasOwnProperty('decay')) {

        setDecay(settings.decay);

    }

    if (settings.hasOwnProperty('spread')) {

        setSpread(settings.spread);

    }

    if (settings.hasOwnProperty('startVelocity')) {

        setStartVelocity(settings.startVelocity);

    }

    if (settings.hasOwnProperty('elementCount')) {

        setElementCount(settings.elementCount);

    }

}

 

function getSettings() {

    log('getSettings()');

    log('returning settings<br><p>'+JSON.stringify(confettiSettings)+"</p>");

    sendPageMessage({'action':'settings', 'payload':confettiSettings});

}

 

function setAngle(angle) {

    log("setAngle("+angle.toString()+")");

    if (angle < 0) {

        angle = 0

    } else if (angle > 360) {

        angle = 360;

    }

    confettiSettings.angle = angle;

}

 

function setDecay(decay) {

    log("setDecay("+decay.toString()+")");

    if (decay < 0.1) {

        decay = 0.1

    } else if (decay > 1.0) {

        decay = 1.0;

    }

    confettiSettings.decay = decay;

}

 

function setSpread(spread) {

    log("setSpread("+spread.toString()+")");

    if (spread < 0) {

        spread = 0

    } else if (spread > 360) {

        spread = 360;

    }

    confettiSettings.spread = spread;

}

 

function setStartVelocity(startVelocity) {

    log("setStartVelocity("+startVelocity.toString()+")");

    if (startVelocity < 1) {

        startVelocity = 1

    } else if (startVelocity > 100) {

        startVelocity = 100;

    }

    confettiSettings.startVelocity = startVelocity;

}

 

function setElementCount(elementCount) {

    log("setElementCount("+elementCount.toString()+")");

    if (elementCount < 1) {

        elementCount = 1

    } else if (elementCount > 200) {

    elementCount = 200;

    }

    confettiSettings.elementCount = elementCount;

}

 

function activateConfetti() {

    log("activateConfetti...");

    log("confettiSettings:<br><p>"+JSON.stringify(confettiSettings)+"</p>");

    let confettiLaunchRoot = document.getElementById('confettiLaunch');

    confetti(confettiLaunchRoot, confettiSettings);

}

 

</script>

 

</head>

 

<body>

​

<div id="confettiLaunch"></div>

​

<div id="log">

    <div id="logMessages"></div>

</div>

​

<script language="javascript">

    window.onload = function(e){ 

        startup(); 

    }

</script>

<script id="confettiScript">

    const defaultColors = [

        '#a864fd',

        '#29cdff',

        '#78ff44',

        '#ff718d',

        '#fdff6a'

    ];

 

function createElements(root, elementCount, colors) {

    return Array

    .from({ length: elementCount })

    .map((_, index) => {

        const element = document.createElement('div');

        const color = colors[index % colors.length];

        element.style['background-color']= color; // eslint-disable-line space-infix-ops

        element.style.width = '10px';

        element.style.height = '10px';

        element.style.position = 'absolute';

        root.appendChild(element);

        return element;

    });

}

 

function randomPhysics(angle, spread, startVelocity, random) {

    const radAngle = angle * (Math.PI / 180);

    const radSpread = spread * (Math.PI / 180);

    return {

        x: 0,

        y: 0,

        wobble: random() * 10,

        velocity: (startVelocity * 0.5) + (random() * startVelocity),

        angle2D: -radAngle + ((0.5 * radSpread) - (random() * radSpread)),

        angle3D: -(Math.PI / 4) + (random() * (Math.PI / 2)),

        tiltAngle: random() * Math.PI

    };

}

 

function updateFetti(fetti, progress, decay) {

    /* eslint-disable no-param-reassign */

    fetti.physics.x += Math.cos(fetti.physics.angle2D) * fetti.physics.velocity;

    fetti.physics.y += Math.sin(fetti.physics.angle2D) * fetti.physics.velocity;

    fetti.physics.z += Math.sin(fetti.physics.angle3D) * fetti.physics.velocity;

    fetti.physics.wobble += 0.1;

    fetti.physics.velocity *= decay;

    fetti.physics.y += 3;

    fetti.physics.tiltAngle += 0.1;

 

    const { x, y, tiltAngle, wobble } = fetti.physics;

    const wobbleX = x + (10 * Math.cos(wobble));

    const wobbleY = y + (10 * Math.sin(wobble));

    const transform = `translate3d(${wobbleX}px, ${wobbleY}px, 0) rotate3d(1, 1, 1, ${tiltAngle}rad)`;

 

    fetti.element.style.transform = transform;

    fetti.element.style.opacity = 1 - progress;

 

    /* eslint-enable */

}

 

function animate(root, fettis, decay) {

    const totalTicks = 200;

    let tick = 0;

 

    function update() {

        fettis.forEach((fetti) => updateFetti(fetti, tick / totalTicks, decay));

 

        tick += 1;

        if (tick < totalTicks) {

            requestAnimationFrame(update);

        } else {

            fettis.forEach((fetti) => {

                if (fetti.element.parentNode === root) {

                    return root.removeChild(fetti.element);

                }

            });

        }

    }

 

    requestAnimationFrame(update);

}

 

function confetti(root, {

    angle = 90,

    decay = 0.9,

    spread = 45,

    startVelocity = 45,

    elementCount = 50,

    colors = defaultColors,

    random = Math.random,

    } = {}) {

    const elements = createElements(root, elementCount, colors);

    const fettis = elements.map((element) => ({

        element,

        physics: randomPhysics(angle, spread, startVelocity, random)

    }));

 

    animate(root, fettis, decay);

}

</script>

</body>

</html>

HTML Component Code
window.onmessage
processMessage
sendPageMessage
startup
log
enableLog
disableLog
clearLog
updateSettings
getSettings
setAngle
setDecay
setSpread
setStartVelocity
setElementCount
activateConfetti
log (debug) element
confetti launch point
confetti script by Daniel Lundin
createElements
randomPhysics
updateFetti
animate
confetti

© 2018 by Steve Cropper. Proudly created with Wix.com

  • Google+ - White Circle
  • Facebook - White Circle
  • Twitter - White Circle
bottom of page