xxxxxxxxxx
const emotion_list = [
"Ignorance",
"Anger",
"Hatred / Rage",
"Impotence",
"Disgust",
"Humiliation",
"Shame",
"Suffering",
"Courage",
"Empathy",
"Indifference",
"Discomfort",
"To know more",
"Solidarity",
"Need for reparation"
]
const numberOfDots = emotion_list.length;
const MIN_DIST = 80;
const TEXT_SIZE = 30;
const DOTS_SHIFT = -50;
const DOTS_COLOR = '#FFFFFF';
const POTATO_COLOR = '#AE9576';
const BACKGROUND_COLOR = '#000000';
const THREAD_DB = [
['#A4243B', 'My ancestors were enslaved'],
['#DE61CF', 'My ancestors participated or benefited directly or indirectly from slavery'],
['#D8973C', 'I am not directly concerned by slavery'],
['#3A7CF4', 'My country benefited directly or indirectly from slavery'],
['#6AB5D3', 'I do not know what my links to slavery are']
]
let dots = [];
let my_potato = null;
let active_thread = null;
let E_h, E_k, E_rx, E_ry, E_rx2, E_ry2;
class Potato {
constructor(color) {
this.color = color;
this.left = windowWidth / 2;
this.top = windowHeight / 2;
this.width = windowWidth;
this.height = windowHeight;
}
draw() {
fill(this.color);
noStroke();
ellipse(this.left, this.top, this.width, this.height);
}
}
class Thread {
constructor(db) {
this.dots = [];
this.color = db[0];
this.title = db[1];
this.open = true;
}
add(dot) {
if (!this.open) return;
this.dots.forEach((d) => {
if (!this.open) return;
this.open = !(d == dot);
})
this.dots.push(dot);
}
connect() {
// Draw the circles
this.dots.forEach((dot) => {
fill(this.color);
noStroke();
circle(dot.pos.x, dot.pos.y, dot.r);
});
// Draw the thread
noFill();
stroke(this.color);
strokeWeight(2);
beginShape();
let previous_dot = null;
this.dots.forEach((dot) => {
// On the first dot
if (previous_dot == null) {
curveVertex(dot.pos.x - 20, dot.pos.y - 20);
}
curveVertex(dot.pos.x, dot.pos.y);
previous_dot = dot;
});
if (this.dots.length > 2) {
//curveVertex(previous_dot.pos.x + 20, previous_dot.pos.y + 20);
//const dot1 = this.dots[this.dots.length - 2];
//const dot2 = this.dots[this.dots.length - 1];
//line(dot1.pos.x, dot1.pos.y, dot2.pos.x, dot2.pos.y);
}
endShape();
}
}
class Dot {
constructor(text) {
this.text = text;
this.padding = 50;
this.range = 300;
this.pos = {};
this.d = 40; //random(15, 30);
this.r = this.d / 2;
this.margin_x = this.r / 1.5;
this.margin_y = this.r / 3;
this.color = DOTS_COLOR;
this.fill = DOTS_COLOR;
colorMode(HSB);
this.setRandomPos();
}
render() {
fill(this.fill);
noStroke();
// Draw a simple circle
circle(this.pos.x, this.pos.y, this.r);
// Let's write a label!
textSize(TEXT_SIZE);
text(this.text, this.pos.x + this.margin_x, this.pos.y + this.margin_y);
}
setRandomPos() {
this.pos = createVector(
random(this.padding, width - this.padding),
random(this.padding, height - this.padding)
);
}
}
function inPotato(pos) {
let EL = ((pos.x - E_h) * (pos.x - E_h)) / E_rx2;
let ER = ((pos.y - E_k) * (pos.y - E_k)) / E_ry2;
return EL + ER <= 1;
}
function nearBy(my_dot, other_dots) {
let too_close = false;
other_dots.forEach(function(dot) {
if (too_close) return;
too_close = MIN_DIST > dist(dot.pos.x, dot.pos.y, my_dot.pos.x, my_dot.pos.y);
});
return too_close;
}
function createDots(inside_of) {
dots = [];
emotion_list.forEach(function(emotion) {
let new_dot = new Dot(emotion);
let try_harder = 10;
while (
(!inPotato(new_dot.pos) || nearBy(new_dot, dots)) &&
--try_harder > 0
) { new_dot.setRandomPos(); }
if (try_harder < 2) { console.log('Close call!') }
new_dot.pos.x += DOTS_SHIFT;
dots.push(new_dot);
});
}
function resetActiveButtons() {
document.getElementsByClassName('active').forEach(function(e){e.className='';});
}
function setup() {
createCanvas(windowWidth, windowHeight);
// Precalculate potato extents
E_h = windowWidth / 2;
E_k = windowHeight / 2;
E_rx = E_h * 0.9;
E_ry = E_k * 0.7;
E_rx2 = E_rx * E_rx;
E_ry2 = E_ry * E_ry;
smooth();
// Create the thread buttons
THREAD_DB.forEach(function(thread, ix) {
button = createButton(thread[1]);
button.position(0, 28 * ix);
button.mousePressed(function() {
resetActiveButtons();
this.class('active');
return startThread(thread);
});
button.style('background-color', thread[0]);
});
// Create the reset button
button = createButton('Reset');
button.position(windowWidth - 100, 0);
button.mousePressed(function() {
drawScene();
});
button.style('background-color', 'white');
drawScene();
}
function drawScene() {
// Draw some stuff
clear();
background(BACKGROUND_COLOR);
my_potato = new Potato(POTATO_COLOR);
my_potato.draw();
createDots(my_potato);
// Draw all the dots
dots.forEach(function(dot) {
dot.render();
});
// Reset the thread
active_thread = null;
resetActiveButtons();
}
function startThread(next_thread) {
// Create a new thread with the color that the user chose
active_thread = new Thread(next_thread);
return false;
}
function draw() {
//circle(mouseX, mouseY, 20);
}
function mouseClicked() {
if (!active_thread) return;
dots.forEach(function(dot) {
if (mouseX < dot.pos.x + dot.r && mouseX > dot.pos.x - dot.r &&
mouseY < dot.pos.y + dot.r && mouseY > dot.pos.y - dot.r) {
// I clicked on a dot, and now add it to my thread
active_thread.add(dot);
}
});
// Connect my threads
active_thread.connect();
//ellipse(mouseX, mouseY, 5, 5);
// prevent default
return false;
}