Sketch Particles in Wix

How can we modify and use this cool effect in a page?

https://www.wixshow.com/wix-code-sketch-particles

It works good but is it usable?

1 Like

It seems a little buggy, the curser keeps changing to text mode and back to pointer and there is a clearly increasing lag to it even after just a few seconds.

All this kind of scripts is very CPU intense in the browser I notice. The buggy thing is that the WIX SHOW text is above the effects so that is why it changes from mouse cursor and text cursor :slight_smile: It is just a sample.

This link appears to be broken - can we get an update? I’d love to see it. I am trying to get a confetti effect but am just not advanced enough with my coding skills.

Here is all the code which you can paste into any HTML Component.

<html>
    <head>
        <title>sketch.js &raquo; Basic Example</title>
        <link rel="stylesheet" href="css/example.css">
        <style type="text/css">
            html, body {
                background: #222;
            }
        </style>
    </head>
    <body>
        <div id="container"></div>
        
        <script>

/* Copyright (C) 2013 Justin Windle, http://soulwire.co.uk */

(function ( root, factory ) {

if ( typeof exports === 'object' ) {

	// CommonJS like
	module.exports = factory(root, root.document);

} else if ( typeof define === 'function' && define.amd ) {

	// AMD
	define( function() { return factory( root, root.document ); });

} else {

	// Browser global
	root.Sketch = factory( root, root.document );
}

}( typeof window !== "undefined" ? window : this, function ( window, document ) {


"use strict";

/*
----------------------------------------------------------------------

	Config

----------------------------------------------------------------------
*/

var MATH_PROPS = 'E LN10 LN2 LOG2E LOG10E PI SQRT1_2 SQRT2 abs acos asin atan ceil cos exp floor log round sin sqrt tan atan2 pow max min'.split( ' ' );
var HAS_SKETCH = '__hasSketch';
var M = Math;

var CANVAS = 'canvas';
var WEBGL = 'webgl';
var DOM = 'dom';

var doc = document;
var win = window;

var instances = [];

var defaults = {

	fullscreen: true,
	autostart: true,
	autoclear: true,
	autopause: true,
	container: doc.body,
	interval: 1,
	globals: true,
	retina: false,
	type: CANVAS
};

var keyMap = {

	 8: 'BACKSPACE',
	 9: 'TAB',
	13: 'ENTER',
	16: 'SHIFT',
	27: 'ESCAPE',
	32: 'SPACE',
	37: 'LEFT',
	38: 'UP',
	39: 'RIGHT',
	40: 'DOWN'
};

/*
----------------------------------------------------------------------

	Utilities

----------------------------------------------------------------------
*/

function isArray( object ) {

	return Object.prototype.toString.call( object ) == '[object Array]';
}

function isFunction( object ) {

	return typeof object == 'function';
}

function isNumber( object ) {

	return typeof object == 'number';
}

function isString( object ) {

	return typeof object == 'string';
}

function keyName( code ) {

	return keyMap[ code ] || String.fromCharCode( code );
}

function extend( target, source, overwrite ) {

	for ( var key in source )

		if ( overwrite || !( key in target ) )

			target[ key ] = source[ key ];

	return target;
}

function proxy( method, context ) {

	return function() {

		method.apply( context, arguments );
	};
}

function clone( target ) {

	var object = {};

	for ( var key in target ) {

		if ( key === 'webkitMovementX' || key === 'webkitMovementY' )
			continue;

		if ( isFunction( target[ key ] ) )

			object[ key ] = proxy( target[ key ], target );

		else

			object[ key ] = target[ key ];
	}

	return object;
}

/*
----------------------------------------------------------------------

	Constructor

----------------------------------------------------------------------
*/

function constructor( context ) {

	var request, handler, target, parent, bounds, index, suffix, clock, node, copy, type, key, val, min, max, w, h;

	var counter = 0;
	var touches = [];
	var resized = false;
	var setup = false;
	var ratio = win.devicePixelRatio || 1;
	var isDiv = context.type == DOM;
	var is2D = context.type == CANVAS;

	var mouse = {
		x:  0.0, y:  0.0,
		ox: 0.0, oy: 0.0,
		dx: 0.0, dy: 0.0
	};

	var eventMap = [

		context.eventTarget || context.element,

			pointer, 'mousedown', 'touchstart',
			pointer, 'mousemove', 'touchmove',
			pointer, 'mouseup', 'touchend',
			pointer, 'click',
			pointer, 'mouseout',
			pointer, 'mouseover',

		doc,

			keypress, 'keydown', 'keyup',

		win,

			active, 'focus', 'blur',
			resize, 'resize'
	];

	var keys = {}; for ( key in keyMap ) keys[ keyMap[ key ] ] = false;

	function trigger( method ) {

		if ( isFunction( method ) )

			method.apply( context, [].splice.call( arguments, 1 ) );
	}

	function bind( on ) {

		for ( index = 0; index < eventMap.length; index++ ) {

			node = eventMap[ index ];

			if ( isString( node ) )

				target[ ( on ? 'add' : 'remove' ) + 'EventListener' ].call( target, node, handler, false );

			else if ( isFunction( node ) )

				handler = node;

			else target = node;
		}
	}

	function update() {

		cAF( request );
		request = rAF( update );

		if ( !setup ) {

			trigger( context.setup );
			setup = isFunction( context.setup );
		}

		if ( !resized ) {
			trigger( context.resize );
			resized = isFunction( context.resize );
		}

		if ( context.running && !counter ) {

			context.dt = ( clock = +new Date() ) - context.now;
			context.millis += context.dt;
			context.now = clock;

			trigger( context.update );

			// Pre draw

			if ( is2D ) {

				if ( context.retina ) {

					context.save();
					context.scale( ratio, ratio );
				}

				if ( context.autoclear )

					context.clear();
			}

			// Draw

			trigger( context.draw );

			// Post draw

			if ( is2D && context.retina )

				context.restore();
		}

		counter = ++counter % context.interval;
	}

	function resize() {

		target = isDiv ? context.style : context.canvas;
		suffix = isDiv ? 'px' : '';

		w = context.width;
		h = context.height;

		if ( context.fullscreen ) {

			h = context.height = win.innerHeight;
			w = context.width = win.innerWidth;
		}

		if ( context.retina && is2D && ratio ) {

			target.style.height = h + 'px';
			target.style.width = w + 'px';

			w *= ratio;
			h *= ratio;
		}

		if ( target.height !== h )

			target.height = h + suffix;

		if ( target.width !== w )

			target.width = w + suffix;

		if ( is2D && !context.autoclear )

			context.scale( ratio, ratio );

		if ( setup ) trigger( context.resize );
	}

	function align( touch, target ) {

		bounds = target.getBoundingClientRect();

		touch.x = touch.pageX - bounds.left - (win.scrollX || win.pageXOffset);
		touch.y = touch.pageY - bounds.top - (win.scrollY || win.pageYOffset);

		return touch;
	}

	function augment( touch, target ) {

		align( touch, context.element );

		target = target || {};

		target.ox = target.x || touch.x;
		target.oy = target.y || touch.y;

		target.x = touch.x;
		target.y = touch.y;

		target.dx = target.x - target.ox;
		target.dy = target.y - target.oy;

		return target;
	}

	function process( event ) {

		event.preventDefault();

		copy = clone( event );
		copy.originalEvent = event;

		if ( copy.touches ) {

			touches.length = copy.touches.length;

			for ( index = 0; index < copy.touches.length; index++ )

				touches[ index ] = augment( copy.touches[ index ], touches[ index ] );

		} else {

			touches.length = 0;
			touches[0] = augment( copy, mouse );
		}

		extend( mouse, touches[0], true );

		return copy;
	}

	function pointer( event ) {

		event = process( event );

		min = ( max = eventMap.indexOf( type = event.type ) ) - 1;

		context.dragging =

			/down|start/.test( type ) ? true :

			/up|end/.test( type ) ? false :

			context.dragging;

		while( min )

			isString( eventMap[ min ] ) ?

				trigger( context[ eventMap[ min-- ] ], event ) :

			isString( eventMap[ max ] ) ?

				trigger( context[ eventMap[ max++ ] ], event ) :

			min = 0;
	}

	function keypress( event ) {

		key = event.keyCode;
		val = event.type == 'keyup';
		keys[ key ] = keys[ keyName( key ) ] = !val;

		trigger( context[ event.type ], event );
	}

	function active( event ) {

		if ( context.autopause )

			( event.type == 'blur' ? stop : start )();

		trigger( context[ event.type ], event );
	}

	// Public API

	function start() {

		context.now = +new Date();
		context.running = true;
	}

	function stop() {

		context.running = false;
	}

	function toggle() {

		( context.running ? stop : start )();
	}

	function clear() {

		if ( is2D )

			context.clearRect( 0, 0, context.width * ratio, context.height * ratio );
	}

	function destroy() {

		parent = context.element.parentNode;
		index = instances.indexOf( context );

		if ( parent ) parent.removeChild( context.element );
		if ( ~index ) instances.splice( index, 1 );

		bind( false );
		stop();
	}

	extend( context, {

		touches: touches,
		mouse: mouse,
		keys: keys,

		dragging: false,
		running: false,
		millis: 0,
		now: NaN,
		dt: NaN,

		destroy: destroy,
		toggle: toggle,
		clear: clear,
		start: start,
		stop: stop
	});

	instances.push( context );

	return ( context.autostart && start(), bind( true ), resize(), update(), context );
}

/*
----------------------------------------------------------------------

	Global API

----------------------------------------------------------------------
*/

var element, context, Sketch = {

	CANVAS: CANVAS,
	WEB_GL: WEBGL,
	WEBGL: WEBGL,
	DOM: DOM,

	instances: instances,

	install: function( context ) {

		if ( !context[ HAS_SKETCH ] ) {

			for ( var i = 0; i < MATH_PROPS.length; i++ )

				context[ MATH_PROPS[i] ] = M[ MATH_PROPS[i] ];

			extend( context, {

				TWO_PI: M.PI * 2,
				HALF_PI: M.PI / 2,
				QUARTER_PI: M.PI / 4,

				random: function( min, max ) {

					if ( isArray( min ) )

						return min[ ~~( M.random() * min.length ) ];

					if ( !isNumber( max ) )

						max = min || 1, min = 0;

					return min + M.random() * ( max - min );
				},

				lerp: function( min, max, amount ) {

					return min + amount * ( max - min );
				},

				map: function( num, minA, maxA, minB, maxB ) {

					return ( num - minA ) / ( maxA - minA ) * ( maxB - minB ) + minB;
				}
			});

			context[ HAS_SKETCH ] = true;
		}
	},

	create: function( options ) {

		options = extend( options || {}, defaults );

		if ( options.globals ) Sketch.install( self );

		element = options.element = options.element || doc.createElement( options.type === DOM ? 'div' : 'canvas' );

		context = options.context = options.context || (function() {

			switch( options.type ) {

				case CANVAS:

					return element.getContext( '2d', options );

				case WEBGL:

					return element.getContext( 'webgl', options ) || element.getContext( 'experimental-webgl', options );

				case DOM:

					return element.canvas = element;
			}

		})();

		( options.container || doc.body ).appendChild( element );

		return Sketch.augment( context, options );
	},

	augment: function( context, options ) {

		options = extend( options || {}, defaults );

		options.element = context.canvas || context;
		options.element.className += ' sketch';

		extend( context, options, true );

		return constructor( context );
	}
};

/*
----------------------------------------------------------------------

	Shims

----------------------------------------------------------------------
*/

var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
var scope = self;
var then = 0;

var a = 'AnimationFrame';
var b = 'request' + a;
var c = 'cancel' + a;

var rAF = scope[ b ];
var cAF = scope[ c ];

for ( var i = 0; i < vendors.length && !rAF; i++ ) {

	rAF = scope[ vendors[ i ] + 'Request' + a ];
	cAF = scope[ vendors[ i ] + 'Cancel' + a ];
}

scope[ b ] = rAF = rAF || function( callback ) {

	var now = +new Date();
	var dt = M.max( 0, 16 - ( now - then ) );
	var id = setTimeout( function() {
		callback( now + dt );
	}, dt );

	then = now + dt;
	return id;
};

scope[ c ] = cAF = cAF || function( id ) {
	clearTimeout( id );
};

/*
----------------------------------------------------------------------

	Output

----------------------------------------------------------------------
*/

return Sketch;

}));


        </script>
        <script>

        // ----------------------------------------
        // Particle
        // ----------------------------------------

        function Particle( x, y, radius ) {
            this.init( x, y, radius );
        }

        Particle.prototype = {

            init: function( x, y, radius ) {

                this.alive = true;

                this.radius = radius || 10;
                this.wander = 0.15;
                this.theta = random( TWO_PI );
                this.drag = 0.92;
                this.color = '#fff';

                this.x = x || 0.0;
                this.y = y || 0.0;

                this.vx = 0.0;
                this.vy = 0.0;
            },

            move: function() {

                this.x += this.vx;
                this.y += this.vy;

                this.vx *= this.drag;
                this.vy *= this.drag;

                this.theta += random( -0.5, 0.5 ) * this.wander;
                this.vx += sin( this.theta ) * 0.1;
                this.vy += cos( this.theta ) * 0.1;

                this.radius *= 0.96;
                this.alive = this.radius > 0.5;
            },

            draw: function( ctx ) {

                ctx.beginPath();
                ctx.arc( this.x, this.y, this.radius, 0, TWO_PI );
                ctx.fillStyle = this.color;
                ctx.fill();
            }
        };

        // ----------------------------------------
        // Example
        // ----------------------------------------

        var MAX_PARTICLES = 280;
        var COLOURS = [ '#69D2E7', '#A7DBD8', '#E0E4CC', '#F38630', '#FA6900', '#FF4E50', '#F9D423' ];

        var particles = [];
        var pool = [];

        var demo = Sketch.create({
            container: document.getElementById( 'container' ),
            retina: 'auto'
        });

        demo.setup = function() {

            // Set off some initial particles.
            var i, x, y;

            for ( i = 0; i < 20; i++ ) {
                x = ( demo.width * 0.5 ) + random( -100, 100 );
                y = ( demo.height * 0.5 ) + random( -100, 100 );
                demo.spawn( x, y );
            }
        };

        demo.spawn = function( x, y ) {

            var particle, theta, force;

            if ( particles.length >= MAX_PARTICLES )
                pool.push( particles.shift() );

            particle = pool.length ? pool.pop() : new Particle();
            particle.init( x, y, random( 5, 40 ) );

            particle.wander = random( 0.5, 2.0 );
            particle.color = random( COLOURS );
            particle.drag = random( 0.9, 0.99 );

            theta = random( TWO_PI );
            force = random( 2, 8 );

            particle.vx = sin( theta ) * force;
            particle.vy = cos( theta ) * force;

            particles.push( particle );
        };

        demo.update = function() {

            var i, particle;

            for ( i = particles.length - 1; i >= 0; i-- ) {

                particle = particles[i];

                if ( particle.alive ) particle.move();
                else pool.push( particles.splice( i, 1 )[0] );
            }
        };

        demo.draw = function() {

            demo.globalCompositeOperation  = 'lighter';

            for ( var i = particles.length - 1; i >= 0; i-- ) {
                particles[i].draw( demo );
            }
        };

        demo.mousemove = function() {

            var particle, theta, force, touch, max, i, j, n;

            for ( i = 0, n = demo.touches.length; i < n; i++ ) {

                touch = demo.touches[i], max = random( 1, 4 );
                for ( j = 0; j < max; j++ ) {
                  demo.spawn( touch.x, touch.y );
                }

            }
        };

        </script>
    </body>
