diff --git a/vis/globe/animation.js b/vis/globe/animation.js index 0a63da8..f56c611 100644 --- a/vis/globe/animation.js +++ b/vis/globe/animation.js @@ -6,13 +6,15 @@ let time; -let mainAnimationPlaying = false; -let mainAnimationDone = true; +let mainAnimationPlaying = false; +let mainAnimationDone = true; +let droppingMeteorites = false; -let mainAnimationTimeouts = []; +let mainAnimationTimeouts = []; +let droppingMeteoritesTimeout = null; -let yearCallbackSchedule = {}; -let yearMinimumDurations = {}; +let yearCallbackSchedule = {}; +let yearMinimumDurations = {}; /* Functions @@ -55,113 +57,120 @@ function clearMinimumDurations() { yearMinimumDurations = {}; } -function incrementTime() { +function setTime(newTime) { - if (time < timelineEnd()) { + if (newTime < timelineStart() || newTime > timelineEnd()) { + return; + } - // Increment time - time++; + // Set time + time = newTime; - // Update the timeline time indicator - updateTimeIndicator(); + // Update the timeline time indicator + updateTimeIndicator(); - // Check if there are callbacks - // scheduled for this year - if (time in yearCallbackSchedule) { + hideMessage(); - // Run the scheduled callbacks - yearCallbackSchedule[time].forEach(callback => callback(time)); + // Check if there are callbacks + // scheduled for this year + if (time in yearCallbackSchedule) { - // Remove the callbacks - delete yearCallbackSchedule[time]; + // Run the scheduled callbacks + yearCallbackSchedule[time].forEach(callback => callback(time)); - } + // Remove the callbacks + delete yearCallbackSchedule[time]; } } -// function mainAnimation() { -function nextYear() { - - function dropMeteorites() { - - mainAnimationTimeouts = []; +function dropMeteorites() { - const FILTERED_DATA = meteoriteData.filter(entry => entry.year.getFullYear() === time); - const COUNT = FILTERED_DATA.length; + clearMainAnimationTimeouts(); - const LOG = Math.log10(COUNT); - - let totalDuration; - - if (COUNT === 0) { + if (droppingMeteoritesTimeout !== null) { + clearTimeout(droppingMeteoritesTimeout); + droppingMeteoritesTimeout = null; + droppingMeteorites = false; + } - totalDuration = SECOND; + const FILTERED_DATA = meteoriteData.filter(entry => entry.year.getFullYear() === time); + const COUNT = FILTERED_DATA.length; - // } else if (COUNT < 16) { + if (COUNT === 0) { + return; + } - // totalDuration = FALL_DURATION; + droppingMeteorites = true; - } else { + const LOG = Math.log10(COUNT); - const LAUNCH_DURATION = (LOG ** 3) * SECOND; + const LAUNCH_DURATION = (LOG ** 3) * SECOND; - const SQRT = Math.sqrt(COUNT); - const GROUP_COUNT = Math.round(SQRT); - const WHOLE_GROUP_SIZE = Math.ceil(SQRT); + const SQRT = Math.sqrt(COUNT); + const GROUP_COUNT = Math.round(SQRT); + const WHOLE_GROUP_SIZE = Math.ceil(SQRT); - const DELTA_TIME = (GROUP_COUNT === 1) ? 0 : LAUNCH_DURATION / (GROUP_COUNT - 1); + const DELTA_TIME = (GROUP_COUNT === 1) ? 0 : LAUNCH_DURATION / (GROUP_COUNT - 1); - totalDuration = LAUNCH_DURATION + FALL_DURATION; + /*let index = 0; + for (let i = 0 ; i < GROUP_COUNT ; i++) { + setTimeout(() => { - /*let index = 0; - for (let i = 0 ; i < GROUP_COUNT ; i++) { - setTimeout(() => { + FILTERED_DATA.slice(index, index + WHOLE_GROUP_SIZE).forEach((meteorite, i) => + launchMeteorite(meteorite.long, meteorite.lat, meteorite.mass)); - FILTERED_DATA.slice(index, index + WHOLE_GROUP_SIZE).forEach((meteorite, i) => - launchMeteorite(meteorite.long, meteorite.lat, meteorite.mass)); + index += WHOLE_GROUP_SIZE; - index += WHOLE_GROUP_SIZE; + }, DELTA_TIME * i); + }*/ - }, DELTA_TIME * i); - }*/ + let duration = 0; + let largestDuration = 0; - let duration = 0; - FILTERED_DATA.forEach((meteorite, i) => { + FILTERED_DATA.forEach((meteorite, i) => { - mainAnimationTimeouts.push(setTimeout(() => { - launchMeteorite(meteorite.long, meteorite.lat, meteorite.mass); - }, duration)); + mainAnimationTimeouts.push(setTimeout(() => { + launchMeteorite(meteorite.long, meteorite.lat, meteorite.mass); + }, duration)); - duration += 50; - duration %= LAUNCH_DURATION; + if (duration > largestDuration) { + largestDuration = duration; + } - }); + duration += 50; + duration %= LAUNCH_DURATION; - /*FILTERED_DATA.forEach((meteorite, i) => { - setTimeout(() => dropMeteorite(meteorite.long, meteorite.lat, meteorite.mass), - i * 500); - });*/ + }); - } + /*FILTERED_DATA.forEach((meteorite, i) => { + setTimeout(() => dropMeteorite(meteorite.long, meteorite.lat, meteorite.mass), + i * 500); + });*/ - } + droppingMeteoritesTimeout = setTimeout(() => { + droppingMeteorites = false; + }, largestDuration + FALL_DURATION); - if (mainAnimationPlaying) { +} - incrementTime(); +function setYear(year) { - dropMeteorites(); + setTime(year); - if (time === timelineEnd()) { - mainAnimationDone = true; - } + dropMeteorites(); + if (time === timelineEnd()) { + mainAnimationDone = true; } } +function nextYear() { + setYear(time + 1); +} + function resumeMainAnimation() { if (!mainAnimationPlaying) { @@ -187,6 +196,7 @@ function startMainAnimation() { mainAnimationPlaying = true; mainAnimationDone = false; + droppingMeteorites = false; resumeGlobeAnimation(); @@ -214,4 +224,5 @@ function backToGlobalView() { function clearMainAnimationTimeouts() { mainAnimationTimeouts.forEach(timeout => clearTimeout(timeout)); + mainAnimationTimeouts = []; } diff --git a/vis/globe/main.js b/vis/globe/main.js index 7766be8..8135d2b 100644 --- a/vis/globe/main.js +++ b/vis/globe/main.js @@ -271,11 +271,13 @@ function renderLoop() { } if (mainAnimationPlaying) { + updateMeteorites(); - } - if ((METEORITES.length === 0) && !mainAnimationDone) { - nextYear(); + if (!droppingMeteorites && !mainAnimationDone) { + nextYear(); + } + } adjustCameraZoom(); diff --git a/vis/message.js b/vis/message.js index bacfca9..d493294 100644 --- a/vis/message.js +++ b/vis/message.js @@ -117,3 +117,7 @@ function showMessage(year) { $(this).delay(50 * i).fadeIn(300); }); } + +function hideMessage() { + $("#messages").empty(); +} diff --git a/vis/timeline/main.js b/vis/timeline/main.js index 016efa5..dad4ea3 100644 --- a/vis/timeline/main.js +++ b/vis/timeline/main.js @@ -43,7 +43,9 @@ const TIMELINE_TRANSITION = d3.transition() let xTimeline = d3.scaleTime() .range([0, TIMELINE_CHART_DIMENSIONS.WIDTH]); -let xAxisTimeline = d3.axisBottom(xTimeline); +let xAxisTimeline = d3.axisBottom(xTimeline) + .ticks(d3.timeYear.every(20)) + .tickFormat(d3.timeFormat('%Y')); let timelineBarWidth = 0; @@ -135,7 +137,6 @@ function timelineBarsClickListener(d) { clearMainAnimationTimeouts(); explodeMeteoritesInMidAir(); - time = d.year.getFullYear(); - updateTimeIndicator(); + setYear(d.year.getFullYear()); } diff --git a/vis/timeline/time-indicator.js b/vis/timeline/time-indicator.js index 19e79df..2dbe1b1 100644 --- a/vis/timeline/time-indicator.js +++ b/vis/timeline/time-indicator.js @@ -91,13 +91,11 @@ window.addEventListener('mouseup', event => { const X = clamp(event.clientX, LEFT_LIMIT, RIGHT_LIMIT) - LEFT_LIMIT; - time = clamp(xTimeline.invert(X).getFullYear(), timelineStart(), timelineEnd()); - - updateTimeIndicator(); - clearMainAnimationTimeouts(); explodeMeteoritesInMidAir(); + setYear(clamp(xTimeline.invert(X).getFullYear(), timelineStart(), timelineEnd())); + if (playPauseState) { resumeMainAnimation(); }