Skip to content

Instantly share code, notes, and snippets.

@uwcc
Last active May 4, 2021 23:38
Show Gist options
  • Save uwcc/be8276c2c2ca0a7695a2aa41c0567737 to your computer and use it in GitHub Desktop.
Save uwcc/be8276c2c2ca0a7695a2aa41c0567737 to your computer and use it in GitHub Desktop.
Assignment 2: Parametric Alphabet Jierui Zhuge
license: mit

MDDN 242 2021 Assignment 2

At the beginning of Project2, I operated normally according to the method of terminal clone given in the email, but just like project1, I still failed and tried for many times. So I found another way, which was to download a desktop version of GitHub for cloning and uploading. However, there are still some problems. The desktop version of GitHub often fails to fetch my updates to the Preview page, and I am not quite clear about the reason. After consulting the information, the problem cannot be solved. So my updates are a matter of luck;

My original idea was to make an alphabet out of some basic shapes. For example, as I've shown in Sketch, I don't want to pursue very abstract shapes; But then they realized that they had to create a variety of letters, so they tried other ways to create these alphabets. My inspiration comes from the patterns of some traditional Chinese ethnic groups. Some ethnic patterns are combined with colorful lines and one-sided changes. However, my ability is limited, so I have made some geometric patterns. Construct a global symmetry. The pursuit of harmony and symmetry is also the traditional aesthetic of these national patterns in China, and the use of symmetrical composition ideas to create. I combine these patterns and letters as a kind of inspired decoration; Then use different colors to create a different feeling. This helps the overall design feel more simple, clear and soft.

Because I often meet the situation that I can't git, I always make modifications and save them in the local computer memo. This feeling is quite unpleasant, because the code is very difficult and there are many problems in the process of git, which makes people easily become quite irritable.

Some ethnic patterns are very bright, but I also want to add more colors that I like. In example2, I think I can add some sense of Yin and Yang, because the characteristics of Yin and Yang are abstraction, relevance and relativity. In my opinion, the arrangement and combination of these letters are actually very abstract. Some letters may not be able to see the rules of arrangement if they are not in order. In addition, some graphs cannot be moved, just like the interdependence and restriction of letters. So I thought black and white was very interesting.

In conclusion, I think my alphabet is buggy in some places; It becomes more and more abstract because it doesn't look very complete, because of the uniqueness of some of the letter shapes. I also adjusted some parameters and the position of the letters. But the effect is not very significant;

