Examples: add Voronoi, Q*bertify and Nyan Rainbow to Paperjs.org folder.

This commit is contained in:
Jonathan Puckey 2013-03-02 20:58:09 +01:00
parent d13f1b88d6
commit a3880bab5e
3 changed files with 469 additions and 0 deletions

View file

@ -0,0 +1,197 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Radial Rainbows</title>
<link rel="stylesheet" href="../css/style.css">
<script type="text/javascript" src="../../dist/paper.js"></script>
<script type="text/javascript" src="http://paperjs.org/static/mediaelement/mediaelement.js"></script>
<script type="text/paperscript" canvas="canvas">
// A tribute to Nyan Cat http://www.youtube.com/watch?v=QH2-TGUlwu4
var mediaElement;
var playing = false;
MediaElement('nyan', {
pluginPath: '/static/mediaelement/',
success: function(me) {
mediaElement = me;
me.play();
me.addEventListener('timeupdate', function(time) {
if (me.currentTime > 3.7)
playing = true;
});
}
});
var mousePos = view.center + [view.bounds.width / 3, 100];
var position = view.center;
function onFrame(event) {
position += (mousePos - position) / 10;
var vector = (view.center - position) / 10;
moveStars(vector * 3);
moveRainbow(vector, event);
}
function onMouseMove(event) {
mousePos = event.point;
}
function onKeyDown(event) {
if (event.key == 'space')
project.activeLayer.selected = !project.activeLayer.selected;
}
var moveStars = new function() {
// The amount of symbol we want to place;
var count = 50;
// Create a symbol, which we will use to place instances of later:
var path = new Path.Circle(new Point(0, 0), 5);
path.style = {
fillColor: 'white',
strokeColor: 'black'
};
var symbol = new Symbol(path);
// Place the instances of the symbol:
for (var i = 0; i < count; i++) {
// The center position is a random point in the view:
var center = Point.random() * view.size;
var placed = symbol.place(center);
placed.scale(i / count + 0.01);
placed.data = {};
placed.data.vector = new Point({
angle: Math.random() * 360,
length : (i / count) * Math.random() / 5
});
}
var vector = new Point({
angle: 45,
length: 0
});
function keepInView(item) {
var position = item.position;
var viewBounds = view.bounds;
if (position.isInside(viewBounds))
return;
var itemBounds = item.bounds;
if (position.x > viewBounds.width + 5) {
position.x = -item.bounds.width;
}
if (position.x < -itemBounds.width - 5) {
position.x = viewBounds.width;
}
if (position.y > viewBounds.height + 5) {
position.y = -itemBounds.height;
}
if (position.y < -itemBounds.height - 5) {
position.y = viewBounds.height
}
}
return function(vector) {
// Run through the active layer's children list and change
// the position of the placed symbols:
var layer = project.activeLayer;
for (var i = 0; i < count; i++) {
var item = layer.children[i];
var size = item.bounds.size;
var length = vector.length / 10 * size.width / 10;
item.position += vector.normalize(length) + item.data.vector;
keepInView(item);
}
};
};
var moveRainbow = new function() {
var paths = [];
var colors = ['red', 'orange', 'yellow', 'lime', 'blue', 'purple'];
for (var i = 0; i < colors.length; i++) {
var path = new Path();
path.fillColor = colors[i];
paths.push(path);
}
var count = 30;
var group = new Group(paths);
var headGroup;
var eyePosition = new Point();
var eyeFollow = (Point.random() - 0.5);
var blinkTime = 200;
function createHead(vector, count) {
var eyeVector = (eyePosition - eyeFollow);
eyePosition -= eyeVector / 4;
if (eyeVector.length < 0.00001)
eyeFollow = (Point.random() - 0.5);
if (headGroup) {
headGroup.remove();
}
var top = paths[0].lastSegment.point;
var bottom = paths[paths.length - 1].firstSegment.point;
var middle = top + (bottom - top) / 2;
var radius = (bottom - top).length / 2;
circle = new Path.Circle(middle, radius);
circle.scale(vector.length / 100, 1);
circle.rotate(vector.angle, circle.center);
circle.fillColor = 'black';
innerCircle = circle.clone();
innerCircle.scale(0.5);
innerCircle.fillColor = (count % blinkTime < 3)
|| (count % (blinkTime + 5) < 3) ? 'black' : 'white';
if (count % (blinkTime + 40) == 0)
blinkTime = Math.round(Math.random() * 40) + 200;
eye = circle.clone();
eye.position += eyePosition * radius;
eye.scale(0.15, innerCircle.position);
eye.fillColor = 'black';
headGroup = new Group(circle, innerCircle, eye);
}
return function(vector, event) {
var vector = (view.center - position) / 10;
if (vector.length < 5)
vector.length = 5;
count += vector.length / 100;
group.translate(vector);
var rotated = vector.rotate(90);
var middle = paths.length / 2;
for (var j = 0; j < paths.length; j++) {
var path = paths[j];
var nyanSwing = playing ? Math.sin(event.count / 2) * vector.length : 1;
var unitLength = vector.length * (2 + Math.sin(event.count / 10)) / 2;
var length = (j - middle) * unitLength + nyanSwing;
var top = view.center + rotated.normalize(length);
var bottom = view.center + rotated.normalize(length + unitLength);
path.add(top);
path.insert(0, bottom);
if (path.segments.length > 200) {
var index = Math.round(path.segments.length / 2);
path.segments[index].remove();
path.segments[index - 1].remove();
}
path.smooth();
}
createHead(vector, event.count);
if (mediaElement)
mediaElement.setVolume(vector.length / 200);
}
}
</script>
<style>
body {
background: black;
}
</style>
</head>
<body>
<audio id="nyan" src="http://dl.dropbox.com/u/31703/nyan.mp3" autoplay autobuffer preload=none loop style='display:none'></audio>
<canvas id="canvas" resize></canvas>
</body>
</html>

