Merge pull request #1428 from Hans5958/live-love-life/2

Various "minor" changes (2)
This commit is contained in:
Stefano 2023-04-07 13:11:08 +02:00 committed by GitHub
commit 2dfd02a8a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 9109 additions and 9284 deletions

1
.gitignore vendored
View file

@ -16,7 +16,6 @@ combined.js
# Build files
node_modules/
/yarn.lock
dist*/
# Cache folders

View file

@ -2,7 +2,7 @@
This project is open source, and contributions are welcome. In fact, the Atlas relies on user contributions.
You may contribute to the project by submitting a Pull Request on the GitHub repo or sending your submissions through [Reddit](https://www.reddit.com/r/placeAtlas2). Other than than, you cau use [Discord](https://discord.gg/pJkm23b2nA) or [Reddit](https://www.reddit.com/r/placeAtlas2) for help.
You may contribute to the project by submitting a Pull Request on the GitHub repo or sending your submissions through [Reddit](https://www.reddit.com/r/placeAtlas2). Other than that, you can get help from [Discord](https://discord.gg/pJkm23b2nA) or [Reddit](https://www.reddit.com/r/placeAtlas2).
## New Atlas entries
@ -26,7 +26,9 @@ When you're happy with the shape you've drawn, press <kbd>Finish</kbd>. You will
All fields but the name are optional. For example, a country flag doesn't necessarily need a description.
Once you've entered all the information, you'll be presented with a pop-up window containing some [JSON](https://en.wikipedia.org/wiki/JSON)-formatted data. You can press the <kbd>Post Direct to Reddit</kbd> button, or copy the entire JSON text and [create a new text post on the subreddit](https://www.reddit.com/r/placeAtlas2/submit). Remember to flair your post with <kbd>New Entry</kvd>.
Once you've entered all the information, you'll be presented with a pop-up window containing some [JSON](https://en.wikipedia.org/wiki/JSON)-formatted data. You can press the <kbd>Post Direct to Reddit</kbd> button and just press the send button on Reddit, or copy the entire JSON text and [create a new text post on the subreddit](https://www.reddit.com/r/placeAtlas2/submit). You don't need to add any other text; just directly send the data.
Remember to flair your post with <kbd>New Entry</kbd>. On New Reddit, click the <kbd>Flair</kbd> button on the bottom part, and select <kbd>New Entry</kbd>. On Old Reddit, click the <kbd>select</kbd> button on the "choose a flair" section instead.
## Edits to Atlas entries
@ -34,7 +36,7 @@ Other than adding new ones, you can edit existing atlas entries.
### Using the web interface
You can use the website to edit single entries easily. On the website, click <kbd>Edit</kbd> on an entry box. Afterwards, you can follow the same instructions as [when creating a new entry](#new-atlas-entries). Upon submitting, please label it as <kbd>Edit Entry</kbd> instead.
You can use the website to edit single entries easily. On the website, click <kbd>Edit</kbd> on an entry box. Afterwards, you are now on the drawing mode, editing the entry, in which you can follow the same instructions as [when creating a new entry](#new-atlas-entries). Upon submitting, please flair it as <kbd>Edit Entry</kbd> instead.
As an alternative, you can also submit an issue on GitHub using [this form](https://github.com/placeAtlas/atlas/issues/new?assignees=&labels=entry+update&template=edit-entry.yml).
@ -44,6 +46,15 @@ Edits are also welcome on this repository through GitHub. You may use GitHub for
`web/atlas.json` is where the Atlas data is located, in which you can edit on GitHub. Below is an example of an entry. The example has been expanded, but please save it in the way so each line is an entry which is minified.
Upon creating a fork of this repository and pushing the changes, create a Pull Request against the `cleanup` branch. A member will merge the pull request if it is adequate.
To help find duplicates, [use the Overlap mode](https://place-atlas.stefanocoding.me?mode=overlap).
### Example
Hereforth is an example of the structured data.
```json5
{
"id": "tu203o",
@ -56,13 +67,10 @@ Edits are also welcome on this repository through GitHub. You may use GitHub for
"wiki": ["An_Entry", "An_Entry_2"]
},
"path": {
// 109-166: Default canvas variation (r/place), period 109 to 166.
// T:0-1: "The Final Clean" canvas variation, period 0 (The Final Clean) to 1 (Unofficial Corrections).
"109-166, T:0-1": [
[1527, 1712],
[1625, 1712],
[1625, 1682],
// ...
[1625, 1682]
]
},
"center": {
@ -71,9 +79,9 @@ Edits are also welcome on this repository through GitHub. You may use GitHub for
}
```
Upon creating a fork of this repository and pushing the changes, create a Pull Request against the `cleanup` branch. A member will merge the pull request if it is adequate.
To help find duplicates, [use the Overlap mode](https://place-atlas.stefanocoding.me?mode=overlap).
`109-166, T:0-1` has this meaning.
- `109-166`: Default canvas variation (r/place), period [109](https://place-atlas.stefanocoding.me/#/109) to [166](https://place-atlas.stefanocoding.me/#/166).
- `T:0-1`: "The Final Clean" canvas variation, period [0](https://place-atlas.stefanocoding.me/#/T:0) (The Final Clean) to [1](https://place-atlas.stefanocoding.me/#/T:1) (Unofficial Corrections).
## Development

17966
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,24 @@
{
"devDependencies": {
"@fullhuman/postcss-purgecss": "^4.1.3",
"@parcel/packager-raw-url": "^2.5.0",
"@parcel/transformer-jsonld": "^2.5.0",
"@parcel/transformer-webmanifest": "^2.5.0",
"parcel": "^2.5.0",
"parcel-namer-rewrite": "^2.0.0-rc.2",
"@fullhuman/postcss-purgecss": "^5.0.0",
"@parcel/packager-raw-url": "^2.8.3",
"@parcel/transformer-jsonld": "^2.8.3",
"@parcel/transformer-webmanifest": "^2.8.3",
"parcel": "^2.8.3",
"parcel-namer-rewrite": "^2.0.0-rc.3",
"parcel-resolver-ignore": "^2.1.3",
"postcss": "^8.4.12",
"all-contributors-cli": "^6.23.1"
"postcss": "^8.4.21",
"all-contributors-cli": "^6.24.0"
},
"parcel-namer-rewrite": {
"rules": {
"^(icon-.+)\\.(svg|png|gif|jpg|jpeg)": "_img/pwa/$1.$2",
"^(screenshot-.+)\\.(svg|png|gif|jpg|jpeg)": "_img/pwa/$1.$2",
"(.*)\\.(svg|png|gif|jpg|jpeg)": "_img/$1.$2",
"(.*)\\.(css|woff2?)": "_css/$1{.hash}.$2",
"(.*)\\.(js)": "_js/$1{.hash}.$2"
}
},
"parcelIgnore": [
"sw.js"
"sw.js",
"_img/.+"
],
"browserslist": [
">= 0.5%",

View file

@ -94,7 +94,7 @@ const variationsConfig = {
{ "timestamp": 1648911600, "url": ["./_img/canvas/place30/049.png", "./_img/canvas/place30/051_049.png"] },
{ "timestamp": 1648913400, "url": ["./_img/canvas/place30/049.png", "./_img/canvas/place30/052_049.png"] },
{ "timestamp": 1648915200, "url": ["./_img/canvas/place30/049.png", "./_img/canvas/place30/053_049.png"] },
{ "timestamp": 1648917000, "url": ["./_img/canvas/place30/049.png", "./_img/canvas/place30/054_049.png"] },
{ "timestamp": ["First Expansion", 1648917000], "url": ["./_img/canvas/place30/049.png", "./_img/canvas/place30/054_049.png"] },
{ "timestamp": 1648918800, "url": ["./_img/canvas/place30/060.png", "./_img/canvas/place30/055_060.png"] },
{ "timestamp": 1648920600, "url": ["./_img/canvas/place30/060.png", "./_img/canvas/place30/056_060.png"] },
{ "timestamp": 1648922400, "url": ["./_img/canvas/place30/060.png", "./_img/canvas/place30/057_060.png"] },
@ -148,7 +148,7 @@ const variationsConfig = {
{ "timestamp": 1649008800, "url": ["./_img/canvas/place30/104.png", "./_img/canvas/place30/105_104.png"] },
{ "timestamp": 1649010600, "url": ["./_img/canvas/place30/104.png", "./_img/canvas/place30/106_104.png"] },
{ "timestamp": 1649012400, "url": ["./_img/canvas/place30/104.png", "./_img/canvas/place30/107_104.png"] },
{ "timestamp": 1649014200, "url": ["./_img/canvas/place30/104.png", "./_img/canvas/place30/108_104.png"] },
{ "timestamp": ["Second Expansion", 1649014200], "url": ["./_img/canvas/place30/104.png", "./_img/canvas/place30/108_104.png"] },
{ "timestamp": 1649016000, "url": ["./_img/canvas/place30/104.png", "./_img/canvas/place30/109_104.png"] },
{ "timestamp": 1649017800, "url": ["./_img/canvas/place30/115.png", "./_img/canvas/place30/110_115.png"] },
{ "timestamp": 1649019600, "url": ["./_img/canvas/place30/115.png", "./_img/canvas/place30/111_115.png"] },
@ -203,7 +203,7 @@ const variationsConfig = {
{ "timestamp": 1649107800, "url": ["./_img/canvas/place30/159.png", "./_img/canvas/place30/160_159.png"] },
{ "timestamp": 1649109600, "url": ["./_img/canvas/place30/159.png", "./_img/canvas/place30/161_159.png"] },
{ "timestamp": 1649111400, "url": ["./_img/canvas/place30/159.png", "./_img/canvas/place30/162_159.png"] },
{ "timestamp": 1649112460, "url": ["./_img/canvas/place30ex/final.png"] },
{ "timestamp": ["Final Canvas", 1649112460], "url": ["./_img/canvas/place30ex/final.png"] },
{ "timestamp": 1649113200, "url": ["./_img/canvas/place30/159.png", "./_img/canvas/place30/163_159.png"] },
{ "timestamp": 1649115000, "url": ["./_img/canvas/place30/159.png", "./_img/canvas/place30/164_159.png"] },
{ "timestamp": 1649116800, "url": ["./_img/canvas/place30/159.png", "./_img/canvas/place30/165_159.png"] },
@ -245,6 +245,15 @@ const variationsConfig = {
}
window.variationsConfig = variationsConfig
let defaultVariation = 'default'
window.defaultVariation = defaultVariation
let defaultPeriod = variationsConfig[defaultVariation].default
window.defaultPeriod = defaultPeriod
const useNumericalId = false
window.useNumericalId = useNumericalId
console.info(`%cThe 2022 r/place Atlas
%cCopyright (c) 2017 Roland Rytz <roland@draemm.li>
Copyright (c) 2022 Place Atlas contributors

View file

@ -5,7 +5,7 @@
* Licensed under AGPL-3.0 (https://place-atlas.stefanocoding.me/license.txt)
*/
window.addEventListener("error", function (e) {
window.addEventListener("error", e => {
console.error(e)
let errorMessage = "<h4 class=\"mb-3\">An error has occurred:</h4>"
errorMessage += "<p class=\"text-danger\">" + e.message + "</p>"

View file

@ -118,7 +118,7 @@ function initDraw() {
render(path)
container.addEventListener("mousedown", function (e) {
container.addEventListener("mousedown", e => {
lastPos = [
e.clientX,
e.clientY
@ -147,7 +147,7 @@ function initDraw() {
return pos
}
container.addEventListener("mouseup", function (e) {
container.addEventListener("mouseup", e => {
if (Math.abs(lastPos[0] - e.clientX) + Math.abs(lastPos[1] - e.clientY) <= 4 && drawing) {
@ -168,7 +168,7 @@ function initDraw() {
}
})
container.addEventListener("mousemove", function (e) {
container.addEventListener("mousemove", e => {
if (!dragging && drawing && path.length > 0) {
const coords = getCanvasCoords(e.clientX, e.clientY)
render([...path, coords])
@ -181,7 +181,7 @@ function initDraw() {
}
})
window.addEventListener("keyup", function (e) {
window.addEventListener("keyup", e => {
if (e.key === "z" && e.ctrlKey) {
undo()
} else if (e.key === "y" && e.ctrlKey) {
@ -196,7 +196,7 @@ function initDraw() {
}
})
window.addEventListener("keydown", function (e) {
window.addEventListener("keydown", e => {
if (e.key === "Shift") {
if (e.code === "ShiftRight") {
rShiftPressed = true
@ -211,19 +211,19 @@ function initDraw() {
finish()
})
undoButton.addEventListener("click", function (e) {
undoButton.addEventListener("click", e => {
undo()
const coords = getCanvasCoords(e.clientX, e.clientY)
render([...path, coords])
})
redoButton.addEventListener("click", function (e) {
redoButton.addEventListener("click", e => {
redo()
const coords = getCanvasCoords(e.clientX, e.clientY)
render([...path, coords])
})
resetButton.addEventListener("click", function (e) {
resetButton.addEventListener("click", e => {
reset()
const coords = getCanvasCoords(e.clientX, e.clientY)
render([...path, coords])
@ -243,7 +243,7 @@ function initDraw() {
exportButton.focus()
})
objectInfoForm.addEventListener('submit', function (e) {
objectInfoForm.addEventListener('submit', e => {
e.preventDefault()
// Allows for html form validation with preview button
if (e.submitter && e.submitter.value === "Preview") {
@ -268,6 +268,10 @@ function initDraw() {
center: {},
}
if (useNumericalId) {
if (!isNaN(Number(exportObject.id))) exportObject.id = Number(exportObject.id)
}
const pathWithPeriodsTemp = JSON.parse(JSON.stringify(pathWithPeriods))
for (let i = pathWithPeriodsTemp.length - 1; i > 0; i--) {
@ -347,19 +351,17 @@ function initDraw() {
}
function undo() {
if (path.length > 0 && drawing) {
undoHistory.push(path.pop())
redoButton.disabled = false
updatePath(path, undoHistory)
}
if (path.length == 0 || !drawing) return
undoHistory.push(path.pop())
redoButton.disabled = false
updatePath(path, undoHistory)
}
function redo() {
if (undoHistory.length > 0 && drawing) {
path.push(undoHistory.pop())
undoButton.disabled = false
updatePath(path, undoHistory)
}
if (undoHistory.length == 0 || !drawing) return
path.push(undoHistory.pop())
undoButton.disabled = false
updatePath(path, undoHistory)
}
function finish() {
@ -436,7 +438,7 @@ function initDraw() {
function renderBackground() {
backgroundContext.clearRect(0, 0, canvas.width, canvas.height)
backgroundContext.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height)
backgroundContext.fillStyle = "rgba(0, 0, 0, 1)"
//backgroundContext.fillRect(0, 0, canvas.width, canvas.height)
@ -465,60 +467,59 @@ function initDraw() {
if (!Array.isArray(path)) return
context.globalCompositeOperation = "source-over"
context.clearRect(0, 0, canvas.width, canvas.height)
highlightContext.globalCompositeOperation = "source-over"
highlightContext.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height)
if (highlightUncharted) {
context.drawImage(backgroundCanvas, 0, 0)
context.fillStyle = "rgba(0, 0, 0, 0.4)"
highlightContext.drawImage(backgroundCanvas, 0, 0)
highlightContext.fillStyle = "rgba(0, 0, 0, 0.4)"
} else {
context.fillStyle = "rgba(0, 0, 0, 0.6)"
highlightContext.fillStyle = "rgba(0, 0, 0, 0.6)"
}
context.fillRect(0, 0, canvas.width, canvas.height)
highlightContext.fillRect(0, 0, highlightCanvas.width, highlightCanvas.height)
context.beginPath()
highlightContext.beginPath()
if (path[0]) {
context.moveTo(path[0][0], path[0][1])
highlightContext.moveTo(path[0][0], path[0][1])
}
for (let i = 1; i < path.length; i++) {
context.lineTo(path[i][0], path[i][1])
highlightContext.lineTo(path[i][0], path[i][1])
}
context.closePath()
highlightContext.closePath()
context.strokeStyle = "rgba(255, 255, 255, 1)"
context.stroke()
highlightContext.strokeStyle = "rgba(255, 255, 255, 1)"
highlightContext.stroke()
context.globalCompositeOperation = "destination-out"
highlightContext.globalCompositeOperation = "destination-out"
context.fillStyle = "rgba(0, 0, 0, 1)"
context.fill()
highlightContext.fillStyle = "rgba(0, 0, 0, 1)"
highlightContext.fill()
}
function updateHovering(e, tapped) {
if (!dragging && (!fixed || tapped)) {
const pos = [
(e.clientX - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft)) / zoom,
(e.clientY - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop)) / zoom
]
if (dragging || (fixed && !tapped)) return
const pos = [
(e.clientX - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft)) / zoom,
(e.clientY - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop)) / zoom
]
const coords_p = document.getElementById("coords_p")
const coordsEl = document.getElementById("coords_p")
// Displays coordinates as zero instead of NaN
if (isNaN(pos[0]) === true) {
coords_p.textContent = "0, 0"
} else {
coords_p.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
}
// Displays coordinates as zero instead of NaN
if (isNaN(pos[0])) {
coordsEl.textContent = "0, 0"
} else {
coordsEl.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
}
}
const getEntry = id => {
const entries = atlasAll.filter(entry => entry.id === id)
const entries = atlasAll.filter(entry => entry.id.toString() === id.toString())
if (entries.length === 1) return entries[0]
return {}
}
@ -597,7 +598,7 @@ function initDraw() {
inputField.pattern = "^r\/[A-Za-z0-9][A-Za-z0-9_]{1,20}$"
inputField.title = "Subreddit in format of r/example"
inputField.minLength = "4"
inputField.maxLength = "23"
inputField.maxLength = "22"
inputField.setAttribute("aria-labelledby", "subredditLabel")
inputField.setAttribute("aria-describedby", "subredditField" + index + "-addon")
if (link) {
@ -623,7 +624,7 @@ function initDraw() {
inputButton.addEventListener('click', () => removeFieldButton(inputGroup, array, index))
}
inputField.addEventListener('paste', (event) => {
inputField.addEventListener('paste', event => {
let paste = (event.clipboardData || window.clipboardData).getData('text')
paste = paste.trim().match(subredditPattern)?.[1]
if (paste) {
@ -668,7 +669,7 @@ function initDraw() {
inputButton.addEventListener('click', () => removeFieldButton(inputGroup, array, index))
}
inputField.addEventListener('paste', (event) => {
inputField.addEventListener('paste', event => {
let paste = (event.clipboardData || window.clipboardData).getData('text')
paste = paste.trim().match(discordPattern)?.[1]
if (paste) {
@ -782,7 +783,7 @@ function initDraw() {
drawBackButton.href = "./" + formatHash(entryId, currentPeriod, currentPeriod, currentVariation)
document.addEventListener('timeupdate', (event) => {
document.addEventListener('timeupdate', event => {
drawBackButton.href = "./" + formatHash(entryId, event.detail.period, event.detail.period, event.detail.variation)
})
@ -870,7 +871,7 @@ function initPeriodGroups() {
if (startPeriodEl.max === 0) periodGroupEl.classList.add('no-time-slider')
else periodGroupEl.classList.remove('no-time-slider')
// If one period disable delete
// Disable delete if only one period
if (pathWithPeriods.length === 1) periodDeleteEl.disabled = true
startPeriodEl.addEventListener('input', () => {
@ -1160,7 +1161,7 @@ function updatePeriodGroups() {
startPeriodEl.disabled = false
endPeriodEl.disabled = false
// If one period disable delete
// Disable delete if only one period
if (pathWithPeriods.length === 1) periodDeleteEl.disabled = true
else periodDeleteEl.disabled = false
@ -1331,8 +1332,8 @@ function getConflicts() {
(start1 <= start2 && start2 <= end1) ||
(start1 <= end2 && end2 <= end1)
) {
if (!conflicts[i]) conflicts[i] = []
if (!conflicts[j]) conflicts[j] = []
conflicts[i] ||= []
conflicts[j] ||= []
conflicts[i].push(j)
conflicts[j].push(i)
}

View file

@ -7,14 +7,14 @@
const innerContainer = document.getElementById("innerContainer")
const container = document.getElementById("container")
const canvas = document.getElementById("highlightCanvas")
const canvasImage = document.getElementById('image')
const context = canvas.getContext("2d")
const highlightCanvas = document.getElementById("highlightCanvas")
const imageCanvas = document.getElementById('image')
const highlightContext = highlightCanvas.getContext("2d")
canvas.width = canvasSize.x
canvas.height = canvasSize.y
canvasImage.width = canvasSize.x
canvasImage.height = canvasSize.y
highlightCanvas.width = canvasSize.x
highlightCanvas.height = canvasSize.y
imageCanvas.width = canvasSize.x
imageCanvas.height = canvasSize.y
let zoom = 1
@ -95,13 +95,10 @@ async function init() {
const args = window.location.search
const params = new URLSearchParams(args)
if (args) {
mode = params.get("mode")
if (!mode) {
mode = "view"
}
mode = params.get("mode") || "view"
// Backwards compatibility for old links using "search" id arg
if (params.has('id') && params.get('mode') !== 'draw') {
if (params.has('id') && mode !== 'draw') {
const id = params.get('id')
params.delete('id')
const newLocation = new URL(window.location)
@ -146,6 +143,8 @@ async function init() {
if (initOverlap) {
initOverlap()
}
} else if (mode === "explore") {
initExplore()
} else if (mode.startsWith("diff")) {
try {
const liveResp = await fetch(`https://${prodDomain}/atlas.json`)
@ -195,8 +194,6 @@ async function init() {
initView()
}
}
} else if (mode === "explore") {
initExplore()
} else {
initView()
}
@ -220,7 +217,7 @@ async function init() {
initialPinchZoom = zoom
lastPosition = [x, y]
zoom = zoom * 2
zoom *= 2
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
applyZoom(x, y, zoom)
@ -258,7 +255,7 @@ async function init() {
applyView()
})
container.addEventListener("dblclick", function (e) {
container.addEventListener("dblclick", e => {
/*if(zoomAnimationFrame){
window.cancelAnimationFrame(zoomAnimationFrame)
}*/
@ -285,7 +282,7 @@ async function init() {
})
container.addEventListener("wheel", function (e) {
container.addEventListener("wheel", e => {
/*if(zoomAnimationFrame){
window.cancelAnimationFrame(zoomAnimationFrame)
@ -311,14 +308,8 @@ async function init() {
// This creates a smoother experience
zoom -= e.deltaY * (0.001 * zoom)
} else {
if (e.deltaY > 0) {
zoom = zoom / 2
} else if (e.deltaY < 0) {
zoom = zoom * 2
}
if (e.deltaY > 0) zoom /= 2
else if (e.deltaY < 0) zoom *= 2
}
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
@ -339,12 +330,12 @@ async function init() {
}
}*/
container.addEventListener("mousedown", function (e) {
container.addEventListener("mousedown", e => {
mousedown(e.clientX, e.clientY)
e.preventDefault()
})
container.addEventListener("touchstart", function (e) {
container.addEventListener("touchstart", e => {
if (e.touches.length === 2) {
e.preventDefault()
@ -387,14 +378,14 @@ async function init() {
}
window.addEventListener("mousemove", function (e) {
window.addEventListener("mousemove", e => {
updateLines()
mousemove(e.clientX, e.clientY)
if (dragging) {
e.preventDefault()
}
})
window.addEventListener("touchmove", function (e) {
window.addEventListener("touchmove", e => {
if (e.touches.length === 2 || e.scale > 1) {
e.preventDefault()
@ -469,7 +460,7 @@ async function init() {
updateLines()
}
window.addEventListener("mouseup", function (e) {
window.addEventListener("mouseup", e => {
if (hovered.length > 0) {
container.style.cursor = "pointer"
} else if (drawing === true) {
@ -495,6 +486,7 @@ async function init() {
if (e.touches.length === 0) {
mouseup()
setTimeout(() => updateLines(), 0)
} else if (e.touches.length === 1) {
initialPinchZoom = zoom

View file

@ -15,7 +15,7 @@ function initOverlap() {
renderBackground(atlas)
render()
document.addEventListener('timeupdate', (event) => {
document.addEventListener('timeupdate', () => {
sortedAtlas = atlas.concat()
resetEntriesList(null, null)
renderBackground(sortedAtlas)
@ -32,14 +32,14 @@ function initOverlap() {
function renderBackground(atlas) {
backgroundContext.clearRect(0, 0, canvas.width, canvas.height)
backgroundContext.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height)
backgroundContext.fillStyle = "rgba(255, 255, 255, 1)"
backgroundContext.fillRect(0, 0, canvas.width, canvas.height)
backgroundContext.fillRect(0, 0, highlightCanvas.width, highlightCanvas.height)
for (let i = 0; i < atlas.length; i++) {
for (const entry of atlas) {
const path = atlas[i].path
const path = entry.path
backgroundContext.beginPath()

View file

@ -8,9 +8,9 @@
let areasSum = 0
const areas = []
for (let q = 0; q < atlas.length; q++) {
for (const entry of atlas) {
const path = atlas[q].path
const path = entry.path
let area = 0,
i,
@ -30,31 +30,13 @@ for (let q = 0; q < atlas.length; q++) {
areasSum += area
areas.push(area)
atlas[q].area = area
entry.area = area
}
areas.sort(function (a, b) {
if (a < b) {
return -1
}
if (a > b) {
return 1
}
// a must be equal to b
return 0
})
areas.sort((a, b) => a - b)
atlas.sort(function (a, b) {
if (a.area < b.area) {
return -1
}
if (a.area > b.area) {
return 1
}
// a must be equal to b
return 0
})
atlas.sort((a, b) => a.area - b.area)
const el = document.createElement("canvas")
el.style.position = "absolute"
@ -68,10 +50,8 @@ const max = 1500
let largerThanMax = 0
for (const i in areas) {
if (areas[i] > max) {
largerThanMax++
}
for (const area of areas) {
if (area > max) largerThanMax++
}
console.info("There are " + largerThanMax + " entries larger than " + max + ", accounting for " + (largerThanMax / areas.length * 100) + "% of all entries.")
@ -88,9 +68,7 @@ for (const i in areas) {
if (areas[i] > (bracket + 1) * (max / steps)) {
mostCounts = Math.max(mostCounts, counts[bracket])
bracket++
if (bracket >= steps) {
break
}
if (bracket >= steps) break
counts[bracket] = 0
brackets[bracket] = (bracket + 1) * (max / steps)
}
@ -185,11 +163,8 @@ ctx.fillStyle = "#FF0000"
ctx.strokeStyle = "#CC0000"
for (let i = 0; i < counts.length; i++) {
if (i % 2 === 0) {
ctx.fillStyle = "#FF0000"
} else {
ctx.fillStyle = "#DD0000"
}
if (i % 2) ctx.fillStyle = "#DD0000"
else ctx.fillStyle = "#FF0000"
ctx.fillRect(
~~((i / steps) * (el.width - 125) + 75),

View file

@ -27,12 +27,10 @@ let currentUpdateIndex = 0
let updateTimeout = setTimeout(null, 0)
let tooltipDelayHide = setTimeout(null, 0)
let currentVariation = "default"
const defaultPeriod = variationsConfig[currentVariation].default
const defaultVariation = currentVariation
let currentVariation = defaultVariation
let currentPeriod = defaultPeriod
window.currentPeriod = currentPeriod
window.currentVariation = currentVariation
window.currentPeriod = currentPeriod
// SETUP
if (variationsConfig[currentVariation].versions.length === 1) bottomBar.classList.add('no-time-slider')
@ -41,9 +39,9 @@ timelineSlider.max = variationsConfig[currentVariation].versions.length - 1
timelineSlider.value = currentPeriod
timelineList.children[0].value = defaultPeriod
timelineSlider.addEventListener("input", (e) => timelineParser(e.target.value))
timelineSlider.addEventListener("input", e => timelineParser(e.target.value))
timelineSlider.addEventListener("wheel", function (e) {
timelineSlider.addEventListener("wheel", e => {
if (e.deltaY < 0) {
this.valueAsNumber += 1;
timelineParser(this.value)
@ -67,7 +65,7 @@ function timelineParser(value) {
}, 25)
}
variantsEl.addEventListener("input", (event) => {
variantsEl.addEventListener("input", event => {
updateTime(-1, event.target.value)
})
@ -103,6 +101,8 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren
const configObject = variationConfig.versions[currentPeriod]
let layerUrls = []
let layers = []
if (typeof configObject.url === "string") {
layerUrls.push(configObject.url)
} else {
@ -110,19 +110,23 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren
}
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
context.canvas.width = canvasSize.x
context.canvas.height = canvasSize.y
for await (const url of layerUrls) {
const imageLayer = new Image()
await new Promise(resolve => {
imageLayer.onload = () => {
context.drawImage(imageLayer, 0, 0)
context.canvas.width = Math.max(imageLayer.width, context.canvas.width)
context.canvas.height = Math.max(imageLayer.height, context.canvas.height)
layers.push(imageLayer)
resolve()
}
imageLayer.src = url
})
}
for (const imageLayer of layers) {
context.drawImage(imageLayer, 0, 0)
}
if (currentUpdateIndex !== myUpdateIndex) return [configObject, newPeriod, newVariation]
const blob = await new Promise(resolve => canvas.toBlob(resolve))
canvasUrl = URL.createObjectURL(blob)
@ -205,8 +209,15 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
function updateTooltip(period, variation) {
const configObject = variationsConfig[variation].versions[period]
// If timestap is a number return a UTC formatted date otherwise use exact timestap label
if (typeof configObject.timestamp === "number") tooltip.querySelector('div').textContent = new Date(configObject.timestamp * 1000).toUTCString()
// If timestamp is a number return a UTC formatted date, otherwise use exact timestamp label
if (Array.isArray(configObject.timestamp)) {
tooltip.querySelector('div').textContent = ""
configObject.timestamp.forEach(timestamp => {
if (tooltip.querySelector('div').textContent) tooltip.querySelector('div').innerHTML += "<br />"
if (typeof timestamp === "number") tooltip.querySelector('div').innerHTML += new Date(timestamp * 1000).toUTCString()
else tooltip.querySelector('div').innerHTML += timestamp
})
} else if (typeof configObject.timestamp === "number") tooltip.querySelector('div').textContent = new Date(configObject.timestamp * 1000).toUTCString()
else tooltip.querySelector('div').textContent = configObject.timestamp
// Clamps position of tooltip to prevent from going off screen

View file

@ -115,7 +115,7 @@ offcanvasList.addEventListener('show.bs.offcanvas', function () {
applyView()
})
offcanvasList.addEventListener('shown.bs.offcanvas', function (e) {
offcanvasList.addEventListener('shown.bs.offcanvas', e => {
entriesListShown = true
wrapper.classList.remove('listTransitioning')
updateHovering(e)
@ -130,7 +130,7 @@ offcanvasList.addEventListener('hide.bs.offcanvas', function () {
applyView()
})
offcanvasList.addEventListener('hidden.bs.offcanvas', function (e) {
offcanvasList.addEventListener('hidden.bs.offcanvas', e => {
entriesListShown = false
wrapper.classList.remove('listTransitioning')
updateHovering(e)
@ -181,7 +181,7 @@ objectsContainer.addEventListener("scroll", function () {
updateLines()
})
window.addEventListener("resize", function (e) {
window.addEventListener("resize", e => {
applyView()
render()
@ -257,7 +257,7 @@ function updateLines() {
function renderBackground(atlas) {
backgroundContext.clearRect(0, 0, canvas.width, canvas.height)
backgroundContext.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height)
//backgroundCanvas.width = 1000 * zoom
//backgroundCanvas.height = 1000 * zoom
@ -397,8 +397,7 @@ function buildObjectsList(filter = null, sort = null) {
}
const element = createInfoBlock(sortedAtlas[i])
element.entry = sortedAtlas[i]
const entry = sortedAtlas[i]
element.addEventListener("mouseenter", function () {
if (!fixed && !dragging) {
@ -408,9 +407,9 @@ function buildObjectsList(filter = null, sort = null) {
previousScaleZoomOrigin = [scaleZoomOrigin[0], scaleZoomOrigin[1]]
applyView()
setView(this.entry.center[0], this.entry.center[1], setZoomByPath(this.entry.path))
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
hovered = [this.entry]
hovered = [entry]
render()
hovered[0].element = this
updateLines()
@ -418,7 +417,7 @@ function buildObjectsList(filter = null, sort = null) {
})
element.addEventListener("click", function (e) {
element.addEventListener("click", e => {
toggleFixed(e)
if (fixed) {
applyView()
@ -466,13 +465,13 @@ function resetEntriesList() {
async function render() {
context.clearRect(0, 0, canvas.width, canvas.height)
highlightContext.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height)
//canvas.width = 1000*zoom
//canvas.height = 1000*zoom
context.globalCompositeOperation = "source-over"
context.clearRect(0, 0, canvas.width, canvas.height)
highlightContext.globalCompositeOperation = "source-over"
highlightContext.clearRect(0, 0, highlightCanvas.width, highlightCanvas.height)
if (hovered.length > 0) {
container.style.cursor = "pointer"
@ -486,28 +485,28 @@ async function render() {
const path = hovered[i].path
context.beginPath()
highlightContext.beginPath()
if (path[0]) {
//context.moveTo(path[0][0]*zoom, path[0][1]*zoom)
context.moveTo(path[0][0], path[0][1])
highlightContext.moveTo(path[0][0], path[0][1])
}
for (let p = 1; p < path.length; p++) {
//context.lineTo(path[p][0]*zoom, path[p][1]*zoom)
context.lineTo(path[p][0], path[p][1])
highlightContext.lineTo(path[p][0], path[p][1])
}
context.closePath()
highlightContext.closePath()
context.globalCompositeOperation = "source-over"
highlightContext.globalCompositeOperation = "source-over"
context.fillStyle = "rgba(0, 0, 0, 1)"
context.fill()
highlightContext.fillStyle = "rgba(0, 0, 0, 1)"
highlightContext.fill()
}
context.globalCompositeOperation = "source-out"
context.drawImage(backgroundCanvas, 0, 0)
highlightContext.globalCompositeOperation = "source-out"
highlightContext.drawImage(backgroundCanvas, 0, 0)
if (hovered.length === 1 && hovered[0].path.length && hovered[0].overrideImage) {
const undisputableHovered = hovered[0]
@ -523,8 +522,8 @@ async function render() {
overrideImage.src = "imageOverrides/" + undisputableHovered.overrideImage
try {
await loadingPromise
context.globalCompositeOperation = "source-over"
context.drawImage(overrideImage, startX, startY)
highlightContext.globalCompositeOperation = "source-over"
highlightContext.drawImage(overrideImage, startX, startY)
} catch (ex) {
console.error("Cannot override image.", ex)
}
@ -535,21 +534,21 @@ async function render() {
const path = hovered[i].path
context.beginPath()
highlightContext.beginPath()
if (path[0]) {
//context.moveTo(path[0][0]*zoom, path[0][1]*zoom)
context.moveTo(path[0][0], path[0][1])
highlightContext.moveTo(path[0][0], path[0][1])
}
for (let p = 1; p < path.length; p++) {
//context.lineTo(path[p][0]*zoom, path[p][1]*zoom)
context.lineTo(path[p][0], path[p][1])
highlightContext.lineTo(path[p][0], path[p][1])
}
context.closePath()
highlightContext.closePath()
context.globalCompositeOperation = "source-over"
highlightContext.globalCompositeOperation = "source-over"
let hoverStrokeStyle
switch (hovered[i].diff) {
@ -563,9 +562,9 @@ async function render() {
hoverStrokeStyle = "rgba(0, 0, 0, 1)"
break
}
context.strokeStyle = hoverStrokeStyle
highlightContext.strokeStyle = hoverStrokeStyle
//context.lineWidth = zoom
context.stroke()
highlightContext.stroke()
}
}
@ -665,7 +664,7 @@ function highlightEntryFromUrl() {
if (!id) return
const entries = atlas.filter(function (e) {
const entries = atlas.filter(e => {
return e.id === id
})
@ -751,18 +750,17 @@ function initExplore() {
window.render = function () { }
function updateHovering(e, tapped) {
if (!dragging && (!fixed || tapped)) {
const pos = [
(e.clientX - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft)) / zoom,
(e.clientY - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop)) / zoom
]
const coords_p = document.getElementById("coords_p")
// Displays coordinates as zero instead of NaN
if (isNaN(pos[0]) === true) {
coords_p.textContent = "0, 0"
} else {
coords_p.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
}
if (dragging || (fixed && !tapped)) return
const pos = [
(e.clientX - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft)) / zoom,
(e.clientY - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop)) / zoom
]
const coordsEl = document.getElementById("coords_p")
// Displays coordinates as zero instead of NaN
if (isNaN(pos[0])) {
coordsEl.textContent = "0, 0"
} else {
coordsEl.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
}
}
@ -773,7 +771,7 @@ function initExplore() {
}
function initGlobal() {
container.addEventListener("mousemove", function (e) {
container.addEventListener("mousemove", e => {
if (e.sourceCapabilities) {
if (!e.sourceCapabilities.firesTouchEvents) {
updateHovering(e)
@ -783,7 +781,7 @@ function initGlobal() {
}
})
document.addEventListener('timeupdate', (event) => {
document.addEventListener('timeupdate', event => {
let hashData = window.location.hash.substring(1).split('/')
const targetHash = formatHash(hashData[0], event.detail.period, event.detail.period, event.detail.variation)
if (location.hash !== targetHash) history.replaceState({}, "", `./${targetHash}`)
@ -791,14 +789,14 @@ function initGlobal() {
}
function initViewGlobal() {
container.addEventListener("mousedown", function (e) {
container.addEventListener("mousedown", e => {
lastPos = [
e.clientX,
e.clientY
]
})
container.addEventListener("touchstart", function (e) {
container.addEventListener("touchstart", e => {
if (e.touches.length === 1) {
lastPos = [
e.touches[0].clientX,
@ -807,13 +805,13 @@ function initViewGlobal() {
}
}, { passive: true })
container.addEventListener("mouseup", function (e) {
container.addEventListener("mouseup", e => {
if (Math.abs(lastPos[0] - e.clientX) + Math.abs(lastPos[1] - e.clientY) <= 4) {
toggleFixed(e)
}
})
container.addEventListener("touchend", function (e) {
container.addEventListener("touchend", e => {
e.preventDefault()
//console.log(e)
@ -828,16 +826,14 @@ function initViewGlobal() {
//console.log("Foo!!")
dragging = false
fixed = false
setTimeout(function () {
updateHovering(e, true)
}, 10)
setTimeout(() => updateHovering(e, true), 0)
})
if (window.location.hash) { // both "/" and just "/#" will be an empty hash string
highlightEntryFromUrl()
}
document.addEventListener('timeupdate', (event) => {
document.addEventListener('timeupdate', event => {
drawButton.href = "./?mode=draw" + formatHash(undefined, event.detail.period, event.detail.period, event.detail.variation)
})
}

View file

@ -2,7 +2,7 @@
importScripts('https://cdn.jsdelivr.net/npm/workbox-sw@6.5.4/build/workbox-sw.js');
self.addEventListener("message", (event) => {
self.addEventListener("message", event => {
if (event.data && event.data.type === "SKIP_WAITING") {
self.skipWaiting();
}