Skip to content

Commit

Permalink
Feature: Add previous and next buttons for EE PA (#872)
Browse files Browse the repository at this point in the history
* Add next and previous button.

* Fix bug

* Fix condition.

* Fix bubble showing.

* Fix navigation using next and previous buttons.

* Add disable buttons functions.

* Use different variable for cancelling promise.

* Fix animation problems and errors.

* Fix condition for cursor.

* Make the previous and next button invisible when and unclickable in interactive mode.

* Add some performance improvements.

* Fix page unresponsive

* Add spacing.

* Draw user icon.

* Fix bugs in bubbles.

* Use requestAnimationFrame instead of setTimeout.
  • Loading branch information
amovar18 committed Dec 12, 2024
1 parent b758db7 commit 59256d3
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 100 deletions.
14 changes: 14 additions & 0 deletions packages/explorable-explanations/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@
<div id="ps-canvas">
<div id="canvas-container">
<div class="controls">
<button id="previous-div" disabled class="play-pause-button">
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px"
fill="#808080">
<path
d="M220-240v-480h80v480h-80Zm520 0L380-480l360-240v480Zm-80-240Zm0 90v-180l-136 90 136 90Z" />
</svg>
</button>
<button id="next-div" class="play-pause-button">
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px"
fill="#808080">
<path
d="M660-240v-480h80v480h-80Zm-440 0v-480l360 240-360 240Zm80-240Zm0 90 136-90-136-90v180Z" />
</svg>
</button>
<div class="play-pause-button" id="play-pause-button">
<button id="play" class="hidden">
<img src="./icons/play-button.png" alt="play" />
Expand Down
4 changes: 2 additions & 2 deletions packages/explorable-explanations/src/components/branches.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const Branches = async ({ x1, y1, branches }) => {

return new Promise((resolve) => {
const animate = () => {
if (window.cancelPromise) {
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
resolve(endpoints);
return;
}
Expand Down Expand Up @@ -96,7 +96,7 @@ const drawAnimatedTimeline = (x, y, branches) => {
// Draw the horizontal line
p.line(x, y, x + progress, y);

if (window.cancelPromise) {
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
resolve();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const ProgressLine = ({

return new Promise((resolve) => {
const animate = () => {
if (window.cancelPromise) {
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
resolve();
return;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/explorable-explanations/src/lib/ripple-effect.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ rippleEffect.start = (x = 0, y = 0) => {
config.rippleEffect.rippled = true;

const animate = (timestamp) => {
if (window.cancelPromise) {
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
resolve();
return;
}
Expand Down
33 changes: 33 additions & 0 deletions packages/explorable-explanations/src/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ utils.triangle = (size, x, y, direction = 'right', color = 'black') => {
utils.delay = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};

utils.wipeAndRecreateMainCanvas = () => {
const { height, width } = utils.calculateCanvasDimensions();
const canvas = app.p.createCanvas(width, height);
canvas.parent('ps-canvas');
canvas.style('z-index', 0);
app.p.background(config.canvas.background);
app.p.textSize(config.canvas.fontSize);
};

utils.wipeAndRecreateInterestCanvas = () => {
const { height, width } = utils.calculateCanvasDimensions();
const overlayCanvas = app.igp.createCanvas(width, height);
Expand Down Expand Up @@ -332,4 +342,27 @@ utils.isOverControls = (mouseX, mouseY) => {
return false;
};

utils.markVisitedValue = (index, value) => {
config.timeline.circles = config.timeline.circles.map((circle, i) => {
if (i < index && index >= 0) {
circle.visited = value;
}
return circle;
});
};

utils.disableButtons = () => {
app.prevButton.style.cursor =
app.timeline.currentIndex > 0 ? 'pointer' : 'default';
app.prevButton.disabled = app.timeline.currentIndex > 0 ? false : true;
app.nextButton.disabled =
app.timeline.currentIndex === config.timeline.circles.length - 1
? true
: false;
app.nextButton.style.cursor =
app.timeline.currentIndex >= config.timeline.circles.length - 1
? 'default'
: 'pointer';
};

export default utils;
2 changes: 1 addition & 1 deletion packages/explorable-explanations/src/modules/auctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ auction.draw = async (index) => {
}

for (const step of steps) {
if (window.cancelPromise) {
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
return;
}

Expand Down
33 changes: 19 additions & 14 deletions packages/explorable-explanations/src/modules/bubbles.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ bubbles.init = () => {
bubbles.generateBubbles = (recalculate = false) => {
const interestGroupsToBeAdded =
config.timeline.circles[app.timeline.currentIndex]?.igGroupsCount ?? 0;

if (!recalculate) {
for (let index = 0; index < interestGroupsToBeAdded; index++) {
app.bubbles.positions.push({
Expand All @@ -69,7 +70,6 @@ bubbles.generateBubbles = (recalculate = false) => {

const groups = d3.map(app.bubbles.positions, (d) => d.group);
const color = d3.scaleOrdinal(groups, d3.schemeTableau10);

app.bubbles.positions = app.bubbles.positions.map((data, i) => {
return {
...data,
Expand Down Expand Up @@ -137,13 +137,13 @@ bubbles.barrageAnimation = async (index) => {

await new Promise((resolve) => {
const animate = () => {
if (app.timeline.isPaused) {
requestAnimationFrame(animate); // Keep the animation loop alive but paused.
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
resolve();
return;
}

if (window.cancelPromise) {
resolve();
if (app.timeline.isPaused) {
requestAnimationFrame(animate); // Keep the animation loop alive but paused.
return;
}

Expand Down Expand Up @@ -246,7 +246,6 @@ bubbles.reverseBarrageAnimation = async (index) => {
const target = igp.createVector(midPointX, midPointY);
const { color: currentColor } = app.bubbles.positions[i];
const color = currentColor;

positionsOfCircles.push({
x:
dspTags?.props?.x() +
Expand All @@ -266,13 +265,13 @@ bubbles.reverseBarrageAnimation = async (index) => {

await new Promise((resolve) => {
const animate = () => {
if (app.timeline.isPaused) {
requestAnimationFrame(animate);
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
resolve();
return;
}

if (window.cancelPromise) {
resolve();
if (app.timeline.isPaused) {
requestAnimationFrame(animate);
return;
}

Expand Down Expand Up @@ -427,6 +426,7 @@ bubbles.bubbleChart = (
const totalBubbles = bubbles.calculateTotalBubblesForAnimation(
app.timeline.currentIndex
);

data = data.filter((_data, i) => {
if (i < totalBubbles) {
return true;
Expand Down Expand Up @@ -555,12 +555,17 @@ bubbles.clearAndRewriteBubbles = () => {

bubbles.calculateTotalBubblesForAnimation = (index) => {
let bubblesCount = 0;
if (config.isInteractiveMode) {
config.timeline.circles.forEach((circle) => {
if (circle.visited) {
bubblesCount += circle.igGroupsCount ?? 0;
}
});
return bubblesCount;
}

config.timeline.circles.forEach((circle, currIndex) => {
if (
(currIndex < index && !config.isInteractiveMode) ||
(currIndex <= index && config.isInteractiveMode)
) {
if (currIndex < index) {
bubblesCount += circle.igGroupsCount ?? 0;
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,18 @@ joinInterestGroup.setUp = (index) => {
*/
joinInterestGroup.draw = async (index) => {
app.p.textAlign(app.p.CENTER, app.p.CENTER);

bubbles.generateBubbles();
const steps = app.joinInterestGroup.joinings[index];

if (!steps) {
return;
}

for (const step of steps) {
if (window.cancelPromise) {
if (window.cancelPromise || window.cancelPromiseForPreviousAndNext) {
return;
}

const { component, props, callBack } = step;

const returnValue = await component(props); // eslint-disable-line no-await-in-loop
Expand All @@ -173,8 +174,6 @@ joinInterestGroup.draw = async (index) => {
await utils.delay(delay); // eslint-disable-line no-await-in-loop
}

bubbles.generateBubbles();

await bubbles.reverseBarrageAnimation(index);

if (config.bubbles.isExpanded) {
Expand All @@ -183,8 +182,10 @@ joinInterestGroup.draw = async (index) => {
bubbles.showMinifiedBubbles();
}

config.bubbles.interestGroupCounts +=
config.timeline.circles[index]?.igGroupsCount ?? 0;
if (!window.cancelPromiseForPreviousAndNext) {
config.bubbles.interestGroupCounts +=
config.timeline.circles[index]?.igGroupsCount ?? 0;
}

flow.clearBelowTimelineCircles();
};
Expand Down
87 changes: 45 additions & 42 deletions packages/explorable-explanations/src/modules/timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const timeline = {};
* and drawing the initial timeline and user icon.
*/
timeline.init = () => {
app.timeline.circlePublisherIndices = [];
config.timeline.circles.forEach((circle, index) => {
if (circle.type === 'publisher') {
app.timeline.circlePublisherIndices.push(index);
Expand Down Expand Up @@ -92,19 +93,19 @@ timeline.init = () => {
utils.wipeAndRecreateUserCanvas();
timeline.renderUserIcon();
await app.drawFlows(clickedIndex);
config.timeline.circles[clickedIndex].visited = true;
bubbles.clearAndRewriteBubbles();
bubbles.showMinifiedBubbles();
config.shouldRespondToClick = true;
config.timeline.circles[clickedIndex].visited = true;
utils.wipeAndRecreateUserCanvas();
timeline.renderUserIcon();
}
};
} else {
app.timeline.drawTimelineLine();
app.timeline.renderUserIcon();
timeline.drawTimelineLine();
timeline.renderUserIcon();
}
app.timeline.drawTimeline(config.timeline);
timeline.drawTimeline(config.timeline);
};

/**
Expand Down Expand Up @@ -134,30 +135,37 @@ timeline.drawTimeline = ({ position, circleProps, circles }) => {
p.textAlign(p.CENTER, p.CENTER);
// Draw circles and text at the timeline position
circles.forEach((circleItem, index) => {
const xPositionForCircle =
config.timeline.position.x + diameter / 2 + circleVerticalSpace * index;
const yPositionForCircle = position.y + circleVerticalSpace;

app.timeline.circlePositions.push({
x: xPositionForCircle,
y: yPositionForCircle,
});

p.push();
p.stroke(config.timeline.colors.grey);
timeline.drawCircle(index);
p.pop();
if (!window.cancelPromiseForPreviousAndNext) {
const xPositionForCircle =
config.timeline.position.x + diameter / 2 + circleVerticalSpace * index;
const yPositionForCircle = position.y + circleVerticalSpace;

app.timeline.circlePositions.push({
x: xPositionForCircle,
y: yPositionForCircle,
});

p.push();
p.fill(config.timeline.colors.black);
p.textSize(12);
p.strokeWeight(0.1);
p.textFont('ui-sans-serif');
if (!config.isInteractiveMode) {
p.text(circleItem.datetime, xPositionForCircle, position.y);
p.push();
p.stroke(config.timeline.colors.grey);
timeline.drawCircle(index);
p.pop();

p.push();
p.fill(config.timeline.colors.black);
p.textSize(12);
p.strokeWeight(0.1);
p.textFont('ui-sans-serif');
if (!config.isInteractiveMode) {
p.text(circleItem.datetime, xPositionForCircle, position.y);
}
p.text(circleItem.website, xPositionForCircle, position.y + 20);
p.pop();
} else {
p.push();
p.stroke(config.timeline.colors.grey);
timeline.drawCircle(index);
p.pop();
}
p.text(circleItem.website, xPositionForCircle, position.y + 20);
p.pop();

timeline.drawLineAboveCircle(index);
});
Expand All @@ -179,19 +187,16 @@ timeline.drawTimelineLine = () => {
const p = app.p;
let x = 0;

if (app.timeline.currentIndex === 0) {
p.push();
p.stroke(colors.grey);
p.line(
0,
yPositonForLine,
config.timeline.position.x +
circleVerticalSpace * (config.timeline.circles.length - 1),
yPositonForLine
);
p.pop();
return;
}
p.push();
p.stroke(colors.grey);
p.line(
0,
yPositonForLine,
config.timeline.position.x +
circleVerticalSpace * (config.timeline.circles.length - 1),
yPositonForLine
);
p.pop();

while (
x <=
Expand All @@ -200,7 +205,7 @@ timeline.drawTimelineLine = () => {
app.timeline.currentIndex < config.timeline.circles.length
) {
p.push();
p.stroke(26, 115, 232);
p.stroke(colors.visitedBlue);
p.line(0, yPositonForLine, x, yPositonForLine);
p.pop();
x = x + 1;
Expand Down Expand Up @@ -237,7 +242,6 @@ timeline.renderUserIcon = () => {
}

const user = config.timeline.user;

timeline.eraseAndRedraw();
utils.wipeAndRecreateInterestCanvas();

Expand Down Expand Up @@ -269,7 +273,6 @@ timeline.eraseAndRedraw = () => {
utils.wipeAndRecreateUserCanvas();

if (currentIndex > 0) {
timeline.drawTimelineLine();
let i = 0;
while (i < currentIndex) {
app.p.push();
Expand Down
Loading

0 comments on commit 59256d3

Please sign in to comment.