Use the attached files to copy the examples shown in our 'Custom CSS & Javascript: Part 6' Blog Post.


Hexagon Light Paths:


Copy and paste the following code into your portal's Custom HTML box:

<div id="hex-container" class="hex-container"></div>
<!--<h1 class="hex-heading">We Love Colour</h1>-->

Copy and paste the following code into your portal's Custom CSS box: 

.inside-page-content{
width: 100%;
height: 90vh;
margin: 0;
padding: 0;
overflow: auto;
}
.hex-container{
width: 100%;
height: 90vh;
margin: 0;
padding: 0;
background-color: #000000;
display: flex;
align-items: center;
justify-content: center;
}

h1.hex-heading{
position:absolute;
top:40%;
left:35%;
margin:auto auto;
padding:0px;
text-align:center;
font-size:90px;
color:#fff;
font-weight:800;
}

Copy and paste the following code into your portal's Custom Javascript box: 

var RENDERER = {
RESIZE_INTERVAL : 30,
RADIUS : 25,
RATE : 0.98,

init : function(){
this.setParameters();
this.setup();
this.reconstructMethods();
this.bindEvent();
this.render();
},
setParameters : function(){
this.$window = $(window);
this.$container = $('#hex-container');
this.$canvas = $('<canvas />');
this.context = this.$canvas.appendTo(this.$container).get(0).getContext('2d');
this.hexagons = [];
this.resizeIds = [];
},
setup : function(){
this.hexagons.length = 0;
this.resizeIds.length = 0;
this.width = this.$container.width();
this.height = this.$container.height();
this.$canvas.attr({width : this.width, height : this.height});
this.createHexagons();
},
getRandomValue : function(min, max){
return min + (max - min) * Math.random() | 0;
},
createHexagons : function(){
this.radius = this.RADIUS * this.RATE;
this.vertices = [];

for(var i = 0; i < 6; i++){
this.vertices.push({x : this.radius * Math.sin(Math.PI / 3 * i), y : -this.radius * Math.cos(Math.PI / 3 * i)});
}
this.vertices.push(this.vertices[0]);
this.hexWidth = this.RADIUS * Math.cos(Math.PI / 6) * 2;
this.hexHeight = this.RADIUS * (2 - Math.sin(Math.PI / 6));

var countX = Math.ceil(this.width / this.hexWidth) + 1,
countY = Math.ceil(this.height / this.hexHeight) + 1,
offsetX = -(countX * this.hexWidth - this.width) / 2,
offsetY = -(countY * this.hexHeight - this.height) / 2;

countX++;

for(var y = 0; y < countY; y++){
for(var x = 0; x < countX; x++){
this.hexagons.push(new HEXAGON(this, offsetX + (x + 0.5) * this.hexWidth - (y % 2 == 1 ? 0 : this.hexWidth / 2), offsetY + (y + 0.5) * this.hexHeight));
}
}
for(var y = 0; y < countY; y++){
for(var x = 0; x < countX; x++){
var hexagon = this.hexagons[y * countX + x];

if(x < countX - 1){
hexagon.neighbors[0] = this.hexagons[y * countX + x + 1];
}
if((x < countX - 1 || y % 2 == 0) && y < countY - 1){
hexagon.neighbors[1] = this.hexagons[(y + 1) * countX + x + (y % 2 == 1 ? 1 : 0)];
}
if((x > 0 || y % 2 == 1) && y < countY - 1){
hexagon.neighbors[2] = this.hexagons[(y + 1) * countX + x + (y % 2 == 1 ? 0 : -1)];
}
if(x > 0){
hexagon.neighbors[3] = this.hexagons[y * countX + x - 1];
}
if((x > 0 || y % 2 == 1) && y > 0){
hexagon.neighbors[4] = this.hexagons[(y - 1) * countX + x + (y % 2 == 1 ? 0 : -1)];
}
if((x < countX - 1 || y % 2 == 0) && y > 0){
hexagon.neighbors[5] = this.hexagons[(y - 1) * countX + x + (y % 2 == 1 ? 1 : 0)];
}
}
}
this.hexagons[this.getRandomValue(0, this.hexagons.length - 1)].select();
},
watchWindowSize : function(){
while(this.resizeIds.length > 0){
clearTimeout(this.resizeIds.pop());
}
this.tmpWidth = this.$window.width();
this.tmpHeight = this.$window.height();
this.resizeIds.push(setTimeout(this.jdugeToStopResize, this.RESIZE_INTERVAL));
},
jdugeToStopResize : function(){
var width = this.$window.width(),
height = this.$window.height(),
stopped = (width == this.tmpWidth && height == this.tmpHeight);

this.tmpWidth = width;
this.tmpHeight = height;

if(stopped){
this.setup();
}
},
reconstructMethods : function(){
this.selectHexagon = this.selectHexagon.bind(this);
this.watchWindowSize = this.watchWindowSize.bind(this);
this.jdugeToStopResize = this.jdugeToStopResize.bind(this);
this.render = this.render.bind(this);
},
selectHexagon : function(event){
var axis = this.getAxis(event);

for(var i = 0, count = this.hexagons.length; i < count; i++){
this.hexagons[i].judge(axis.x, axis.y);
}
},
getAxis : function(event){
var offset = this.$container.offset();
return {x : event.clientX - offset.left + this.$window.scrollLeft(), y : event.clientY - offset.top + this.$window.scrollTop()};
},
bindEvent : function(){
this.$window.on('resize', this.watchWindowSize);
this.$container.on('click', this.selectHexagon);
},
render : function(){
requestAnimationFrame(this.render);

this.context.fillStyle = 'hsla(210, 70%, 10%, 0.3)';
this.context.fillRect(0, 0, this.width, this.height);

for(var i = 0, count = this.hexagons.length; i < count; i++){
this.hexagons[i].render(this.context);
}
}
};
var HEXAGON = function(renderer, x, y){
this.renderer = renderer;
this.x = x;
this.y = y;
this.init();
};
HEXAGON.prototype = {
COUNT : {MIN : 5, MAX : 50},
LUMINANCE : {MIN : 10, MAX : 70},

init : function(){
this.selections = [];
this.neighbors = new Array(6);
this.sourceIndices = [];
},
judge : function(x, y){
if(x < this.x - this.renderer.hexWidth / 2 || x > this.x + this.renderer.hexWidth / 2
|| y < this.y - this.renderer.RADIUS || y > this.y + this.renderer.RADIUS
|| y < this.y && Math.abs((x - this.x) / (y - this.y + this.renderer.RADIUS)) > Math.tan(Math.PI / 3)
|| y > this.y && Math.abs((x - this.x) / (y - this.y - this.renderer.RADIUS)) > Math.tan(Math.PI / 3)){
return;
}
this.select();
},
select : function(){
this.hue = this.renderer.getRandomValue(100, 300);
this.selections.push({count : 0, hue : this.hue});
},
relate : function(sourceIndices){
this.sourceIndices.push(sourceIndices);
},
draw : function(context, targets){
for(var i = 0; i < targets.length; i++){
var target = targets[i],
fillLuminance = 0,
strokeLuminance = 0;

if(target.count < this.COUNT.MIN){
fillLuminance = this.LUMINANCE.MIN + (this.LUMINANCE.MAX - this.LUMINANCE.MIN) * Math.pow(Math.sin(Math.PI / 2 * target.count / this.COUNT.MIN), 3);
}else if(target.count < this.COUNT.MAX){
fillLuminance = this.LUMINANCE.MIN + (this.LUMINANCE.MAX - this.LUMINANCE.MIN) * Math.pow(Math.sin(Math.PI / 2 * (1 + (target.count - this.COUNT.MIN) / (this.COUNT.MAX - this.COUNT.MIN))), 3);
}
if(target.count < this.COUNT.MIN * 2){
strokeLuminance = this.LUMINANCE.MIN + (this.LUMINANCE.MAX - this.LUMINANCE.MIN) * Math.sin(Math.PI / 2 * target.count / this.COUNT.MIN / 2);
}else if(target.count < this.COUNT.MAX * 2){
strokeLuminance = this.LUMINANCE.MIN + (this.LUMINANCE.MAX - this.LUMINANCE.MIN) * Math.sin(Math.PI / 2 * (1 + (target.count - this.COUNT.MIN * 2) / (this.COUNT.MAX - this.COUNT.MIN) / 2));
}
context.fillStyle = 'hsla(' + target.hue + ', 70%, ' + fillLuminance + '%, 0.3)';
context.fill();
context.strokeStyle = 'hsla(' + target.hue + ', 70%, ' + strokeLuminance + '%, 0.3)';
context.stroke();
}
},
render : function(context){
context.save();
context.globalCompositeOperation = 'lighter';
context.translate(this.x, this.y);
context.beginPath();

for(var i = 0, vertices = this.renderer.vertices; i < 6; i++){
context[i == 0 ? 'moveTo' : 'lineTo'](vertices[i].x, vertices[i].y);
}
context.closePath();
context.fillStyle = 'hsla(210, 70%, ' + this.LUMINANCE.MIN + '%, 0.3)';
context.fill();

this.draw(context, this.selections);
this.draw(context, this.sourceIndices);
context.restore();

for(var i = this.selections.length - 1; i >= 0; i--){
var selection = this.selections[i];

if(selection.count == this.COUNT.MIN){
for(var j = 0; j < 6; j++){
if(this.neighbors[j]){
var indices = [];

for(var k = 0; k < 3; k++){
var index = j - 1 + k;
index += 6;
index %= 6;
indices.push(index);
}
this.neighbors[j].relate({indices : indices, hue : this.hue, count : 0});
}
}
}
if(++selection.count == this.COUNT.MAX * 2){
this.selections.splice(i, 1);
}
}
for(var i = this.sourceIndices.length - 1; i >= 0; i--){
var indices = this.sourceIndices[i],
index = indices.indices[this.renderer.getRandomValue(0, 3)];

if(this.neighbors[index] && indices.count == this.COUNT.MIN){
this.neighbors[index].relate({indices : indices.indices, hue : indices.hue, count : 0});
}
if(++indices.count == this.COUNT.MAX * 2){
this.sourceIndices.splice(i, 1);
}
}
}
};
$(function(){
RENDERER.init();
});


