This README explains the three different paramaterized faces for part2.
I still wanted to keep my abstract faces, and used if statements to change certain things about the eyes in my first face.
| license: mit |
| <head> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/addons/p5.dom.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.3/seedrandom.min.js"></script> | |
| <script src="https://d3js.org/d3-random.v1.min.js"></script> | |
| <script language="javascript" type="text/javascript" src="z_purview_helper.js"></script> | |
| <script language="javascript" type="text/javascript" src="sketch2.js"></script> | |
| <style> | |
| body { padding: 0; margin: 0; } | |
| .inner { position: absolute; } | |
| #controls { | |
| font: 300 12px "Helvetica Neue"; | |
| padding: 5; | |
| margin: 5; | |
| background: #f0f0f0; | |
| opacity: 0.0; | |
| -webkit-transition: opacity 0.2s ease; | |
| -moz-transition: opacity 0.2s ease; | |
| -o-transition: opacity 0.2s ease; | |
| -ms-transition: opacity 0.2s ease; | |
| } | |
| #controls:hover { opacity: 0.9; } | |
| </style> | |
| </head> | |
| <body style="background-color:white"> | |
| <div class="outer"> | |
| <div class="inner"> | |
| <div id="canvasContainer"></div> | |
| <a href="index1.html">part1</a> | |
| </div> | |
| <div class="inner" id="controls" height="500px"> | |
| <table> | |
| <tr> | |
| <td>Setting 1</td> | |
| <td id="slider1Container"></td> | |
| </tr> | |
| <tr> | |
| <td>Setting 2</td> | |
| <td id="slider2Container"></td> | |
| </tr> | |
| <tr> | |
| <td>Setting 3</td> | |
| <td id="slider3Container"></td> | |
| </tr> | |
| <tr> | |
| <td>Setting 4</td> | |
| <td id="slider4Container"></td> | |
| </tr> | |
| <tr> | |
| <td>Setting 5</td> | |
| <td id="slider5Container"></td> | |
| </tr> | |
| <tr> | |
| <td>Face</td> | |
| <td id="selector1Container"></td> | |
| </tr> | |
| </table> | |
| </div> | |
| </div> | |
| </table> | |
| </body> |
| <head> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/addons/p5.dom.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.3/seedrandom.min.js"></script> | |
| <script src="https://d3js.org/d3-random.v1.min.js"></script> | |
| <script language="javascript" type="text/javascript" src="z_purview_helper.js"></script> | |
| <script language="javascript" type="text/javascript" src="sketch.js"></script> | |
| <style> | |
| body { padding: 0; margin: 0; } | |
| .inner { position: absolute; } | |
| #controls { | |
| font: 300 12px "Helvetica Neue"; | |
| padding: 5; | |
| margin: 5; | |
| background: #f0f0f0; | |
| opacity: 0.0; | |
| -webkit-transition: opacity 0.2s ease; | |
| -moz-transition: opacity 0.2s ease; | |
| -o-transition: opacity 0.2s ease; | |
| -ms-transition: opacity 0.2s ease; | |
| } | |
| #controls:hover { opacity: 0.9; } | |
| </style> | |
| </head> | |
| <body style="background-color:white"> | |
| <div class="outer"> | |
| <div class="inner"> | |
| <div id="canvasContainer"></div> | |
| </div> | |
| <div class="inner" id="controls" height="500px"> | |
| <table> | |
| <tr> | |
| <td>(future interface here)</td> | |
| <td id="selector1Container"></td> | |
| </tr> | |
| </table> | |
| </div> | |
| </div> | |
| </table> | |
| </body> |
| const canvasWidth = 960; | |
| const canvasHeight = 500; | |
| function setup () { | |
| // create the drawing canvas, save the canvas element | |
| main_canvas = createCanvas(canvasWidth, canvasHeight); | |
| // position each element on the page | |
| main_canvas.parent('canvasContainer'); | |
| // rotation in degrees | |
| angleMode(DEGREES); | |
| } | |
| // global variables for colors | |
| const bg_color = "#1e0028"; | |
| const fg_color1 = "#eaadff"; | |
| const fg_color2 = "#8ce8ff"; | |
| const stroke_color = "#ffffff"; | |
| function draw () { | |
| // background color | |
| background(bg_color); | |
| // stroke color | |
| stroke(stroke_color) | |
| // move to position1 | |
| push(); | |
| translate(1000/4, 300/2); | |
| noFill(); | |
| stroke(stroke_color); | |
| strokeWeight(4); | |
| ellipse(0, -6, 20, 20); //left eye | |
| ellipse(80, -7, 20, 20); //right eye | |
| bezier(95, 5, 10, 5, 90, 90, 15, 120); //nose | |
| bezier(-30, 120, 30, 140, 60, 170, 100, 140); //mouth | |
| bezier(-5, 180, 10, 200, 30, 200, 45, 190); | |
| bezier(-40, -25, -30, 7, 0, 3, 20, 15); //eye underline | |
| pop(); | |
| // move to position2, rotate, draw "head" ellipse | |
| push(); | |
| translate(3*900/4, 300/2); | |
| noFill(); | |
| stroke(fg_color1); | |
| strokeWeight(2); | |
| bezier(-80, -25, -30, 10, 60, 10, 70, 160); //main line | |
| //"sketch" lines | |
| bezier(-80, -35, -30, 20, 50, 0, 70, 160); | |
| bezier(-80, -25, -30, 15, 70, 20, 65, 160); | |
| //left eye | |
| bezier(-110, 50, -90, 70, -70, 60, -50, 50); //main line | |
| //"sketch" lines | |
| bezier(-110, 50, -90, 70, -70, 65, -50, 55); | |
| bezier(-110, 55, -90, 70, -70, 60, -50, 50); | |
| //nose | |
| bezier(-50, 110, -10, 110, -20, 170, 30, 160); //main line | |
| //"sketch" lines | |
| bezier(-50, 115, -10, 110, -20, 170, 30, 155); | |
| //mouth | |
| bezier(20, 230, 50, 210, 60, 200, 120, 190); //main line | |
| //"sketch" lines | |
| bezier(20, 225, 50, 210, 60, 200, 120, 195); | |
| pop(); | |
| } | |
| function keyTyped() { | |
| if (key == '!') { | |
| saveBlocksImages(); | |
| } | |
| else if (key == '@') { | |
| saveBlocksImages(true); | |
| } | |
| } |
| var canvasWidth = 960; | |
| var canvasHeight = 500; | |
| var slider1, slider2, slider3, slider4, slider5; | |
| var faceSelector; | |
| function setup () { | |
| // create the drawing canvas, save the canvas element | |
| var main_canvas = createCanvas(canvasWidth, canvasHeight); | |
| main_canvas.parent('canvasContainer'); | |
| // create sliders | |
| slider1 = createSlider(0, 100, 50); | |
| slider2 = createSlider(0, 100, 50); | |
| slider3 = createSlider(0, 100, 50); | |
| slider4 = createSlider(0, 100, 50); | |
| slider5 = createSlider(0, 100, 50); | |
| slider1.parent('slider1Container'); | |
| slider2.parent('slider2Container'); | |
| slider3.parent('slider3Container'); | |
| slider4.parent('slider4Container'); | |
| slider5.parent('slider5Container'); | |
| faceSelector = createSelect(); | |
| faceSelector.option('1'); | |
| faceSelector.option('2'); | |
| faceSelector.option('3'); | |
| faceSelector.option('all') | |
| faceSelector.value('all'); | |
| faceSelector.parent('selector1Container'); | |
| // rotation in degrees | |
| angleMode(DEGREES); | |
| } | |
| // global variables for colors | |
| var bg_color1 = [50, 0, 81]; | |
| var bg_color2 = [0, 28, 81]; | |
| var bg_color3 = [81, 0, 46]; | |
| var fg_color1 = [239, 204, 255]; | |
| var fg_color2 = [255, 204, 242]; | |
| var fg_color3 = [204, 232, 255]; | |
| var stroke_color1 = [95, 52, 8]; | |
| var stroke_color2 = [210, 219, 189]; | |
| var stroke_color3 = [50, 50, 50]; | |
| var colorHair = [20, 20, 0]; | |
| function drawFace1(x, y, w, h, tilt_value, eye_value, mouth_value) { | |
| push(); | |
| translate(x, y); | |
| rotate(tilt_value); | |
| var extent = 0; | |
| if(h < w) { | |
| extent = h / 2; | |
| } | |
| else { | |
| extent = w / 2; | |
| } | |
| var scale = extent / 220.0; | |
| stroke(fg_color1); | |
| noFill(); | |
| strokeWeight(2); | |
| quad(-75, -100, 25, -50, 0, 63, -50, 5); //face | |
| // eyes | |
| if (eye_value === 1) { | |
| quad( 0, -80, 20, -90, 40, -80, 20, -70); | |
| quad( -60, -50, -40, -60, -20, -50, -40, -40); //left | |
| } | |
| if (eye_value == 2) { | |
| quad( -60, -50, -40, -60, -20, -50, -40, -40); //left | |
| quad( 0, -50, 20, -40, 40, -50, 20, -40); | |
| } | |
| if (eye_value == 3){ | |
| quad( 0, -50, 20, -40, 40, -50, 20, -40); | |
| quad( -60, -50, -40, -60, -20, -50, -40, -60); //left | |
| } | |
| // mouth | |
| fill(bg_color1); | |
| triangle(-30, 15, -20, 5, 0, 15); //top lip | |
| triangle(-15, 20, 15, 20, 5, 30); | |
| pop(); | |
| } | |
| function drawFace2(x, y, w, h, hair_value, eye_value, blink_value) { | |
| rectMode(CENTER); | |
| push(); | |
| translate(x, y); | |
| var extent = 0; | |
| if(h < w) { | |
| extent = h / 2; | |
| } | |
| else { | |
| extent = w / 2; | |
| } | |
| var scale = extent / 220.0; | |
| stroke(stroke_color3); | |
| fill(fg_color3); | |
| ellipse(0, 0, 300 * scale, 400 * scale); | |
| // eyes. first check for blinking | |
| if(blink_value > 0) { | |
| fill(bg_color3); | |
| ellipse(-50 * scale, -80 * scale, 50 * scale, 2 * scale); | |
| ellipse( 50 * scale, -80 * scale, 50 * scale, 2 * scale); | |
| } | |
| else { | |
| fill(bg_color3); | |
| ellipse(-50 * scale, -80 * scale, 50 * scale, 18 * scale); | |
| ellipse( 50 * scale, -80 * scale, 50 * scale, 18 * scale); | |
| fill(fg_color3); | |
| ellipse((-50 + eye_value) * scale, -80 * scale, 20 * scale, 20 * scale); | |
| ellipse(( 50 + eye_value) * scale, -80 * scale, 20 * scale, 20 * scale); | |
| } | |
| // mouth | |
| fill(bg_color3); | |
| ellipse(0 * scale, 70 * scale, 150 * scale, 20 * scale); | |
| // TODO: paramaterize hair | |
| var follicles = [ | |
| [346,138], | |
| [391,120], | |
| [391,67], | |
| [439,76], | |
| [463,42], | |
| [487,18], | |
| [481,101], | |
| [520,102], | |
| [520,78], | |
| [533,54], | |
| [560,108], | |
| [580,76], | |
| [596,124], | |
| [618,124] | |
| ]; | |
| resetMatrix(); | |
| fill(colorHair); | |
| var radius = hair_value * scale; | |
| for(var i=0; i<follicles.length; i++) { | |
| ellipse(240+follicles[i][0]/2, 120 + (follicles[i][1]/2), radius, radius); | |
| } | |
| rectMode(CORNER); | |
| resetMatrix(); | |
| } | |
| function drawFace3(x, y, w, h, width_value, eye_value, mouth_value) { | |
| push(); | |
| rectMode(CENTER); | |
| translate(x, y); | |
| // rotate(width_value); | |
| var extent = 0; | |
| if(h < w) { | |
| extent = h / 2; | |
| } | |
| else { | |
| extent = w / 2; | |
| } | |
| var scale = extent / 220.0; | |
| stroke(stroke_color2) | |
| fill(fg_color2); | |
| rect(0, 0, (300 + width_value) * scale, 400 * scale); | |
| // eyes | |
| if (eye_value === 1 || eye_value == 3) { | |
| fill(bg_color2); | |
| rect( 0, -80 * scale, 50 * scale, 30 * scale); | |
| fill(fg_color2); | |
| ellipse(-10 * scale, -80 * scale, 20 * scale, 20 * scale); | |
| } | |
| if (eye_value >= 2) { | |
| fill(bg_color2); | |
| rect(-60 * scale, -80 * scale, 50 * scale, 30 * scale); | |
| rect( 60 * scale, -80 * scale, 50 * scale, 30 * scale); | |
| fill(fg_color2); | |
| ellipse(-60 * scale, -80 * scale, 20 * scale, 20 * scale); | |
| ellipse( 60 * scale, -80 * scale, 20 * scale, 20 * scale); | |
| } | |
| // mouth | |
| fill(bg_color2); | |
| rect(0 * scale, 70 * scale, 150 * scale, mouth_value * scale); | |
| rectMode(CORNER); | |
| pop(); | |
| } | |
| function draw () { | |
| noStroke(); | |
| var mode = faceSelector.value(); | |
| if (mode != 'all') { | |
| if (mode == '1') { | |
| background(bg_color1); | |
| } | |
| else if (mode == '2') { | |
| background(bg_color2); | |
| } | |
| else if (mode == '3') { | |
| background(bg_color3); | |
| } | |
| } | |
| var s1 = slider1.value(); | |
| var s2 = slider2.value(); | |
| var s3 = slider3.value(); | |
| var s4 = slider4.value(); | |
| var s5 = slider5.value(); | |
| // use same size / y_pos for all faces | |
| var face_w = canvasWidth / 4; | |
| var face_h = face_w; | |
| var face_y = height / 2; | |
| var face_x = width / 2; | |
| if (mode == '1' || mode == 'all') { | |
| // draw 1st face | |
| fill(bg_color1); | |
| rect(0, 0, width/3, height); | |
| var tilt_value = map(s1, 0, 100, -90, 90); | |
| var mouth_value = map(s3, 0, 100, 0, 200); | |
| var eye_value = Math.floor(map(s2, 0, 100, 1, 3)); | |
| if (mode == 'all') { | |
| face_x = width / 6; | |
| } | |
| drawFace1(face_x, face_y, face_w, face_h, tilt_value, eye_value, mouth_value); | |
| } | |
| if (mode == '2' || mode == 'all') { | |
| // draw 2nd face | |
| fill(bg_color2); | |
| rect(width/3, 0, 2*width/3, height); | |
| var hair_value = map(s1, 0, 100, 2, 90); | |
| var blink_value = Math.floor(map(s3, 0, 100, 0, 1)); | |
| var eye_value = map(s2, 0, 100, -15, 15); | |
| if (mode == 'all') { | |
| face_x = 3 * width / 6; | |
| } | |
| drawFace2(face_x, face_y, face_w, face_h, hair_value, eye_value, blink_value); | |
| } | |
| if (mode == '3' || mode == 'all') { | |
| // draw 3nd face | |
| fill(bg_color3); | |
| rect(2*width/3, 0, width, height); | |
| var width_value = map(s1, 0, 100, 0, 100); | |
| var mouth_value = map(s3, 0, 100, 0, 200); | |
| var eye_value = Math.floor(map(s2, 0, 100, 0, 3)); | |
| if (mode == 'all') { | |
| face_x = 5 * width / 6; | |
| } | |
| drawFace3(face_x, face_y, face_w, face_h, width_value, eye_value, mouth_value); | |
| } | |
| } | |
| function keyTyped() { | |
| if (key == '!') { | |
| saveBlocksImages(); | |
| } | |
| else if (key == '@') { | |
| saveBlocksImages(true); | |
| } | |
| } |
| // note: this file is poorly named - it can generally be ignored. | |
| // helper functions below for supporting blocks/purview | |
| function saveBlocksImages(doZoom) { | |
| if(doZoom == null) { | |
| doZoom = false; | |
| } | |
| // generate 960x500 preview.jpg of entire canvas | |
| // TODO: should this be recycled? | |
| var offscreenCanvas = document.createElement('canvas'); | |
| offscreenCanvas.width = 960; | |
| offscreenCanvas.height = 500; | |
| var context = offscreenCanvas.getContext('2d'); | |
| // background is flat white | |
| context.fillStyle="#FFFFFF"; | |
| context.fillRect(0, 0, 960, 500); | |
| context.drawImage(this.canvas, 0, 0, 960, 500); | |
| // save to browser | |
| var downloadMime = 'image/octet-stream'; | |
| var imageData = offscreenCanvas.toDataURL('image/jpeg'); | |
| imageData = imageData.replace('image/jpeg', downloadMime); | |
| p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg'); | |
| // generate 230x120 thumbnail.png centered on mouse | |
| offscreenCanvas.width = 230; | |
| offscreenCanvas.height = 120; | |
| // background is flat white | |
| context = offscreenCanvas.getContext('2d'); | |
| context.fillStyle="#FFFFFF"; | |
| context.fillRect(0, 0, 230, 120); | |
| if(doZoom) { | |
| // pixelDensity does the right thing on retina displays | |
| var pd = this._pixelDensity; | |
| var sx = pd * mouseX - pd * 230/2; | |
| var sy = pd * mouseY - pd * 120/2; | |
| var sw = pd * 230; | |
| var sh = pd * 120; | |
| // bounds checking - just displace if necessary | |
| if (sx < 0) { | |
| sx = 0; | |
| } | |
| if (sx > this.canvas.width - sw) { | |
| sx = this.canvas.width - sw; | |
| } | |
| if (sy < 0) { | |
| sy = 0; | |
| } | |
| if (sy > this.canvas.height - sh) { | |
| sy = this.canvas.height - sh; | |
| } | |
| // save to browser | |
| context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120); | |
| } | |
| else { | |
| // now scaledown | |
| var full_width = this.canvas.width; | |
| var full_height = this.canvas.height; | |
| context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120); | |
| } | |
| imageData = offscreenCanvas.toDataURL('image/png'); | |
| imageData = imageData.replace('image/png', downloadMime); | |
| // call this function after 1 second | |
| setTimeout(function(){ | |
| p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png'); | |
| }, 1000); | |
| } |