• Black Vimeo Icon

©2020 BY JENNY LIN

Collective Emotions Live Data Visualization Presented

Updated: Jan 21, 2019


What have you been feeling the most lately?



As I was trying to figure out the best way to create the interface and the buttons for emotions I based off from this feelings wheel using bootstrap, Atharva told me about Flexbox which I found very helpful and eventually built my interface with.



After creating the first button page and the second input page, there went the most challenging part in this process - data visualization. I was introduced by Adi to D3.js, a library for interactive data visualization, which could create interactive data visualization as the following two examples.






In my original plan, I wanted the bubbles to form the word of the corresponded feeling when the bubbles of that feeling were hovered.



Yet, after looking at the examples from D3.js, I decided to go a little simpler and give myself a break. Ultimately, I decided to make something like this after comparing with the other pattern and researching on how to make it.


However, after hours of effort trying to apply D3.js, I just could not figure out how to make it work even with the help of some guidance.



Hence, I went back to the first half of my original idea - colorful bubbles for data visualization and gave up on trying to be fancy.


It turned out people actually think it is beautiful. Yet, there are still many things I could think more about to make the data visualization more intuitive. For instance, changing the intensity of the color to represent the intensity of the feelings, making sure the size of the bubbles in each color corresponds to the number of them, is it more effective to have the bubbles stay in the screen or have them disappear when they are hovered, which color is more intuitively associated with certain emotions, and etc.


Thus, I would like to carry this project and work on it more as I take the course Rest of You next semester.




Codes


First Button Page


<!DOCTYPE html><html><head>

<script src="p5.min.js"></script>

<script src="p5.dom.min.js"></script>

<script src="p5.sound.min.js"></script>

<link rel="stylesheet" type="text/css" href="style.css">

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> -->

</head>



<body>

<script src="sketch.js"></script>

<h1>What Have You Been Feeling The Most Lately?</h1>

<div class="flex-container">

<div class="flex-row">

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Happy</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Stressed</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Scared</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Surprised</a>

</div>

<div class="flex-row">

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Sad</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Disgusted</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Proud</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Angry</a>

</div>

<div class="flex-row">

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Ashamed</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Intrigued</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Peaceful</a>

<a class="flex-item" href="http://localhost:8000/Downloads/ICM_Final_Q2_2018_12_04_06_00_16/">Loving</a>

</div>

<script src="jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

<script src="popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>

<!-- <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> -->



</div></body></html>



html,

body {

background-color: #292342;

margin: 0;

padding: 0;

}


h1,

p {

font-size: 48px;

text-align: center;

color: white;

}


canvas {

display: block;

border: 5px solid white;

margin-left: auto;

margin-right: auto;

}


div {

color: white;

}


a {

text-decoration: none;

}


/* .content {

min-width: 400px;

max-width: 800px;

margin-right: auto;

margin-left: auto;

} */


/* .emotionButton {

margin-top: 36px;

max-width: 360px;

width: 100%;

box-shadow: 0px 0px 4px #BDBDBD;

background-color: #fff;

display: inline-block;

}

*/

.flex-container {

padding: 0;

margin: 0;

list-style: none;

/* display: -webkit-box;

display: -moz-box;

display: -ms-flexbox;

display: -webkit-flex; */

display: flex;

flex-direction: column;

-webkit-flex-flow: row wrap;

/* flex-direction: row | row-reverse | column | column-reverse;

flex-wrap: nowrap | wrap | wrap-reverse; */

justify-content: center;

}


.flex-row {

display: flex;

}


.flex-item {

-moz-box-shadow: inset 0px 80px 0px -24px #8763a5;

-webkit-box-shadow:inset 0px 80px 0px -24px #8763a5;

box-shadow:inset 0px 80px 0px -24px #8763a5;

background: #73558d;

padding: 5px;

width: 200px;

height: 100px;

margin-top: 50px;

margin-right: 50px;

line-height: 100px;

color: white;

font-weight: bold;

font-size: 32px;

text-align: center;

border-radius: 6px;

}


.flex-item:last-child {

margin-right: 0;

}


Second Input Page


<!DOCTYPE html><html><head>

<script src="p5.min.js"></script>

<script src="p5.dom.min.js"></script>

<script src="p5.sound.min.js"></script>

<link rel="stylesheet" type="text/css" href="style.css">

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

</head>



<body>

<h1>What Happened That Makes You Feel That Way?</h1>

<script src="sketch.js"></script>