</html>

Thanks so much Andreas that is amazingly helpful! Is there any way to make the background transparent not black. I have managed to change the particle colours but not the background.

Never mind I figured it out :slight_smile:

please showcase your page

Yes, Please.

BTW… Here’s the original post by Justin Windle it’s creator:

For some reason I am unable to copy the code. As soon as I select the code and hit copy, the page freezes and I get a black box over the code window.

I tried it also and it didnt work out. Now with your code it is working.
But here is my question:
Where is the script tag for sketch.js ??? Like:

Usually you need to add it…

Actually I have been able to do this by adding an html element with this code:

<html>

<head>
  <meta charset="UTF-8">
  <script src="https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
  
  <style>
    /* ---- reset ---- */

    body {
      margin: 0;
      font: normal 75% Arial, Helvetica, sans-serif;
    }

    canvas {
      display: block;
      vertical-align: bottom;
    }

    /* ---- particles.js container ---- */

    #particles-js {
    width: 100%;
    height: 100%;
    background-color: transparent;
    background-image: url('');
    background-size: cover;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    position: absolute;
    top: 0;
    z-index: 1;
  }

  </style>
  <script>
    window.console = window.console || function(t) {};
  </script>
  <script>
    if (document.location.search.match(/type=embed/gi)) {
      window.parent.postMessage("resize", "*");
    }
  </script>
