Last active
November 12, 2015 20:19
-
-
Save john4/a94884f618a8813d414c to your computer and use it in GitHub Desktop.
MiMedia.com Bubble Canvas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ViewModel from "../core/view-model"; | |
import Circle from "../core/circle"; | |
export default class Canvas extends ViewModel { | |
constructor() { | |
super(); | |
const desktopData = [ | |
{size: 20, fx: "left", x: 250, fy: "top", y: 240, color: "rgba(105, 201, 193, .5)"}, | |
{size: 70, fx: "left", x: 200, fy: "top", y: 120, color: "rgba(30, 129, 127, .5)"}, | |
{size: 130, fx: "left", x: 70, fy: "top", y: 40, color: "rgba(60, 181, 144, .5)"}, | |
{size: 50, fx: "left", x: 70, fy: "top", y: 170, color: "rgba(192, 220, 104, .5)"}, | |
{size: 90, fx: "left", x: -15, fy: "top", y: 170, color: "rgba(142, 195, 112, .5)"}, | |
{size: 10, fx: "left", x: 30, fy: "top", y: 270, color: "rgba(217, 183, 75, .5)"}, | |
{size: 190, fx: "right", x: 150, fy: "top", y: 130, color: "rgba(107, 212, 194, .5)"}, | |
{size: 14, fx: "right", x: -150, fy: "top", y: 290, color: "rgba(192, 220, 104, .5)"}, | |
{size: 14, fx: "left", x: 110, fy: "top", y: 900, color: "rgba(60, 181, 144, .5)"}, | |
{size: 70, fx: "left", x: 15, fy: "top", y: 1100, color: "rgba(192, 220, 104, .5)"}, | |
{size: 30, fx: "left", x: 65, fy: "top", y: 1050, color: "rgba(217, 183, 75, .5)"}, | |
{size: 55, fx: "right", x: -15, fy: "top", y: 1300, color: "rgba(192, 231, 109, .5)"}, | |
{size: 240, fx: "left", x: 220, fy: "bottom", y: -320, color: "rgba(107, 212, 194, .5)"}, | |
{size: 180, fx: "left", x: 100, fy: "bottom", y: -340, color: "rgba(42, 148, 132, .5)"}, | |
{size: 160, fx: "left", x: 260, fy: "bottom", y: -180, color: "rgba(192, 220, 104, .5)"}, | |
{size: 110, fx: "left", x: 430, fy: "bottom", y: -320, color: "rgba(217, 183, 75, .5)"}, | |
{size: 50, fx: "left", x: 580, fy: "bottom", y: -500, color: "rgba(192, 231, 109, .5)"}, | |
{size: 15, fx: "left", x: 40, fy: "bottom", y: -620, color: "rgba(217, 183, 75, .5)"}, | |
{size: 110, fx: "right", x: -600, fy: "bottom", y: -310, color: "rgba(105, 201, 193, .5)"}, | |
{size: 20, fx: "right", x: -630, fy: "bottom", y: -540, color: "rgba(60, 181, 144, .5)"}, | |
{size: 22, fx: "right", x: -500, fy: "bottom", y: -480, color: "rgba(192, 231, 109, .5)"}, | |
{size: 22, fx: "right", x: -340, fy: "bottom", y: -700, color: "rgba(192, 231, 109, .5)"}, | |
{size: 180, fx: "right", x: 0, fy: "bottom", y: -330, color: "rgba(107, 212, 194, .5)"}, | |
{size: 110, fx: "right", x: 85, fy: "bottom", y: -300, color: "rgba(42, 148, 132, .5)"}, | |
{size: 120, fx: "right", x: -15, fy: "bottom", y: -470, color: "rgba(192, 220, 104, .5)"}, | |
{size: 90, fx: "right", x: -150, fy: "bottom", y: -400, color: "rgba(217, 183, 75, .5)"} | |
]; | |
const mobileData = [ | |
{size: 20, fx: "right", x: -40, fy: "top", y: 690, color: "rgba(30, 129, 127, .5)"}, | |
{size: 130, fx: "right", x: -50, fy: "top", y: 470, color: "rgba(60, 181, 144, .5)"}, | |
{size: 50, fx: "right", x: -70, fy: "top", y: 360, color: "rgba(192, 220, 104, .5)"}, | |
{size: 90, fx: "right", x: 15, fy: "top", y: 370, color: "rgba(142, 195, 112, .5)"}, | |
{size: 180, fx: "left", x: 0, fy: "bottom", y: -330, color: "rgba(107, 212, 194, .5)"}, | |
{size: 110, fx: "left", x: -85, fy: "bottom", y: -300, color: "rgba(42, 148, 132, .5)"}, | |
{size: 120, fx: "left", x: 15, fy: "bottom", y: -470, color: "rgba(192, 220, 104, .5)"}, | |
{size: 90, fx: "left", x: 150, fy: "bottom", y: -400, color: "rgba(217, 183, 75, .5)"}, | |
{size: 170, fx: "right", x: 20, fy: "bottom", y: -60, color: "rgba(105, 201, 193, .5)"}, | |
{size: 50, fx: "right", x: -20, fy: "bottom", y: -600, color: "rgba(192, 231, 109, .5)"}, | |
{size: 20, fx: "right", x: -80, fy: "bottom", y: -650, color: "rgba(60, 181, 144, .5)"}, | |
{size: 90, fx: "right", x: -150, fy: "bottom", y: -70, color: "rgba(217, 183, 75, .5)"}, | |
{size: 110, fx: "right", x: -70, fy: "bottom", y: -200, color: "rgba(192, 220, 104, .5)"} | |
]; | |
const ctx = this.instantiateCanvas(); | |
let circles = []; | |
if (this.isMobile()) { | |
circles = this.instantiateCircles(mobileData); | |
} else { | |
circles = this.instantiateCircles(desktopData); | |
} | |
window.addEventListener("resize", () => { | |
this.resizeCanvas(ctx); | |
this.step(circles, ctx); | |
}); | |
this.resizeCanvas(ctx); | |
// TweenLite.ticker.addEventListener("tick", this.draw(circles, ctx)); | |
TweenLite.ticker.addEventListener("tick", () => { this.draw(circles, ctx); }); | |
this.step(circles, ctx); | |
} | |
instantiateCanvas() { | |
const ctx = document.getElementById("canvas").getContext("2d"); | |
ctx.globalCompositeOperation = "destination-over"; | |
return ctx; | |
} | |
instantiateCircles(data) { | |
const circles = []; | |
// Instantiate circles | |
for (let i = 0; i < data.length; i++) { | |
const newCircle = new Circle(); | |
newCircle.color = data[i].color; | |
newCircle.radius = data[i].size; | |
newCircle.fixedX = data[i].fx; | |
newCircle.fixedY = data[i].fy; | |
newCircle.scale = 1.0; | |
newCircle.setOriginalPosition(data[i].x, data[i].y); | |
circles.push(newCircle); | |
} | |
return circles; | |
} | |
step(circles, ctx) { | |
// Wiggle circles | |
for (const i in circles) { | |
this.wiggleCircle(circles[i], ctx); | |
} | |
} | |
wiggleCircle(circle) { | |
if (circle.isWiggling) { | |
const tweenProperties = [ | |
{ | |
name: "scale", | |
min: 0.93, | |
max: 1 | |
}, { | |
name: "x", | |
min: circle.x - 12, | |
max: circle.x + 12 | |
}, { | |
name: "y", | |
min: circle.y - 12, | |
max: circle.y + 12 | |
}]; | |
this.wiggleProperties(circle, tweenProperties); | |
} | |
} | |
wiggleProperties(obj, properties) { | |
const duration = Math.random() * 4 + 1.5; | |
const tweenOptions = { | |
ease: Power1.easeInOut, | |
onComplete: () => { this.wiggleProperties(obj, properties); } | |
}; | |
for (const i in properties) { | |
const property = properties[i]; | |
tweenOptions[property.name] = Math.random() * (property.max - property.min) + property.min; | |
} | |
TweenLite.to(obj, duration, tweenOptions); | |
} | |
draw(circles, ctx) { | |
const canvasEl = ctx.canvas; | |
// Clear canvas | |
ctx.clearRect(0, 0, canvasEl.clientWidth, canvasEl.clientHeight); | |
// Draw circles | |
for (const i in circles) { | |
this.drawCircle(circles[i], ctx); | |
} | |
} | |
drawCircle(circle, ctx) { | |
const rad = circle.calculateRadius(); | |
const pos = circle.calculateRelativePosition(ctx); | |
ctx.beginPath(); | |
ctx.arc(pos.x, pos.y, rad, 0, 2 * Math.PI, false); | |
ctx.fillStyle = circle.color; | |
ctx.fill(); | |
} | |
resizeCanvas(ctx) { | |
const wrapperEl = document.getElementById("canvas__wrapper"); | |
ctx.canvas.height = wrapperEl.clientHeight; | |
ctx.canvas.width = wrapperEl.clientWidth; | |
} | |
destroy() { | |
super.destroy(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class circle { | |
constructor(color, radius) { | |
this.color = color; | |
this.radius = radius; | |
this.fixedX = "left"; | |
this.fixedY = "top"; | |
this.scale = 1; | |
this.isWiggling = true; | |
} | |
setOriginalPosition(x, y) { | |
// Origin coordinates should be set as pixels | |
// These coordinates will be intreprested through the lens of where this | |
// object is fixed. | |
this.origin = {x, y}; | |
this.x = x; | |
this.y = y; | |
} | |
calculateRelativePosition(ctx) { | |
// This will return the calculated position of this object within the | |
// given canvas context based on where this object is fixed. | |
const height = ctx.canvas.height; | |
const width = ctx.canvas.width; | |
const pos = { | |
x: this.x, | |
y: this.y | |
}; | |
if (this.fixedX === "right") { | |
pos.x += width; | |
} | |
if (this.fixedY === "bottom") { | |
pos.y += height; | |
} | |
return pos; | |
} | |
calculateRadius() { | |
return this.radius * this.scale; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is stripped directly out of our environment for the site, and so will be missing plenty of dependencies such as our
ViewModel
thatCanvas
extends. Use this as guidance or inspiration.