Under Water Glow:


Copy and paste the following code into your portal's Custom HTML box:

<canvas id="c"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

Copy and paste the following code into your portal's Custom CSS box:

* {
overflow: hidden;
background:#000;
}

canvas {
display: block;
/* background:#00e1e9; */
background:radial-gradient(ellipse at top, #00e1e9 50%, #000 100%);
}

.page-portalpage-3b9e9093-5f93-4edb-b764-7cfa6da4a89d .container {
width:100%;
padding:0px;
margin:0px;
}

Copy and paste the following code into your portal's Custom Javascript box:

function dmLoad() {
// Customize these...
var n = 300,
speed = 15,
startSize = rand(200,500);

// ...not these
var c = document.getElementById("c"),
ctx = c.getContext("2d"),
cw = (c.width = window.innerWidth),
ch = (c.height = window.innerHeight),
mousePos = {x:"", y:""},
img = new Image(),
particles = [],
particleNumber = 0,
Particle = function(index) {
this.index = index;
this.dur = (100-rand(9, 90))/speed;
this.draw = function() {
ctx.translate( this.x, this.y );
ctx.globalAlpha = this.alpha;
ctx.globalCompositeOperation = 'lighter';
// if (index%1.5==0) ctx.globalCompositeOperation = 'overlay';
if (index%2==0) ctx.globalCompositeOperation = 'xor';
ctx.drawImage(img, -this.size/2, -this.size/2, this.size, this.size);
ctx.translate( -this.x, -this.y );
}
};

c.onmousemove = function(e){ mousePos = { x:e.clientX, y:e.clientY }; }
document.onmouseleave = function(e){ mousePos = {x:"", y:""} }

function setParticle(p, firstRun) {
var _x = cw*rand(0,1), _y = ch*rand(0,1), _s = startSize;
if (rand(0,1)>0.3 && mousePos.x!=""){ //console.log(mousePos)
_x = mousePos.x;
_y = mousePos.y;
_s = _s/10;
}
var _tl = new TimelineMax()
.fromTo(p, p.dur, {
x:_x,
y:_y,
size:_s,
alpha:0
},{
size:'+='+String(rand(200,400)),
bezier:[{alpha:rand(0.15,0.65)},{alpha:0}],
ease:Power1.easeOut,//ease:Power0.easeNone,
onComplete:function(){ setParticle(p); }
});

if (firstRun) _tl.seek(p.dur*rand()); //fast-forward on first run
}


TweenMax.ticker.addEventListener("tick", function(){
ctx.clearRect(0, 0, cw, ch);
for (var i=0; i<n; i++) particles[i].draw();
});


window.addEventListener('resize', doResize)
function doResize() {
particleNumber = 0;
cw = (c.width = window.innerWidth);
ch = (c.height = window.innerHeight);
for (var i=0; i<n; i++) {
TweenMax.killTweensOf(particles[i]);
setParticle(particles[i], true);
}
TweenMax.fromTo(c, 0.3, {alpha:0},{alpha:1, ease:Power3.easeInOut});
}

// First run
for (var i=0; i<n; i++) particles.push(new Particle(i));
doResize();


function rand(min, max) {
(min) ? min=min : min=0;
(max) ? max=max : max=1;
return min + (max-min)*Math.random();
}



};


Waves:


Copy and paste the following code into your portal's Custom HTML box:

<div class="wave-heading">
<!--Content before waves-->
<div class="inner-header flex">
<!--<h1>WELCOME TO COLOUR BLOCKS!</h1>-->
</div>
<!--Waves Container-->
<div>
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
<defs>
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="48" y="0" fill="rgba(255,255,255,0.7" />
<use xlink:href="#gentle-wave" x="48" y="3" fill="rgba(255,255,255,0.5)" />
<use xlink:href="#gentle-wave" x="48" y="5" fill="rgba(255,255,255,0.3)" />
<use xlink:href="#gentle-wave" x="48" y="7" fill="#fff" />
</g>
</svg>
</div>
<!--Waves end-->
</div>

Copy and paste the following code into your portal's Custom CSS box: 

.page-portalpage-388e86d8-adf6-407c-9b63-c6ae01395cfb .container {
margin:0px;
padding:0px;
width:100%;
}

@import url(//fonts.googleapis.com/css?family=Lato:300:400);


.page-portalpage-388e86d8-adf6-407c-9b63-c6ae01395cfb h1 {
font-family: 'Lato', sans-serif;
font-weight:600;
letter-spacing: 2px;
font-size:48px;
color:#fff;
padding-top:30px;
}

.page-portalpage-388e86d8-adf6-407c-9b63-c6ae01395cfb .wave-heading {
position:relative;
text-align:center;
background: linear-gradient(60deg, rgba(84,58,183,1) 0%, rgba(0,172,193,1) 100%);
color:white;
}

.inner-header {
height:60vh;
width:100%;
margin: 0;
padding: 0;
}

.flex { /*Flexbox for containers*/
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}

.waves {
position:relative;
width: 100%;
height:15vh;
margin-bottom:-7px; /*Fix for safari gap*/
min-height:100px;
max-height:150px;
}



/* Animation */

.parallax > use {
animation: move-forever 25s cubic-bezier(.55,.5,.45,.5) infinite;
}
.parallax > use:nth-child(1) {
animation-delay: -2s;
animation-duration: 7s;
}
.parallax > use:nth-child(2) {
animation-delay: -3s;
animation-duration: 10s;
}
.parallax > use:nth-child(3) {
animation-delay: -4s;
animation-duration: 13s;
}
.parallax > use:nth-child(4) {
animation-delay: -5s;
animation-duration: 20s;
}
@keyframes move-forever {
0% {
transform: translate3d(-90px,0,0);
}
100% {
transform: translate3d(85px,0,0);
}
}
/*Shrinking for mobile*/
@media (max-width: 768px) {
.waves {
height:40px;
min-height:40px;
}

h1 {
font-size:24px;
}
}


Particle Wave:




Copy and paste the following code into your portal's Custom Javascript box:

<canvas id="particle-canvas"></canvas>

<script>
function dmLoad() {
// modified version of random-normal
function normalPool(o) {
var r = 0;
do {
var a = Math.round(normal({
mean: o.mean,
dev: o.dev
}));
if (a < o.pool.length && a >= 0) return o.pool[a];
r++;
} while (r < 100);
}

function randomNormal(o) {
if (
((o = Object.assign({
mean: 0,
dev: 1,
pool: []
}, o)),
Array.isArray(o.pool) && o.pool.length > 0)
)
return normalPool(o);
var r,
a,
n,
e,
l = o.mean,
t = o.dev;
do {
r = (a = 2 * Math.random() - 1) * a + (n = 2 * Math.random() - 1) * n;
} while (r >= 1);
return (e = a * Math.sqrt(-2 * Math.log(r) / r)), t * e + l;
}

const NUM_PARTICLES = 600;
const PARTICLE_SIZE = 0.5; // View heights
const SPEED = 20000; // Milliseconds

let particles = [];

function rand(low, high) {
return Math.random() * (high - low) + low;
}

function createParticle(canvas) {
const colour = {
r: 255,
g: randomNormal({
mean: 125,
dev: 20
}),
b: 50,
a: rand(0, 1)
};
return {
x: -2,
y: -2,
diameter: Math.max(
0,
randomNormal({
mean: PARTICLE_SIZE,
dev: PARTICLE_SIZE / 2
})
),
duration: randomNormal({
mean: SPEED,
dev: SPEED * 0.1
}),
amplitude: randomNormal({
mean: 16,
dev: 2
}),
offsetY: randomNormal({
mean: 0,
dev: 10
}),
arc: Math.PI * 2,
startTime: performance.now() - rand(0, SPEED),
colour: `rgba(${colour.r}, ${colour.g}, ${colour.b}, ${colour.a})`
};
}

function moveParticle(particle, canvas, time) {
const progress =
((time - particle.startTime) % particle.duration) / particle.duration;
return {
...particle,
x: progress,
y: Math.sin(progress * particle.arc) * particle.amplitude + particle.offsetY
};
}

function drawParticle(particle, canvas, ctx) {
canvas = document.getElementById("particle-canvas");
const vh = canvas.height / 100;

ctx.fillStyle = particle.colour;
ctx.beginPath();
ctx.ellipse(
particle.x * canvas.width,
particle.y * vh + canvas.height / 2,
particle.diameter * vh,
particle.diameter * vh,
0,
0,
2 * Math.PI
);
ctx.fill();
}

function draw(time, canvas, ctx) {
// Move particles
particles.forEach((particle, index) => {
particles[index] = moveParticle(particle, canvas, time);
});

// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Draw the particles
particles.forEach(particle => {
drawParticle(particle, canvas, ctx);
});

// Schedule next frame
requestAnimationFrame(time => draw(time, canvas, ctx));
}

function initializeCanvas() {
let canvas = document.getElementById("particle-canvas");
canvas.width = canvas.offsetWidth * window.devicePixelRatio;
canvas.height = canvas.offsetHeight * window.devicePixelRatio;
let ctx = canvas.getContext("2d");

window.addEventListener("resize", () => {
canvas.width = canvas.offsetWidth * window.devicePixelRatio;
canvas.height = canvas.offsetHeight * window.devicePixelRatio;
ctx = canvas.getContext("2d");
});

return [canvas, ctx];
}

function startAnimation() {
const [canvas, ctx] = initializeCanvas();

// Create a bunch of particles
for (let i = 0; i < NUM_PARTICLES; i++) {
particles.push(createParticle(canvas));
}

requestAnimationFrame(time => draw(time, canvas, ctx));
}

// Start animation when document is loaded
(function() {
if (document.readystate !== "loading") {
startAnimation();
} else {
document.addEventListener("DOMContentLoaded", () => {
startAnimation();
});
}
})();

};
</script>

Copy and paste the following code into your portal's Custom CSS box:

.page-portalpage-95ef7e92-e924-4396-b819-736e38faccd9 .container {
width:100%;
margin:0px;
padding:0px;
}

#particle-canvas {
width: 100%;
height: 90vh;
background: linear-gradient(to bottom, rgb(10, 10, 50) 0%,rgb(60, 10, 60) 100%);
vertical-align: middle;
}


.inside-page-content {
margin-bottom:0px;
padding-bottom: 0px;
}