</head>

<body translate="no">

  <div id="particles-js"><canvas class="particles-js-canvas-el" style="width: 100%; height: 100%;" width="1853" height="491"></canvas></div>

  <script id="rendered-js">
    /* ---- particles.js config ---- */

    particlesJS("particles-js", {
        "particles": {
          "number": {
            "value": 100,
            "density": {
              "enable": true,
              "value_area": 800
            }
          },
          "color": {
            "value": "#FFF"
          },
          "shape": {
            "type": "circle",
            "stroke": {
              "width": 0,
              "color": "#FFF"
            },
            "polygon": {
              "nb_sides": 6
            },
            "image": {
              "src": "",
              "width": 100,
              "height": 100
            }
          },
          "opacity": {
            "value": 0.75,
            "random": false,
            "anim": {
              "enable": false,
              "speed": 1,
              "opacity_min": 0.1,
              "sync": false
            }
          },
          "size": {
            "value": 4,
            "random": true,
            "anim": {
              "enable": false,
              "speed": 40,
              "size_min": 0.1,
              "sync": false
            }
          },
          "line_linked": {
            "enable": true,
            "distance": 150,
            "color": "#ffffff",
            "opacity": 0.5,
            "width": 1
          },
          "move": {
            "enable": true,
            "speed": 4,
            "direction": "none",
            "random": false,
            "straight": false,
            "out_mode": "out",
            "attract": {
              "enable": false,
              "rotateX": 600,
              "rotateY": 1200
            }
          }
        },
        "interactivity": {
          "detect_on": "canvas",
          "events": {
            "onhover": {
              "enable": false,
              "mode": "grab"
            },
            "onclick": {
              "enable": true,
              "mode": "push"
            },
            "resize": true
          },
          "modes": {
            "grab": {
              "distance": 400,
              "line_linked": {
                "opacity": 1
              }
            },
            "bubble": {
              "distance": 400,
              "size": 40,
              "duration": 2,
              "opacity": 8,
              "speed": 3
            },
            "repulse": {
              "distance": 200
            },
            "push": {
              "particles_nb": 4
            },
            "remove": {
              "particles_nb": 2
            }
          }
        },
        "retina_detect": true,
        "config_demo": {
          "hide_card": false,
          "background_color": "transparent",
          "background_image": "",
          "background_position": "50% 50%",
          "background_repeat": "no-repeat",
          "background_size": "cover",
          "position": "absolute",
          "z-index": "1",
          "top": "0"
        }
      });


  </script>

</body>

</html>