<script src="jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

<script src="popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>



</body></html>



function setup() {

noCanvas();

emotionContent = createDiv();

emotionContent.addClass('content');


reasonAlign = createDiv();

reasonAlign.parent(emotionContent);

reasonAlign.attribute('align', 'center');

reason = createInput('Please share with me in one sentence.');

reason.size(800, 70);

reason.style('font-size', '32px');

reason.style('text-align', 'center');

reason.parent(reasonAlign);


submitAlign = createDiv();

submitAlign.addClass('flex-container');

submitAlign.attribute('align', 'center');

submit = createA('https://editor.p5js.org/wcl341@nyu.edu/full/SkHqvy3sm', 'Check out how others feel');

submit.style('text-decoration', 'none');

submit.addClass('flex-item');

submit.parent(submitAlign);

}



html,

body {

background-color: #292342;

margin: 0;

padding: 0;

}


h1,

p {

font-size: 48px;

text-align: center;

color: white;

}


canvas {

display: block;

border: 5px solid white;

margin-left: auto;

margin-right: auto;

}


.content {

max-width: 800px;

margin-right: auto;

margin-left: auto;

}


.flex-container {

padding: 0;

margin: 0;

list-style: none;

/* display: -webkit-box;

display: -moz-box;

display: -ms-flexbox;

display: -webkit-flex; */

display: flex;

flex-direction: column;

-webkit-flex-flow: row wrap;

/* flex-direction: row | row-reverse | column | column-reverse;

flex-wrap: nowrap | wrap | wrap-reverse; */

justify-content: center;

}



.flex-item {

-moz-box-shadow: inset 0px 70px 0px -24px #8763a5;

-webkit-box-shadow:inset 0px 70px 0px -24px #8763a5;

box-shadow:inset 0px 70px 0px -24px #8763a5;

background: #73558d;

padding: 5px;

width: 400px;

height: 80px;

margin-top: 50px;

margin-right: 50px;

line-height: 80px;

color: white;

font-weight: bold;

font-size: 32px;

text-align: center;

border-radius: 6px;

}



Third Data Visualization Page

<!DOCTYPE html>


<html class="gr__vallandingham_me">


<head>

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.dom.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js"></script>

<script src="https://d3js.org/d3.v5.min.js"></script>

<link rel="stylesheet" type="text/css" href="style.css">

<link rel="stylesheet" type="text/css" href="css/bubble_chart.css">

<link rel="stylesheet" type="text/css" href="css/reset.css">

<meta charset="utf-8" />

<script src="src/bubble_chart.js"></script>

<script src="src/tooltip.js"></script>

<script src="lib/d3.js"></script>


</head>


<body data-gr-c-s-loaded="true">

<script src="sketch.js"></script>

<script src="ball.js"></script>

</body>


</html>



var balls = [];

let feeling, emotion, movement;


function preload() {

feeling = loadJSON("emotion.json", gotData);

}


function setup() {

createCanvas(windowWidth, windowHeight);

console.log(feeling);

emotion = emotionInfo.emotion;

for (let a = 0; a < emotion[0].reason.length; a++) {

let xa = random(width);

let ya = random(height);

let speedxa = random(-0.4, 0.4);

let speedya = random(-0.5, 0.5);

balls.push(new Ball(xa, ya, speedxa, speedya, 25, 255, 153, 0, emotion[0].name, emotion[0].reason[a]));

}

for (let b = 0; b < emotion[1].reason.length; b++) {

let xb = random(width);

let yb = random(height);

let speedxb = random(-0.4, 0.4);

let speedyb = random(-0.5, 0.5);

balls.push(new Ball(xb, yb, speedxb, speedyb, 35, 255, 204, 0, emotion[1].name, emotion[1].reason[b]));

}

for (let c = 0; c < emotion[2].reason.length; c++) {

let xc = random(width);

let yc = random(height);

let speedxc = random(-0.4, 0.4);

let speedyc = random(-0.5, 0.5);

balls.push(new Ball(xc, yc, speedxc, speedyc, 45, 51, 204, 51, emotion[2].name, emotion[2].reason[c]));

}

for (let d = 0; d < emotion[3].reason.length; d++) {

let xd = random(width);

let yd = random(height);

let speedxd = random(-0.4, 0.4);

let speedyd = random(-0.5, 0.5);

balls.push(new Ball(xd, yd, speedxd, speedyd, 55, 51, 204, 255, emotion[3].name, emotion[3].reason[d]));

}

for (let e = 0; e < emotion[4].reason.length; e++) {

let xe = random(width);

let ye = random(height);

let speedxe = random(-0.4, 0.4);

let speedye = random(-0.5, 0.5);

balls.push(new Ball(xe, ye, speedxe, speedye, 65, 153, 51, 255, emotion[4].name, emotion[4].reason[e]));

}

for (let f = 0; f < emotion[5].reason.length; f++) {

let xf = random(width);

let yf = random(height);

let speedxf = random(-0.4, 0.4);

let speedyf = random(-0.5, 0.5);

balls.push(new Ball(xf, yf, speedxf, speedyf, 75, 255, 0, 102, emotion[5].name, emotion[5].reason[f]));

}

}


function draw() {


background(20);

for (a = 0; a < balls.length; a++) {

balls[a].move();

balls[a].bounce();

balls[a].display();


if (balls[a].isTouched(mouseX, mouseY)) {

balls[a].reasonText();

balls[a].pause();

}

// else {

// balls[a].move();

// balls[a].bounce();

// balls[a].display();

// }

}


for (b = 0; b < balls.length; b++) {

balls[b].move();

balls[b].bounce();

balls[b].display();


if (balls[b].isTouched(mouseX, mouseY)) {

balls[b].reasonText();

balls[b].pause();

}

// else {

// balls[b].move();

// balls[b].bounce();

// balls[b].display();

// }

}


for (c = 0; c < balls.length; c++) {

balls[c].move();

balls[c].bounce();

balls[c].display();


if (balls[c].isTouched(mouseX, mouseY)) {

balls[c].reasonText();

balls[c].pause();

}

// else {

// balls[c].move();

// balls[c].bounce();

// balls[c].display();

// }

}


for (d = 0; d < balls.length; d++) {

balls[d].move();

balls[d].bounce();

balls[d].display();


if (balls[d].isTouched(mouseX, mouseY)) {

balls[d].reasonText();

balls[d].pause();

}

// else {

// balls[d].move();

// balls[d].bounce();

// balls[d].display();

// }

}


for (e = 0; e < balls.length; e++) {

balls[e].move();

balls[e].bounce();

balls[e].display();


if (balls[e].isTouched(mouseX, mouseY)) {

balls[e].reasonText();

balls[e].pause();

}

// else {

// balls[a].move();

// balls[e].bounce();

// balls[e].display();

// }

}


for (f = 0; f < balls.length; f++) {

balls[f].move();

balls[f].bounce();

balls[f].display();


if (balls[f].isTouched(mouseX, mouseY)) {

balls[f].reasonText();

balls[f].pause();

}

// else {

// balls[a].move();

// balls[f].bounce();

// balls[f].display();

// }

}

}


function gotData(data) {

emotionInfo = data;

}


class Ball {

constructor(_x, _y, _speedx, _speedy, _r, _colR, _colG, _colB, _emotion, _reason) {

this.x = _x;

this.y = _y;

this.speedx = _speedx;

this.speedy = _speedy;

this.r = _r;

this.colR = _colR;

this.colG = _colG;

this.colB = _colB;

this.emotion = _emotion;

this.reason = _reason;

}


move() {

this.x += this.speedx;

this.y += this.speedy;

}


pause() {

this.speedx = 0;

this.speedy = 0;

}


resume() {

this.speedx = random(-0.4, 0.4);

this.speedy = random(-0.5, 0.5);

}


bounce() {

if (this.x > width || this.x < 0) {

this.speedx = this.speedx * -1;

}

if (this.y > height || this.y < 0) {

this.speedy = this.speedy * -1;

}

}


reasonText() {

push();

translate(this.x, this.y);

rect(0, 0, 200, 60);

pop();

fill(255);

text(this.emotion + " : " + this.reason, this.x + 10, this.y + 7, 180, 50)

}


display() {

noStroke();

fill(this.colR, this.colG, this.colB, 80);

ellipse(this.x, this.y, this.r);

}


isTouched(mx, my) {

return abs(dist(mx, my, this.x, this.y)) <= this.r / 2;

}


isNotTouched(mx, my) {

return abs(dist(mx, my, this.x, this.y)) > this.r / 2;

}


}



html, body {

margin: 0;

padding: 0;

}

canvas {

display: block;

}


#ITP #ICM #final #collectiveEmotions #dataVisualization #D3 #Flexbox #bootstrap