{
"commits": [
{
"sha": "3d5b2027d9910c81b611f9313935fb33c099503e",
"name": "final"
},
{
"sha": "b1a2f47f299f4e2c33d6a37c9e62f10e7f1198dc",
"name": "coloured example"
},
{
"sha": "77424207bea73415814c0192a8a139fbc5ee4179",
"name": "sketch"
}
]
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="letters.js"></script>
<script language="javascript" type="text/javascript" src="draw_letters.js"></script>
<script language="javascript" type="text/javascript" src="alphabet.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
<p>
Links to other sections:
<ul>
<li><a href="sketch.html">sketch</a>
<li><a href="alphabet.html">alphabet</a>
<li><a href="editor.html">editor</a>
<li><a href="interaction.html">interaction</a>
<li><a href="exhibition.html">exhibition</a>
<ul>
</body>
/*
* do not edit this file, instead edit the letter
* drawing code in draw_letters.js
*/
if (typeof systemBackgroundColor === 'undefined') {
var systemBackgroundColor = "#e3eded";
}
if (typeof systemLineColor === 'undefined') {
var systemLineColor = "#000090";
}
if (typeof systemBoxColor === 'undefined') {
var systemBoxColor = "#00c800";
}
const canvasWidth = 960;
const canvasHeight = 500;
// Handy string of all letters available
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?";
let debugBox = false;
function setup () {
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
// with no animation, redrawing the screen is not necessary
noLoop();
}
function mouseClicked() {
debugBox = !debugBox;
// console.log("debugBox is now: " + debugBox);
redraw();
}
function draw () {
// clear screen
background(systemBackgroundColor);
// compute the center of the canvas
let center_x = canvasWidth / 2;
let center_y = canvasHeight / 2;
// draw the letters A, B, C from saved data
push();
scale(0.5);
// constants
const left_margin = 40;
const right_margin = 2*width - 40;
const top_margin = 80;
const bottom_margin = 2*height - 60;
const x_step = 140;
const y_step = 280;
const first_letter_offset_x = 20;
let cur_letter_index = 0;
for(let j=top_margin; j<bottom_margin-y_step; j+=y_step) {
push();
translate(0, j);
// draw lines
stroke(systemLineColor);
line(left_margin, 0, right_margin, 0);
for (let i=left_margin; i<right_margin-8; i+=30) {
line(i, 100, i+12, 100);
}
line(left_margin, 200, right_margin, 200);
translate(left_margin+first_letter_offset_x, 0);
for (let i=left_margin+first_letter_offset_x; i<right_margin-x_step+1; i+=x_step) {
if (cur_letter_index < letters.length) {
if (debugBox) {
noFill()
strokeWeight(4);
stroke(systemBoxColor);
rect(0, 0, 100, 200);
}
let letter = letters[cur_letter_index];
if (letter in alphabet) {
drawLetter(alphabet[letter]);
}
else {
drawLetter(alphabet["default"]);
}
translate(x_step, 0);
cur_letter_index = (cur_letter_index + 1);
}
}
pop();
}
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
}
/*
* Draw the letter given the letterData
*
* Letters should always be drawn with the
* following bounding box guideline:
* from (0,0) to (100, 200)
*/
function drawLetter(letterData) {
angleMode(DEGREES);
//
let ellipseYpos = letterData["ellipseY"];
//
let rectX = letterData["rectX"];
let rectY = letterData["rectY"];
let rectWidth = letterData["rectW"];
let rectHeight = letterData["rectH"];
//
let arcHeight = letterData["height"];
let arcWidth = letterData["width"];
let posx = 50 + letterData["offsetx"];
let posy = 110 + letterData["offsety"];
let start =letterData["angleStart"];
let finish =letterData["angleStop"];
// draw ellipse
drawCircle(ellipseYpos);
//draw rect
drawRect(rectX, rectY, rectWidth, rectHeight);
// draw arc
drawArc(posx, posy, arcWidth, arcHeight, start, finish);
}
function drawCircle(yPos){
stroke(72,61,139);
strokeWeight(5);
fill(255,160,122);
ellipse(50,yPos, 50, 60);
fill(123,104,238);
ellipse(50,yPos, 10, 60);
ellipse(50,yPos, 60, 10);
fill( 0,255,127);
ellipse(50,yPos+2, 20, 20);
}
function drawRect(rectX, rectY, width, height){
stroke(72,61,139);
fill(176,224,230);
rect(rectX, rectY, width, height,20);
}
function drawArc(posx, posy, width, height, start, finish){
fill(210,180,140);
arc(posx, posy, width-20, height-20, start, finish);
}
function interpolate_letter(percent, oldObj, newObj) {
let new_letter = {};
new_letter["height"] = map(percent, 0, 100, oldObj["height"], newObj["height"]);
new_letter["width"] = map(percent, 0, 100, oldObj["width"], newObj["width"]);
new_letter["offsetx"] = map(percent/2, 0, 50, oldObj["offsetx"], newObj["offsetx"]);
new_letter["offsety"] = map(percent/2, 0, 50, oldObj["offsety"], newObj["offsety"]);
new_letter["angleStart"] = map(percent/2, 0, 50, oldObj["angleStart"], newObj["angleStart"]);
new_letter["angleStop"] = map(percent/2, 0, 50, oldObj["angleStop"], newObj["angleStop"]);
new_letter["ellipseY"] = map(percent, 0, 100, oldObj["ellipseY"], newObj["ellipseY"]);
if(percent <40){
new_letter["rectW"] = oldObj["rectW"];
new_letter["rectH"] = oldObj["rectH"];
}
else{
new_letter["rectW"] = map(percent, 0, 100, oldObj["rectW"], newObj["rectW"]);
new_letter["rectH"] = map(percent, 0, 100, oldObj["rectH"], newObj["rectH"]);
}
new_letter["rectX"] = map(percent, 0, 100, oldObj["rectX"], newObj["rectX"]);
new_letter["rectY"] = map(percent, 0, 100, oldObj["rectY"], newObj["rectY"]);
return new_letter;
}
var swapWords = [
]
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="letters.js"></script>
<script language="javascript" type="text/javascript" src="draw_letters.js"></script>
<script language="javascript" type="text/javascript" src="editor.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.7;
-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>
<p>
Links to other sections:
<ul>
<li><a href="sketch.html">sketch</a>
<li><a href="alphabet.html">alphabet</a>
<li><a href="editor.html">editor</a>
<li><a href="interaction.html">interaction</a>
<li><a href="exhibition.html">exhibition</a>
<ul>
<p>
</div>
<div class="inner" id="controls" height="500px">
<table class="home">
<tr id="row1" style="display: none">
<td>Param1</td>
<td id="slider1Container"></td>
</tr>
<tr id="row2" style="display: none">
<td>Param2</td>
<td id="slider2Container"></td>
</tr>
<tr id="row3" style="display: none">
<td>Param3</td>
<td id="slider3Container"></td>
</tr>
<tr id="row4" style="display: none">
<td>Param4</td>
<td id="slider4Container"></td>
</tr>
<tr id="row5" style="display: none">
<td>Param5</td>
<td id="slider5Container"></td>
</tr>
<tr id="row6" style="display: none">
<td>Param6</td>
<td id="slider6Container"></td>
</tr>
<tr id="row7" style="display: none">
<td>Param7</td>
<td id="slider7Container"></td>
</tr>
<tr id="row8" style="display: none">
<td>Param8</td>
<td id="slider8Container"></td>
</tr>
<tr id="row9" style="display: none">
<td>Param9</td>
<td id="slider9Container"></td>
</tr>
<tr id="row10" style="display: none">
<td>Param10</td>
<td id="slider10Container"></td>
</tr>
<tr id="row11" style="display: none">
<td>Param11</td>
<td id="slider11Container"></td>
</tr>
<tr id="row12" style="display: none">
<td>Param12</td>
<td id="slider12Container"></td>
</tr>
<tr id="row13" style="display: none">
<td>Param13</td>
<td id="slider13Container"></td>
</tr>
<tr id="row14" style="display: none">
<td>Param14</td>
<td id="slider14Container"></td>
</tr>
<tr id="row15" style="display: none">
<td>Param15</td>
<td id="slider15Container"></td>
</tr>
<tr id="row16" style="display: none">
<td>Param16</td>
<td id="slider16Container"></td>
</tr>
<tr id="row17" style="display: none">
<td>Param17</td>
<td id="slider17Container"></td>
</tr>
<tr id="row18" style="display: none">
<td>Param18</td>
<td id="slider18Container"></td>
</tr>
<tr id="row19" style="display: none">
<td>Param19</td>
<td id="slider19Container"></td>
</tr>
<tr id="row20" style="display: none">
<td>Param20</td>
<td id="slider20Container"></td>
</tr>
<tr id="row21" style="display: none">
<td>Param21</td>
<td id="slider21Container"></td>
</tr>
<tr id="row22" style="display: none">
<td>Param22</td>
<td id="slider22Container"></td>
</tr>
<tr id="row23" style="display: none">
<td>Param23</td>
<td id="slider23Container"></td>
</tr>
<tr id="row24" style="display: none">
<td>Param24</td>
<td id="slider24Container"></td>
</tr>
<tr>
<td>
<hr>
</td>
</tr>
<tr>
<td id="buttonContainer"></td>
</tr>
</table>
</div>
</div>
</body>
const colorBack = "#e3eded";
const colorLines = "#000090";
/*******
* define this "sliderInfo" variable
* have an entry for each slider you want
* and each row should be:
* ["object_field", minimum_bound, maximum_bound]
*/
const sliderInfo = [
["ellipseY", 90, 130],
["width", 10, 85],
["height", 10, 85],
["offsetx", -25, 25],
["offsety", -85, 80],
["angleStart", 0, 360],
["angleStop", 0, 360],
["rectX", 0, 88],
["rectY", 0, 180],
["rectW", 15, 100],
["rectH", 15, 200]
];
// PROBABLY DON't NEED TO EDIT ANYTHING ELSE.
const numSliders = sliderInfo.length;
// if everything is defined above, this should just work
function sliderToDataObject() {
let obj = {};
for (let i=0; i<numSliders; i=i+1) {
o_name = sliderInfo[i][0]
bounds_low = sliderInfo[i][1]
bounds_high = sliderInfo[i][2]
obj[o_name] = map(param_sliders[i].value(), 0, 100, bounds_low, bounds_high);
}
return obj;
}
let param_sliders = [];
let main_canvas = null;
const canvasWidth = 960;
const canvasHeight = 500;
let debugBox = false;
function setup () {
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
// rotation in degrees (more slider friendly)
angleMode(DEGREES);
for(let i=0; i<numSliders; i++) {
let cur_row = select("#row" + (i+1))
cur_row.show();
let cur_slider = createSlider(0, 100, 50)
let containerString = "slider" + (i+1) + "Container"
cur_slider.parent(containerString);
param_sliders.push(cur_slider);
}
button = createButton('show data');
button.mousePressed(buttonPressedEvent);
button.parent(buttonContainer);
}
function buttonPressedEvent() {
let obj = sliderToDataObject();
json = JSON.stringify(obj, null, 2);
alert(json);
}
function draw () {
// clear screen
background(colorBack);
// compute the center of the canvas
let center_x = canvasWidth / 2;
let center_y = canvasHeight / 2;
// draw the letters A, B, C from saved data
push();
scale(2);
translate(width/4 - 50, 25);
if (debugBox) {
noFill()
strokeWeight(4);
stroke(0, 200, 0);
rect(0, 0, 100, 200);
}
let obj = sliderToDataObject();
drawLetter(obj);
pop();
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
else if (key == 'd') {
debugBox = !debugBox;
// console.log("debugBox is now: " + debugBox);
redraw();
}
else if (key == ' ') {
let obj = sliderToDataObject();
json = JSON.stringify(obj, null, 2);
console.log(json);
}
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="letters.js"></script>
<script language="javascript" type="text/javascript" src="draw_letters.js"></script>
<script language="javascript" type="text/javascript" src="exhibition.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
<p>
Links to other sections:
<ul>
<li><a href="sketch.html">sketch</a>
<li><a href="alphabet.html">alphabet</a>
<li><a href="editor.html">editor</a>
<li><a href="interaction.html">interaction</a>
<li><a href="exhibition.html">exhibition</a>
<ul>
</body>
/*
* do not edit this file, instead edit the letter
* drawing code in draw_letters.js
*/
if (typeof systemBackgroundColor === 'undefined') {
var systemBackgroundColor = "#e3eded";
}
const canvasWidth = 960;
const canvasHeight = 500;
// these variables are used for animation
let soloCurLetter = "B";
let soloLastLetter = "A"
let soloPrevObj = alphabet["default"];
let soloIsAnimating = false;
let soloNumAnimationFrames = 30;
let soloCurAnimationFrame = 0;
// Handy string of all letters available
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?";
let chosenLetters = [];
let chosenPrevObjs = [null, null, null, null, null, null, null, null];
let chosenIsAnimating = [false, false, false, false, false, false, false, false];
let chosenNumAnimationFrames = 30;
let chosenCurAnimationFrame = [0, 0, 0, 0, 0, 0, 0, 0];
let curChosenLetter = 0;
let lastKeyPressedTime;
let secondsUntilSwapMode = 15;
let lastWordSwappedTime;
let isSwappingWords = true;
let secondsPerWord = 8;
let curSwapWord = 0;
var defaultSwapWords = [
"ACTUALLY",
"1234567?",
"EXPECTED",
"PROPERTY",
"ADDITION",
"FOLLOWED",
"PROVIDED",
"ALTHOUGH",
"HAPPENED",
"QUESTION",
"AMERICAN",
"INCREASE",
"RECEIVED",
"ANYTHING",
"INDUSTRY",
"RELIGION",
"BUILDING",
"INTEREST",
"REMEMBER",
"BUSINESS",
"INVOLVED",
"REQUIRED",
"CHILDREN",
"NATIONAL",
"SERVICES",
"COMPLETE",
"ORGANIZE",
"SOUTHERN",
"CONSIDER",
"PERSONAL",
"STANDARD",
"CONTINUE",
"PLANNING",
"STRENGTH",
"ALPHABET",
"POSITION",
"STUDENTS",
"DECISION",
"POSSIBLE",
"SUDDENLY",
"DIRECTLY",
"PRESSURE",
"THINKING",
"DISTRICT",
"PROBABLY",
"TOGETHER",
"ECONOMIC",
"PROBLEMS",
"TRAINING",
"EVIDENCE",
"PROGRAMS"
]
const interpolation_is_on = (typeof interpolate_letter === "function")
function setup () {
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
let now = millis();
lastKeyPressedTime = now;
lastWordSwappedTime = now;
if (typeof swapWords === 'undefined') {
// the variable is defined
swapWords = [];
}
swapWords = swapWords.concat(defaultSwapWords);
chosenLetters = [];
let first_word = swapWords[0];
for(let i=0; i<first_word.length; i++) {
chosenLetters.push(first_word[i]);
}
}
function getCharacterInterpolationObj(percent, oldObj, newObj) {
if (interpolation_is_on) {
// safe to use the function
obj = interpolate_letter(percent, oldObj, newObj)
}
else {
if(percent == 0) {
obj = oldObj;
}
else {
obj = newObj;
}
}
return obj;
}
function getObjFromChar(c) {
if (c in alphabet) {
return alphabet[c];
}
else {
return alphabet["default"];
}
}
function getCharacterInterpolation(percent, oldChar, newChar) {
let oldObj = getObjFromChar(oldChar);
let newObj = getObjFromChar(newChar);
return getCharacterInterpolationObj(percent, oldObj, newObj);
}
function computeCurrentSoloChar() {
// now figure out what object to draw
let obj;
if (soloIsAnimating) {
nextObj = getObjFromChar(soloCurLetter);
progress = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, 0, 100);
obj = getCharacterInterpolationObj(progress, soloPrevObj, nextObj)
}
else {
obj = getObjFromChar(soloCurLetter);
}
return obj;
}
// draws a single character given an object, position, and scale
function drawFromDataObject(x, y, s, obj) {
push();
translate(x, y);
scale(s, s);
drawLetter(obj);
pop();
}
function computeCurrentChosenChar(n) {
// now figure out what object to draw
var obj;
if (chosenIsAnimating[n]) {
if(chosenCurAnimationFrame[n] < 0) {
obj = chosenPrevObjs[n];
}
else {
nextObj = getObjFromChar(chosenLetters[n]);
if (interpolation_is_on) {
// safe to use the function
let percent = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, 0, 100)
// obj["box1"]["position"] = map(chosenCurAnimationFrame[n], 0, chosenNumAnimationFrames, chosenPrevObjs[n]["box1"]["position"], nextObj["box1"]["position"])
obj = interpolate_letter(percent, chosenPrevObjs[n], nextObj)
}
else {
obj = nextObj;
}
}
}
else {
obj = getObjFromChar(chosenLetters[n]);
}
return obj;
}
function draw () {
now = millis();
// check to see if we should go into swapping mode
if(!isSwappingWords && lastKeyPressedTime + 1000 * secondsUntilSwapMode < now) {
isSwappingWords = true;
}
if(isSwappingWords) {
if(lastWordSwappedTime + 1000 * secondsPerWord < now) {
lastWordSwappedTime = now;
curSwapWord = (curSwapWord + 1) % swapWords.length;
for(var i=0; i<8; i++) {
var c = swapWords[curSwapWord][i];
swapExhibitLetter(i, c, 6*i);
}
}
}
background(systemBackgroundColor);
// shorthand variables to allow margin
var o = 20
var w2 = width - 2 * o
var h2 = height - 2 * o
for(var i=0; i<8; i++) {
// see if animation should be turned off
if(chosenIsAnimating[i] && chosenCurAnimationFrame[i] >= chosenNumAnimationFrames) {
chosenIsAnimating[i] = false;
}
// if we are animating, increment the number of animation frames
if(chosenIsAnimating[i]) {
chosenCurAnimationFrame[i] = chosenCurAnimationFrame[i] + 1;
}
var obj = computeCurrentChosenChar(i);
drawFromDataObject(o + i*w2/8.0, o + h2/2.0 - 120, 1.0, obj)
}
}
function swapExhibitLetter(n, c, frameDelay) {
chosenPrevObjs[n] = computeCurrentChosenChar(n);
chosenLetters[n] = c;
chosenIsAnimating[n] = true;
chosenCurAnimationFrame[n] = 0 - frameDelay;
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
else {
lastKeyPressedTime = millis();
if(isSwappingWords) {
isSwappingWords = false;
}
upper_key = key.toUpperCase();
swapExhibitLetter(curChosenLetter, upper_key, 0);
curChosenLetter = (curChosenLetter + 1) % 8;
}
}
File descriptions
-sketch.js
This is where you do your first experiment! A simple drawing of ABC using a single drawLetter() function. This file is only connected to sketch.html
-draw_letters.js
This is where you will do most of your coding for this project. This is where you will use the data from letters.js to inform how your letters will look.
-letters.js
This is the file that will hold the data that draws your letters. This is a javascript file that just holds information in a way that is similar to .json files. This file does not have any functions that you can call, it only holds information.
-editor.js
OPTIONAL
We will go over this in class. If you set up this file correctly you can use it to help generate data for your letters.js file.
- alphabet.js
You should not need to touch it.
- exhibition.js
You should not need to touch it.
- interaction.js
You should not need to touch it.
-html's
Generally, the html pages will display their corresponding .js file. Their purpose within the brief will be discussed in class
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
<p>
Links to other sections:
<ul>
<li><a href="sketch.html">sketch</a>
<li><a href="alphabet.html">alphabet</a>
<li><a href="editor.html">editor</a>
<li><a href="interaction.html">interaction</a>
<li><a href="exhibition.html">exhibition</a>
<ul>
</body>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="letters.js"></script>
<script language="javascript" type="text/javascript" src="draw_letters.js"></script>
<script language="javascript" type="text/javascript" src="interaction.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
<p>
Links to other sections:
<ul>
<li><a href="sketch.html">sketch</a>
<li><a href="alphabet.html">alphabet</a>
<li><a href="editor.html">editor</a>
<li><a href="interaction.html">interaction</a>
<li><a href="exhibition.html">exhibition</a>
<ul>
</body>
/*
* do not edit this file, instead edit the letter
* drawing code in draw_letters.js
*/
if (typeof systemBackgroundColor === 'undefined') {
var systemBackgroundColor = "#e3eded";
}
if (typeof systemLineColor === 'undefined') {
var systemLineColor = "#000090";
}
if (typeof systemBoxColor === 'undefined') {
var systemBoxColor = "#00c800";
}
const canvasWidth = 960;
const canvasHeight = 500;
// these variables are used for animation
let soloCurLetter = "B";
let soloLastLetter = "A"
let soloPrevObj = alphabet["default"];
let soloIsAnimating = false;
let soloNumAnimationFrames = 30;
let soloCurAnimationFrame = 0;
let debugBox = false;
// Handy string of all letters available
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?";
function setup () {
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
// with no animation, redrawing the screen is not necessary
// noLoop();
}
function mouseClicked() {
debugBox = !debugBox;
// console.log("debugBox is now: " + debugBox);
redraw();
}
const interpolation_is_on = (typeof interpolate_letter === "function")
function getCharacterInterpolationObj(percent, oldObj, newObj) {
if (interpolation_is_on) {
// safe to use the function
obj = interpolate_letter(percent, oldObj, newObj)
}
else {
if(percent == 0) {
obj = oldObj;
}
else {
obj = newObj;
}
}
return obj;
}
function getObjFromChar(c) {
if (c in alphabet) {
return alphabet[c];
}
else {
return alphabet["default"];
}
}
function getCharacterInterpolation(percent, oldChar, newChar) {
let oldObj = getObjFromChar(oldChar);
let newObj = getObjFromChar(newChar);
return getCharacterInterpolationObj(percent, oldObj, newObj);
}
function computeCurrentSoloChar() {
// now figure out what object to draw
var obj;
if (soloIsAnimating) {
nextObj = getObjFromChar(soloCurLetter);
progress = map(soloCurAnimationFrame, 0, soloNumAnimationFrames, 0, 100);
obj = getCharacterInterpolationObj(progress, soloPrevObj, nextObj)
}
else {
obj = getObjFromChar(soloCurLetter);
}
return obj;
}
let hot_key_press = false;
function draw () {
// clear screen
background(systemBackgroundColor);
// draw the interpolation on the guidelines
push();
scale(0.5);
// constants
const left_margin = 40;
const right_margin = 2*width - 40;
const top_margin = 80;
const bottom_margin = 2*height - 60;
const numSteps = 11;
const x_step = (right_margin - left_margin + 100) / (numSteps + 1)
const first_letter_offset_x = 20;
translate(0, top_margin);
// draw lines
stroke(systemLineColor);
line(left_margin, 0, right_margin, 0);
for(let i=left_margin; i<right_margin-8; i+=30) {
line(i, 100, i+12, 100);
}
line(left_margin, 200, right_margin, 200);
translate(left_margin+first_letter_offset_x, 0);
for(let i=0; i<numSteps; i = i+1) {
let percent = map(i, 0, numSteps, 0, 100);
let curLetterObj = getCharacterInterpolation(percent, soloLastLetter, soloCurLetter);
// print(curLetterObj, soloLastLetter, soloCurLetter);
if (debugBox) {
noFill()
strokeWeight(4);
stroke(systemBoxColor);
rect(0, 0, 100, 200);
}
if (interpolation_is_on || (i==0 || i==numSteps-1)) {
drawLetter(curLetterObj);
}
stroke(systemLineColor);
fill(systemLineColor);
textSize(50);
textAlign(CENTER)
if (i == 0) {
text(soloLastLetter, 50, 280);
}
else if (i == (numSteps -1)) {
if (hot_key_press) {
rect(50-40, 280-40, 80, 80);
hot_key_press = false;
}
text(soloCurLetter, 50, 280);
}
else if (interpolation_is_on) {
text("" + i*10 + "%", 50, 280);
}
translate(x_step, 0);
}
pop();
// now draw the letter full size below
// compute the center of the canvas
let center_x = canvasWidth / 2;
let center_y = canvasHeight / 2;
// see if animation should be turned off
if(soloIsAnimating && soloCurAnimationFrame >= soloNumAnimationFrames) {
soloIsAnimating = false;
}
// if we are animating, increment the number of animation frames
if(soloIsAnimating) {
soloCurAnimationFrame = soloCurAnimationFrame + 1;
}
push();
translate(center_x, center_y);
let cur_obj = computeCurrentSoloChar();
drawLetter(cur_obj);
pop();
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
else if (key == '@') {
saveBlocksImages(true);
}
else {
lastKeyPressedTime = millis();
let upper_key = key.toUpperCase();
hot_key_press = true;
soloPrevObj = computeCurrentSoloChar();
soloLastLetter = soloCurLetter;
soloCurLetter = upper_key;
soloIsAnimating = true;
soloCurAnimationFrame = 0;
}
}
const alphabet = {
"default": {
"ellipseY": 90,
"width": 45,
"height": 45,
"offsetx": 0,
"offsety": 60,
"angleStart": 0,
"angleStop": 0,
"rectX": 41,
"rectY": 44,
"rectW": 17,
"rectH": 92
},
"A": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 180,
"angleStop": 0,
"rectX": 80,
"rectY": 126,
"rectW": 17,
"rectH": 54
},
"B": {
"ellipseY": 130,
"width": 87,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 270,
"angleStop": 90,
"rectX": 3,
"rectY": 26,
"rectW": 17,
"rectH": 153
},
"C": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 335,
"angleStop": 75,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"D": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 90,
"angleStop": 270,
"rectX": 81,
"rectY": 26,
"rectW": 17,
"rectH": 153
},
"E": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 180,
"angleStop": 0,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"F": {
"ellipseY": 130,
"width": 85,
"height": 65,
"offsetx": -5,
"offsety": -65,
"angleStart": 180,
"angleStop": 0,
"rectX": 3,
"rectY": 38,
"rectW": 17,
"rectH": 143
},
"G": {
"ellipseY": 90,
"width": 67,
"height": 38,
"offsetx": 14,
"offsety": 65,
"angleStart": 0,
"angleStop": 180,
"rectX": 80,
"rectY": 58,
"rectW": 17,
"rectH": 123
},
"H": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 50,
"angleStop": 118,
"rectX": 3,
"rectY": 26,
"rectW": 17,
"rectH": 153
},
"I": {
"ellipseY": 130,
"width": 40,
"height": 40,
"offsetx": 0,
"offsety": -75,
"angleStart": 0,
"angleStop": 0,
"rectX": 42,
"rectY": 83,
"rectW": 17,
"rectH": 94
},
"J": {
"ellipseY": 140,
"width": 20,
"height": 20,
"offsetx": 37,
"offsety": -81,
"angleStart": 0,
"angleStop": 0,
"rectX": 78,
"rectY": 49,
"rectW": 17,
"rectH": 90
},
"K": {
"ellipseY": 90,
"width": 65,
"height": 65,
"offsetx": -14,
"offsety": 44,
"angleStart": 235,
"angleStop": 55,
"rectX": 3,
"rectY": 17,
"rectW": 17,
"rectH": 163
},
"L": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 0,
"angleStop": 180,
"rectX": 3,
"rectY": 17,
"rectW": 17,
"rectH": 126
},
"M": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 234,
"angleStop": 315,
"rectX": 2,
"rectY": 80,
"rectW": 17,
"rectH": 100
},
"N": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 50,
"angleStop": 118,
"rectX": 2,
"rectY": 80,
"rectW": 17,
"rectH": 100
},
"O": {
"ellipseY": 130,
"width": 45,
"height": 45,
"offsetx": 0,
"offsety": 20,
"angleStart": 0,
"angleStop": 0,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"P": {
"ellipseY": 90,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": -20,
"angleStart": 180,
"angleStop": 0,
"rectX": 3,
"rectY": 84,
"rectW": 17,
"rectH": 102
},
"Q": {
"ellipseY": 90,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": -20,
"angleStart": 180,
"angleStop": 43,
"rectX": 80,
"rectY": 86,
"rectW": 17,
"rectH": 100
},
"R": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 180,
"angleStop": 0,
"rectX": 2,
"rectY": 80,
"rectW": 17,
"rectH": 100
},
"S": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 234,
"angleStop": 54,
"rectX": 19,
"rectY": 156,
"rectW": 56,
"rectH": 17
},
"T": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": -28,
"angleStart": 0,
"angleStop": 180,
"rectX": 41,
"rectY": 26,
"rectW": 17,
"rectH": 151
},
"U": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 234,
"angleStop": 315,
"rectX": 80,
"rectY": 80,
"rectW": 17,
"rectH": 100
},
"V": {
"ellipseY": 130,
"width": 110,
"height": 130,
"offsetx": 0,
"offsety": 25,
"angleStart": 234,
"angleStop": 315,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"W": {
"ellipseY": 130,
"width": 95,
"height": 95,
"offsetx": 0,
"offsety": 20,
"angleStart": 50,
"angleStop": 118,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"X": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 162,
"angleStop": 342,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"Y": {
"ellipseY": 90,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": -20,
"angleStart": 216,
"angleStop": 326,
"rectX": 80,
"rectY": 60,
"rectW": 17,
"rectH": 133
},
"Z": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 322,
"angleStop": 142,
"rectX": 18,
"rectY": 86,
"rectW": 64,
"rectH": 17
},
"0": {
"ellipseY": 130,
"width": 45,
"height": 60,
"offsetx": 0,
"offsety": 20,
"angleStart": 0,
"angleStop": 0,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"1": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 180,
"angleStop": 90,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"2": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 125,
"angleStop": 306,
"rectX": 24,
"rectY": 160,
"rectW": 72,
"rectH": 17
},
"3": {
"ellipseY": 130,
"width": 53,
"height": 61,
"offsetx": 18.5,
"offsety": -52,
"angleStart": 292,
"angleStop": 118,
"rectX": 20,
"rectY": 28,
"rectW": 62,
"rectH": 17
},
"4": {
"ellipseY": 130,
"width": 98.5,
"height": 96.5,
"offsetx": 5.5,
"offsety": 24,
"angleStart": 180,
"angleStop": 270,
"rectX": 39,
"rectY": 84,
"rectW": 17,
"rectH": 108
},
"5": {
"ellipseY": 130,
"width": 85,
"height": 65,
"offsetx": -5,
"offsety": -55,
"angleStart": 180,
"angleStop": 0,
"rectX": 3,
"rectY": 43,
"rectW": 17,
"rectH": 82
},
"6": {
"ellipseY": 130,
"width": 85,
"height": 78,
"offsetx": -3,
"offsety": -38,
"angleStart": 140,
"angleStop": 324,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"7": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": 20,
"angleStart": 288,
"angleStop": 108,
"rectX": 0,
"rectY": 84,
"rectW": 67,
"rectH": 17
},
"8": {
"ellipseY": 130,
"width": 85,
"height": 85,
"offsetx": 0,
"offsety": -65,
"angleStart": 0,
"angleStop": 0,
"rectX": 50,
"rectY": 100,
"rectW": 0,
"rectH": 0
},
"9": {
"ellipseY": 90,
"width": 45,
"height": 45,
"offsetx": 0,
"offsety": -20,
"angleStart": 0,
"angleStop": 0,
"rectX": 80,
"rectY": 55,
"rectW": 17,
"rectH": 120
}
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.js"></script>
<script language="javascript" type="text/javascript" src="z_purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
</head>
<body style="background-color:white">
<div class="outer">
<div class="inner">
<div id="canvasContainer"></div>
</div>
</div>
<p>
Links to other sections:
<ul>
<li><a href="sketch.html">sketch</a>
<li><a href="alphabet.html">alphabet</a>
<li><a href="editor.html">editor</a>
<li><a href="interaction.html">interaction</a>
<li><a href="exhibition.html">exhibition</a>
<ul>
</body>
const canvasWidth = 960;
const canvasHeight = 500;
/*
* my three variable per letter are:
*
size: radius of the second circle (in pixels)
offsetx: x offset (in pixels) of the second circle
relative to the first one
offsety: y offset (in pixels) of the second circle
relative to the first one
*
*/
const letterA = {
"topRectWidth": 130,
"middleRectWidth": 130,
"bottomRectWidth": 0,
"topRectHeight": 30,
"middleRectHeight": 30,
"bottomRectHeight": 0,
"leftRectWidth": 30,
"leftRectHeight": 180,
"rightRectWidth": 30,
"rightRectHeight": 180,
"size": 80,
"offsetx": 0,
"offsety": 35,
"rotateValue": 90
}
const letterB = {
"topRectWidth": 130,
"middleRectWidth": 130,
"bottomRectWidth": 130,
"topRectHeight": 30,
"middleRectHeight": 30,
"bottomRectHeight": 30,
"leftRectWidth": 30,
"leftRectHeight": 180,
"rightRectWidth": 30,
"rightRectHeight": 180,
"size": 150,
"offsetx": 0,
"offsety": -145
}
const letterC = {
"topRectWidth": 130,
"middleRectWidth": 0,
"bottomRectWidth": 130,
"topRectHeight": 30,
"middleRectHeight": 0,
"bottomRectHeight": 30,
"leftRectWidth": 30,
"leftRectHeight": 180,
"rightRectWidth": 0,
"rightRectHeight": 0,
"size": 100,
"offsetx": 30,
"offsety": 0
}
function setup () {
// create the drawing canvas, save the canvas element
main_canvas = createCanvas(canvasWidth, canvasHeight);
main_canvas.parent('canvasContainer');
// color/stroke setup
stroke(25,25,112);
angleMode(DEGREES);
strokeWeight(15);
}
function drawLetter(posx, posy, letterData) {
// determine parameters for second circle
// let i = letterData["shapeType"];
// let size2 = letterData["size"];
let pos2x = posx + letterData["offsetx"];
let pos2y = posy + letterData["offsety"];
let topRectW = letterData["topRectWidth"];
let middleRectW = letterData["middleRectWidth"];
let botRectW = letterData["bottomRectWidth"];
let topRectH = letterData["topRectHeight"];
let middleRectH = letterData["middleRectHeight"];
let botRectH = letterData["bottomRectHeight"];
let leftRectW = letterData["leftRectWidth"];
let leftRectH = letterData["leftRectHeight"];
let rightRectW = letterData["rightRectWidth"];
let rightRectH = letterData["rightRectHeight"];
fill(255,192,203);
rect(posx,posy - 80,leftRectW,leftRectH); //left strip (A,B,C)
rect(posx + 100, posy - 80, rightRectW, rightRectH); //right strip (A,B)
rect(posx,posy,middleRectW, middleRectH); //middle strip (A,B)
ellipse(posx+65,posy-70,130,40); //top (A,B,C)
ellipse(posx+65,posy+100,botRectW, botRectH); //bottom (B,C)
}
function draw () {
background(176,196,222);
// compute the center of the canvas
let center_x = canvasWidth / 2;
let center_y = canvasHeight / 2;
// draw the letters A, B, C from saved data
drawLetter(center_x - 200, center_y, letterA);
drawLetter(center_x , center_y, letterB);
drawLetter(center_x + 200, center_y, letterC);
}
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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment