Skip to content

Instantly share code, notes, and snippets.

@edeetee
Forked from dribnet/.block
Last active September 27, 2018 11:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save edeetee/2344d8b867fb4f69093d1934894c14d1 to your computer and use it in GitHub Desktop.
Save edeetee/2344d8b867fb4f69093d1934894c14d1 to your computer and use it in GitHub Desktop.
17.2.MDDN342 PS4
license: mit
height: 720

Vapor Pipes

In this work, I was trying to go for a similar aesthetic to the classic windows 95 screensavers, such as pipes. It was a requirement for this wallpaper to have some kind of ambient animation, so I changed the rendering code to allow the individual p5 canvases to update. While experimenting with things moving across the screen, I came to a point where I could represent the perlin noise that we were exploring through detail changing it's representation at different levels. This was especially represented through my animations, where at close levels you can see the noise moving across the elements over time. It was at this point that I came to the realisation that I was very much going towards a vaporwave style, a style deep in nostalgia for the 90s and the experience of the internet back then.

From there, I decided to replace my palette with colors that are often found in this genre (vaporwave is also a music genre) and started playing around with using some of the text assets often seen in vaporwave music videos at the closest levels. If you look close enough, you should be able to find a caption that is spinning around

/*
* This is the funciton to implement to make your own abstract design.
*
* arguments:
* p5: the p5.js object - all draw commands should be prefixed with this object
* x1, x2, y1, y2: draw the pattern contained in the rectangle x1,y1 to x2, y2
* z: use this as the noise z offset (can be shifted)
* zoom: current zoom level (starts at 0), useful to decide how much detail to draw
*
* The destination drawing should be in the square 0, 0, 255, 255.
*/
var amount = 1;
var maxLevel = 2;
var colors = [
"#ff71ce",
"#01cdfe",
"#05ffa1",
"#b967ff",
"#8694E7"
]
shuffle(colors)
var vaporWords = [
"jazz cabbage", "JAZZ", "vapor", "euphoria", "pepsi c r y s t a l", "無用漢字", "A E S T H E T I C", "wave", "情報デスク", "VIRTUAL",
"AOL", "Netscape", "TOKYO", "Windows95", "ultra", ".js", "Explorer"
]
/* TOUR VARIABLES (required)
/* the random number seed for the tour */
var tourSeed = 99;
/* triplets of locations: zoom, x, y */
var tourPath = [
[0, 631, 3872],
[1, 637, 3858],
[2, 590, 3786],
[3, 602, 3755],
[4, 599, 3755],
[5, 597, 3756],
[10, 594, 3758]
]
/* OPTIONAL VARIABLES */
/* what is the initial zoom level (defaults to 0) */
// var initialZoomLevel = 3;
/* what is the maximum zoom level (make this at least 10. defaults to 16) */
var maxZoomLevel = 10;
/**
* @param {p5} p
* @param {Number} x1
* @param {Number} x2
* @param {Number} y1
* @param {Number} y2
* @param {Number} z
* @param {Number} zoom
*/
function drawGrid(p, x1, x2, y1, y2, z, zoom, level) {
level = level || 0
zoom = zoom || 0
if(level == 0){
p.background(0, 0, 100, 0.1)
p.noFill();
p.colorMode(p.HSB)
p.ellipseMode(p.CORNER)
p.rectMode(p.CORNER)
p.strokeCap(p.ROUND)
p.textAlign(p.CENTER)
p.textFont("ArialBlack")
}
//render lower levels
if(level < maxLevel){
for(let x = 0; x < 2; x++){
for(let y = 0; y < 2; y++){
p.push()
p.translate(255*x/2, 255*y/2)
p.scale(0.5)
drawGrid(p,
p.map(x, 0, 2, x1, x2),
p.map(x+1, 0, 2, x1, x2),
p.map(y, 0, 2, y1, y2),
p.map(y+1, 0, 2, y1, y2),
z, zoom+1, level+1)
p.translate(-255*x/2, -255*y/2)
p.pop()
}
}
}
// debug - show border
var noiseScale=0.02;
let scale = (x2-x1)/255
var padding = level == 0 ? 5 : 1;
let min = padding;
let max = 255-padding;
function padMap(p){
return min + p*(max-min)
}
let depth = level/maxLevel;
let color = p.color(colors[zoom%colors.length])
color.a = 1-depth*0.9;
p.stroke(color)
p.strokeWeight(10)
function drawCurves(lines){
let positions = [
[0, 0], [0, 0.5], [0, 1], [0.5, 1], [1, 1], [1, 0.5], [1, 0], [0.5, 0]
].map(function(pos){
pos = pos.map(padMap)
return p.createVector(pos[0], pos[1])
})
for(let i = 0; i < lines; i++){
let typeNoise = p.noise(5123+x1*noiseScale, 126+y1*noiseScale, i)
let posI = p.floor(typeNoise*positions.length)
let pos = positions[posI];
positions.splice(posI, 1);
//draw from center to point
drawCurve(drawSine(p.createVector(padMap(0.5), padMap(0.5)), pos))
}
}
let linesNoise = p.noise(x1*noiseScale, y1*noiseScale);
//draw the generated lines
drawCurves(p.floor(linesNoise*linesNoise*8))
//draw the text
let jazzNoise = p.noise(x1*zoom*123566.8, y1*zoom*123096);
if(jazzNoise < p.min(0.03*zoom, 0.2)){
p.push();
p.fill(0,0,0)
p.textSize(10 + 20*p.noise(x1*123, y1*451))
p.noStroke()
p.textStyle(p.noise(x1*99, y1*1001) < 0.5 ? p.NORMAL : p.ITALIC)
p.translate(255/2, 255/2);
p.rotate((p.noise(x1*1564123, y1*673212) < 0.2) ? p.millis()/10000*p.TWO_PI : 0);
let word = vaporWords[p.floor(p.noise(x1*100, y1*100)*vaporWords.length)];
p.text(word, 0, 0);
p.pop();
}
//generate the sine save over points
function drawSine(start, end){
var offDir = p5.Vector.fromAngle(start.angleBetween(end))
offDir.mult(80)
return fillArray(8-4*depth, 0).map((val, i, arr) => {
let prog = (-1+i)/(arr.length-3);
let v = p5.Vector.lerp(start, end, prog)
let offset = (-1 + 2*p.noise(
(x1 + v.x*scale)*noiseScale,
(y1 + v.y*scale)*noiseScale,
p.millis()/2000))
//neutralize at edges
offset *= p.sin(v.x/255*v.x/255*p.PI) * p.sin(v.y/255*v.y/255*p.PI)
// let offset = 80 * p.sin(x1*y1 + scale*prog*p.TWO_PI + scale*p.millis()/5000*p.TWO_PI)
v.add(p5.Vector.mult(offDir, offset));
return v;
})
}
//draw a list of points to a curve
function drawCurve(points){
p.beginShape()
for(let i = 0; i < points.length; i++){
let point = points[i.mod(points.length)]
p.curveVertex(point.x, point.y)
}
p.endShape()
}
}
/**
*
* @param {number} n
* @param {*} val
*/
function fillArray(n, val){
let array = []
for(let i = 0; i<n; i++){
array.push(val || i)
}
return array;
}
//mod helper
Number.prototype.mod = function(y){
return this - y * Math.floor(this / y)
}
/**
* Shuffles array in place.
* @param {Array} a items An array containing the items.
*/
function shuffle(a) {
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
}
/* This is an example of 10print translated into the PS4 framework */
var blue = "#0000AA"
var light_blue = "#0088FF"
function drawLayer(p5, slashsize, x1, x2, y1, y2, z) {
var noiseScale=1/16.0;
var startx = slashsize * (Math.floor(x1/slashsize) - 1);
var starty = slashsize * (Math.floor(y1/slashsize) - 1);
var endx = slashsize * (Math.floor(x2/slashsize) + 1);
var endy = slashsize * (Math.floor(y2/slashsize) + 1);
var char_width = 256 / ((x2-x1)/slashsize);
var char_height = 256 / ((y2-y1)/slashsize);
var pixel_width = char_width / 8;
var pixel_height = char_height / 8;
p5.strokeWeight(pixel_width);
for(var x=startx; x<endx; x+=slashsize) {
var n_x = x / slashsize;
var x_pos = p5.map(x, x1, x2, 0, 256);
for(var y=starty; y<endy; y+=slashsize) {
var n_y = y / slashsize;
var y_pos = p5.map(y, y1, y2, 0, 256);
var noiseValue = p5.noise(x * noiseScale, y * noiseScale, z);
if (noiseValue < 0.5) {
p5.line(x_pos, y_pos, x_pos+char_width, y_pos+char_height);
}
else {
p5.line(x_pos, y_pos+char_height, x_pos+char_width, y_pos);
}
}
}
}
function drawGrid(p5, x1, x2, y1, y2, z, zoom) {
p5.noiseDetail(8,0.5);
p5.background(blue);
p5.stroke(light_blue);
drawLayer(p5, 16, x1, x2, y1, y2, z);
}
var max_thickness = 64;
var max_movement = 32;
var ball_radius = 32;
var line_width = 8;
var grid_size = 64;
function getOffsetPoint(p5, x, y, z, noiseScale) {
var noiseX = p5.noise(x * noiseScale,
y * noiseScale, z);
var noiseY = p5.noise(x * noiseScale,
y * noiseScale, z+50);
var offsetX = p5.map(noiseX, 0, 1, -max_movement, max_movement);
var offsetY = p5.map(noiseY, 0, 1, -max_movement, max_movement);
return [x+offsetX, y+offsetY]
}
function snap_to_grid(num, gsize) {
return (num - (num % gsize));
}
/*
* This is the funciton to implement to make your own abstract design.
*
* arguments:
* p5: the p5.js object - all draw commands should be prefixed with this object
* x1, x2, y1, y2: draw the pattern contained in the rectangle x1,y1 to x2, y2
* z: use this as the noise z offset (can be shifted)
* zoom: current zoom level (starts at 0), useful to decide how much detail to draw
*
* The destination drawing should be in the square 0, 0, 255, 255.
*/
function drawGrid(p5, x1, x2, y1, y2, z, zoom) {
// debug - show border
var max_shift = max_thickness + max_movement;
var min_x = snap_to_grid(x1 - max_shift, grid_size);
var max_x = snap_to_grid(x2 + max_shift + grid_size, grid_size);
var min_y = snap_to_grid(y1 - max_shift, grid_size);
var max_y = snap_to_grid(y2 + max_shift + grid_size, grid_size);
var c_p00 = p5.map(0, x1, x2, 0, 256);
var c_plwidth = p5.map(line_width, x1, x2, 0, 256);
var c_pball = p5.map(ball_radius, x1, x2, 0, 256);
var cur_line_width = c_plwidth - c_p00;
var cur_ball_radius = c_pball - c_p00;
p5.background(255);
p5.fill(0, 0, 128);
for(var x=min_x; x<max_x; x+=grid_size) {
for(var y=min_y; y<max_y; y+=grid_size) {
var shift_point = getOffsetPoint(p5, x, y, z, 0.1);
var x_pos = p5.map(shift_point[0], x1, x2, 0, 256);
var y_pos = p5.map(shift_point[1], y1, y2, 0, 256);
p5.strokeWeight(cur_line_width);
p5.stroke(0, 0, 128);
var shift_point2 = getOffsetPoint(p5, x+grid_size, y, z, 0.1);
var x_pos2 = p5.map(shift_point2[0], x1, x2, 0, 256);
var y_pos2 = p5.map(shift_point2[1], y1, y2, 0, 256);
p5.line(x_pos, y_pos, x_pos2, y_pos2);
p5.stroke(0, 128, 0);
var shift_point2 = getOffsetPoint(p5, x, y+grid_size, z, 0.1);
var x_pos2 = p5.map(shift_point2[0], x1, x2, 0, 256);
var y_pos2 = p5.map(shift_point2[1], y1, y2, 0, 256);
p5.line(x_pos, y_pos, x_pos2, y_pos2);
p5.noStroke();
p5.ellipse(x_pos, y_pos, cur_ball_radius);
}
}
}
var max_thickness = 64;
var max_movement = 32;
var ball_radius = 32;
var line_width = 8;
var grid_size = 64;
/* the random number seed for the tour */
var tourSeed = 301;
/* triplets of locations: zoom, x, y */
var tourPath = [
[1, 356.500000000000, 665.750000000000],
[3, 353.250000000000, 668.187500000000],
[4, 322.562500000000, 645.093750000000],
[5, 322.562500000000, 645.109375000000],
[7, 317.984375000000, 643.636718750000],
[3, 317.984375000000, 643.636718750000]
]
function getOffsetPoint(p5, x, y, z, noiseScale) {
var noiseX = p5.noise(x * noiseScale,
y * noiseScale, z);
var noiseY = p5.noise(x * noiseScale,
y * noiseScale, z+50);
var offsetX = p5.map(noiseX, 0, 1, -max_movement, max_movement);
var offsetY = p5.map(noiseY, 0, 1, -max_movement, max_movement);
return [x+offsetX, y+offsetY]
}
function snap_to_grid(num, gsize) {
return (num - (num % gsize));
}
function drawPetals(p5, x1, x2, y1, y2, pos_x, pos_y, rad1, rad2) {
var offsets = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0]
]
var pixel_posx1 = p5.map(pos_x, x1, x2, 0, 256);
var pixel_posx2 = p5.map(pos_x+rad2, x1, x2, 0, 256);
var pixel_radius = pixel_posx2 - pixel_posx1;
for(var i=0; i<offsets.length; i++) {
var offset = offsets[i];
var pixel_x = p5.map(pos_x+0.5*rad1*offset[0], x1, x2, 0, 256);
var pixel_y = p5.map(pos_y+0.5*rad1*offset[1], y1, y2, 0, 256);
p5.ellipse(pixel_x, pixel_y, pixel_radius);
}
}
function drawStamens(p5, x1, x2, y1, y2, pos_x, pos_y, rad1, rad2, drawLines) {
var offsets = [
[1, 1],
[1, -1],
[-1, 1],
[-1, -1]
]
var pixel_posx1 = p5.map(pos_x, x1, x2, 0, 256);
var pixel_posx2 = p5.map(pos_x+rad2, x1, x2, 0, 256);
var pixel_radius = pixel_posx2 - pixel_posx1;
for(var i=0; i<offsets.length; i++) {
var offset = offsets[i];
var pixel_x = p5.map(pos_x+0.5*rad1*offset[0], x1, x2, 0, 256);
var pixel_y = p5.map(pos_y+0.5*rad1*offset[1], y1, y2, 0, 256);
p5.strokeWeight(0);
p5.ellipse(pixel_x, pixel_y, pixel_radius);
if(drawLines) {
p5.strokeWeight(pixel_radius / 20);
p5.line(pixel_x-pixel_radius, pixel_y, pixel_x+pixel_radius, pixel_y);
p5.line(pixel_x, pixel_y-pixel_radius, pixel_x, pixel_y+pixel_radius);
p5.strokeWeight(0);
p5.ellipse(pixel_x, pixel_y, pixel_radius / 12);
}
}
}
/*
* This is the funciton to implement to make your own abstract design.
*
* arguments:
* p5: the p5.js object - all draw commands should be prefixed with this object
* x1, x2, y1, y2: draw the pattern contained in the rectangle x1,y1 to x2, y2
* z: use this as the noise z offset (can be shifted)
* zoom: current zoom level (starts at 0), useful to decide how much detail to draw
*
* The destination drawing should be in the square 0, 0, 255, 255.
*/
function drawGrid(p5, x1, x2, y1, y2, z, zoom) {
// debug - show border
var max_shift = max_thickness + max_movement;
var min_x = snap_to_grid(x1 - max_shift, grid_size);
var max_x = snap_to_grid(x2 + max_shift + grid_size, grid_size);
var min_y = snap_to_grid(y1 - max_shift, grid_size);
var max_y = snap_to_grid(y2 + max_shift + grid_size, grid_size);
var c_p00 = p5.map(0, x1, x2, 0, 256);
var c_plwidth = p5.map(line_width, x1, x2, 0, 256);
var c_pball = p5.map(ball_radius, x1, x2, 0, 256);
var cur_line_width = c_plwidth - c_p00;
var cur_ball_radius = c_pball - c_p00;
p5.background(255);
for(var x=min_x; x<max_x; x+=grid_size) {
for(var y=min_y; y<max_y; y+=grid_size) {
var shift_point = getOffsetPoint(p5, x, y, z, 0.1);
var x_pos = p5.map(shift_point[0], x1, x2, 0, 256);
var y_pos = p5.map(shift_point[1], y1, y2, 0, 256);
p5.strokeWeight(cur_line_width);
p5.stroke(0, 128, 0);
var shift_point2 = getOffsetPoint(p5, x+grid_size, y, z, 0.1);
var x_pos2 = p5.map(shift_point2[0], x1, x2, 0, 256);
var y_pos2 = p5.map(shift_point2[1], y1, y2, 0, 256);
p5.line(x_pos, y_pos, x_pos2, y_pos2);
var shift_point2 = getOffsetPoint(p5, x, y+grid_size, z, 0.1);
var x_pos2 = p5.map(shift_point2[0], x1, x2, 0, 256);
var y_pos2 = p5.map(shift_point2[1], y1, y2, 0, 256);
p5.line(x_pos, y_pos, x_pos2, y_pos2);
p5.noStroke();
// if zoomed: first, draw petals *behind* the ellipse
if(zoom >= 3) {
p5.fill(0, 0, 255);
drawPetals(p5, x1, x2, y1, y2, shift_point[0], shift_point[1], ball_radius, line_width);
}
// draw ellipse
p5.fill(0, 0, 128);
p5.ellipse(x_pos, y_pos, cur_ball_radius);
// if zoomed: last draw stamens *in front of* the ellipse
if(zoom >= 3) {
// now if we are super zoomed, draw lines in the stamen
var drawLines = false;
if (zoom >= 5) drawLines = true;
p5.fill(0, 0, 255);
p5.stroke(0, 0, 128);
drawStamens(p5, x1, x2, y1, y2, shift_point[0], shift_point[1], ball_radius/3, line_width/2, drawLines);
}
}
}
}
/*
* This is the funciton to implement to make your own abstract design.
*
* arguments:
* p5: the p5.js object - all draw commands should be prefixed with this object
* x1, x2, y1, y2: draw the pattern contained in the rectangle x1,y1 to x2, y2
* z: use this as the noise z offset (can be shifted)
* zoom: current zoom level (starts at 0), useful to decide how much detail to draw
*
* The destination drawing should be in the square 0, 0, 255, 255.
*/
// This version draws two rectangles and two ellipses.
// The rectangles are 960x720 and centered at 512,512.
function drawGrid(p5, x1, x2, y1, y2, z, zoom) {
console.log(y1, y2);
p5.background(255);
p5.rectMode(p5.CORNERS);
// The first red rectangle fills the entire space
var cx = p5.map(512-960/2, x1, x2, 0, 256);
var cy = p5.map(512-720/2, y1, y2, 0, 256);
var cx2 = p5.map(512+960/2, x1, x2, 0, 256);
var cy2 = p5.map(512+720/2, y1, y2, 0, 256);
p5.fill(255, 0, 0);
p5.rect(cx, cy, cx2, cy2);
// The second black rectangle is inset to form a frame inset by 20 units
cx = p5.map(512-940/2, x1, x2, 0, 256);
cy = p5.map(512-700/2, y1, y2, 0, 256);
cx2 = p5.map(512+940/2, x1, x2, 0, 256);
cy2 = p5.map(512+700/2, y1, y2, 0, 256);
p5.fill(0);
p5.rect(cx, cy, cx2, cy2);
// Two ellipses with a radius of 50 units are then added.
var cx = p5.map(512, x1, x2, 0, 256);
var cy = p5.map(512, y1, y2, 0, 256);
var cx2 = p5.map(512+50, x1, x2, 0, 256);
p5.fill(0, 0, 255);
p5.ellipse(cx, cy, (cx2-cx));
// The second green ellipse is above and to the left of the first one.
var cx = p5.map(412, x1, x2, 0, 256);
var cy = p5.map(412, y1, y2, 0, 256);
var cx2 = p5.map(412+50, x1, x2, 0, 256);
p5.fill(0, 255, 0);
p5.ellipse(cx, cy, (cx2-cx));
}
/*
* This is the funciton to implement to make your own abstract design.
*
* arguments:
* p5: the p5.js object - all draw commands should be prefixed with this object
* x1, x2, y1, y2: draw the pattern contained in the rectangle x1,y1 to x2, y2
* z: use this as the noise z offset (can be shifted)
* zoom: current zoom level (starts at 0), useful to decide how much detail to draw
*
* The destination drawing should be in the square 0, 0, 255, 255.
*/
/* TOUR VARIABLES (required)
/* the random number seed for the tour */
var tourSeed = 100;
/* triplets of locations: zoom, x, y */
var tourPath = [
[5, 510, 507],
[7, 507, 506],
[3, 512, 515],
[1, 512, 512]
]
/* OPTIONAL VARIABLES */
/* what is the initial zoom level (defaults to 0) */
var initialZoomLevel = 3;
/* what is the maximum zoom level (make this at least 10. defaults to 16) */
var maxZoomLevel = 12;
function drawPetals(p5, x1, x2, y1, y2, pos_x, pos_y, rad1, rad2) {
var offsets = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0]
]
var pixel_posx1 = p5.map(pos_x, x1, x2, 0, 256);
var pixel_posx2 = p5.map(pos_x+rad2, x1, x2, 0, 256);
var pixel_radius = pixel_posx2 - pixel_posx1;
for(var i=0; i<offsets.length; i++) {
var offset = offsets[i];
var pixel_x = p5.map(pos_x+0.5*rad1*offset[0], x1, x2, 0, 256);
var pixel_y = p5.map(pos_y+0.5*rad1*offset[1], y1, y2, 0, 256);
p5.ellipse(pixel_x, pixel_y, pixel_radius);
}
}
function drawStamens(p5, x1, x2, y1, y2, pos_x, pos_y, rad1, rad2, drawLines) {
var offsets = [
[1, 1],
[1, -1],
[-1, 1],
[-1, -1]
]
var pixel_posx1 = p5.map(pos_x, x1, x2, 0, 256);
var pixel_posx2 = p5.map(pos_x+rad2, x1, x2, 0, 256);
var pixel_radius = pixel_posx2 - pixel_posx1;
for(var i=0; i<offsets.length; i++) {
var offset = offsets[i];
var pixel_x = p5.map(pos_x+0.5*rad1*offset[0], x1, x2, 0, 256);
var pixel_y = p5.map(pos_y+0.5*rad1*offset[1], y1, y2, 0, 256);
p5.strokeWeight(0);
p5.ellipse(pixel_x, pixel_y, pixel_radius);
if(drawLines) {
p5.strokeWeight(pixel_radius / 20);
p5.line(pixel_x-pixel_radius, pixel_y, pixel_x+pixel_radius, pixel_y);
p5.line(pixel_x, pixel_y-pixel_radius, pixel_x, pixel_y+pixel_radius);
p5.strokeWeight(0);
p5.ellipse(pixel_x, pixel_y, pixel_radius / 12);
}
}
}
// This version draws two rectangles and two ellipses.
// The rectangles are 960x720 and centered at 512,512.
function drawGrid(p5, x1, x2, y1, y2, z, zoom) {
p5.background(255);
p5.rectMode(p5.CORNERS);
// The first red rectangle fills the entire space
var cx = p5.map(512-960/2, x1, x2, 0, 256);
var cy = p5.map(512-720/2, y1, y2, 0, 256);
var cx2 = p5.map(512+960/2, x1, x2, 0, 256);
var cy2 = p5.map(512+720/2, y1, y2, 0, 256);
p5.fill(255, 0, 0);
p5.rect(cx, cy, cx2, cy2);
// The second black rectangle is inset to form a frame inset by 20 units
cx = p5.map(512-940/2, x1, x2, 0, 256);
cy = p5.map(512-700/2, y1, y2, 0, 256);
cx2 = p5.map(512+940/2, x1, x2, 0, 256);
cy2 = p5.map(512+700/2, y1, y2, 0, 256);
p5.fill(0);
p5.rect(cx, cy, cx2, cy2);
// Two ellipses with a radius of 50 units are then added.
// start with the center dot --
// if zoomed: first, draw petals *behind* the ellipse
if(zoom >= 3) {
p5.fill(0, 128, 128);
drawPetals(p5, x1, x2, y1, y2, 512, 512, 50, 10);
}
// first, draw a blue
var cx = p5.map(512, x1, x2, 0, 256);
var cy = p5.map(512, y1, y2, 0, 256);
var cx2 = p5.map(512+50, x1, x2, 0, 256);
p5.fill(0, 0, 255);
p5.ellipse(cx, cy, (cx2-cx));
// if zoomed: last draw stamens *in front of* the ellipse
if(zoom >= 3) {
// now if we are super zoomed, draw lines in the stamen
var drawLines = false;
if (zoom >= 5) drawLines = true;
p5.fill(0, 128, 128);
p5.stroke(0, 0, 255);
drawStamens(p5, x1, x2, y1, y2, 512, 512, 10, 8, drawLines);
}
// The second green ellipse is above and to the left of the first one.
var cx = p5.map(412, x1, x2, 0, 256);
var cy = p5.map(412, y1, y2, 0, 256);
var cx2 = p5.map(412+50, x1, x2, 0, 256);
p5.fill(0, 255, 0);
p5.ellipse(cx, cy, (cx2-cx));
}
function drawGrid(p5, x1, x2, y1, y2, z, zoom) {
var noiseScale=0.02;
p5.noiseDetail(8,0.5);
p5.noStroke();
for(var i=0; i<16; i++) {
var n_x = p5.map(i, 0, 16, x1, x2);
for(var j=0; j<16; j++) {
var n_y = p5.map(j, 0, 16, y1, y2);
var noiseVal = p5.noise(n_x * noiseScale,
n_y * noiseScale, z);
p5.fill(noiseVal*255);
p5.rect(i*16, j*16, 16, 16);
}
}
// debug - show border
// p5.noFill();
// p5.stroke(255, 0, 0)
// p5.rect(0, 0, 255, 255);
}
<!DOCTYPE html>
<meta charset="utf-8">
<title>framed version</title>
<div class="column">
<h3>960x720 preview</h3>
<div class="index">
<iframe sandbox="allow-popups allow-scripts allow-forms allow-same-origin" src="index.html" marginwidth="0" marginheight="0" style="width:960px;height:720px;" scrolling="no"></iframe>
</div>
</div>
<!DOCTYPE html>
<html>
<head>
<title>17.2.MDDN342 PS4</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
width: 100%;
background-color: white;
}
.leaflet-control-attribution {
font-size: 24px !important;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/addons/p5.dom.js"></script>
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script>
<script src="leaflet-hash.js"></script>
<script src="drawgrid.js"></script>
<script src="map.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>17.2.MDDN342 PS4</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/addons/p5.dom.js"></script>
<script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script>
<script src="leaflet-hash.js"></script>
<script src="tinycolor.js"></script>
<script src="drawgrid.js"></script>
<script src="map.js"></script>
</body>
</html>
(function(window) {
var HAS_HASHCHANGE = (function() {
var doc_mode = window.documentMode;
return ('onhashchange' in window) &&
(doc_mode === undefined || doc_mode > 7);
})();
L.Hash = function(map) {
this.onHashChange = L.Util.bind(this.onHashChange, this);
if (map) {
this.init(map);
}
};
L.Hash.parseHash = function(hash) {
if(hash.indexOf('#') === 0) {
hash = hash.substr(1);
}
var args = hash.split("/");
if (args.length == 5) {
var seed = parseInt(args[0], 10),
zoom = parseInt(args[1], 10),
lat = parseFloat(args[2]),
lon = parseFloat(args[3]);
depth = parseFloat(args[4]);
if (isNaN(zoom) || isNaN(lat) || isNaN(lon)) {
return false;
} else {
return {
center: new L.LatLng(lat, lon),
zoom: zoom,
seed: seed,
depth: depth
};
}
} else {
return false;
}
};
L.Hash.formatHash = function(map) {
var seed = map._p5_seed,
depth = map._p5_depth,
center = map.getCenter(),
zoom = map.getZoom(),
precision = 12;
// precision = Math.max(0, Math.ceil(Math.log(zoom*zoom) / Math.LN2));
return "#" + [seed, zoom,
center.lat.toFixed(precision),
center.lng.toFixed(precision),
depth.toFixed(precision)
].join("/");
},
L.Hash.prototype = {
map: null,
lastHash: null,
parseHash: L.Hash.parseHash,
formatHash: L.Hash.formatHash,
init: function(map) {
this.map = map;
// reset the hash
this.lastHash = null;
this.onHashChange();
if (!this.isListening) {
this.startListening();
}
},
removeFrom: function(map) {
if (this.changeTimeout) {
clearTimeout(this.changeTimeout);
}
if (this.isListening) {
this.stopListening();
}
this.map = null;
},
onMapMove: function() {
// bail if we're moving the map (updating from a hash),
// or if the map is not yet loaded
if (this.movingMap || !this.map._loaded) {
return false;
}
var hash = this.formatHash(this.map);
if (this.lastHash != hash) {
location.replace(hash);
this.lastHash = hash;
}
},
movingMap: false,
update: function() {
var hash = location.hash;
if (hash === this.lastHash) {
return;
}
var parsed = this.parseHash(hash);
if (parsed) {
var do_reset = false;
if (!("_hash_parsed" in this.map)) {
do_reset = true;
}
this.map._hash_parsed = true;
this.map._p5_seed = parsed.seed;
this.map._p5_depth = parsed.depth;
this.movingMap = true;
this.map.setView(parsed.center, parsed.zoom, {reset: do_reset});
this.movingMap = false;
}
else if (!("_hash_parsed" in this.map)) {
this.map._hash_parsed = true;
var center = this.map.getCenter();
var zoom = this.map.getZoom();
this.map.setView(center, zoom, {reset: true});
}
else {
this.onMapMove(this.map);
}
},
// defer hash change updates every 100ms
changeDefer: 100,
changeTimeout: null,
onHashChange: function() {
// throttle calls to update() so that they only happen every
// `changeDefer` ms
if (!this.changeTimeout) {
var that = this;
this.changeTimeout = setTimeout(function() {
that.update();
that.changeTimeout = null;
}, this.changeDefer);
}
},
isListening: false,
hashChangeInterval: null,
startListening: function() {
this.map.on("moveend", this.onMapMove, this);
if (HAS_HASHCHANGE) {
L.DomEvent.addListener(window, "hashchange", this.onHashChange);
} else {
clearInterval(this.hashChangeInterval);
this.hashChangeInterval = setInterval(this.onHashChange, 50);
}
this.isListening = true;
},
stopListening: function() {
this.map.off("moveend", this.onMapMove, this);
if (HAS_HASHCHANGE) {
L.DomEvent.removeListener(window, "hashchange", this.onHashChange);
} else {
clearInterval(this.hashChangeInterval);
}
this.isListening = false;
}
};
L.hash = function(map) {
return new L.Hash(map);
};
L.Map.prototype.addHash = function() {
this._hash = L.hash(this);
};
L.Map.prototype.removeHash = function() {
this._hash.removeFrom();
};
})(window);
var myCRS = L.extend({}, L.CRS.Simple, {
transformation: new L.Transformation(1, 0,
// -1, // works like expected
1, // image travels while zooming
0)
});
if (typeof initialZoomLevel === 'undefined') {
var initialZoomLevel = 0;
}
if (typeof maxZoomLevel === 'undefined') {
var maxZoomLevel = 16;
}
var worldMap = new L.Map('map', {
continuousWorld:true,
minZoom: 0,
maxZoom: maxZoomLevel,
crs: myCRS,
attributionControl: false,
center: [512, 512],
zoom: initialZoomLevel});
worldMap._p5_seed = Math.floor(Math.random() * 1000);
worldMap._p5_depth = 0.0;
// console.log("Seed start", worldMap._p5_seed)
// Assuming your map instance is in a variable called map
var hash = new L.Hash(worldMap);
// console.log("Seed now", worldMap._p5_seed)
var s = function( p ) {
p.setup = function() {
canvas = p.createCanvas(p._L_width, p._L_height);
p.noLoop();
};
p.draw = function() {
if ("_L_size" in p && "_L_nw" in p) {
var nw = p._L_nw;
var t_size = p._L_size;
var zoom = p._L_zoom;
var m_x1 = nw.lng;
var m_y1 = nw.lat;
var m_x2 = m_x1 + t_size;
var m_y2 = m_y1 + t_size;
var depth = p._L_depth;
p.noiseSeed(p._L_seed)
drawGrid(p, m_x1, m_x2, m_y1, m_y2, depth, zoom);
}
};
};
var tiles = new L.GridLayer({continuousWorld: true});
tiles.createTile = function(coords) {
if (!("_hash_parsed" in worldMap)) {
return L.DomUtil.create('canvas', 'leaflet-tile');
}
var size = this.getTileSize();
var myp5 = new p5(s);
myp5._L_width = size.x;
myp5._L_height = size.y;
myp5._L_zoom = coords.z;
myp5._L_seed = worldMap._p5_seed;
myp5._L_depth = worldMap._p5_depth;
myp5._L_coords = coords;
// calculate projection coordinates of top left tile pixel
myp5._L_nwPoint = coords.scaleBy(size);
myp5._L_size = 256.0 / Math.pow(2, coords.z)
// calculate geographic coordinates of top left tile pixel
myp5._L_nw = worldMap.unproject(myp5._L_nwPoint, coords.z)
var tile = myp5.canvas;
tile.rendering = true;
(function doAnimate(){
if(tile.rendering){
myp5.redraw()
requestAnimationFrame(doAnimate)
}
})()
myp5._start();
tile.p5 = myp5
L.DomUtil.addClass(tile, 'leaflet-tile');
return tile;
}
tiles.on('tileunload', function(e){
e.tile.rendering = false;
})
// tiles.on('tileload', function(e){
// /** @type {HTMLCanvasElement} */
// var tile = e.tile
// /** @type {p5} */
// var p5 = tile.p5;
// if(p5){
// console.log(e)
// p5.redraw()
// }
// })
// setInterval(function(){
// if(!tiles.isLoading()){
// tiles.redraw()
// }
// }, 1000)
tiles.addTo(worldMap)
var curLinkIndex = 0;
linkHome = "#0/0/512/512/0"
if (typeof tourPath === 'undefined') {
var tourPath = [
[2, 512, 512],
[4, 512, 512],
[6, 512, 512],
[8, 512, 512]
]
}
tourPath.unshift([initialZoomLevel, 512, 512]);
if (typeof tourSeed === 'undefined') {
var tourSeed = 0;
}
function clickHome() {
worldMap.flyTo([tourPath[0][1], tourPath[0][2]], tourPath[0][0]);
}
function clickDemo() {
if(worldMap._p5_seed != tourSeed) {
var center = worldMap.getCenter();
var zoom = worldMap.getZoom();
worldMap._p5_seed = tourSeed;
tiles.redraw();
// worldMap.setView(center, zoom, {reset: true});
curLinkIndex = 0;
}
else {
curLinkIndex = (curLinkIndex + 1) % tourPath.length
}
var curDest = tourPath[curLinkIndex]
worldMap.flyTo([curDest[1], curDest[2]], curDest[0]);
}
function clickReset() {
window.location.reload();
}
attrib = new L.Control.Attribution
attrib.setPrefix("")
attrStr = '<a href="#" onclick="javascript:clickHome();">home</a> | '
attrStr += '<a href="#" onclick="javascript:clickReset();">reset</a> | '
attrStr += '<a href="#" onclick="javascript:clickDemo();">tour</a>'
attrib.addAttribution(attrStr)
worldMap.addControl(attrib)
{
"commits": [
{
"sha": "13bfd88b788201aeb20ad27509c35039dec8ac78",
"name": "final_version"
},
{
"name": "version 0.1",
"sha": "ff2a11b5b1889d643026a3a5195d8d882c85eff0"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment