Alice Fang and Jaclyn Saik – Final Project

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.

Leave a Reply