xxxxxxxxxx
221
let enable_events_colors = false; //color events
let enable_lines_colors = false; //colore lines
let events_text_start = 0.7; //x.pos
let graph_white_border = true;
let graph_bar_height = 15;
let graph_bar_min_width = 20;
let animationDuration = 400; //animation sec
let clickMode = 'FIXED_SPEED_ALL'; //'FIXED_SPEED_CLICK', 'RANDOM_SPEED_CLICK'
//gradient
let colors_palette = [
[255, 251, 0],
[255, 170, 0],
[174, 0, 255]
]
function preload() {
casesTable = loadTable('statistics1.csv', 'csv').rows;
eventsTable = loadTable('political_events.csv', 'csv').rows;
}
let days = [];
let colors = [];
let casesTable, eventsTable;
let minValue, maxValue;
let mouseLocked = false;
let spinActivated = false;
function setup() {
createCanvas(innerWidth, graph_bar_height * casesTable.length);
textAlign(LEFT, TOP);
textSize(12);
for (let col of colors_palette) {
colors.push(color(col[0], col[1], col[2]));
}
for (let stat of casesTable) { //days
let date = dayjs(stat.arr[0], 'DD-MM-YYYY');
//bar graph
let dayobj = {
date: date,
value: float(stat.arr[1]), //cases
height: 0.0,
animation: 'NONE', ////animation status 'NONE', 'INCREASING', 'DEACREASING'
animationStart: 0.0,
rotation: null
}
days.push(dayobj)
}
//events to days
for (let event of eventsTable) {
let date = dayjs(event.arr[0]);
let day = days.filter(d => d.date.isSame(date))[0]; ////find a day corresponding to the event date
if (day !== undefined) {
day.event = event.arr[1];
}
}
//lowest and highest number of case value
minValue = days.reduce((prev, curr) => prev.value < curr.value ? prev : curr).value;
maxValue = days.reduce((prev, curr) => prev.value > curr.value ? prev : curr).value;
}
function drawDays() {
let textsX = width * events_text_start;
let center = textsX / 2;
let maxW = center * 0.9;
background(0);
noFill();
stroke(255);
if (!mouseIsPressed) {
mouseLocked = false; //release the click after clicking on screen
}
//each of the days
for (let [index, day] of days.entries()) {
let y1 = index * graph_bar_height;
let y2 = (index + 1) * graph_bar_height;
//height increase
if (y2 > scrollY && y1 < scrollY + innerHeight) {
if (day.animation !== 'INCREASE' && day.height < 1.0) {
day.animation = 'INCREASE';
day.animationStart = millis();
}
} else if (day.animation !== 'DECREASE' && day.height > 0.0) { //or decrease
day.animation = 'DECREASE';
day.animationStart = millis();
}
let elapsed = millis() - day.animationStart;
if (day.animation === 'INCREASE') { //when increasing animation is over ans set width to 1
if (elapsed > animationDuration) {
day.height = 1.0;
day.animation = 'NONE';
} else {
day.height = elapsed / animationDuration;
}
} else if (day.animation === 'DECREASE') {
if (elapsed > animationDuration) {
day.height = 0.0;
day.animation = 'NONE';
} else {
day.height = 1.0 - elapsed / animationDuration;
}
}
let rotationSpeed = map(day.value, minValue, maxValue, 1.0, 2.0); //rotaion speed
if (clickMode === 'FIXED_SPEED_ALL' && day.rotation != null) {
let before = day.rotation;
day.rotation += radians(rotationSpeed) * 2;
if (before % PI > day.rotation % PI && !spinActivated) {
day.rotation = null;
}
}
//if the bar is not on screen, stop - computer power
if (y2 < scrollY - 100 || y1 > scrollY + innerHeight + 100) {
continue;
}
let alpha = day.height * 255;
let w = map(day.value * smoothStep(day.height), minValue, maxValue, graph_bar_min_width, maxW); //half width
strokeWeight(1);
let col = gradient(colors, day.value / maxValue);
if (enable_events_colors) fill(red(col), green(col), blue(col), alpha);
else fill(255, alpha); //else white
//when event match the day
if (day.event) {
push();
noStroke();
text(day.event, textsX, y1, width - textsX, 500);
if (enable_lines_colors) stroke(col);
else stroke(255);
let lineX = map(day.height, 0, 1, textsX - 10, center + w); //x.pos animated
line(lineX, y1 + graph_bar_height / 2, textsX - 10, y1 + graph_bar_height / 2);
pop();
}
//animation spin is set to "CLICK" instead of "ALL"
if (!mouseLocked && mouseIsPressed && mouseY > y1 && mouseY < y2 && clickMode.includes('CLICK')) {
mouseLocked = true;
if (day.rotation !== null) {
day.rotation = null;
} else {
day.rotation = 0.0;
}
}
push();
translate(center, y1 + graph_bar_height / 2);
if (day.rotation !== null) {
rotate(day.rotation);
if (clickMode === 'RANDOM_SPEED_CLICK') {
day.rotation += (noise(index + millis() / 1000) - 0.5) * rotationSpeed / 4; //random speed and direction
} else if (clickMode === 'FIXED_SPEED_CLICK') {
day.rotation += radians(rotationSpeed) * 2;
}
}
if (!graph_white_border) noStroke(); //disable white border if the settings graph_white_border is true
fill(red(col), green(col), blue(col), day.height == 0 ? 100 : 100 + alpha / 2);
rect(-w, -graph_bar_height / 2, w * 2, graph_bar_height);
pop();
push();
noStroke();
fill(255, alpha);
if (day.event) { //event bold
textStyle(BOLD);
}
text(day.date.format('DD/MM'), 5, y1 + graph_bar_height / 2 - textSize() / 2);
pop();
}
}
function draw() {
drawDays()
}
function mouseClicked() {
if (clickMode !== 'FIXED_SPEED_ALL') return; //mouseclicked mode
spinActivated = !spinActivated;
if (spinActivated) {
days.forEach(day => day.rotation = 0.0); //if spin activated change every null value
}
}
function gradient(cols, t) {
let step = 1 / (cols.length - 1);
t = t === 1.0 ? 0.999 : t;
for (let i = 0; i < cols.length; i++) {
if (t < step * (i + 1)) {
return lerpColor(cols[i], cols[i + 1], (t % step) * cols.length);
}
}
}
function smoothStep(x, edge0 = 0.0, edge1 = 1.0) {
let t = constrain((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}