This program uses the typeface ‘Avara’ from fontlibrary. Some of the words might not be perfectly aligned if the typeface isn’t installed. If so, here’s the zip file that includes the typeface: acfang_jsaik
And here’s a screen capture of all of the interactions: video
sketch
/*
An interactive display of Maya Angelou's poem "Still I Rise"
Click and move the mouse to interact, and press the right key to continue reading
We were inspired in part by digital children's books and "choose-your-own-adventure", except in this piece of
work, we wanted to create simple interactions in a consistent aesthetic that would complement the words in poem.
We also really love typography, poetry and literature, so we wanted to take the opportunity to augment a person's experience in
the reading of a poem.
We chose "Still I Rise" by Maya Angelou because we felt that her words were especially pertinent in today's social and political climate.
Alice: Stanzas 1, 4, 8, 9, title slide, combining into one file
Jaclyn: Stanzas 3, 5, 6, 7, uploading font ('Avara') into css/html files
Stanza 2 ended up being a combination of the two of us
*/
var state = 0
var instruct = "click and explore to interact, press right key to continue";
// stanza 1
var stanza1a = ["You", "may", "write", "me", "down", "in", "history"];
var stanza1b = ["With", "your", "bitter,", "twisted", "lies,"];
var stanza1c = ["You", "may", "trod", "me", "in", "the", "very", "dirt"];
var stanza1d = ["But", "still,", "like", "dust,", "I’ll", "rise."];
var clickcountStanzaOne = 0;
//stanza 2
var stanzaSassyA = "Does my sassiness upset you?";
var stanzaSassyB = "Why are you beset with gloom?";
var stanzaSassyC = "’Cause I walk like I've got oil wells";
var stanzaSassyD = "Pumping in my living room.";
var AccentStanzaSassyA = "sassiness";
var SassyX = 50;
var SassyY = 200;
var timeKeeping = 0;
var AnotherPositionX = 180;
var AnotherPositionY = 180;
var ROLL = 0.1;
var CircleFill = 40;
// stanza 3
var stanzaThreeA = "Just like moons and like suns,";
var stanzaThreeB = "With the certainty of tides,";
var stanzaThreeC = "Just like hopes springing high,";
var stanzaThreeD = "Still I'll rise.";
var AccentStanzaA = "shoot me";
var AccentStanzaB = "cut me";
var AccentStanzaC = "kill me";
var tX = 50;
var tY = 200;
var y = 200;
var y2 = 200
var speed = 0;
var speed2 = 0;
var acceleration = 0.1;
var acceleration2 = 0.1;
var clicksStanzaThree = 0;
var Ang = 0;
// stanza 4
var stanza4 = "Did you want to see me broken?\nBowed head and lowered eyes?\nShoulders falling down like teardrops,\nWeakened by my soulful cries?";
var teardrops = "teardrops";
var tears = [];
// stanza 5
var stanzaFiveA = "Does my haughtiness offend you?";
var stanzaFiveB = "Don't you take it awful hard";
var stanzaFiveC = "’Cause I laugh like I've got gold mines";
var stanzaFiveD = "Diggin’ in my own backyard.";
var AccentStanzaFiveA = "gold";
var AccentStanzaFiveB = "haughtiness";
var AccentStanzaFiveC = "awful";
var AccentStanzaFiveD = "own";
var AccentStanzaFiveE = "laugh";
var FiveX = 50;
var Fivey = 200;
var ExRan = 10;
var terrainDetailB = 0.01;
var terrainSpeedB = 0.0002;
var imG;
var imgG2;
// stanza 6
var stanzaSixA = "You may shoot me with your words,";
var stanzaSixB = "You may cut me with your eyes,";
var stanzaSixC = "You may kill me with your hatefulness,";
var stanzaSixD ="But still, like air, I’ll rise.";
var AccentStanzaSixA = "shoot me";
var AccentStanzaSixB = "cut me";
var AccentStanzaSixC = "kill me";
var AccentStanzaSixD = "I'll rise.";
var SixtX = 50;
var SixtY = 200;
// stanza 7
var stanzaSevenA = "Does my sexiness upset you?";
var stanzaSevenB = "Does it come as a surprise";
var stanzaSevenC = "That I dance like I've got diamonds";
var stanzaSevenD = "At the meeting of my thighs?";
var AccentStanzaSexy = "sexiness";
var Sevent = 0;
var SevenX = 50;
var SevenY = 200;
var words = [stanzaSevenA.split(" ")];
var speed = 0;
var speed2 = 0;
var acceleration = 0.1;
var acceleration2 = 0.1;
// stanza 8
var array = ["Out", "of", "the", "huts", "of", "history's", "shame"];
var array2 = ["I", "rise"];
var array3 = ["Up", "from", "a", "past", "that's", "rooted", "in", "pain"];
var array4 = ["I", "rise"];
var array5 = ["I'm", "a", "black", "ocean,", "leaping", "and", "wide,"];
var array6 = ["Welling", "and", "swelling", "I", "bear", "in", "the", "tide."];
var waveSpeed = 0.00005;
var waveDetail = 0.005;
var TimeWaveOne = 0.001;
var TimeWaveTwo = 0.0006;
// stanza 9
var stanza9a = "Leaving behind nights of terror and fear\nI rise";
var stanza9b = "Into a daybreak that’s wondrously clear\nI rise";
var stanza9c = "Bringing the gifts that my ancestors gave,\nI am the dream and the hope of the slave.";
var stanza9d = "I rise\nI rise\nI rise.";
var rows;
var cols;
var radius;
var d;
var stateStanzaNine = 0;
function preload() { // load images for stanza 5
var imgURL = "https://i.imgur.com/ppkgvPp.png";
var imgURL2 = "https://i.imgur.com/QDwN1E1.png"
imG = loadImage(imgURL);
imgG2 = loadImage(imgURL2)
}
function setup() {
createCanvas(480, 480);
textFont("avara");
// for stanza 4, pushing teardrops into array
for (var i = 0; i < 8; i++) {
var rainX = random(width);
var rainY = -10;
tears[i] = makerain(rainX, rainY);
}
// for stanza 9, determining grid variables
rows = 100;
cols = rows;
radius = (width / rows) / 2;
d = radius * 2;
}
function draw() {
// change stanza when state changes; state changes when right key is pressed
if (state === 0) {
StanzaZero();
} else if (state === 1) {
StanzaOne();
} else if (state === 2) {
StanzaTwo();
} else if (state === 3) {
StanzaThree();
} else if (state === 4) {
StanzaFour();
broken();
for (var j = 0; j < tears.length; j++) { // draw and move teardrop objects
tears[j].draw();
tears[j].move();
}
} else if (state === 5) {
StanzaFive();
} else if (state === 6) {
StanzaSix();
} else if (state === 7) {
StanzaSeven();
} else if (state === 8) {
wavey();
foam();
StanzaEight();
} else if (state === 9 || state > 9) {
StanzaNine();
}
}
// introduction slide
function StanzaZero() {
background(66, 77, 88);
fill('AliceBlue');
textSize(30);
textAlign(LEFT);
text("Still I Rise", 50, 120);
textSize(18);
text("Maya Angelou", 50, 150);
fill(240, 248, 255, 150);
text("an interactive poem", 50, 240, 60);
textSize(12);
textAlign(RIGHT);
text(instruct, 430, 430);
}
// stanza 1
function StanzaOne() { // as mouse is clicked, words appear on screen
background(66, 77, 88);
textSize(18);
textAlign(LEFT);
fill('AliceBlue');
var offset1 = 0;
var offset2 = 0;
var offset3 = 0;
var offset4 = 0;
var yPOS = 200; // original y position of first line
for (var i = 0; i < clickcountStanzaOne; i++) { // with each line, stanza length increases by previous line
var sLength;
if (i < stanza1a.length) {
var WORD1 = textWidth(stanza1a[i]);
text(stanza1a[i], 5 * i + offset1 + 50, yPOS);
offset1 += WORD1; //offset determines spacing between words based of width of previous word
} else if (i - stanza1a.length < stanza1b.length) {
sLength = i - stanza1a.length;
var WORD2 = textWidth(stanza1b[sLength]);
text(stanza1b[sLength], 5 * (sLength) + offset2 + 50, yPOS + 25);
offset2 += WORD2;
} else if (i - stanza1a.length - stanza1b.length < stanza1c.length) {
sLength = i - stanza1a.length - stanza1b.length;
var WORD3 = textWidth(stanza1c[sLength]);
text(stanza1c[sLength], 5 * (sLength) + offset3 + 50, yPOS + 50);
offset3 += WORD3;
} else if (i - stanza1a.length - stanza1b.length - stanza1c.length < stanza1d.length) {
sLength = i - stanza1a.length - stanza1b.length - stanza1c.length;
var WORD4 = textWidth(stanza1d[sLength]);
text(stanza1d[sLength], 5 * (sLength) + offset4 + 50, yPOS + 75);
offset4 += WORD4;
}
}
}
// stanza 2
function StanzaTwo() {
trial(); //function for rotating oil blobs
StanzaSassyWords(); //function for printing stanza 2 words
Stretch();
}
function StanzaSassyWords() {
push();
noStroke();
textSize(18);
fill('AliceBlue');
text(stanzaSassyB, SassyX, SassyY + 30); //manually setting leading for the type
text(stanzaSassyC, SassyX, SassyY + 60);
text(stanzaSassyD, SassyX, SassyY + 90);
pop();
}
function trial() {
fill(66, 77, 88);
rect(-3, -3, width + 3, height + 3); //background rectangle
for (var i = 0; i < 360; i += 3) { //for loop for the angle that the blobs rotate and generate
var x = 0; //variables for blob's position and width
var y = 0;
var w = 0;
floor(x = cos(radians(i)) * 100 + width / 3); //floor function for whole numbers
floor(y = sin(radians(i)) * 100 + height / 2);
floor(w = sin(radians(timeKeeping/4 + i)) * 400); //the timekeeping variable keeps the blobs constantly moving
w = abs(w); //whole and positive numbers for w, since it defines width
float(colOR = map(i, 0, 360, 0, 30)); //color mapped from a range of gray
circleFill = map(mouseX, 0, width, 0, 40); //opacity mapped so it changes with mouseX
noStroke();
fill(colOR, circleFill);
ellipse(x, y, w, w);
fill(255);
}
timeKeeping++;
}
function Stretch() {
push(); //stretch text vertically and horizontally based on mouse
textSize(18);
fill('AliceBlue');
var MouseScaleX = map(mouseX, 100, width, 1, 2);
var MouseScaleY = map(mouseY, 100, height, 1, 2);
scale(MouseScaleX, MouseScaleY);
text(stanzaSassyA, SassyX, SassyY);
pop();
}
// stanza 3
function StanzaThree() {
StanzaThreeWords();
if (clicksStanzaThree > 0) {
BounceOne(); //call bounce function when screen is clicked
}
if (clicksStanzaThree > 1) {
clicksStanzaThree = 0; //resets click count specifically for this stanza
}
BounceClick() //keeps click count increasing when mouse is pressed
Moon(); //function for rotating sun and moon
}
function StanzaThreeWords() {
push();
fill(66, 77, 88);
rect(-3, -3, width + 10, height + 10); //background rectangle
noStroke();
textSize(18);
textFont("Avara");
fill(255, 255, 255);
text(stanzaThreeA, tX, tY);
text(stanzaThreeB, tX, tY + 30);
text(stanzaThreeC, tX, tY + 60);
text(stanzaThreeD, tX, tY + 90);
stroke(66, 77, 88);
strokeWeight(2);
fill(66, 77, 88);
text("springing", 183, 260); //type to cover existing type in stanza,
text("hopes", 127, 260); //makes room for bouncing type
noStroke();
pop();
}
function BounceOne() {
textSize(18);
fill(255);
textFont("Avara");
text("springing", 183, y + 60);
y += speed;
speed += acceleration;
if (y + 60 > height || y + 60 < 1) { //invert direction if the type hits the bottom of the page
speed = -speed;
}
text("hopes", 127, y2 + 60);
y2 += speed2;
speed2 += acceleration2; //acceleration makes type get progressively faster
if (y2 + 60 > height || y2 + 60 < 1) { //invert direction if the type hits the bottom of the page
speed2 = -speed2;
}
}
function BounceClick() {
if (mouseIsPressed) {
clicksStanzaThree++; //adds clicks to stanza click variable
}
}
function Moon() {
noStroke();
push();
translate(240, 240); //translates center to the center of the page
rotate(radians(Ang)); //rotates by Angle defined globally
Ang += 0.7;
var moonX = 200; //moon and sun inversely positioned to each other
var moonY = 90;
var sunX = -200;
var sunY = -90;
fill(255);
ellipse(moonX, moonY, 30, 30);
fill(66, 77, 88, 220);
ellipse(moonX - 10, moonY, 30, 30); //moon is made of 2 ellipses
noStroke();
fill(255);
sunshine(sunX, sunY); //calls function for sun rays
pop();
}
function sunshine(sx, sy) { //seperate function for sun rays
strokeWeight(2);
stroke(255);
line(sx - 20, sy, sx + 20, sy);
line(sx, sy - 20, sx, sy + 20);
line(sx - 15, sy - 15, sx + 15, sy + 15);
line(sx + 15, sy - 15, sx - 15, sy + 15);
stroke(66, 77, 88);
strokeWeight(3);
ellipse(sx, sy, 30, 30);
}
// stanza 4
function StanzaFour() {
background(66, 77, 88);
fill('AliceBlue');
textSize(18);
noStroke();
text(stanza4, 50, 180);
text(teardrops, 299, 225);
}
function makerain() {
var drop = { x: random(0, width),
y: -10,
speed: random(1, 2),
draw: drawrain,
move: moverain}
return drop;
}
function drawrain() { // create falling teardrops
textSize(12);
var tearOpacity = map(this.y, 0, height, 200, 0);
stroke(240, 248, 255, tearOpacity);
noFill();
var tearSize = random(4, 8);
ellipse(this.x, this.y, tearSize, tearSize);
noStroke();
}
function moverain() {
this.y += this.speed;
if (this.y > height) {
this.y = -10;
}
}
function broken() { // as mouseY changes, background darkens, highlighting last line of stanza
var OP = map(mouseY, 0, height, 0, 255); // map opacity to mouseY
background(30, 30, 40, OP);
fill('AliceBlue');
text("Weakened by my soulful cries?", 50, 248);
}
// stanza 5
function StanzaFive() {
DarkHill(); //background and digging person function
StanzaFiveWords(); //stanza word placement
DrawTwoo(); //function for the cursor effect
GoldenWords(); //word interaction function
}
function StanzaFiveWords() { //simlpe placement of stanza
push();
noStroke();
textSize(18);
textFont("Avara");
fill(255, 255, 255);
text(stanzaFiveA, FiveX, Fivey);
text(stanzaFiveB, FiveX, Fivey + 30);
text(stanzaFiveC, FiveX, Fivey + 60);
text(stanzaFiveD, FiveX, Fivey + 90);
pop();
}
function DrawTwoo() { //cursor effect to illuminate the mouse
stroke(255, 215, 80);
strokeWeight(4);
line(mouseX, mouseY, pmouseX, pmouseY);
}
function GoldenWords() { //function for the gold words when mouse hovers
push();
stroke(255, 215, 80); //includes background type and also
strokeWeight(1);
textSize(18);
textFont("Avara");
fill(255, 215, 80);
ExRan = random(0, 2);
if (dist(mouseX, mouseY, 285 + 5, 260) < 40) {
text(AccentStanzaFiveA, 285, 260); // "gold"
strokeWeight(3);
textSize(27);
textFont("Avara");
fill(255, 215, 80, 20);
stroke(255, 215, 80, 20);
text(AccentStanzaFiveA, 285 + ExRan, 260 + ExRan); // "gold"
}
if (dist(mouseX, mouseY, 135 + 10, 200) < 40) {
text(AccentStanzaFiveB, 135, 200); // "haughty"
strokeWeight(3);
textSize(27);
textFont("Avara");
fill(255, 215, 80, 20);
stroke(255, 215, 80, 20);
text(AccentStanzaFiveB, 135 + ExRan, 200 + ExRan); // "haughty"
}
if (dist(mouseX, mouseY, 201 + 5, 230) < 40) {
text(AccentStanzaFiveC, 201, 230); // "awful"
strokeWeight(3);
textSize(27);
textFont("Avara");
fill(255, 215, 80, 20);
stroke(255, 215, 80, 20);
text(AccentStanzaFiveC, 201 + ExRan, 230 + ExRan); // "awful"
}
if (dist(mouseX, mouseY, 182 + 5, 290) < 40) {
text(AccentStanzaFiveD, 182, 290); // "own"
strokeWeight(3);
textSize(27);
textFont("Avara");
fill(255, 215, 80, 20);
stroke(255, 215, 80, 20);
text(AccentStanzaFiveD, 182 + ExRan, 290 + ExRan); // "own"
}
if (dist(mouseX, mouseY, 124 + 5, 260) < 40) {
text(AccentStanzaFiveE, 124, 260); // "laugh"
strokeWeight(3);
textSize(27);
textFont("Avara");
fill(255, 215, 80, 20);
stroke(255, 215, 80, 20);
text(AccentStanzaFiveE, 124 + ExRan, 260 + ExRan); // "laugh"
}
noStroke();
pop();
}
function DarkHill() { //function for background hill and digging
push();
background(66, 77, 88); //generative landscape based on milliseconds
beginShape();
stroke(0, 30);
for (var x = 0; x < width; x++) { //
var t = (x * terrainDetailB) + (millis() * terrainSpeedB);
var y = map(noise(t), 0,1, 100, 200);
line(x, y, x, height);
}
endShape();
pop();
if (dist(mouseX, mouseY, 285 + 5, 260) < 80) { //mouse trigger for the digging person to animate
image(imgG2, 100, 100);
} else {
image(imG, 100, 100);
}
}
// stanza 6
function StanzaSix() {
background(66, 77, 88);
Shootin(); //function for stanza six type
Blinds(); //function for closing blinds
Accent(); //function for accent type above blinds
}
function Shootin() {
push();
fill(66, 77, 88);
rect(0, 0, width, height);
noStroke();
textSize(18);
textFont("Avara");
fill(255, 255, 255);
text(stanzaSixA,SixtX,SixtY);
text(stanzaSixB,SixtX,SixtY + 30);
text(stanzaSixC,SixtX,SixtY + 60);
text(stanzaSixD,SixtX,SixtY + 90);
pop();
}
function Blinds() {
noStroke();
var whyOne = max(0, min(mouseY, 479));
var gentleOne = 0.5; //determines easing function for each "blind"
var gentleTwo = 0.7;
var y = 1; //y length for blind 1
var y2 = 1; //y length for blind 2
var disy = whyOne - y; //finds distance between mapped y vaiable and y position
var disy2 = whyOne - y2;
y += disy * gentleOne; //applies distance to easing
y2 += disy2 * gentleTwo;
//blinds 1
fill(30, 30, 40, 220);//opacity
rect(480, 0, -y, 480); //negative y value so that the blinds open and close on both sides
rect(0, 0, y, 480)
//blinds2
fill(30, 30, 40, 220);
rect(480, 0, -y2, 480);
rect(0, 0, y2, 480)
}
function Accent() { //simple function for placing selected accent words on top of blinds
fill(255);
textSize(18);
textFont("Avara");
text(AccentStanzaSixA, SixtX + 83.5, SixtY);
text(AccentStanzaSixB, SixtX + 83.5, SixtY + 30);
text(AccentStanzaSixC, SixtX + 83.5, SixtY + 60);
text(AccentStanzaSixD, SixtX + 152.5, SixtY + 90);
}
// stanza 7
function StanzaSeven(){
mouseGlow(); //mouse background function to make type more readible when mouse hovers
wavee() //wave function for diamond pattern
Sexy1(); //basic stanza type
if (mouseIsPressed) {
Sexy2(); //second type interaction
}
}
function Sexy1() { //basic stanza type
push();
noStroke();
buffer = dist(mouseX, mouseY, SevenX + 150, SevenY + 40);
textSize(18);
textFont("Avara");
fill('AliceBlue');
text(stanzaSevenA, SevenX, SevenY);
text(stanzaSevenB, SevenX, SevenY + 30);
text(stanzaSevenC, SevenX, SevenY + 60);
text(stanzaSevenD, SevenX, SevenY + 90);
pop();
}
function mouseGlow() {
noStroke();
fill(66, 77, 88);
ellipse(mouseX, mouseY, 120, 120); //ellipse follows mouse, function placed BEHIND
//all other functions so this becomes another background
}
function wavee() {
background(66, 77, 88, 20);
noFill();
stroke(255, 180);
strokeWeight(1);
for (var x = 0; x <= width; x = x + 90) {
for (var y = 0; y <= height; y = y + 60) { //nested for loop defines grid system for diamonds
var xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, true); //maps angle around a circle so it's based on
var yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, true); //the mouse x and y positions
var angle = xAngle * (x / width) + yAngle * (y / height); //angle tells diamond to osccillate
var myX = x + 20 * cos(2 * PI * Sevent + angle); //synthesize x and y angles to one data point for each diamond
var myY = y + 20 * sin(2 * PI * Sevent + angle);//also makes the diamond change over time regardless of mouse
Diamond(myX, myY);
}
}
Sevent = Sevent + 0.01; //time function
}
function Diamond(vx, vy) { //function to manually draw diamond shapes
noFill();
beginShape();
vertex(vx, vy);
vertex(vx + 4, vy);
vertex(vx + 8, vy + 4);
vertex(vx, vy + 12);
vertex(vx - 8, vy + 4);
vertex(vx - 4, vy);
endShape(CLOSE);
beginShape();
vertex(vx - 8, vy + 4);
vertex(vx + 8, vy + 4);
vertex(vx, vy + 12);
vertex(vx - 4, vy + 4);
vertex(vx, vy);
vertex(vx + 4, vy + 4);
vertex(vx, vy + 12);
endShape(CLOSE);
}
function Sexy2() { //function for interaction with the words "sexinesss"
textSize(18);
textFont("Avara");
fill(0);
fill(255, 215, 80);
noStroke();
text(AccentStanzaSexy, 134.5, 200);
}
// stanza 8
function StanzaEight() { // "wavy" text, affected by mouseX and mouseY
fill('AliceBlue');
noStroke();
var offset1 = 0;
var yPOS = 85;
for (var a = 0; a < array.length; a++) { //first line
var WORD1 = textWidth(array[a]);
text(array[a], 5 * a + offset1 + 50, yPOS);
offset1 += WORD1; // offset determines spacing between words based on width of previous word
var d = dist(mouseX, mouseY, 5 * a + offset1 + 10, yPOS);
if (d > 0 & d < 20) { // based on distance, word will rise/ fall
yPOS += 1;
}
if (d > 0 & d < 35) {
yPOS += 5;
}
if (d > 0 & d < 50) {
yPOS += 8;
}
}
var offset2 = 0;
var yPOS2 = 135;
for (var b = 0; b < array2.length; b++) { //second line
var WORD2 = textWidth(array2[b]);
text(array2[b], 5 * b + offset2 + 50, yPOS2);
offset2 += WORD2;
var dd = dist(mouseX, mouseY, 5 * b + offset2 + 10, yPOS2);
if (dd > 0 & dd < 20) { // based on distance, word will rise/ fall
yPOS2 += 1;
}
if (dd > 0 & dd < 35) {
yPOS2 += 5;
}
if (dd > 0 & dd < 50) {
yPOS2 += 8;
}
}
var offset3 = 0;
var yPOS3 = 185;
for (var c = 0; c < array3.length; c++) { //third line
var WORD3 = textWidth(array3[c]);
text(array3[c], 5 * c + offset3 + 50, yPOS3);
offset3 += WORD3;
var ddd = dist(mouseX, mouseY, 5 * c + offset3 + 10, yPOS3);
if (ddd > 0 & ddd < 20) { // based on distance, word will rise/ fall
yPOS3 += 1;
}
if (ddd > 0 & ddd < 35) {
yPOS3 += 5;
}
if (ddd > 0 & ddd < 50) {
yPOS3 += 8;
}
}
var offset4 = 0;
var yPOS4 = 235;
for (var d = 0; d < array4.length; d++) { //fourth line
var WORD4 = textWidth(array4[d]);
text(array4[d], 5 * d + offset4 + 50, yPOS4);
offset4 += WORD4;
var dddd = dist(mouseX, mouseY, 5 * d + offset4 + 10, yPOS4);
if (dddd > 0 & dddd < 20) { // based on distance, word will rise/ fall
yPOS4 += 1;
}
if (dddd > 0 & dddd < 35) {
yPOS4 += 5;
}
if (dddd > 0 & dddd < 50) {
yPOS4 += 8;
}
}
var offset5 = 0;
var yPOS5 = 285;
for (var e = 0; e < array5.length; e++) { //fifth line
var WORD5 = textWidth(array5[e]);
text(array5[e], 5 * e + offset5 + 50, yPOS5);
offset5 += WORD5;
var ddddd = dist(mouseX, mouseY, 5 * e + offset5 + 10, yPOS5);
if (ddddd > 0 & ddddd < 20) { // based on distance, word will rise/ fall
yPOS5 += 1;
}
if (ddddd > 0 & ddddd < 35) {
yPOS5 += 5;
}
if (ddddd > 0 & ddddd < 50) {
yPOS5 += 8;
}
}
var offset6 = 0;
var yPOS6 = 335;
for (var f = 0; f < array6.length; f++) { //sixth line
var WORD6 = textWidth(array6[f]);
text(array6[f], 5 * f + offset6 + 50, yPOS6);
offset6 += WORD6;
var dddddd = dist(mouseX, mouseY, 5 * f + offset6 + 10, yPOS6);
if (dddddd > 0 & dddddd < 20) { // based on distance, word will rise/ fall
yPOS6 += 1;
}
if (dddddd > 0 & dddddd < 35) {
yPOS6 += 5;
}
if (dddddd > 0 & dddddd < 50) {
yPOS6 += 8;
}
}
}
// create wave and foam for stanza 8
function wavey() {
background(66, 77, 88);
beginShape();
stroke(30, 30, 40);
for (var w = 0; w < width; w++) {
var t = (w * TimeWaveOne) + (millis() * TimeWaveTwo);
var waveY = map(noise(t), 0, 0.5, 0, mouseY);
line(w, waveY, w, width);
} endShape();
}
function foam() {
beginShape();
stroke(255, 255, 255, 90);
for (var waveF = 0; waveF < width; waveF++) {
var t = (waveF * TimeWaveOne) + (millis() * TimeWaveTwo);
var foamY = map(noise(t), 0, 0.5, 0, mouseY);
vertex(waveF, foamY - 5);
vertex(waveF, foamY - 5);
} endShape();
}
// stanza 9
function StanzaNine() {
if (stateStanzaNine == 0) { //highlight only first two lines
fill('AliceBlue');
stroke(0);
textSize(18);
text(stanza9a, 50, 125);
if (mouseX > 40 & mouseX < 140 && mouseY > 105 && mouseY < 165) {
fill(66, 77, 88);
text("rise", 62.25, 147.25) //change color when mouse hovers to indicate "click"
}
}
if (stateStanzaNine == 1) { //highlight only third and fourth lines
fill('AliceBlue');
stroke(0);
text(stanza9b, 50, 170);
if (mouseX > 40 & mouseX < 140 && mouseY > 150 && mouseY < 215) {
fill(66, 77, 88);
text("rise", 62.25, 192.25) //change color when mouse hovers to indicate "click"
}
}
if (stateStanzaNine == 2) { //highlight only fifth and sixth lines
fill('AliceBlue');
text(stanza9c, 50, 215);
stroke(0);
fill(255, 215, 80);
text("hope", 268.25, 237.5); //change color when mouse hovers to indicate "click"
}
drawGrid(); // create spotlight
if (stateStanzaNine == 3) { //reveal last stanza
background(255, 250, 205);
fill(110);
text(stanza9a, 50, 125);
text(stanza9b, 50, 170);
text(stanza9c, 50, 215);
fill(0);
text(stanza9d, 50, 300);
}
}
function drawGrid() { //create spotlight grid
for (var gridY = 0; gridY < height; gridY += d) {
for (var gridX = 0; gridX < width; gridX += d) {
var modifiedX = gridX;
if ((gridY % (d * 2)) === 0) {
modifiedX = gridX + radius;
}
fill(0);
var distance = dist(mouseX, mouseY, modifiedX, gridY);
opacity = map(distance, 0, 160, 0, 255); //zero opacity at center of spotlight, fade as dist increases
noStroke();
fill(0, 0, 0, opacity);
rectMode(CENTER);
rect(gridX, gridY, d, d);
}
}
}
// for stanza nine
function mouseClicked() { //range for click-ability to switch lines
if (state === 9 & mouseX > 40 && mouseX < 140 && mouseY > 105 && mouseY < 165) { //if clicked in this range, next two lines will be revealed
stateStanzaNine = 1;
} else if (state === 9 & mouseX > 40 && mouseX < 140 && mouseY > 150 && mouseY < 215) { //if clicked in this range, next two lines will be revealed
stateStanzaNine = 2;
} else if (state === 9 & mouseX > 268 && mouseX < 310 && mouseY > 223 && mouseY < 243) { //if clicked in this range, reveal all of stanza
stateStanzaNine = 3;
}
}
// for global state change
function keyPressed() {
if (keyCode === RIGHT_ARROW) { //when right key is pressed, change stanzas
state++;
}
}
// for stanza one
function mousePressed() { //allow text to appear word by word in stanza one
clickcountStanzaOne++;
}
Both of us are very interested in poetry and literature, so for this final project we wanted to take the opportunity to use animation and mouse interaction to augment the experience of reading a poem. We were inspired in part by digital children’s books and “choose-your-own-adventure”, except in this piece of work, we wanted to create simple interactions in a consistent aesthetic that would complement the words in poem. We chose “Still I Rise” by Maya Angelou because we felt that her words were especially pertinent in today’s social and political climate.
This project was challenging to accomplish, and luckily we were able to work together well in order to tackle bigger problems. One of the most time-consuming struggles we encountered was the process of uploading, arranging, aligning, ordering and placing all of the type: we had to learn a couple new functions in order to manipulate the text in certain ways and treat some words as objects. We got sucked into the technicalities of typography, and spend more time than we should have finding and uploading the correct typeface. In the treatment of individual words, when placing words from a string in a for loop to appear one at a time, spacing became a tricky thing to deal with because our typeface wasn’t monospace. Another thing we struggled with was synthesizing all of our work. Because we would create sketches for each slide in a separate file, we had to establish a guide for how we labeled our variables so that they didn’t conflict. We also had to be careful about universal functions like mousePressed and keyPressed.
Inspiration credit:
p5.js official Wavemaker exampled
bounce function from p5.js official examples
Yasai openprocessing CircleShift Sketch
Even if we were working on different stanzas, we were able to talk problems out with each other and give advice. Although Alice focused on the opening slide, stanzas 1, 4, 8, and 9, and Jaclyn focused on stanzas 2, 3, 5, 6, and 7, the collaborative nature of our workflow allowed both of us to have a holistic influence to the project.
Overall, we are happy how this project turned out, and excited that we got to explore typography within p5.js.