View file

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Q*bertify</title>
<link rel="stylesheet" href="../css/style.css">
<script type="text/javascript" src="../../dist/paper.js"></script>
<script type="text/paperscript" canvas="canvas">
// Please note: dragging and dropping images only works for
// certain browsers when serving this script online:
var values = {
amount: 30
};
var raster, group;
var piece = createPiece();
var count = 0;
handleImage('mona');
var text = new PointText({
point: view.center,
justification: 'center',
fillColor: 'white',
fontSize: 15,
content: window.FileReader
? 'Drag & drop an image from your desktop'
: 'To drag & drop images, please use Webkit, Firefox, Chrome or IE 10'
});
function createPiece() {
var group = new Group();
var hexagon = new Path.RegularPolygon(view.center, 6, 50);
hexagon.fillColor = 'gray';
group.addChild(hexagon);
for (var i = 0; i < 2; i++) {
var path = new Path();
for (var j = 0; j < 3; j++) {
var index = (i * 2 + j) % hexagon.segments.length;
path.add(hexagon.segments[index].clone());
}
path.add(hexagon.bounds.center);
path.closed = true;
path.selected = true;
group.addChild(path);
}
group.children[1].fillColor = 'white';
group.lastChild.fillColor = 'black';
// Remove the group from the document, so it is not drawn:
group.remove();
return group;
}
function handleImage(image) {
count = 0;
var size = piece.bounds.size;
if (group)
group.remove();
raster = new Raster(image);
raster.remove();
// Transform the raster, so it fills the view:
raster.fitBounds(view.bounds, true);
group = new Group();
for (var y = 0; y < values.amount; y++) {
for (var x = 0; x < values.amount; x++) {
var copy = piece.clone();
copy.position += size * [x + (y % 2 ? 0.5 : 0), y * 0.75];
group.addChild(copy);
}
}
// Transform the group so it covers the view:
group.fitBounds(view.bounds, true);
group.scale(1.1);
}
function onFrame(event) {
// Loop through the hexagons in the group and fill them with the
// average color:
var length = Math.min(count + values.amount, group.children.length);
for (var i = count; i < length; i++) {
piece = group.children[i];
var hexagon = piece.children[0];
var color = raster.getAverageColor(hexagon);
if (color) {
hexagon.fillColor = color;
// hexagon.strokeColor = color;
var top = piece.children[1];
top.fillColor = color.clone();
top.fillColor.brightness *= 1.5;
var right = piece.children[2];
right.fillColor = color.clone();
right.fillColor.brightness *= 0.5;
}
}
count += values.amount;
}
function onResize() {
project.activeLayer.position = view.center;
}
function onDocumentDrag(event) {
event.preventDefault();
}
function onDocumentDrop(event) {
event.preventDefault();
var file = event.dataTransfer.files[0];
var reader = new FileReader();
reader.onload = function ( event ) {
var image = document.createElement('img');
image.onload = function () {
handleImage(image);
view.draw();
};
image.src = event.target.result;
};
reader.readAsDataURL(file);
}
DomEvent.add(document, {
drop: onDocumentDrop,
dragover: onDocumentDrag,
dragleave: onDocumentDrag
});
</script>
</head>
<body>
<canvas id="canvas" resize></canvas>
</body>
</html>

View file

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Voronoi</title>
<link rel="stylesheet" href="../css/style.css">
<script type="text/javascript" src="../../dist/paper.js"></script>
<script type="text/javascript" src="http://jonathanpuckey.com/static/rhill-voronoi-core.js"></script>
<script type="text/paperscript" canvas="canvas">
var voronoi = new Voronoi();
var sites = generateBeeHivePoints(view.size / 200, true);
var bbox, diagram;
var oldSize = view.size;
var spotColor = new Color('red');
var mousePos = view.center;
var selected = false;
onResize();
function onMouseDown(event) {
sites.push(event.point);
renderDiagram();
}
function onMouseMove(event) {
mousePos = event.point;
if (event.count == 0)
sites.push(event.point);
sites[sites.length - 1] = event.point;
renderDiagram();
}
function renderDiagram() {
project.activeLayer.children = [];
var diagram = voronoi.compute(sites, bbox);
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, sites[i]);
}
}
}
}
}
function removeSmallBits(path) {
var averageLength = path.length / path.segments.length;
var min = path.length / 50;
for(var i = path.segments.length - 1; i >= 0; i--) {
var segment = path.segments[i];
var cur = segment.point;
var nextSegment = segment.next;
var next = nextSegment.point + nextSegment.handleIn;
if (cur.getDistance(next) < min) {
segment.remove();
}
}
}
function generateBeeHivePoints(size, loose) {
var points = [];
var col = view.size / size;
for(var i = -1; i < size.width + 1; i++) {
for(var j = -1; j < size.height + 1; j++) {
var point = new Point(i, j) / new Point(size) * view.size + col / 2;
if(j % 2)
point += new Point(col.width / 2, 0);
if(loose)
point += (col / 4) * Point.random() - col / 4;
points.push(point);
}
}
return points;
}
function createPath(points, center) {
var path = new Path();
if (!selected) {
path.fillColor = spotColor;
} else {
path.fullySelected = selected;
}
path.closed = true;
for (var i = 0, l = points.length; i < l; i++) {
var point = points[i];
var next = points[(i + 1) == points.length ? 0 : i + 1];
var vector = (next - point) / 2;
path.add({
point: point + vector,
handleIn: -vector,
handleOut: vector
});
}
path.scale(0.95);
removeSmallBits(path);
return path;
}
function onResize() {
var margin = 20;
bbox = {
xl: margin,
xr: view.bounds.width - margin,
yt: margin,
yb: view.bounds.height - margin
};
for (var i = 0, l = sites.length; i < l; i++) {
sites[i] = sites[i] * view.size / oldSize;
}
oldSize = view.size;
renderDiagram();
}
function onKeyDown(event) {
if (event.key == 'space') {
selected = !selected;
renderDiagram();
}
}
</script>
</head>
<body>
<canvas id="canvas" resize></canvas>
</body>
</html>