28 Feb 2015
I thought the Bang & Olufsen BeoSound Moment was pretty slick looking and tried to make something similar. This required manually creating an angular gradient since paper.js only supports linear and radial. Show code
<script type="text/paperscript" canvas="canvas-0021">
view.element.style.backgroundColor = '#111';
var color = new Color('#ead839');
var inc = 0.2;
var circle = new Group();
var radius = view.size.width * 0.25;
for (a=360; a>0; a-=inc) {
color.hue += inc;
var line = Path.Line({
from: [0, 0],
to: [radius, radius],
strokeColor: color
});
line.rotate(a, [0, 0]);
circle.addChild(line);
}
circle.opacity = 0.75;
circle.rotate(220);
var circleMid = new Shape.Circle([0, 0], radius * 1.41 * 0.75);
circleMid.fillColor = "#fff";
circleMid.opacity = 0.1;
circleMid.blendMode = 'color-dodge';
var circleInner = new Shape.Circle([0, 0], radius * 1.41 * 0.48);
circleInner.fillColor = "#fff";
circleInner.opacity = 0.15;
circleInner.blendMode = 'color-dodge';
var hole = new Shape.Circle([0, 0], radius * 1.41 * 0.2);
hole.fillColor = "#111";
project.activeLayer.position = view.center;
</script>
<canvas id="canvas-0021" height="300"></canvas>
14 Nov 2014
I tried to recreate the background effect from this Ticketmaster redesign concept. This was the first time I've tried masking paths using boolean intersections. Show code
<script type="text/paperscript" canvas="canvas-0020">
var raster = new Raster('/pixelbits/assets/ron-burgundy.jpg');
raster.visible = false;
var boxSize = view.size.width / 50;
raster.on('load', function() {
// Resize image to a manageable size
raster.size = new Size(50, 50);
for (var y = 0; y < raster.height; y++) {
for(var x = 0; x < raster.width; x++) {
var color = raster.getPixel(x, y);
// bounding box
var box = new Rectangle(new Point(x * boxSize, y * boxSize), new Size(boxSize, boxSize));
var pathBox = new Path.Rectangle(box);
// fill line
var lineWidth = map(color.brightness, 0, 1, boxSize/2, 1);
var line = new Rectangle(new Point(x * boxSize, y * boxSize - boxSize / 2), new Size(lineWidth, boxSize * 2));
var pathLine = new Path.Rectangle(line);
pathLine.rotate(45, new Point(x * boxSize, (y + 1) * boxSize));
// mask the rotated fill line by the bounding box using the intersection
newPath = pathBox.intersect(pathLine);
newPath.fillColor = '#84184b';
newPath.opacity = 0.5;
pathBox.remove();
pathLine.remove();
}
}
});
project.activeLayer.position = view.center;
function map(value, vMin, vMax, dMin, dMax) {
var vValue = parseFloat(value);
var vRange = vMax - vMin;
var dRange = dMax - dMin;
return (vValue - vMin) * dRange / vRange + dMin;
}
</script>
<canvas id="canvas-0020" height="300"></canvas>
13 Nov 2014
Another hue flower. You can get some interesting effects just adding more layers and playing with blend modes. Show code
<script type="text/paperscript" canvas="canvas-0019">
view.element.style.backgroundColor = '#111';
var color = new Color('#0074d9');
var rectangle = new Rectangle(new Point(0, 0), new Size(100, 200));
var shape = new Path.Ellipse(rectangle);
shape.fillColor = color;
var numLayers = 3;
var blendModes = ['screen', 'screen', 'multiply'];
// make it pointy
shape.segments[1].handleIn.x = 0;
shape.segments[1].handleOut.x = 0;
shape.segments[3].handleIn.x = 0;
shape.segments[3].handleOut.x = 0;
var opacity = 0.3;
for (i = 0; i < numLayers; i++) {
for (j = 0; j < 360; j += 15) {
var newShape = shape.clone();
newShape.scale(1 - (i * 0.33));
newShape.fillColor.hue += j;
newShape.opacity = opacity;
newShape.blendMode = blendModes[i];
newShape.rotate(j, [50, 220]);
}
opacity += 0.2;
}
shape.remove();
project.activeLayer.position = view.center;
</script>
<canvas id="canvas-0019" height="250"></canvas>
11 Nov 2014
Trying out some polar coordinates to make oscillating dots. The circle sizing here is linear and would be nicer if it followed a sine wave. Show code
<script type="text/paperscript" canvas="canvas-0018">
RADIUS_MIN = 1;
RADIUS_MAX = 4;
function Ball(p, r) {
this.radius = r;
this.point = p;
this.growing = false;
this.circle = Shape.Circle(p, r);
this.circle.fillColor = '#ed25bc';
}
Ball.prototype = {
iterate: function() {
if (this.growing) {
if (this.circle.radius >= RADIUS_MAX) {
this.growing = false;
}
else {
this.circle.radius += 0.1;
this.circle.fillColor.hue += 1;
}
}
else {
if (this.circle.radius <= RADIUS_MIN) {
this.growing = true;
}
else {
this.circle.radius -= 0.1;
this.circle.fillColor.hue -= 1;
}
}
}
}
var balls = [];
view.element.style.background = "#111";
width = view.size.width;
height = view.size.height;
radius = RADIUS_MIN;
for (i=3; i<12; i++) {
for (a=0; a<360; a+=15) {
var x = Math.cos(radians(a + (i*7.5))) * (20 * i);
var y = Math.sin(radians(a + (i*7.5))) * (20 * i);
balls.push(new Ball(new Point(x, y), radius));
}
radius += 1;
}
project.activeLayer.position = view.center;
function radians(angle) {
return (angle / 180) * Math.PI;
}
function onFrame(event) {
for (var i = 0, l = balls.length; i < l; i++) {
balls[i].iterate();
}
}
</script>
<canvas id="canvas-0018" height="250"></canvas>
07 Nov 2014
Derping around with sine wave phasing. Show code
<script type="text/paperscript" canvas="canvas-0017">
view.element.style.background = "linear-gradient(to bottom, #3a1d3a 0%,#e7584c 100%)";
width = view.size.width;
yMid = view.size.height / 2;
for (var i=0; i<18; i++) {
for (var x=0; x<width; x+=3) {
_x = (x + 500) * Math.PI/180 / 20;
y = (Math.sin(_x*(8 - i/12)*Math.PI) +
Math.sin(_x*(9 + i/13)*Math.PI) +
Math.sin(_x*(10 - i/14)*Math.PI)) * 50;
var shape = new Shape.Circle(new Point(x, y), 1);
shape.fillColor = '#fff';
shape.opacity = 0.7;
}
}
project.activeLayer.position = view.center;
</script>
<canvas id="canvas-0017"></canvas>
06 Nov 2014
Simple spiral experiment with circles and radians. Show code
<script type="text/paperscript" canvas="canvas-0016">
for (var i=15; i<100; i++) {
var f = i * 0.8;
var x = Math.cos(radians(i * 5)) * f;
var y = Math.sin(radians(i * 5)) * f;
var r = i * 1.6;
var shape = new Shape.Circle(new Point(x, y), r);
shape.strokeColor = '#aaa';
}
project.activeLayer.position = view.center;
function radians(angle) {
return (angle / 180) * Math.PI;
}
</script>
<canvas id="canvas-0016"></canvas>
05 Nov 2014
This uses a similar algorithm to our GitHub identicons. The colors stay the same, but the identicon shapes are random each time this page loads. (BTW, if you're a GitHub user, did you know that everyone has an identicon – even if you use an avatar? Just swap in your user name in this URL https://github.com/identicons/jasonlong.png. Show code
<script src="/pixelbits/js/rhill-voronoi-core.min.js"></script>
<script type="text/paperscript" canvas="canvas-0015">
// Colors from http://clrs.cc/
var colors = ['#0074d9', '#01ff70', '#f012be', '#ff851b', '#ffdc00'];
var perRow = 10;
var spriteSize = 5;
// leave room for side gutters and spacing in between
var pixelSize = view.size.width / ((perRow + 2) + (perRow / 2)) / 5;
var marginSize = spriteSize * pixelSize / 2;
view.element.style.backgroundColor = '#111';
for (y = 0; y < colors.length; y++) {
identicon = generateIdenticon(pixelSize, spriteSize);
identicon.fillColor = colors[y];
identicon.shadowColor = colors[y];
identicon.shadowBlur = 25;
for (x = 0; x < perRow; x++) {
newIdenticon = identicon.clone();
newIdenticon.position.x = x * ((pixelSize * spriteSize) + marginSize);
newIdenticon.position.y = y * ((pixelSize * spriteSize) + marginSize);
}
identicon.remove();
}
project.activeLayer.position = view.center;
// build ship
var ship = new Group();
var base = new Rectangle(
new Point(view.size.width / 2, view.size.height - pixelSize * 5),
new Size(pixelSize * 5, pixelSize));
var turret = new Rectangle(
new Point(view.size.width / 2 + (pixelSize * 2), view.size.height - pixelSize * 6),
new Size(pixelSize, pixelSize * 2));
ship.addChildren([new Shape.Rectangle(base), new Shape.Rectangle(turret)]);
ship.fillColor = '#eee';
function generateIdenticon(pixelSize, spriteSize) {
var identicon = new Group();
var halfAxis = (spriteSize -1) / 2;
var i = 0;
var x = halfAxis * pixelSize;
while (x >= 0) {
var y = 0;
while (y < spriteSize * pixelSize) {
if (Math.floor(Math.random() * 100) % 2) {
var rect = new Rectangle(
new Point(x, y),
new Size(pixelSize, pixelSize));
var pixel = new Shape.Rectangle(rect);
identicon.addChild(pixel);
if (x != halfAxis * pixelSize) {
xStart = 2 * halfAxis * pixelSize -x;
var rect = new Rectangle(
new Point(xStart, y),
new Size(pixelSize, pixelSize));
var pixel = new Shape.Rectangle(rect);
identicon.addChild(pixel);
}
}
i += 1;
y += pixelSize;
}
x -= pixelSize;
}
return identicon;
}
</script>
<canvas id="canvas-0015" height="250"></canvas>
04 Nov 2014
An initial experiment with Voronoi diagrams. The points for the cells are randomly generated and each cell has a random color brightness applied. Show code
<script src="/pixelbits/js/rhill-voronoi-core.min.js"></script>
<script type="text/paperscript" canvas="canvas-0014">
var voronoi = new Voronoi();
var bbox = {
xl: 0,
xr: view.bounds.width,
yt: 0,
yb: view.bounds.height
};
var sites = generateRandomPoints(70);
var diagram = voronoi.compute(sites, bbox);
var baseColor = new Color('#3d9970');
var strokeColor = new Color(0, 0, 0, 0.2);
if (diagram) {
for (var i = 0, l = sites.length; i < l; i++) {
var cell = diagram.cells[sites[i].voronoiId];
if (cell) {
var halfedges = cell.halfedges,
length = halfedges.length;
if (length > 2) {
var points = [];
for (var j = 0; j < length; j++) {
v = halfedges[j].getEndpoint();
points.push(new Point(v));
}
createPath(points);
}
}
}
}
function generateRandomPoints(count) {
var points = [];
for (var i=0; i<count; i++) {
x = getRandomInt(0, view.size.width);
y = getRandomInt(0, view.size.height);
points[i] = {'x':x, 'y':y};
}
return points;
}
function createPath(points) {
var path = new Path();
path.fillColor = generateColor(baseColor);
path.strokeColor = strokeColor;
path.closed = true;
for (var i=0, l=points.length; i < l; i++) {
path.add(points[i]);
}
return path;
}
function generateColor(baseColor) {
var newColor = baseColor;
var adjustment = getRandomInt(0, 10);
newColor.brightness += adjustment / 1000;
return newColor;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
</script>
<canvas id="canvas-0014"></canvas>
30 Oct 2014
I recreated the smoke effect I made for http://bounty.github.com with Paper.js. It is a fairly straightforward particle emitter using circles whereas the Bounty site uses a png image. The effect here isn't quite as nice, but could probably be made better with some further variable tweaking. Show code
<script type="text/paperscript" canvas="canvas-0013">
view.element.style.backgroundColor = '#111111';
var NUM_PARTICLES = 100;
var EMITTER_X = view.size.width / 2;
var EMITTER_Y = view.size.height - view.size.height * 0.2;
var MIN_SIZE = 1.5;
var MAX_SIZE = 2.5;
var MIN_VELOCITY_Y = 0.2;
var MAX_VELOCITY_Y = 0.8;
var VELOCITY_X = 0;
var MIN_ALPHA = 0.25;
var MAX_ALPHA = 0.45;
var FADE_SPEED = 0.001;
var GROWTH_SPEED = 1.005;
var WIND_SPEED = 0.13;
var particles = [];
function SmokeParticle(x, y, visible) {
this.circle = new Shape.Circle({
center: [x, y],
radius: (Math.random()*(MAX_SIZE - MIN_SIZE)) + MIN_SIZE,
fillColor: '#333',
shadowColor: '#777',
shadowBlur: 70,
visible: visible
});
this.circle.fillColor.alpha = (Math.random()*(MAX_ALPHA - MIN_ALPHA)) + MIN_ALPHA;
this.velX = VELOCITY_X;
this.velY = (Math.random()*(MAX_VELOCITY_Y - MIN_VELOCITY_Y)) + MIN_VELOCITY_Y;
this.reborn = false;
this.isDead = function() {
return this.circle.fillColor.alpha === 0;
}
this.update = function() {
this.circle.position.x += this.velX + WIND_SPEED;
this.circle.position.y -= this.velY;
this.circle.radius *= GROWTH_SPEED;
this.circle.fillColor.alpha -= FADE_SPEED;
if (this.circle.fillColor.alpha < 0) this.circle.fillColor.alpha = 0;
}
}
cig = new Shape.Circle({
center: [EMITTER_X, EMITTER_Y+2],
radius: 2,
fillColor: '#ee6f37',
strokeColor: '#f00',
shadowColor: '#f00',
shadowBlur: 12
});
for (var i = 0; i < NUM_PARTICLES; i++) {
var particle = new SmokeParticle(EMITTER_X, EMITTER_Y, false);
particles.push(particle);
}
function onFrame(event) {
for (var i = 0; i < NUM_PARTICLES; i++) {
p = particles[i];
if (p.isDead()) {
p.circle.remove();
particles[i] = new SmokeParticle(EMITTER_X, EMITTER_Y, true);
}
p.update();
}
}
</script>
<canvas id="canvas-0013"></canvas>
15 Oct 2014
Random arc grid inspired by the way more awesome Is this art? project by James Mellers. Show code
<script type="text/paperscript" canvas="canvas-0012">
view.element.style.backgroundColor = '#85144b';
arcSize = view.size.height / 12;
// Start with a circle...
var arc = new Path.Circle(new Point(100, 70), arcSize);
// And trim it down to a quarter circle.
arc.removeSegment(3);
arc.segments[0].handleIn.y = 0;
arc.segments[1].handleOut.x = 0;
arc.segments[2].handleIn.x = 0;
arc.segments[2].handleOut.y = 0;
arc.segments[2].point.x = 100;
arc.fillColor = '#ffffff';
for (y=0; y<10; y++) {
for (x=0; x<10; x++) {
newArc = arc.clone();
newArc.position = new Point(x*arcSize, y*arcSize);
switch (getRandomInt(0, 3)) {
case 0:
newArc.rotate(0);
break;
case 1:
newArc.rotate(90);
break;
case 2:
newArc.rotate(180);
break;
case 3:
newArc.rotate(270);
}
opacity = getRandomInt(40, 95);
if (opacity < 45) {
opacity = 0;
}
newArc.fillColor.alpha = opacity/100;
}
}
arc.remove();
project.activeLayer.position = view.center;
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
</script>
<canvas id="canvas-0012" height="250"></canvas>