mirror of
https://github.com/placeAtlas/atlas.git
synced 2024-12-24 18:44:19 +01:00
parent
5b0b1484ef
commit
3704799761
31 changed files with 548 additions and 439 deletions
|
@ -92,9 +92,27 @@
|
|||
"design",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Hans5958",
|
||||
"name": "Hans5958",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11584103?v=4",
|
||||
"profile": "https://github.com/Hans5958",
|
||||
"contributions": [
|
||||
"a11y",
|
||||
"bug",
|
||||
"code",
|
||||
"content",
|
||||
"data",
|
||||
"doc",
|
||||
"design",
|
||||
"maintenance",
|
||||
"projectManagement",
|
||||
"tool"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"contributorsPerLine": 4,
|
||||
"skipCi": true,
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
|
|
10
.github/ISSUE_TEMPLATE/3-edit-json.yml
vendored
10
.github/ISSUE_TEMPLATE/3-edit-json.yml
vendored
|
@ -1,6 +1,6 @@
|
|||
name: Entry edit submission
|
||||
description: Edit an existing entry after using the website
|
||||
labels: ["entry update"]
|
||||
name: Patch submission
|
||||
description: Make changes to the Atlas data after using the website
|
||||
labels: ["atlas data: patch"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
@ -14,8 +14,8 @@ body:
|
|||
- type: textarea
|
||||
id: json
|
||||
attributes:
|
||||
label: Entry data
|
||||
description: Upon editing, please copy the exported JSON-formatted data. This will be automatically formatted into code, so no need for backticks.
|
||||
label: Patch
|
||||
description: Upon editing, please copy the exported JSON-formatted patch. This will be automatically formatted into code, so no need for backticks.
|
||||
render: json
|
||||
validations:
|
||||
required: true
|
4
.github/ISSUE_TEMPLATE/4-edit-request.yml
vendored
4
.github/ISSUE_TEMPLATE/4-edit-request.yml
vendored
|
@ -1,6 +1,6 @@
|
|||
name: Edit request
|
||||
description: Request for edits of the Atlas data
|
||||
labels: ["entry update"]
|
||||
description: Request for changes to the Atlas data
|
||||
labels: ["atlas data: request"]
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
|
|
3
.github/labeler-pr.yml
vendored
Normal file
3
.github/labeler-pr.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
staging merge:
|
||||
- 'cleanup'
|
||||
- 'staging/*'
|
5
.github/labeler.yml
vendored
Normal file
5
.github/labeler.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
'atlas data: patch':
|
||||
- data/patches/**
|
||||
|
||||
'atlas data: direct':
|
||||
- web/atlas.json
|
13
.github/workflows/pr-labeler.yml
vendored
Normal file
13
.github/workflows/pr-labeler.yml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
name: "PR Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
name: Triage
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
6
.github/workflows/qodana.yml
vendored
6
.github/workflows/qodana.yml
vendored
|
@ -20,6 +20,12 @@ jobs:
|
|||
qodana:
|
||||
name: Qodana
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'placeAtlas'
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
checks: write
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
|
8
.github/workflows/validate-json.yml
vendored
8
.github/workflows/validate-json.yml
vendored
|
@ -1,14 +1,18 @@
|
|||
name: Validate Atlas data
|
||||
name: Validate JSON files
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- web/atlas.json
|
||||
- data/patches/*.json
|
||||
pull_request:
|
||||
paths:
|
||||
- web/atlas.json
|
||||
- data/patches/*.json
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
@ -17,7 +21,7 @@ jobs:
|
|||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('tools/ci/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
- name: Validate
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Contributing
|
||||
|
||||
This project is open source, and contributions are welcome. In fact, the Atlas relies on user contributions.
|
||||
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 that, you can get help from [Discord](https://discord.gg/pJkm23b2nA) or [Reddit](https://www.reddit.com/r/placeAtlas2).
|
||||
|
||||
|
@ -8,15 +8,17 @@ You may contribute to the project by submitting a Pull Request on the GitHub rep
|
|||
|
||||
To contribute to the map, we require a certain format for artwork region and labels. This can be generated on [the drawing mode](https://2022.place-atlas.stefanocoding.me?mode=draw) on the website.
|
||||
|
||||
To add a new entry, go to [the drawing mode](https://2022.place-atlas.stefanocoding.me?mode=draw) and draw a shape/polygon around the region you'd like to describe. You can use the <kbd>Undo</kbd>, <kbd>Redo</kbd>, and <kbd>Reset</kbd> buttons to help you creating a good polygon. Make sure that the lines you're drawing don't form a [self-intersecting polygon](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Complex_polygon.svg/288px-Complex_polygon.svg.png).
|
||||
To add a new entry, go to [the drawing mode](https://2022.place-atlas.stefanocoding.me?mode=draw) and draw a shape/polygon around the region you'd like to describe. You can use the <kbd>Undo</kbd>, <kbd>Redo</kbd>, and <kbd>Reset</kbd> buttons to help you creating a good polygon. Make sure that the lines you're drawing don't form a [self-intersecting polygon](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Complex_polygon.svg/288px-Complex_polygon.svg.png).
|
||||
|
||||
Multiple periods can be added to represent the changing state of the artwork on different times. You can set the start and end period, as well as chosing the appropriate canvas variations. You can also copy the polygon from one period to the other, duplicating a period to be edited later, as well as deleting a period (if there is more than one). An alert is also shown if there are errors for assistance.
|
||||
If you want to see which areas of the canvas do not have entries yet, select "Highlight Empty" to hide areas that already have entries.
|
||||
|
||||
When you're happy with the shape you've drawn, press <kbd>Finish</kbd>. You will now be able to enter some information about the highlighted region:
|
||||
Multiple periods can be added to represent the changing state of the artwork on different times. You can set the start and end period, as well as chosing the appropriate canvas variations. You can also copy the polygon from one period to the other, duplicating a period to be edited later, as well as deleting a period (if there is more than one). An alert is also shown if there are errors that needed attention.
|
||||
|
||||
When you're happy with the shape you've drawn, press <kbd>Finish</kbd>. You will now be able to enter some information about the entry:
|
||||
|
||||
- **Name**: A short, descriptive name.
|
||||
- **Description**: A short description that will also be understood by somebody not familiar with the topic. Usually, the first sentence on Wikipedia is a good example.
|
||||
- **Links**: Some links that's either most relevant to the topic, or that was responsible for creating the artwork.
|
||||
- **Description**: A short description that can be understood by somebody not familiar with the topic. If you were involved in drawing this artwork, you may include the meta, describing the process of drawing the artwork in the event. To include lengthy, additional information, consider creating a page on [the r/place Wiki](https://place-wiki.stefanocoding.me/).
|
||||
- **Links**: Some links that are most relevant to the topic, and/or regarding the process of the drawing the artwork in the event.
|
||||
- **Website**: If you're describing a project, the project's main website would be suitable here.
|
||||
- **Subreddit**: Format it like `r/subreddit`.
|
||||
- **Discord**: Write the invite code, that the invite link without the `discord.gg/` part.
|
||||
|
@ -24,13 +26,13 @@ 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 submission data. Depending on the method, there are two preferred methods.
|
||||
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. This is the patch that you are going to submit. Depending on the method, there are two preferred methods.
|
||||
|
||||
### Through Reddit
|
||||
|
||||
You can press the <kbd>Post Direct to Reddit</kbd> button, which will open a page with the title and body already been filled for you. You don't need to change anything what has been prepared.
|
||||
|
||||
If that didn't work, 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.
|
||||
If that didn't work, 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 patch.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -38,7 +40,14 @@ Remember to flair your post with <kbd>New Entry</kbd>. On New Reddit, click the
|
|||
|
||||
If you know about Git and how to create a pull request on GitHub, you can try create a patch that will be merged, along with other patches, by one of the members.
|
||||
|
||||
You can try pressing the <kbd>Submit Direct to GitHub</kbd> button, which will open a page with the patch file already been prepared to you. If you haven't forked the repository, you would need to fork it with the provided instruction shown on the page. You may add attribution by adding an `_author` key, explained in the next paragraphs. After that, you can press <kbd>Submit changes</kbd>, add follow the steps to create a pull request within GitHub.
|
||||
You can try pressing the <kbd>Submit Direct to GitHub</kbd> button, which will open a page with the patch file already been prepared to you.
|
||||
|
||||
If that didn't work, copy the entire JSON text and [create a new patch file to the repository through GitHub](https://github.com/placeAtlas/atlas-2022/new/cleanup/data/patches?filename=gh-0000-ENTRY-NAME-HERE.json
|
||||
). Upon opening, replace the `ENTRY-NAME-HERE` into the name of the entry (with the slug format, if possible, e.g. `foo-bar`). You don't need to add any other text; just directly send the patch.
|
||||
|
||||
If you haven't forked the repository, you would need to fork it with the provided instruction shown on the page. You may add attribution by adding an `_author` key, explained in the next paragraphs. After that, you can press <kbd>Submit changes</kbd>, add follow the steps to create a pull request within GitHub.
|
||||
|
||||
The commit message and description doesn't matter, but you may change it into something more descriptive to make it easier for checking (e.g. <kbd>Add Foo Bar</kbd> or <kbd>Edit Foo Bar</kbd> for the commit message). However, we suggest you to edit the title (at least) and the description of the pull request, containing the changes that you want to do (something like <kbd>Add Foo Bar</kbd> or <kbd>Edit Foo Bar</kbd> for the title, similar to the commit message, is also sufficient).
|
||||
|
||||
If you can fork and clone the repository, you can use the provided `tools/create_patch.py` script. This script helps you to create a working patch, along with additional data such as your name for attribution sakes. Simply run the script inside the `tools/` folder and follow the given instructions.
|
||||
|
||||
|
@ -46,15 +55,15 @@ If you want to do this manually (e.g. you don't have Python), you can create a p
|
|||
|
||||
```json5
|
||||
{
|
||||
"id": 0,
|
||||
"id": -1, // -1 signififies a new entry.
|
||||
// ...
|
||||
"_author": "Hans5958_",
|
||||
// or...
|
||||
"_author": "gh:Hans5958",
|
||||
// Choose one of the folllowing:
|
||||
"_author": "Hans5958_", // Links to https://reddit.com/user/Hans5958_
|
||||
"_author": "gh:Hans5958", // Links to https://github.com/Hans5958
|
||||
}
|
||||
```
|
||||
|
||||
Once you have successfully created the patch, the file can be committed, and a pull request towards the `cleanup` branch can be created. A member will merge the pull request if it is adequate.
|
||||
Once you have successfully created the patch, the file can be committed, and a pull request towards the `cleanup` branch can be created. A member will merge the pull request if it is adequate.
|
||||
|
||||
## Edits to Atlas entries
|
||||
|
||||
|
@ -68,9 +77,9 @@ Upon submitting, if you use Reddit, please flair it as <kbd>Edit Entry</kbd> ins
|
|||
|
||||
As an alternative, you can also submit an issue on GitHub using [this form](https://github.com/placeAtlas/atlas-2022/issues/new?assignees=&labels=entry+update&template=edit-entry.yml) or report it on our Discord server.
|
||||
|
||||
### Manually
|
||||
### Manually by direct edits
|
||||
|
||||
Edits are also welcome on this repository using Git through GitHub. You may use Git or GitHub for bulk or large-scale changes, such as removing duplicates.
|
||||
Direct edits to the `web/atlas.json` are also welcome on this repository using Git through GitHub. You may use Git or GitHub for bulk or large-scale changes, such as removing duplicates, or doing those that are not possible by using patches, such as removing an entry. Keep in mind that this may causes conflicts, so only do it when necessary.
|
||||
|
||||
`web/atlas.json` is where the Atlas data is located, in which you can edit on GitHub. The next section includes an example of an entry.
|
||||
|
||||
|
@ -80,11 +89,11 @@ To help find duplicates, [use the Overlap mode](https://2022.place-atlas.stefano
|
|||
|
||||
### Example
|
||||
|
||||
Hereforth is an example of the structured data. The example has been expanded, but please save it in the way so each line is an entry which is minified. The `aformatter.py` script can help you with this.
|
||||
Hereforth is an example of the structured entry data. The example has been expanded, but when editing directly, please save it in the way so each line is an entry that is minified. The `tools/aformatter.py` script can help you with this.
|
||||
|
||||
```json5
|
||||
{
|
||||
"id": "tu203o",
|
||||
"id": 1,
|
||||
"name": "An entry",
|
||||
"description": "This is an entry, it is remarkable.",
|
||||
"links": {
|
||||
|
@ -124,15 +133,11 @@ Opening the HTML file on your browser is adequate enough to edit. If it doesn't
|
|||
# Run it inside the web/ folder.
|
||||
cd web
|
||||
|
||||
# Choose one of the following.
|
||||
# Python 2
|
||||
python -m SimpleHTTPServer 8000
|
||||
# Python 3
|
||||
python -m http.server 8000
|
||||
# Node.js (http-server)
|
||||
npx http-server
|
||||
# Node.js (serve)
|
||||
npx serve
|
||||
# Choose one of the following:
|
||||
python -m SimpleHTTPServer 8000 # Python 2
|
||||
python -m http.server 8000 # Python 3
|
||||
npx http-server # Node.js (http-server)
|
||||
npx serve # Node.js (serve)
|
||||
```
|
||||
|
||||
### Tools
|
||||
|
@ -143,4 +148,4 @@ The `tools` folder have various scripts for the maintainance of the project, suc
|
|||
- Formatting/tidying up the data
|
||||
- Building the site for production
|
||||
|
||||
The tools are built using either Node.js and/or Python (3).
|
||||
The tools may built with various programming languages, but mostly it is made in Python (3).
|
17
README.md
17
README.md
|
@ -27,7 +27,7 @@ Please read [CONTRIBUTING.md](CONTRIBUTING.md) to learn how to submit a new entr
|
|||
## Contributors
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat)](#contributors)
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat)](#contributors)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key))):
|
||||
|
@ -38,12 +38,15 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://stefanocoding.me"><img src="https://avatars.githubusercontent.com/u/25939526?v=4?s=100" width="100px;" alt="Stefano"/><br /><sub><b>Stefano</b></sub></a><br /><a href="#business-Codixer" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas-2022/commits?author=Codixer" title="Code">💻</a> <a href="#content-Codixer" title="Content">🖋</a> <a href="#data-Codixer" title="Data">🔣</a> <a href="#design-Codixer" title="Design">🎨</a> <a href="#fundingFinding-Codixer" title="Funding Finding">🔍</a> <a href="#infra-Codixer" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-Codixer" title="Maintenance">🚧</a> <a href="#projectManagement-Codixer" title="Project Management">📆</a> <a href="#question-Codixer" title="Answering Questions">💬</a> <a href="#security-Codixer" title="Security">🛡️</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ab-gh"><img src="https://avatars.githubusercontent.com/u/18347932?v=4?s=100" width="100px;" alt="ash"/><br /><sub><b>ash</b></sub></a><br /><a href="#business-ab-gh" title="Business development">💼</a> <a href="#content-ab-gh" title="Content">🖋</a> <a href="#data-ab-gh" title="Data">🔣</a> <a href="#projectManagement-ab-gh" title="Project Management">📆</a> <a href="https://github.com/placeAtlas/atlas-2022/pulls?q=is%3Apr+reviewed-by%3Aab-gh" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://linktr.ee/aeywoo"><img src="https://avatars.githubusercontent.com/u/65846594?v=4?s=100" width="100px;" alt="Aeywoo"/><br /><sub><b>Aeywoo</b></sub></a><br /><a href="#business-Aeywoo" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas-2022/issues?q=author%3AAeywoo" title="Bug reports">🐛</a> <a href="#blog-Aeywoo" title="Blogposts">📝</a> <a href="#content-Aeywoo" title="Content">🖋</a> <a href="#maintenance-Aeywoo" title="Maintenance">🚧</a> <a href="#research-Aeywoo" title="Research">🔬</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AnonymousRandomPerson"><img src="https://avatars.githubusercontent.com/u/6516839?v=4?s=100" width="100px;" alt="AnonymousRandomPerson"/><br /><sub><b>AnonymousRandomPerson</b></sub></a><br /><a href="#data-AnonymousRandomPerson" title="Data">🔣</a> <a href="#content-AnonymousRandomPerson" title="Content">🖋</a> <a href="#research-AnonymousRandomPerson" title="Research">🔬</a> <a href="https://github.com/placeAtlas/atlas-2022/commits?author=AnonymousRandomPerson" title="Code">💻</a> <a href="https://github.com/placeAtlas/atlas-2022/pulls?q=is%3Apr+reviewed-by%3AAnonymousRandomPerson" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mxdanger"><img src="https://avatars.githubusercontent.com/u/32040254?v=4?s=100" width="100px;" alt="mxdanger"/><br /><sub><b>mxdanger</b></sub></a><br /><a href="https://github.com/placeAtlas/atlas-2022/commits?author=mxdanger" title="Code">💻</a> <a href="#a11y-mxdanger" title="Accessibility">️️️️♿️</a> <a href="https://github.com/placeAtlas/atlas-2022/issues?q=author%3Amxdanger" title="Bug reports">🐛</a> <a href="#design-mxdanger" title="Design">🎨</a> <a href="#ideas-mxdanger" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-mxdanger" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-mxdanger" title="Maintenance">🚧</a> <a href="#tool-mxdanger" title="Tools">🔧</a> <a href="#userTesting-mxdanger" title="User Testing">📓</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/artillect"><img src="https://avatars.githubusercontent.com/u/8906201?v=4?s=100" width="100px;" alt="Riley"/><br /><sub><b>Riley</b></sub></a><br /><a href="#data-artillect" title="Data">🔣</a> <a href="#design-artillect" title="Design">🎨</a> <a href="https://github.com/placeAtlas/atlas-2022/commits?author=artillect" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="25%"><a href="https://stefanocoding.me"><img src="https://avatars.githubusercontent.com/u/25939526?v=4?s=100" width="100px;" alt="Stefano"/><br /><sub><b>Stefano</b></sub></a><br /><a href="#business-Codixer" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Codixer" title="Code">💻</a> <a href="#content-Codixer" title="Content">🖋</a> <a href="#data-Codixer" title="Data">🔣</a> <a href="#design-Codixer" title="Design">🎨</a> <a href="#fundingFinding-Codixer" title="Funding Finding">🔍</a> <a href="#infra-Codixer" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-Codixer" title="Maintenance">🚧</a> <a href="#projectManagement-Codixer" title="Project Management">📆</a> <a href="#question-Codixer" title="Answering Questions">💬</a> <a href="#security-Codixer" title="Security">🛡️</a></td>
|
||||
<td align="center" valign="top" width="25%"><a href="https://github.com/ab-gh"><img src="https://avatars.githubusercontent.com/u/18347932?v=4?s=100" width="100px;" alt="ash"/><br /><sub><b>ash</b></sub></a><br /><a href="#business-ab-gh" title="Business development">💼</a> <a href="#content-ab-gh" title="Content">🖋</a> <a href="#data-ab-gh" title="Data">🔣</a> <a href="#projectManagement-ab-gh" title="Project Management">📆</a> <a href="https://github.com/placeAtlas/atlas/pulls?q=is%3Apr+reviewed-by%3Aab-gh" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center" valign="top" width="25%"><a href="https://linktr.ee/aeywoo"><img src="https://avatars.githubusercontent.com/u/65846594?v=4?s=100" width="100px;" alt="Aeywoo"/><br /><sub><b>Aeywoo</b></sub></a><br /><a href="#business-Aeywoo" title="Business development">💼</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3AAeywoo" title="Bug reports">🐛</a> <a href="#blog-Aeywoo" title="Blogposts">📝</a> <a href="#content-Aeywoo" title="Content">🖋</a> <a href="#maintenance-Aeywoo" title="Maintenance">🚧</a> <a href="#research-Aeywoo" title="Research">🔬</a></td>
|
||||
<td align="center" valign="top" width="25%"><a href="https://github.com/AnonymousRandomPerson"><img src="https://avatars.githubusercontent.com/u/6516839?v=4?s=100" width="100px;" alt="AnonymousRandomPerson"/><br /><sub><b>AnonymousRandomPerson</b></sub></a><br /><a href="#data-AnonymousRandomPerson" title="Data">🔣</a> <a href="#content-AnonymousRandomPerson" title="Content">🖋</a> <a href="#research-AnonymousRandomPerson" title="Research">🔬</a> <a href="https://github.com/placeAtlas/atlas/commits?author=AnonymousRandomPerson" title="Code">💻</a> <a href="https://github.com/placeAtlas/atlas/pulls?q=is%3Apr+reviewed-by%3AAnonymousRandomPerson" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="25%"><a href="https://github.com/mxdanger"><img src="https://avatars.githubusercontent.com/u/32040254?v=4?s=100" width="100px;" alt="mxdanger"/><br /><sub><b>mxdanger</b></sub></a><br /><a href="https://github.com/placeAtlas/atlas/commits?author=mxdanger" title="Code">💻</a> <a href="#a11y-mxdanger" title="Accessibility">️️️️♿️</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3Amxdanger" title="Bug reports">🐛</a> <a href="#design-mxdanger" title="Design">🎨</a> <a href="#ideas-mxdanger" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-mxdanger" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-mxdanger" title="Maintenance">🚧</a> <a href="#tool-mxdanger" title="Tools">🔧</a> <a href="#userTesting-mxdanger" title="User Testing">📓</a></td>
|
||||
<td align="center" valign="top" width="25%"><a href="https://github.com/artillect"><img src="https://avatars.githubusercontent.com/u/8906201?v=4?s=100" width="100px;" alt="Riley"/><br /><sub><b>Riley</b></sub></a><br /><a href="#data-artillect" title="Data">🔣</a> <a href="#design-artillect" title="Design">🎨</a> <a href="https://github.com/placeAtlas/atlas/commits?author=artillect" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="25%"><a href="https://github.com/Hans5958"><img src="https://avatars.githubusercontent.com/u/11584103?v=4?s=100" width="100px;" alt="Hans5958"/><br /><sub><b>Hans5958</b></sub></a><br /><a href="#a11y-Hans5958" title="Accessibility">️️️️♿️</a> <a href="https://github.com/placeAtlas/atlas/issues?q=author%3AHans5958" title="Bug reports">🐛</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Hans5958" title="Code">💻</a> <a href="#content-Hans5958" title="Content">🖋</a> <a href="#data-Hans5958" title="Data">🔣</a> <a href="https://github.com/placeAtlas/atlas/commits?author=Hans5958" title="Documentation">📖</a> <a href="#design-Hans5958" title="Design">🎨</a> <a href="#maintenance-Hans5958" title="Maintenance">🚧</a> <a href="#projectManagement-Hans5958" title="Project Management">📆</a> <a href="#tool-Hans5958" title="Tools">🔧</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
[build]
|
||||
publish = "dist/"
|
||||
command = "FILE=tools/ci/build-prod.sh; rm -rf dist/; if [ -f $FILE ]; then bash $FILE; else cp -r web/ dist/; fi"
|
||||
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF web/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
|
||||
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF web/ tools/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
|
||||
|
||||
[build.environment]
|
||||
PYTHON_VERSION = "3.8"
|
||||
|
||||
[context.deploy-preview]
|
||||
command = "FILE=tools/ci/build-preview.sh; rm -rf dist/; if [ -f $FILE ]; then bash $FILE; else cp -r web/ dist/; fi"
|
||||
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF data/patches/ web/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
|
||||
ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF data/patches/ web/ tools/ .parcelrc netlify.toml package-lock.json package.json postcss.config.js"
|
||||
|
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -10,11 +10,11 @@
|
|||
"@parcel/packager-raw-url": "^2.8.3",
|
||||
"@parcel/transformer-jsonld": "^2.8.3",
|
||||
"@parcel/transformer-webmanifest": "^2.8.3",
|
||||
"all-contributors-cli": "^6.26.1",
|
||||
"parcel": "2.8",
|
||||
"all-contributors-cli": "^6.24.0",
|
||||
"parcel": "^2.8.3",
|
||||
"parcel-namer-rewrite": "^2.0.0-rc.3",
|
||||
"parcel-resolver-ignore": "^2.1.5",
|
||||
"postcss": "^8.4.26"
|
||||
"parcel-resolver-ignore": "^2.1.3",
|
||||
"postcss": "^8.4.21"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
"@parcel/transformer-webmanifest": "^2.8.3",
|
||||
"parcel": "^2.8.3",
|
||||
"parcel-namer-rewrite": "^2.0.0-rc.3",
|
||||
"parcel-resolver-ignore": "^2.1.5",
|
||||
"postcss": "^8.4.26",
|
||||
"all-contributors-cli": "^6.26.1"
|
||||
"parcel-resolver-ignore": "^2.1.3",
|
||||
"postcss": "^8.4.21",
|
||||
"all-contributors-cli": "^6.24.0"
|
||||
},
|
||||
"parcel-namer-rewrite": {
|
||||
"rules": {
|
||||
|
|
|
@ -8,6 +8,8 @@ rm -rf .parcel-cache
|
|||
cp -r web/ dist-temp/
|
||||
|
||||
npm i
|
||||
pip install -r tools/ci/requirements.txt
|
||||
|
||||
python tools/ci/cdn_to_local.py
|
||||
python tools/merge_out.py # On previews, attempt to merge patches
|
||||
npx parcel build dist-temp/index.html dist-temp/**.html --dist-dir "dist" --no-source-maps --no-content-hash
|
||||
|
|
|
@ -8,6 +8,8 @@ rm -rf .parcel-cache
|
|||
cp -r web/ dist-temp/
|
||||
|
||||
npm i
|
||||
pip install -r tools/ci/requirements.txt
|
||||
|
||||
python tools/ci/cdn_to_local.py
|
||||
npx parcel build dist-temp/index.html dist-temp/**.html --dist-dir "dist" --no-source-maps --no-content-hash
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
jsonschema
|
||||
jsonschema
|
||||
tqdm
|
|
@ -2,6 +2,7 @@
|
|||
import os
|
||||
import secrets
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
while not os.path.exists('README.md'):
|
||||
os.chdir('..')
|
||||
|
@ -32,8 +33,11 @@
|
|||
if author:
|
||||
entry['_author'] = author
|
||||
|
||||
filename = f'gh-{secrets.token_hex(2)}-{"-".join(entry["name"].split()).lower()}.json'
|
||||
with open(f'{patches_dir}gh-{secrets.token_hex(2)}-{"-".join(entry["name"].split()).lower()}.json', 'w', encoding='utf-8') as out_file:
|
||||
slug_name = re.sub('\s+', ' ', entry['name'])
|
||||
slug_name = re.sub('[^a-zA-Z0-9 ]', '', slug_name)
|
||||
slug_name = "-".join(slug_name.split(' ')).lower()
|
||||
filename = f'gh-{secrets.token_hex(2)}-{slug_name}.json'
|
||||
with open(f'{patches_dir}{filename}', 'w', encoding='utf-8') as out_file:
|
||||
out_file.write(json.dumps(entry, ensure_ascii=False))
|
||||
|
||||
print("Patch created as " + filename + "!")
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
import os
|
||||
from aformatter import format_all_entries, per_line_entries
|
||||
import traceback
|
||||
import scale_back
|
||||
from scale_back import ScaleConfig
|
||||
|
||||
IS_DEPLOY_PREVIEW = False
|
||||
|
||||
if os.getenv('NETLIFY') == 'true' and os.getenv('CONTEXT') == 'deploy-preview':
|
||||
IS_DEPLOY_PREVIEW = True
|
||||
|
||||
out_ids = []
|
||||
atlas_ids = {}
|
||||
|
@ -23,12 +26,14 @@
|
|||
|
||||
last_id = 0
|
||||
|
||||
for i, entry in enumerate(atlas_data):
|
||||
atlas_ids[entry['id']] = i
|
||||
id = entry['id']
|
||||
|
||||
if isinstance(id, int) and id > last_id and id - last_id < 100:
|
||||
last_id = int(id)
|
||||
if not IS_DEPLOY_PREVIEW:
|
||||
for i, entry in enumerate(atlas_data):
|
||||
atlas_ids[entry['id']] = i
|
||||
id = entry['id']
|
||||
if type(id) is str and id.isnumeric():
|
||||
id = id.isnumeric()
|
||||
if type(id) is int and id > last_id and id - last_id < 100:
|
||||
last_id = int(id)
|
||||
|
||||
patches_dir = "data/patches/"
|
||||
permanent_patch_file = "tools/temp-atlas.json"
|
||||
|
@ -70,12 +75,14 @@
|
|||
scale_back.scale_back_entries(entries)
|
||||
|
||||
for entry in entries:
|
||||
if entry is None:
|
||||
continue
|
||||
if '_reddit_id' in entry:
|
||||
reddit_id = entry['_reddit_id']
|
||||
if reddit_id in out_ids:
|
||||
print(f"{filename}: Submission from {entry['id']} has been included! This will be ignored from the merge.")
|
||||
continue
|
||||
out_ids.append(str(reddit_id))
|
||||
out_ids.append(reddit_id)
|
||||
del entry['_reddit_id']
|
||||
|
||||
# This wouldn't work if it is an edit.
|
||||
|
@ -91,11 +98,16 @@
|
|||
del entry['_author']
|
||||
|
||||
if isinstance(entry['id'], int) and entry['id'] < 1 or entry['id'] == '0':
|
||||
last_id += 1
|
||||
if IS_DEPLOY_PREVIEW:
|
||||
last_id -= 1
|
||||
else:
|
||||
last_id += 1
|
||||
print(f"{filename}: Entry is new, assigned ID {last_id}")
|
||||
entry['id'] = last_id
|
||||
elif not is_permanent_file and entry['id'] not in out_ids:
|
||||
out_ids.append(str(entry['id']))
|
||||
elif isinstance(entry['id'], str) and entry['id'].isnumeric():
|
||||
entry['id'] = int(entry['id'])
|
||||
elif not is_permanent_file and type(entry['id']) is str and len(entry['id']) > 5 and entry['id'] not in out_ids:
|
||||
out_ids.append(entry['id'])
|
||||
|
||||
if entry['id'] in atlas_ids:
|
||||
index = atlas_ids[entry['id']]
|
||||
|
@ -105,8 +117,8 @@
|
|||
print(f"{filename}: Added {entry['id']}.")
|
||||
atlas_data.append(entry)
|
||||
|
||||
if not is_permanent_file:
|
||||
os.remove(f)
|
||||
if not is_permanent_file:
|
||||
os.remove(f)
|
||||
|
||||
except:
|
||||
print(f"{filename}: Something went wrong; patch couldn't be implemented. Skipping.")
|
||||
|
|
|
@ -26,14 +26,12 @@
|
|||
from praw import Reddit
|
||||
from praw.models import Submission
|
||||
import json
|
||||
import time
|
||||
import re
|
||||
import traceback
|
||||
from aformatter import format_all, validate
|
||||
from pathlib import Path
|
||||
import humanize
|
||||
from datetime import datetime
|
||||
import secrets
|
||||
import os
|
||||
|
||||
while not os.path.exists('README.md'):
|
||||
|
|
|
@ -30,6 +30,7 @@ svg.icon {
|
|||
body[data-mode] {
|
||||
overflow: hidden;
|
||||
background-color: #111;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
|
@ -82,7 +83,6 @@ #container {
|
|||
width: calc(100% - 400px);
|
||||
height: 100%;
|
||||
margin-left: 400px;
|
||||
touch-action: manipulation;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
@ -435,6 +435,11 @@ .period-group.no-time-slider .period-input-controls {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
[data-mode="explore"] #entriesListControls,
|
||||
[data-mode="explore"] #entriesList {
|
||||
display: none !important
|
||||
}
|
||||
|
||||
/* about.html */
|
||||
|
||||
#credits a {
|
||||
|
|
|
@ -17,7 +17,7 @@ fetch('all-authors.txt')
|
|||
.then(text => text.trim().split('\n').sort((a, b) => {
|
||||
const aSplit = a.split(':')
|
||||
const bSplit = b.split(':')
|
||||
return aSplit[aSplit.length - 1] > bSplit[bSplit.length - 1]
|
||||
return aSplit[aSplit.length - 1].localeCompare(bSplit[bSplit.length - 1])
|
||||
}))
|
||||
.then(contributors => {
|
||||
document.querySelector('#contributors-count').textContent = contributors.length
|
||||
|
@ -28,7 +28,8 @@ fetch('all-authors.txt')
|
|||
const contributor1 = contributorSplit[1]
|
||||
userEl.href = 'https://github.com/' + contributor1
|
||||
userEl.appendChild(gitHubEl.cloneNode())
|
||||
userEl.appendChild(document.createTextNode(' ' + contributor1))
|
||||
userEl.appendChild(document.createTextNode(' ' + contributor1))
|
||||
// punctuation space ^
|
||||
} else {
|
||||
userEl.href = 'https://reddit.com/user/' + contributor
|
||||
userEl.textContent = contributor
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// This script only applies to this instance of the Atlas.
|
||||
// Please also check code indicated with "@instance-only" outside this file.
|
||||
// Please also check code indicated with "@instanceonly" outside this file.
|
||||
// TODO: Avoid having instance-only code inside the main scripts to make updating easier.
|
||||
|
||||
const prodDomain = "2022.place-atlas.stefanocoding.me"
|
||||
|
@ -23,9 +23,15 @@ const canvasSize = {
|
|||
}
|
||||
window.canvasSize = canvasSize
|
||||
|
||||
const canvasOffset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
window.canvasOffset = canvasOffset
|
||||
|
||||
const canvasCenter = {
|
||||
x: canvasSize.x/2,
|
||||
y: canvasSize.y/2
|
||||
x: canvasSize.x/2 + canvasOffset.x,
|
||||
y: canvasSize.y/2 + canvasOffset.y
|
||||
}
|
||||
window.canvasCenter = canvasCenter
|
||||
|
||||
|
|
|
@ -42,3 +42,4 @@ function pointIsInPolygon(point, polygon) {
|
|||
|
||||
return inside;
|
||||
}
|
||||
window.pointIsInPolygon = pointIsInPolygon
|
|
@ -9,6 +9,7 @@ const finishButton = document.getElementById("finishButton")
|
|||
const resetButton = document.getElementById("resetButton")
|
||||
const undoButton = document.getElementById("undoButton")
|
||||
const redoButton = document.getElementById("redoButton")
|
||||
const highlightUnchartedEl = document.getElementById("highlightUncharted")
|
||||
const highlightUnchartedLabel = document.getElementById("highlightUnchartedLabel")
|
||||
|
||||
const drawControlsBody = document.getElementById("offcanvasDraw-drawControls")
|
||||
|
@ -122,7 +123,7 @@ function initDraw() {
|
|||
let lShiftPressed = false
|
||||
let shiftPressed = false
|
||||
|
||||
let highlightUncharted = false
|
||||
let highlightUncharted = highlightUnchartedEl.checked
|
||||
|
||||
renderBackground(atlas)
|
||||
applyView()
|
||||
|
@ -143,8 +144,8 @@ function initDraw() {
|
|||
y -= container.offsetTop
|
||||
|
||||
const pos = [
|
||||
~~((x - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0])) / zoom) + 0.5,
|
||||
~~((y - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1])) / zoom) + 0.5
|
||||
~~((x - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0])) / zoom) + 0.5 + canvasOffset.x,
|
||||
~~((y - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1])) / zoom) + 0.5 + canvasOffset.y
|
||||
]
|
||||
|
||||
if (shiftPressed && path.length > 0) {
|
||||
|
@ -266,7 +267,7 @@ function initDraw() {
|
|||
}
|
||||
})
|
||||
|
||||
document.getElementById("highlightUncharted").addEventListener("click", function () {
|
||||
highlightUnchartedEl.addEventListener("click", function () {
|
||||
highlightUncharted = this.checked
|
||||
render(path)
|
||||
})
|
||||
|
@ -336,7 +337,7 @@ function initDraw() {
|
|||
|
||||
let redditPostJsonString = " " + prettyJsonString.split("\n").join("\n ")
|
||||
let redditPostUrl = `https://www.reddit.com/r/${instanceSubreddit}/submit?selftext=true&title=`
|
||||
if (exportObject.id === 0) redditPostUrl += `✨%20${encodeURIComponent(exportObject.name ?? entry.name)}`
|
||||
if (exportObject.id === -1) redditPostUrl += `✨%20${encodeURIComponent(exportObject.name ?? entry.name)}`
|
||||
else redditPostUrl += `✏%20${encodeURIComponent(exportObject.name ?? entry.name)}`
|
||||
redditPostUrl += "&text="
|
||||
|
||||
|
@ -358,7 +359,7 @@ function initDraw() {
|
|||
}
|
||||
redditPostButton.href = redditPostUrl
|
||||
|
||||
if (exportObject.id === 0) document.getElementById("redditFlair").textContent = "New Entry"
|
||||
if (exportObject.id === -1) document.getElementById("redditFlair").textContent = "New Entry"
|
||||
else document.getElementById("redditFlair").textContent = "Edit Entry"
|
||||
|
||||
// GitHub
|
||||
|
@ -496,11 +497,11 @@ function initDraw() {
|
|||
backgroundContext.beginPath()
|
||||
|
||||
if (path[0]) {
|
||||
backgroundContext.moveTo(path[0][0], path[0][1])
|
||||
backgroundContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
for (let p = 1; p < path.length; p++) {
|
||||
backgroundContext.lineTo(path[p][0], path[p][1])
|
||||
backgroundContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
backgroundContext.closePath()
|
||||
|
@ -528,11 +529,11 @@ function initDraw() {
|
|||
highlightContext.beginPath()
|
||||
|
||||
if (path[0]) {
|
||||
highlightContext.moveTo(path[0][0], path[0][1])
|
||||
highlightContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
for (let i = 1; i < path.length; i++) {
|
||||
highlightContext.lineTo(path[i][0], path[i][1])
|
||||
highlightContext.lineTo(path[i][0] - canvasOffset.x, path[i][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
highlightContext.closePath()
|
||||
|
@ -549,26 +550,13 @@ function initDraw() {
|
|||
|
||||
function updateHovering(e, tapped) {
|
||||
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])
|
||||
}
|
||||
updateCoordsDisplay(e)
|
||||
}
|
||||
|
||||
const getEntry = id => {
|
||||
if (!id) return
|
||||
const entries = atlasAll.filter(entry => entry.id.toString() === id.toString())
|
||||
if (entries.length === 1) return entries[0]
|
||||
return
|
||||
}
|
||||
|
||||
function addFieldButton(inputButton, inputGroup, array, index, name) {
|
||||
|
@ -727,7 +715,7 @@ function initDraw() {
|
|||
|
||||
function addWikiFields(link, index, array) {
|
||||
const inputGroup = baseInputGroup.cloneNode()
|
||||
wikiGroup.appendChild(inputGroup)
|
||||
// wikiGroup.appendChild(inputGroup)
|
||||
|
||||
const inputField = baseInputField.cloneNode()
|
||||
inputField.id = "wikiField" + index
|
||||
|
@ -813,10 +801,15 @@ function initDraw() {
|
|||
|
||||
initPeriodGroups()
|
||||
|
||||
zoom = 4
|
||||
|
||||
setView(center[0], center[1])
|
||||
const hash = window.location.hash.substring(1)
|
||||
const [,, hashX, hashY, hashZoom] = hash.split('/')
|
||||
|
||||
setView(
|
||||
(isNaN(hashX) || hashX === '') ? center[0] : Number(hashX),
|
||||
(isNaN(hashY) || hashY === '') ? center[1] : Number(hashY),
|
||||
(isNaN(hashZoom) || hashZoom === '') ? 4 : Number(hashZoom)
|
||||
)
|
||||
|
||||
document.addEventListener('timeupdate', () => {
|
||||
renderBackground(atlas)
|
||||
updatePeriodGroups()
|
||||
|
@ -827,7 +820,7 @@ function initDraw() {
|
|||
initPeriodGroups()
|
||||
})
|
||||
|
||||
drawBackButton.href = "./" + formatHash(entry?.id, currentPeriod, currentPeriod, currentVariation)
|
||||
drawBackButton.href = "./" + formatHash(entry?.id)
|
||||
|
||||
document.addEventListener('timeupdate', event => {
|
||||
drawBackButton.href = "./" + formatHash(entry?.id, event.detail.period, event.detail.period, event.detail.variation)
|
||||
|
@ -921,17 +914,6 @@ function initPeriodGroups() {
|
|||
if (pathWithPeriods.length === 1) periodDeleteEl.disabled = true
|
||||
|
||||
startPeriodEl.addEventListener('input', () => {
|
||||
if (path.length >= 3) {
|
||||
periodCenter = calculateCenter(path)
|
||||
// @instance-only
|
||||
if ((periodCenter[1] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
|
||||
// Second expansion
|
||||
startPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[1];
|
||||
} else if ((periodCenter[0] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
|
||||
// First expansion
|
||||
startPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[0];
|
||||
}
|
||||
}
|
||||
startPeriodUpdate(startPeriodEl.value)
|
||||
})
|
||||
startPeriodLeftEl.addEventListener('click', () => {
|
||||
|
@ -971,37 +953,15 @@ function initPeriodGroups() {
|
|||
startPeriodLeftEl.disabled = false
|
||||
startPeriodRightEl.disabled = true
|
||||
} else {
|
||||
if (path.length >= 3) {
|
||||
periodCenter = calculateCenter(path)
|
||||
// @instance-only
|
||||
if ((periodCenter[1] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
|
||||
// Second expansion
|
||||
startPeriodLeftEl.disabled = true
|
||||
startPeriodRightEl.disabled = false
|
||||
} else if ((periodCenter[0] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
|
||||
// First expansion
|
||||
startPeriodLeftEl.disabled = true
|
||||
startPeriodRightEl.disabled = false
|
||||
} else {
|
||||
// Starting area
|
||||
startPeriodLeftEl.disabled = false
|
||||
startPeriodRightEl.disabled = false
|
||||
}
|
||||
}
|
||||
// Starting area
|
||||
startPeriodLeftEl.disabled = false
|
||||
startPeriodRightEl.disabled = false
|
||||
}
|
||||
}
|
||||
|
||||
endPeriodEl.addEventListener('input', () => {
|
||||
if (path.length >= 3) {
|
||||
periodCenter = calculateCenter(path)
|
||||
// @instance-only
|
||||
if ((periodCenter[1] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
|
||||
// Second expansion
|
||||
endPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[1];
|
||||
} else if ((periodCenter[0] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
|
||||
// First expansion
|
||||
endPeriodEl.value = variationsConfig[getCurrentVariation()].expansions[0];
|
||||
}
|
||||
}
|
||||
endPeriodUpdate(endPeriodEl.value)
|
||||
})
|
||||
|
@ -1037,23 +997,8 @@ function initPeriodGroups() {
|
|||
endPeriodLeftEl.disabled = false
|
||||
endPeriodRightEl.disabled = true
|
||||
} else {
|
||||
if (path.length >= 3) {
|
||||
periodCenter = calculateCenter(path)
|
||||
// @instance-only
|
||||
if (periodCenter && (periodCenter[1] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[1])) {
|
||||
// Second expansion
|
||||
endPeriodLeftEl.disabled = true
|
||||
endPeriodRightEl.disabled = false
|
||||
} else if (periodCenter && (periodCenter[0] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[getCurrentVariation()].expansions[0])) {
|
||||
// First expansion
|
||||
endPeriodLeftEl.disabled = true
|
||||
endPeriodRightEl.disabled = false
|
||||
} else {
|
||||
// Starting area
|
||||
endPeriodLeftEl.disabled = false
|
||||
endPeriodRightEl.disabled = false
|
||||
}
|
||||
}
|
||||
endPeriodLeftEl.disabled = false
|
||||
endPeriodRightEl.disabled = false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1216,7 +1161,6 @@ function updatePeriodGroups() {
|
|||
else periodDeleteEl.disabled = false
|
||||
|
||||
// Set start incremental button disabled states
|
||||
// @instance-only
|
||||
if (startPeriodEl.value === startPeriodEl.min) {
|
||||
startPeriodLeftEl.disabled = true
|
||||
startPeriodRightEl.disabled = false
|
||||
|
@ -1224,23 +1168,11 @@ function updatePeriodGroups() {
|
|||
startPeriodLeftEl.disabled = false
|
||||
startPeriodRightEl.disabled = true
|
||||
} else {
|
||||
if (periodCenter && (periodCenter[1] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[1])) {
|
||||
// Second expansion
|
||||
startPeriodLeftEl.disabled = true
|
||||
startPeriodRightEl.disabled = false
|
||||
} else if (periodCenter && (periodCenter[0] > 1000) && (startPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[0])) {
|
||||
// First expansion
|
||||
startPeriodLeftEl.disabled = true
|
||||
startPeriodRightEl.disabled = false
|
||||
} else {
|
||||
// Starting area
|
||||
startPeriodLeftEl.disabled = false
|
||||
startPeriodRightEl.disabled = false
|
||||
}
|
||||
startPeriodLeftEl.disabled = false
|
||||
startPeriodRightEl.disabled = false
|
||||
}
|
||||
|
||||
// Set end incremental button disabled states
|
||||
// @instance-only
|
||||
if (endPeriodEl.value === endPeriodEl.min) {
|
||||
endPeriodLeftEl.disabled = true
|
||||
endPeriodRightEl.disabled = false
|
||||
|
@ -1248,19 +1180,8 @@ function updatePeriodGroups() {
|
|||
endPeriodLeftEl.disabled = false
|
||||
endPeriodRightEl.disabled = true
|
||||
} else {
|
||||
if (periodCenter && (periodCenter[1] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[1])) {
|
||||
// Second expansion
|
||||
endPeriodLeftEl.disabled = true
|
||||
endPeriodRightEl.disabled = false
|
||||
} else if (periodCenter && (periodCenter[0] > 1000) && (endPeriodEl.valueAsNumber <= variationsConfig[periodVariationEl.value].expansions[0])) {
|
||||
// First expansion
|
||||
endPeriodLeftEl.disabled = true
|
||||
endPeriodRightEl.disabled = false
|
||||
} else {
|
||||
// Starting area
|
||||
endPeriodLeftEl.disabled = false
|
||||
endPeriodRightEl.disabled = false
|
||||
}
|
||||
endPeriodLeftEl.disabled = false
|
||||
endPeriodRightEl.disabled = false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -1316,7 +1237,7 @@ function updateErrors() {
|
|||
periodsStatus.textContent = "No paths available on this period!"
|
||||
}
|
||||
|
||||
const { conflicts, insufficientPaths } = getErrors()
|
||||
const { conflicts, insufficientPaths, outOfBounds, periodOutOfBounds } = getErrors()
|
||||
let errorCount = 0
|
||||
// console.log(conflicts, invalidPaths, allErrors)
|
||||
|
||||
|
@ -1324,10 +1245,16 @@ function updateErrors() {
|
|||
const { periodStatusEl, startPeriodViewEl, endPeriodViewEl, periodGroupEl } = el
|
||||
periodStatusEl.textContent = ""
|
||||
periodStatusEl.classList.add("d-none")
|
||||
if (conflicts[index] !== undefined) {
|
||||
if (conflicts?.[index]) {
|
||||
periodStatusEl.textContent += `Period conflicts with path${conflicts[index].length === 1 ? "" : "s"} ${conflicts[index].join(", ")}.\n`
|
||||
}
|
||||
if (insufficientPaths[index] !== undefined) {
|
||||
if (outOfBounds?.[index]) {
|
||||
periodStatusEl.textContent += `A point is placed out of bounds.\n`
|
||||
}
|
||||
if (periodOutOfBounds?.[index]) {
|
||||
periodStatusEl.textContent += `The period is out of bounds for editing.\n`
|
||||
}
|
||||
if (insufficientPaths?.[index] !== undefined) {
|
||||
periodStatusEl.textContent += `Insufficient paths. Got ${insufficientPaths[index]}, need at least 3.\n`
|
||||
startPeriodViewEl.disabled = true
|
||||
endPeriodViewEl.disabled = true
|
||||
|
@ -1394,8 +1321,54 @@ function getConflicts() {
|
|||
|
||||
}
|
||||
|
||||
function getOutOfBounds() {
|
||||
|
||||
const outOfBounds = {}
|
||||
|
||||
pathCheck: for (const i in pathWithPeriods) {
|
||||
const [period, path] = pathWithPeriods[i]
|
||||
const [start, end, variation] = parsePeriod(period)
|
||||
const checkedRefPeriods = []
|
||||
for (let j = start; j <= end; j++) {
|
||||
for (const [refPeriod, refRegion] of variationsConfig[variation]?.drawableRegions) {
|
||||
if (!isOnPeriod(refPeriod[0], refPeriod[1], variation, j, variation) || checkedRefPeriods.includes(refPeriod)) continue
|
||||
checkedRefPeriods.push(refPeriod)
|
||||
const [ refX1, refY1, refX2, refY2 ] = refRegion
|
||||
for (const point of path) {
|
||||
const isOutOfBounds = !pointIsInPolygon(point, [[refX1 - 2, refY1 - 2], [refX2 + 2, refY1 - 2], [refX2 + 2, refY2 + 2], [refX1 - 2, refY2 + 2]])
|
||||
if (!isOutOfBounds) continue
|
||||
outOfBounds[i] = true
|
||||
continue pathCheck
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outOfBounds
|
||||
|
||||
}
|
||||
|
||||
function getPeriodOutOfBounds() {
|
||||
|
||||
const outOfBounds = {}
|
||||
|
||||
pathCheck: for (const i in pathWithPeriods) {
|
||||
const [period] = pathWithPeriods[i]
|
||||
// console.log(i)
|
||||
const [start, end, variation] = parsePeriod(period)
|
||||
for (let j = start; j <= end; j++) {
|
||||
const [refStart, refEnd] = variationsConfig[variation]?.drawablePeriods
|
||||
if (isOnPeriod(refStart, refEnd, variation, j, variation)) continue
|
||||
outOfBounds[i] = true
|
||||
continue pathCheck
|
||||
}
|
||||
}
|
||||
|
||||
return outOfBounds
|
||||
|
||||
}
|
||||
|
||||
function getErrors() {
|
||||
const conflicts = getConflicts()
|
||||
const insufficientPaths = {}
|
||||
|
||||
pathWithPeriods.forEach(([period, path], i) => {
|
||||
|
@ -1406,8 +1379,10 @@ function getErrors() {
|
|||
// console.info('invalid paths', invalidPaths)
|
||||
|
||||
return {
|
||||
conflicts,
|
||||
conflicts: getConflicts(),
|
||||
insufficientPaths,
|
||||
outOfBounds: getOutOfBounds(),
|
||||
periodOutOfBounds: getPeriodOutOfBounds()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@ function createInfoBlock(entry, isPreview) {
|
|||
linkElement.className = "text-decoration-none d-flex justify-content-between text-body"
|
||||
if (isPreview) linkElement.href = "#"
|
||||
else {
|
||||
linkElement.href = formatHash(entry.id)
|
||||
linkElement.href = formatHash(entry.id, null, null, null, false, false, false)
|
||||
linkElement.addEventListener('click', e => {
|
||||
e.preventDefault()
|
||||
location.hash = formatHash(entry.id)
|
||||
location.hash = formatHash(entry.id, null, null, null, false, false, false)
|
||||
window.dispatchEvent(new HashChangeEvent("hashchange"))
|
||||
})
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ function createInfoBlock(entry, isPreview) {
|
|||
if (!link) return
|
||||
const wikiLinkElement = baseLinkElement.cloneNode()
|
||||
wikiLinkElement.href = "https://place-wiki.stefanocoding.me/wiki/" + link.replace(/ /g, '_')
|
||||
wikiLinkElement.innerHTML = `<i class="bi bi-book" aria-hidden="true"></i>r/place Wiki Article`
|
||||
wikiLinkElement.innerHTML = `<i class="bi bi-book" aria-hidden="true"></i> r/place Wiki Article`
|
||||
wikiGroupElement.appendChild(wikiLinkElement)
|
||||
})
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ function createInfoBlock(entry, isPreview) {
|
|||
const editElement = document.createElement("a")
|
||||
editElement.textContent = "Edit"
|
||||
editElement.className = "btn btn-sm btn-outline-primary"
|
||||
editElement.href = "./?mode=draw&id=" + entry.id + formatHash(undefined)
|
||||
editElement.href = "./?mode=draw&id=" + entry.id + formatHash(false)
|
||||
editElement.title = "Edit " + entry.name
|
||||
idElementContainer.appendChild(editElement)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ if (window.devicePixelRatio) {
|
|||
}
|
||||
|
||||
const maxZoom = 128
|
||||
const minZoom = 0.1
|
||||
const minZoom = 0.125
|
||||
|
||||
let zoomOrigin = [0, 0]
|
||||
let scaleZoomOrigin = [0, 0]
|
||||
|
@ -39,30 +39,39 @@ function applyView() {
|
|||
//console.log(zoomOrigin, scaleZoomOrigin)
|
||||
//console.log(scaleZoomOrigin[0])
|
||||
|
||||
scaleZoomOrigin[0] = Math.max(-canvasCenter.x, Math.min(canvasCenter.x, scaleZoomOrigin[0]))
|
||||
scaleZoomOrigin[1] = Math.max(-canvasCenter.y, Math.min(canvasCenter.y, scaleZoomOrigin[1]))
|
||||
scaleZoomOrigin[0] = Math.max(-canvasCenter.x + canvasOffset.x, Math.min(canvasCenter.x - canvasOffset.x, scaleZoomOrigin[0]))
|
||||
scaleZoomOrigin[1] = Math.max(-canvasCenter.y + canvasOffset.y, Math.min(canvasCenter.y - canvasOffset.y, scaleZoomOrigin[1]))
|
||||
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
|
||||
|
||||
zoomOrigin = [scaleZoomOrigin[0] * zoom, scaleZoomOrigin[1] * zoom]
|
||||
|
||||
innerContainer.style.height = (~~(zoom * canvasSize.x)) + "px"
|
||||
innerContainer.style.width = (~~(zoom * canvasSize.y)) + "px"
|
||||
innerContainer.style.width = (~~(zoom * canvasSize.x)) + "px"
|
||||
innerContainer.style.height = (~~(zoom * canvasSize.y)) + "px"
|
||||
|
||||
innerContainer.style.left = ~~(container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft) + "px"
|
||||
innerContainer.style.top = ~~(container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop) + "px"
|
||||
|
||||
}
|
||||
|
||||
function setView(x, y, zoomN = zoom) {
|
||||
|
||||
zoom = zoomN
|
||||
scaleZoomOrigin = [
|
||||
canvasCenter.x - x,
|
||||
canvasCenter.y - y
|
||||
]
|
||||
function setView(targetX, targetY, targetZoom) {
|
||||
|
||||
if (isNaN(targetX)) targetX = null
|
||||
if (isNaN(targetY)) targetY = null
|
||||
|
||||
zoom = targetZoom ?? zoom
|
||||
if ((targetX ?? null) !== null) scaleZoomOrigin[0] = canvasCenter.x - targetX
|
||||
if ((targetY ?? null) !== null) scaleZoomOrigin[1] = canvasCenter.y - targetY
|
||||
|
||||
applyView()
|
||||
|
||||
}
|
||||
|
||||
function updateHash(...args) {
|
||||
const newLocation = new URL(window.location)
|
||||
newLocation.hash = formatHash(...args)
|
||||
if (location.hash !== newLocation.hash) history.replaceState({}, "", newLocation)
|
||||
}
|
||||
|
||||
let atlas = null
|
||||
window.atlas = atlas
|
||||
let atlasAll = null
|
||||
|
@ -77,15 +86,6 @@ async function init() {
|
|||
const args = window.location.search
|
||||
const params = new URLSearchParams(args)
|
||||
|
||||
// For Reviewing Reddit Changes
|
||||
// const atlasRef = '../tools/temp-atlas.json'
|
||||
const atlasRef = params.get('atlas') || './atlas.json'
|
||||
const atlasResp = await fetch(atlasRef)
|
||||
atlas = await atlasResp.json()
|
||||
atlas.sort((a, b) => a.center[1] - b.center[1])
|
||||
|
||||
atlasAll = updateAtlasAll(atlas)
|
||||
|
||||
let mode = "view"
|
||||
|
||||
if (args) {
|
||||
|
@ -102,11 +102,19 @@ async function init() {
|
|||
}
|
||||
}
|
||||
|
||||
const hash = window.location.hash.substring(1)
|
||||
const [, period] = hash.split('/')
|
||||
if (mode === "about") window.location.replace("./about.html")
|
||||
|
||||
if (period) {
|
||||
const [, targetPeriod, targetVariation] = parsePeriod(period)
|
||||
// For Reviewing Reddit Changes
|
||||
// const atlasRef = '../tools/temp-atlas.json'
|
||||
const atlasRef = params.get('atlas') || './atlas.json'
|
||||
const atlasResp = await fetch(atlasRef)
|
||||
atlasAll = updateAtlasAll(await atlasResp.json())
|
||||
|
||||
const hash = window.location.hash.substring(1)
|
||||
const [, hashPeriod, hashX, hashY, hashZoom] = hash.split('/')
|
||||
|
||||
if (hashPeriod) {
|
||||
const [, targetPeriod, targetVariation] = parsePeriod(hashPeriod)
|
||||
await updateTime(targetPeriod, targetVariation, true)
|
||||
} else {
|
||||
await updateTime(currentPeriod, currentVariation, true)
|
||||
|
@ -114,15 +122,18 @@ async function init() {
|
|||
|
||||
//console.log(document.documentElement.clientWidth, document.documentElement.clientHeight)
|
||||
|
||||
zoomOrigin = [0, 0]
|
||||
applyView()
|
||||
setView(
|
||||
(isNaN(hashX) || hashX === '') ? canvasCenter.x : Number(hashX),
|
||||
(isNaN(hashY) || hashY === '') ? canvasCenter.y : Number(hashY),
|
||||
(isNaN(hashZoom) || hashZoom === '') ? zoom : Number(hashZoom)
|
||||
)
|
||||
|
||||
let initialPinchDistance = 0
|
||||
let initialPinchZoom = 0
|
||||
let initialPinchZoomOrigin = [0, 0]
|
||||
|
||||
let desiredZoom
|
||||
let zoomAnimationFrame
|
||||
// let desiredZoom
|
||||
// let zoomAnimationFrame
|
||||
|
||||
document.body.dataset.mode = mode
|
||||
|
||||
|
@ -131,12 +142,8 @@ async function init() {
|
|||
|
||||
if (mode === "draw") {
|
||||
initDraw()
|
||||
} else if (mode === "about") {
|
||||
window.location = "./about.html"
|
||||
} else if (mode === "overlap") {
|
||||
if (initOverlap) {
|
||||
initOverlap()
|
||||
}
|
||||
if (initOverlap) initOverlap()
|
||||
} else if (mode === "explore") {
|
||||
initExplore()
|
||||
} else if (mode.startsWith("diff")) {
|
||||
|
@ -146,13 +153,15 @@ async function init() {
|
|||
let liveAtlas = await liveAtlasResp.json()
|
||||
liveAtlas = updateAtlasAll(liveAtlas)
|
||||
|
||||
const liveAtlasReduced = liveAtlas.reduce(function (a, c) {
|
||||
a[c.id] = c
|
||||
return a
|
||||
const liveAtlasReduced = liveAtlas.reduce((atlas, entry) => {
|
||||
delete entry._index
|
||||
atlas[entry.id] = entry
|
||||
return atlas
|
||||
}, {})
|
||||
// Mark added/edited entries
|
||||
atlasAll = atlasAll.map(function (entry) {
|
||||
if (liveAtlasReduced[entry.id] === undefined) {
|
||||
delete entry._index
|
||||
if (!liveAtlasReduced[entry.id]) {
|
||||
entry.diff = "add"
|
||||
} else if (JSON.stringify(entry) !== JSON.stringify(liveAtlasReduced[entry.id])) {
|
||||
entry.diff = "edit"
|
||||
|
@ -161,24 +170,24 @@ async function init() {
|
|||
})
|
||||
|
||||
// Mark removed entries
|
||||
const atlasReduced = atlasAll.reduce(function (a, c) {
|
||||
a[c.id] = c
|
||||
return a
|
||||
const atlasReduced = atlasAll.reduce((atlas, entry) => {
|
||||
delete entry._index
|
||||
atlas[entry.id] = entry
|
||||
return atlas
|
||||
}, {})
|
||||
const removedEntries = liveAtlas.filter(entry =>
|
||||
atlasReduced[entry.id] === undefined
|
||||
).map(entry => {
|
||||
const removedEntries = liveAtlas.filter(entry => !atlasReduced[entry.id]).map(entry => {
|
||||
delete entry._index
|
||||
entry.diff = "delete"
|
||||
return entry
|
||||
})
|
||||
atlasAll.push(...removedEntries)
|
||||
|
||||
if (mode.includes("only")) {
|
||||
atlasAll = atlasAll.filter(function (entry) {
|
||||
return typeof entry.diff === "string"
|
||||
})
|
||||
atlasAll = atlasAll.filter(entry => entry.diff)
|
||||
}
|
||||
|
||||
atlas = generateAtlasForPeriod()
|
||||
|
||||
} catch (error) {
|
||||
console.warn("Diff mode failed to load, reverting to normal view.", error)
|
||||
} finally {
|
||||
|
@ -309,6 +318,7 @@ async function init() {
|
|||
|
||||
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
|
||||
applyZoom(x, y, zoom)
|
||||
updateHash()
|
||||
}, { passive: true })
|
||||
|
||||
/*function setDesiredZoom(x, y, target){
|
||||
|
@ -365,8 +375,8 @@ async function init() {
|
|||
]
|
||||
|
||||
mousedown(
|
||||
(e.touches[0].clientX + e.touches[1].clientX) / 2,
|
||||
(e.touches[0].clientY + e.touches[1].clientY) / 2
|
||||
(e.touches[0].clientX + e.touches[1].clientX) / 2 - container.offsetLeft,
|
||||
(e.touches[0].clientY + e.touches[1].clientY) / 2 - container.offsetTop
|
||||
)
|
||||
|
||||
}
|
||||
|
@ -374,12 +384,13 @@ async function init() {
|
|||
}
|
||||
|
||||
window.addEventListener("mousemove", e => {
|
||||
updateLines()
|
||||
// updateLines()
|
||||
mousemove(e.clientX, e.clientY)
|
||||
if (dragging) {
|
||||
e.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
window.addEventListener("touchmove", e => {
|
||||
|
||||
if (e.touches.length === 2 || e.scale > 1) {
|
||||
|
@ -412,8 +423,6 @@ async function init() {
|
|||
|
||||
function touchmove(e) {
|
||||
|
||||
updateLines()
|
||||
|
||||
if (e.touches.length === 1) {
|
||||
|
||||
mousemove(e.touches[0].clientX, e.touches[0].clientY)
|
||||
|
@ -470,17 +479,15 @@ async function init() {
|
|||
window.addEventListener("touchend", touchend)
|
||||
|
||||
function mouseup(x, y) {
|
||||
if (dragging) {
|
||||
dragging = false
|
||||
}
|
||||
dragging = false
|
||||
updateHash()
|
||||
}
|
||||
|
||||
function touchend(e) {
|
||||
|
||||
if (e.touches.length === 0) {
|
||||
|
||||
mouseup()
|
||||
setTimeout(() => updateLines(), 0)
|
||||
dragging = false
|
||||
|
||||
} else if (e.touches.length === 1) {
|
||||
initialPinchZoom = zoom
|
||||
|
|
|
@ -11,13 +11,13 @@ function initOverlap() {
|
|||
|
||||
// const hovered = []
|
||||
|
||||
buildObjectsList(null, null)
|
||||
resetEntriesList()
|
||||
renderBackground(atlas)
|
||||
render()
|
||||
|
||||
document.addEventListener('timeupdate', () => {
|
||||
atlasDisplay = atlas.slice()
|
||||
resetEntriesList(null, null)
|
||||
resetEntriesList()
|
||||
renderBackground(atlasDisplay)
|
||||
render()
|
||||
})
|
||||
|
@ -27,7 +27,7 @@ function initOverlap() {
|
|||
updateLines()
|
||||
|
||||
if (window.location.hash) {
|
||||
highlightEntryFromUrl()
|
||||
updateViewFromHash()
|
||||
}
|
||||
|
||||
function renderBackground(atlas) {
|
||||
|
@ -44,11 +44,11 @@ function initOverlap() {
|
|||
backgroundContext.beginPath()
|
||||
|
||||
if (path[0]) {
|
||||
backgroundContext.moveTo(path[0][0], path[0][1])
|
||||
backgroundContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
for (let p = 1; p < path.length; p++) {
|
||||
backgroundContext.lineTo(path[p][0], path[p][1])
|
||||
backgroundContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
backgroundContext.closePath()
|
||||
|
|
|
@ -79,7 +79,8 @@ const dispatchTimeUpdateEvent = (period = currentPeriod, variation = currentVari
|
|||
|
||||
async function updateBackground(newPeriod = currentPeriod, newVariation = currentVariation) {
|
||||
abortController.abort()
|
||||
abortController = new AbortController()
|
||||
myAbortController = new AbortController()
|
||||
abortController = myAbortController
|
||||
currentUpdateIndex++
|
||||
const myUpdateIndex = currentUpdateIndex
|
||||
const variationConfig = variationsConfig[newVariation]
|
||||
|
@ -109,6 +110,7 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren
|
|||
|
||||
layers.length = layerUrls.length
|
||||
await Promise.all(layerUrls.map(async (url, i) => {
|
||||
const imageBlob = await (await fetch(url, { signal: myAbortController.signal })).blob()
|
||||
const imageLayer = new Image()
|
||||
await new Promise(resolve => {
|
||||
imageLayer.onload = () => {
|
||||
|
@ -117,10 +119,14 @@ async function updateBackground(newPeriod = currentPeriod, newVariation = curren
|
|||
layers[i] = imageLayer
|
||||
resolve()
|
||||
}
|
||||
imageLayer.src = url
|
||||
imageLayer.src = URL.createObjectURL(imageBlob)
|
||||
})
|
||||
}))
|
||||
|
||||
if (myAbortController.signal.aborted || newPeriod !== currentPeriod || newVariation !== currentVariation) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const imageLayer of layers) {
|
||||
context.drawImage(imageLayer, 0, 0)
|
||||
}
|
||||
|
@ -137,7 +143,7 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
|
|||
}
|
||||
document.body.dataset.canvasLoading = ""
|
||||
|
||||
const oldPeriod = currentPeriod
|
||||
// const oldPeriod = currentPeriod
|
||||
const oldVariation = currentVariation
|
||||
|
||||
if (!variationsConfig[newVariation]) newVariation = defaultVariation
|
||||
|
@ -163,7 +169,21 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
|
|||
|
||||
await updateBackground(newPeriod, newVariation)
|
||||
|
||||
atlas = []
|
||||
atlas = generateAtlasForPeriod(newPeriod, newVariation)
|
||||
|
||||
dispatchTimeUpdateEvent(newPeriod, newVariation, atlas)
|
||||
delete document.body.dataset.canvasLoading
|
||||
tooltip.dataset.forceVisible = ""
|
||||
clearTimeout(tooltipDelayHide)
|
||||
tooltipDelayHide = setTimeout(() => {
|
||||
delete tooltip.dataset.forceVisible
|
||||
}, 1000)
|
||||
|
||||
}
|
||||
|
||||
function generateAtlasForPeriod(newPeriod = currentPeriod, newVariation = currentVariation) {
|
||||
|
||||
const atlas = []
|
||||
for (const entry of atlasAll) {
|
||||
let chosenIndex
|
||||
|
||||
|
@ -194,13 +214,7 @@ async function updateTime(newPeriod = currentPeriod, newVariation = currentVaria
|
|||
})
|
||||
}
|
||||
|
||||
dispatchTimeUpdateEvent(newPeriod, newVariation, atlas)
|
||||
delete document.body.dataset.canvasLoading
|
||||
tooltip.dataset.forceVisible = ""
|
||||
clearTimeout(tooltipDelayHide)
|
||||
tooltipDelayHide = setTimeout(() => {
|
||||
delete tooltip.dataset.forceVisible
|
||||
}, 1000)
|
||||
return atlas
|
||||
|
||||
}
|
||||
|
||||
|
@ -233,6 +247,7 @@ function isOnPeriod(start, end, variation, currentPeriod, currentVariation) {
|
|||
if (start > end) [start, end] = [end, start]
|
||||
return currentPeriod >= start && currentPeriod <= end && variation === currentVariation
|
||||
}
|
||||
window.isOnPeriod = isOnPeriod
|
||||
|
||||
function parsePeriod(periodString) {
|
||||
let variation = defaultVariation
|
||||
|
@ -256,36 +271,52 @@ function parsePeriod(periodString) {
|
|||
}
|
||||
}
|
||||
|
||||
function formatPeriod(start, end, variation) {
|
||||
start ??= currentPeriod
|
||||
end ??= currentPeriod
|
||||
variation ??= currentVariation
|
||||
function formatPeriod(targetStart, targetEnd, targetVariation, forUrl = false) {
|
||||
targetStart ??= currentPeriod
|
||||
targetEnd ??= currentPeriod
|
||||
targetVariation ??= currentVariation
|
||||
|
||||
let periodString, variationString
|
||||
variationString = variationsConfig[variation].code
|
||||
if (start > end) [start, end] = [end, start]
|
||||
if (start === end) {
|
||||
if (start === variationsConfig[variation].default && variation !== defaultVariation) {
|
||||
variationString = variationsConfig[targetVariation].code
|
||||
if (targetStart > targetEnd) [targetStart, targetEnd] = [targetEnd, targetStart]
|
||||
if (targetStart === targetEnd) {
|
||||
if (forUrl && targetVariation === defaultVariation && targetStart === variationsConfig[defaultVariation].default) {
|
||||
periodString = ""
|
||||
}
|
||||
else periodString = start
|
||||
else periodString = targetStart
|
||||
}
|
||||
else periodString = start + "-" + end
|
||||
if (periodString && variationString) return variationsConfig[variation].code + ":" + periodString
|
||||
else periodString = targetStart + "-" + targetEnd
|
||||
if (periodString && variationString) return variationsConfig[targetVariation].code + ":" + periodString
|
||||
if (variationString) return variationString
|
||||
|
||||
return periodString
|
||||
}
|
||||
|
||||
function formatHash(id, start, end, variation) {
|
||||
start ??= currentPeriod
|
||||
end ??= currentPeriod
|
||||
variation ??= currentVariation
|
||||
function setReferenceVal(reference, newValue) {
|
||||
if (reference === false || reference === "") return null
|
||||
else return reference ?? newValue
|
||||
}
|
||||
|
||||
function formatHash(targetEntry, targetPeriodStart, targetPeriodEnd, targetVariation, targetX, targetY, targetZoom) {
|
||||
let hashData = window.location.hash.substring(1).split('/')
|
||||
|
||||
targetEntry = setReferenceVal(targetEntry, hashData[0])
|
||||
targetPeriodStart = setReferenceVal(targetPeriodStart, currentPeriod)
|
||||
targetPeriodEnd = setReferenceVal(targetPeriodEnd, currentPeriod)
|
||||
targetVariation = setReferenceVal(targetVariation, currentVariation)
|
||||
targetX = setReferenceVal(targetX, canvasCenter.x - scaleZoomOrigin[0])
|
||||
targetY = setReferenceVal(targetY, canvasCenter.y - scaleZoomOrigin[1])
|
||||
targetZoom = setReferenceVal(targetZoom, zoom)
|
||||
|
||||
const result = [id]
|
||||
const targetPeriod = formatPeriod(start, end, variation)
|
||||
if (targetPeriod && targetPeriod !== defaultPeriod) result.push(targetPeriod)
|
||||
if (targetX) targetX = Math.round(targetX)
|
||||
if (targetY) targetY = Math.round(targetY)
|
||||
if (targetZoom) targetZoom = targetZoom.toFixed(3).replace(/\.?0+$/, '')
|
||||
|
||||
const result = [targetEntry]
|
||||
const targetPeriod = formatPeriod(targetPeriodStart, targetPeriodEnd, targetVariation, true)
|
||||
result.push(targetPeriod, targetX, targetY, targetZoom)
|
||||
if (!result.some(el => el || el === 0)) return ''
|
||||
return '#' + result.join('/')
|
||||
return '#' + result.join('/').replace(/\/+$/, '')
|
||||
}
|
||||
|
||||
function downloadCanvas() {
|
||||
|
|
|
@ -31,10 +31,10 @@ const objectsContainer = document.getElementById("objectsList")
|
|||
const closeObjectsListButton = document.getElementById("closeObjectsListButton")
|
||||
const objectsListOverflowNotice = document.getElementById("objectsListOverflowNotice")
|
||||
|
||||
const filterInput = document.getElementById("searchList")
|
||||
const searchInput = document.getElementById("searchList")
|
||||
const sortInput = document.getElementById("sort")
|
||||
|
||||
const entriesList = document.getElementById("entriesList")
|
||||
|
||||
let entriesListShown = false
|
||||
|
||||
const drawButton = document.getElementById("drawLink")
|
||||
|
@ -47,56 +47,36 @@ let atlasDisplay
|
|||
|
||||
const entriesLimit = 50
|
||||
let entriesOffset = 0
|
||||
|
||||
const moreEntriesButton = document.createElement("button")
|
||||
moreEntriesButton.innerHTML = "Show " + entriesLimit + " more"
|
||||
moreEntriesButton.type = "button"
|
||||
moreEntriesButton.className = "btn btn-primary d-block mb-2 mx-auto"
|
||||
|
||||
moreEntriesButton.id = "moreEntriesButton"
|
||||
moreEntriesButton.addEventListener('click', () => {
|
||||
buildObjectsList(null, null)
|
||||
renderBackground(atlas)
|
||||
render()
|
||||
})
|
||||
let showMoreEntries = () => {}
|
||||
|
||||
const moreEntriesObserver = new IntersectionObserver((entries, observer) => {
|
||||
const moreEntriesObserver = new IntersectionObserver(entries => {
|
||||
for (const entry of entries) {
|
||||
if (!entry.isIntersecting) continue
|
||||
moreEntriesButton.click()
|
||||
showMoreEntries()
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
moreEntriesObserver.observe(moreEntriesButton)
|
||||
|
||||
let defaultSort = "shuffle"
|
||||
document.getElementById("sort").value = defaultSort
|
||||
let defaultSort = sortInput.value
|
||||
|
||||
let lastPos = [0, 0]
|
||||
|
||||
let fixed = false; // Fix hovered items in place, so that clicking on links is possible
|
||||
|
||||
filterInput.addEventListener("input", function () {
|
||||
entriesOffset = 0
|
||||
entriesList.replaceChildren()
|
||||
entriesList.appendChild(moreEntriesButton)
|
||||
|
||||
if (this.value === "") {
|
||||
document.getElementById("relevantOption").disabled = true
|
||||
atlasDisplay = atlas.slice(0)
|
||||
buildObjectsList(null, null)
|
||||
} else {
|
||||
document.getElementById("relevantOption").disabled = false
|
||||
buildObjectsList(this.value.toLowerCase(), "relevant")
|
||||
}
|
||||
|
||||
searchInput.addEventListener("input", function () {
|
||||
resetEntriesList()
|
||||
})
|
||||
|
||||
document.getElementById("sort").addEventListener("input", function () {
|
||||
if (this.value !== "relevant") {
|
||||
defaultSort = this.value
|
||||
}
|
||||
resetEntriesList(filterInput.value.toLowerCase(), this.value)
|
||||
sortInput.addEventListener("input", function () {
|
||||
resetEntriesList()
|
||||
})
|
||||
|
||||
offcanvasDraw.addEventListener('show.bs.offcanvas', () => {
|
||||
|
@ -167,6 +147,7 @@ function clearObjectsList() {
|
|||
fixed = false
|
||||
render()
|
||||
objectEditNav.remove()
|
||||
updateHash(false)
|
||||
document.title = pageTitle
|
||||
}
|
||||
|
||||
|
@ -229,8 +210,8 @@ function updateLines() {
|
|||
)
|
||||
}
|
||||
linesContext.lineTo(
|
||||
~~(hovered[i].center[0] * zoom) + innerContainer.offsetLeft,
|
||||
~~(hovered[i].center[1] * zoom) + innerContainer.offsetTop
|
||||
~~((hovered[i].center[0] - canvasOffset.x) * zoom) + innerContainer.offsetLeft,
|
||||
~~((hovered[i].center[1] - canvasOffset.y) * zoom) + innerContainer.offsetTop
|
||||
)
|
||||
linesContext.stroke()
|
||||
}
|
||||
|
@ -259,8 +240,8 @@ function updateLines() {
|
|||
)
|
||||
}
|
||||
linesContext.lineTo(
|
||||
~~(hovered[i].center[0] * zoom) + innerContainer.offsetLeft,
|
||||
~~(hovered[i].center[1] * zoom) + innerContainer.offsetTop
|
||||
~~((hovered[i].center[0] - canvasOffset.x) * zoom) + innerContainer.offsetLeft,
|
||||
~~((hovered[i].center[1] - canvasOffset.y) * zoom) + innerContainer.offsetTop
|
||||
)
|
||||
linesContext.stroke()
|
||||
}
|
||||
|
@ -287,12 +268,12 @@ function renderBackground(atlas) {
|
|||
|
||||
if (path[0]) {
|
||||
//backgroundContext.moveTo(path[0][0]*zoom, path[0][1]*zoom)
|
||||
backgroundContext.moveTo(path[0][0], path[0][1])
|
||||
backgroundContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
for (let p = 1; p < path.length; p++) {
|
||||
//backgroundContext.lineTo(path[p][0]*zoom, path[p][1]*zoom)
|
||||
backgroundContext.lineTo(path[p][0], path[p][1])
|
||||
backgroundContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
backgroundContext.closePath()
|
||||
|
@ -321,13 +302,9 @@ function renderBackground(atlas) {
|
|||
}
|
||||
}
|
||||
|
||||
function buildObjectsList(filter, sort = defaultSort) {
|
||||
function buildObjectsList(filter, sort) {
|
||||
|
||||
if (entriesList.contains(moreEntriesButton)) {
|
||||
entriesList.removeChild(moreEntriesButton)
|
||||
}
|
||||
|
||||
atlasDisplay ||= atlas.slice()
|
||||
atlasDisplay = atlas.slice()
|
||||
|
||||
if (filter) {
|
||||
atlasDisplay = atlas.filter(entry => {
|
||||
|
@ -343,11 +320,10 @@ function buildObjectsList(filter, sort = defaultSort) {
|
|||
document.getElementById("atlasSize").innerHTML = "The Atlas contains " + atlasDisplay.length + " entries."
|
||||
}
|
||||
|
||||
sort ||= defaultSort
|
||||
|
||||
renderBackground(atlasDisplay)
|
||||
render()
|
||||
|
||||
sort ||= defaultSort
|
||||
document.getElementById("sort").value = sort
|
||||
|
||||
//console.log(sort)
|
||||
|
@ -397,60 +373,72 @@ function buildObjectsList(filter, sort = defaultSort) {
|
|||
atlasDisplay.sort(sortFunction)
|
||||
}
|
||||
|
||||
for (let i = entriesOffset; i < entriesOffset + entriesLimit; i++) {
|
||||
moreEntriesButton.removeEventListener('click', showMoreEntries)
|
||||
showMoreEntries = () => {
|
||||
|
||||
if (i >= atlasDisplay.length) break
|
||||
if (entriesList.contains(moreEntriesButton)) {
|
||||
entriesList.removeChild(moreEntriesButton)
|
||||
}
|
||||
|
||||
const element = createInfoBlock(atlasDisplay[i])
|
||||
const entry = atlasDisplay[i]
|
||||
|
||||
element.addEventListener("mouseenter", function () {
|
||||
if (fixed || dragging) return
|
||||
objectsContainer.replaceChildren()
|
||||
|
||||
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
|
||||
previousZoom ??= zoom
|
||||
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
|
||||
|
||||
hovered = [entry]
|
||||
render()
|
||||
hovered[0].element = this
|
||||
updateLines()
|
||||
|
||||
})
|
||||
|
||||
element.addEventListener("click", e => {
|
||||
toggleFixed(e)
|
||||
if (!fixed) return
|
||||
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
|
||||
previousZoom ??= zoom
|
||||
applyView()
|
||||
})
|
||||
|
||||
element.addEventListener("mouseleave", () => {
|
||||
if (fixed || dragging) return
|
||||
|
||||
scaleZoomOrigin = [...previousScaleZoomOrigin]
|
||||
zoom = previousZoom
|
||||
previousScaleZoomOrigin = undefined
|
||||
previousZoom = undefined
|
||||
applyView()
|
||||
|
||||
hovered = []
|
||||
updateLines()
|
||||
render()
|
||||
})
|
||||
|
||||
entriesList.appendChild(element)
|
||||
for (let i = entriesOffset; i < entriesOffset + entriesLimit; i++) {
|
||||
|
||||
if (i >= atlasDisplay.length) break
|
||||
|
||||
const element = createInfoBlock(atlasDisplay[i])
|
||||
const entry = atlasDisplay[i]
|
||||
|
||||
element.addEventListener("mouseenter", function () {
|
||||
if (fixed || dragging) return
|
||||
objectsContainer.replaceChildren()
|
||||
|
||||
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
|
||||
previousZoom ??= zoom
|
||||
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
|
||||
|
||||
hovered = [entry]
|
||||
render()
|
||||
hovered[0].element = this
|
||||
updateLines()
|
||||
|
||||
})
|
||||
|
||||
element.addEventListener("click", e => {
|
||||
toggleFixed(e)
|
||||
if (!fixed) return
|
||||
previousScaleZoomOrigin ??= [...scaleZoomOrigin]
|
||||
previousZoom ??= zoom
|
||||
applyView()
|
||||
})
|
||||
|
||||
element.addEventListener("mouseleave", () => {
|
||||
if (fixed || dragging) return
|
||||
|
||||
scaleZoomOrigin = [...previousScaleZoomOrigin]
|
||||
zoom = previousZoom
|
||||
previousScaleZoomOrigin = undefined
|
||||
previousZoom = undefined
|
||||
applyView()
|
||||
|
||||
hovered = []
|
||||
updateLines()
|
||||
render()
|
||||
})
|
||||
|
||||
entriesList.appendChild(element)
|
||||
|
||||
}
|
||||
|
||||
entriesOffset += entriesLimit
|
||||
|
||||
if (atlasDisplay.length > entriesOffset) {
|
||||
moreEntriesButton.innerHTML = "Show " + Math.min(entriesLimit, atlasDisplay.length - entriesOffset) + " more"
|
||||
entriesList.appendChild(moreEntriesButton)
|
||||
}
|
||||
|
||||
}
|
||||
moreEntriesButton.addEventListener('click', showMoreEntries)
|
||||
showMoreEntries()
|
||||
|
||||
entriesOffset += entriesLimit
|
||||
|
||||
if (atlasDisplay.length > entriesOffset) {
|
||||
moreEntriesButton.innerHTML = "Show " + Math.min(entriesLimit, atlasDisplay.length - entriesOffset) + " more"
|
||||
entriesList.appendChild(moreEntriesButton)
|
||||
}
|
||||
}
|
||||
|
||||
function shuffle() {
|
||||
|
@ -468,8 +456,10 @@ function resetEntriesList() {
|
|||
entriesList.replaceChildren()
|
||||
entriesList.appendChild(moreEntriesButton)
|
||||
|
||||
buildObjectsList(filter = null, sort = null)
|
||||
const sort = sortInput.value || defaultSort
|
||||
const search = searchInput?.value.toLowerCase()
|
||||
|
||||
buildObjectsList(search, sort)
|
||||
}
|
||||
|
||||
async function render() {
|
||||
|
@ -498,12 +488,12 @@ async function render() {
|
|||
|
||||
if (path[0]) {
|
||||
//context.moveTo(path[0][0]*zoom, path[0][1]*zoom)
|
||||
highlightContext.moveTo(path[0][0], path[0][1])
|
||||
highlightContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
for (let p = 1; p < path.length; p++) {
|
||||
//context.lineTo(path[p][0]*zoom, path[p][1]*zoom)
|
||||
highlightContext.lineTo(path[p][0], path[p][1])
|
||||
highlightContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
highlightContext.closePath()
|
||||
|
@ -547,12 +537,12 @@ async function render() {
|
|||
|
||||
if (path[0]) {
|
||||
//context.moveTo(path[0][0]*zoom, path[0][1]*zoom)
|
||||
highlightContext.moveTo(path[0][0], path[0][1])
|
||||
highlightContext.moveTo(path[0][0] - canvasOffset.x, path[0][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
for (let p = 1; p < path.length; p++) {
|
||||
//context.lineTo(path[p][0]*zoom, path[p][1]*zoom)
|
||||
highlightContext.lineTo(path[p][0], path[p][1])
|
||||
highlightContext.lineTo(path[p][0] - canvasOffset.x, path[p][1] - canvasOffset.y)
|
||||
}
|
||||
|
||||
highlightContext.closePath()
|
||||
|
@ -578,13 +568,10 @@ async function render() {
|
|||
|
||||
}
|
||||
|
||||
function updateHovering(e, tapped) {
|
||||
|
||||
if (dragging || (fixed && !tapped)) return
|
||||
|
||||
function updateCoordsDisplay(e) {
|
||||
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
|
||||
(e.clientX - (container.clientWidth / 2 - innerContainer.clientWidth / 2 + zoomOrigin[0] + container.offsetLeft)) / zoom + canvasOffset.x,
|
||||
(e.clientY - (container.clientHeight / 2 - innerContainer.clientHeight / 2 + zoomOrigin[1] + container.offsetTop)) / zoom + canvasOffset.y
|
||||
]
|
||||
const coordsEl = document.getElementById("coords_p")
|
||||
|
||||
|
@ -592,11 +579,19 @@ function updateHovering(e, tapped) {
|
|||
if (isNaN(pos[0])) {
|
||||
coordsEl.textContent = "0, 0"
|
||||
} else {
|
||||
coordsEl.textContent = Math.ceil(pos[0]) + ", " + Math.ceil(pos[1])
|
||||
coordsEl.textContent = Math.floor(pos[0]) + ", " + Math.floor(pos[1])
|
||||
}
|
||||
|
||||
if (!(pos[0] <= 2200 && pos[0] >= -100 && pos[0] <= 2200 && pos[0] >= -100)) return
|
||||
return pos
|
||||
}
|
||||
|
||||
function updateHovering(e, tapped) {
|
||||
|
||||
if (dragging || (fixed && !tapped)) return
|
||||
const pos = updateCoordsDisplay(e)
|
||||
|
||||
if (!(pos[0] <= canvasSize.x + canvasOffset.x + 200 && pos[0] >= canvasOffset.x - 200 && pos[1] <= canvasSize.y + canvasOffset.y + 200 && pos[1] >= canvasOffset.x - 200)) return
|
||||
|
||||
const newHovered = []
|
||||
for (const entry of atlasDisplay) {
|
||||
if (pointIsInPolygon(pos, entry.path)) newHovered.push(entry)
|
||||
|
@ -647,36 +642,44 @@ function updateHovering(e, tapped) {
|
|||
render()
|
||||
}
|
||||
|
||||
window.addEventListener("hashchange", highlightEntryFromUrl)
|
||||
window.addEventListener("hashchange", updateViewFromHash)
|
||||
|
||||
function highlightEntryFromUrl() {
|
||||
function updateViewFromHash() {
|
||||
|
||||
const hash = window.location.hash.substring(1); //Remove hash prefix
|
||||
let [id, period] = hash.split('/')
|
||||
let [hashEntryId, hashPeriod, hashX, hashY, hashZoom] = hash.split('/')
|
||||
|
||||
// Handle zzz and 0.. prefix
|
||||
let newId = id.replace(/^zzz([a-z0-9]{8,})$/g, "$1").replace(/^0+/, '')
|
||||
if (id !== newId) {
|
||||
id = newId
|
||||
let newId = hashEntryId.replace(/^zzz([a-z0-9]{8,})$/g, "$1").replace(/^0+/, '')
|
||||
if (hashEntryId !== newId) {
|
||||
hashEntryId = newId
|
||||
const newLocation = new URL(window.location)
|
||||
newLocation.hash = '#' + [newId, period].join('/')
|
||||
newLocation.hash = '#' + [newId, hashPeriod, hashX, hashY, hashZoom].join('/')
|
||||
history.replaceState({}, "", newLocation)
|
||||
}
|
||||
|
||||
let targetPeriod, targetVariation
|
||||
|
||||
if (period) {
|
||||
[targetPeriod, , targetVariation] = parsePeriod(period)
|
||||
if (hashPeriod) {
|
||||
[targetPeriod, , targetVariation] = parsePeriod(hashPeriod)
|
||||
} else {
|
||||
targetPeriod = defaultPeriod
|
||||
targetVariation = defaultVariation
|
||||
}
|
||||
updateTime(targetPeriod, targetVariation, true)
|
||||
|
||||
if (!id) return
|
||||
setView(
|
||||
(isNaN(hashX) || hashX === '') ? undefined : Number(hashX),
|
||||
(isNaN(hashY) || hashY === '') ? undefined : Number(hashY),
|
||||
(isNaN(hashZoom) || hashZoom === '') ? undefined : Number(hashZoom)
|
||||
)
|
||||
|
||||
if (!hashEntryId) return
|
||||
|
||||
// Highlight entry from hash
|
||||
|
||||
const entries = atlas.filter(e => {
|
||||
return e.id.toString() === id
|
||||
return e.id.toString() === hashEntryId
|
||||
})
|
||||
|
||||
if (entries.length !== 1) return
|
||||
|
@ -686,7 +689,7 @@ function highlightEntryFromUrl() {
|
|||
document.title = entry.name + " on " + pageTitle
|
||||
|
||||
if ((!entry.diff || entry.diff !== "delete")) {
|
||||
objectEditNav.href = "./?mode=draw&id=" + id
|
||||
objectEditNav.href = "./?mode=draw&id=" + hashEntryId
|
||||
objectEditNav.title = "Edit " + entry.name
|
||||
if (!objectEditNav.isConnected) {
|
||||
showListButton.parentElement.appendChild(objectEditNav)
|
||||
|
@ -700,8 +703,11 @@ function highlightEntryFromUrl() {
|
|||
objectsContainer.appendChild(infoElement)
|
||||
|
||||
renderBackground(atlas)
|
||||
applyView()
|
||||
setView(entry.center[0], entry.center[1], setZoomByPath(entry.path))
|
||||
setView(
|
||||
(isNaN(hashX) || hashX === '') ? entry.center[0] : Number(hashX),
|
||||
(isNaN(hashY) || hashY === '') ? entry.center[1] : Number(hashY),
|
||||
(isNaN(hashZoom) || hashZoom === '') ? setZoomByPath(entry.path) : Number(hashZoom)
|
||||
)
|
||||
|
||||
closeObjectsListButton.classList.remove("d-none")
|
||||
entriesList.classList.add("disableHover")
|
||||
|
@ -714,7 +720,7 @@ function highlightEntryFromUrl() {
|
|||
|
||||
function setZoomByPath(path) {
|
||||
|
||||
let boundingBox = [canvasSize.x, 0, canvasSize.y, 0]
|
||||
let boundingBox = [canvasSize.x + canvasOffset.x, canvasOffset.x, canvasSize.y + canvasOffset.y, canvasOffset.y]
|
||||
path?.forEach(([x, y]) => {
|
||||
boundingBox[0] = Math.min(boundingBox[0], x)
|
||||
boundingBox[1] = Math.max(boundingBox[1], x)
|
||||
|
@ -729,6 +735,8 @@ function setZoomByPath(path) {
|
|||
zoom = Math.min(clientSize[0] / boundingBoxSize[0], clientSize[1] / boundingBoxSize[1])
|
||||
zoom = Math.min(4, zoom/2)
|
||||
|
||||
return zoom
|
||||
|
||||
}
|
||||
|
||||
function initView() {
|
||||
|
@ -739,14 +747,14 @@ function initView() {
|
|||
|
||||
document.addEventListener('timeupdate', () => {
|
||||
atlasDisplay = atlas.slice()
|
||||
resetEntriesList(null, null)
|
||||
resetEntriesList()
|
||||
})
|
||||
|
||||
// parse linked atlas entry id from link hash
|
||||
/*if (window.location.hash.substring(3)){
|
||||
zoom = 4
|
||||
applyView()
|
||||
highlightEntryFromUrl()
|
||||
updateViewFromHash()
|
||||
}*/
|
||||
|
||||
applyView()
|
||||
|
@ -762,17 +770,7 @@ function initExplore() {
|
|||
|
||||
function updateHovering(e, tapped) {
|
||||
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])
|
||||
}
|
||||
updateCoordsDisplay(e)
|
||||
}
|
||||
|
||||
renderBackground(atlas)
|
||||
|
@ -793,10 +791,7 @@ function initGlobal() {
|
|||
})
|
||||
|
||||
document.addEventListener('timeupdate', event => {
|
||||
let hashData = window.location.hash.substring(1).split('/')
|
||||
const newLocation = new URL(window.location)
|
||||
newLocation.hash = formatHash(hashData[0], event.detail.period, event.detail.period, event.detail.variation)
|
||||
if (location.hash !== newLocation.hash) history.replaceState({}, "", newLocation)
|
||||
updateHash()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -826,26 +821,22 @@ function initViewGlobal() {
|
|||
container.addEventListener("touchend", e => {
|
||||
e.preventDefault()
|
||||
|
||||
//console.log(e)
|
||||
//console.log(e.changedTouches[0].clientX)
|
||||
if (e.changedTouches.length !== 1) return
|
||||
|
||||
e = e.changedTouches[0]
|
||||
//console.log(lastPos[0] - e.clientX)
|
||||
|
||||
if (Math.abs(lastPos[0] - e.clientX) + Math.abs(lastPos[1] - e.clientY) > 4)
|
||||
if (Math.sqrt(Math.pow(lastPos[0] - e.clientX, 2) + Math.pow(lastPos[1] - e.clientY, 2)) < 10)
|
||||
setTimeout(() => updateHovering(e, true), 0)
|
||||
|
||||
//console.log("Foo!!")
|
||||
dragging = false
|
||||
fixed = false
|
||||
setTimeout(() => updateHovering(e, true), 0)
|
||||
})
|
||||
|
||||
if (window.location.hash) { // both "/" and just "/#" will be an empty hash string
|
||||
highlightEntryFromUrl()
|
||||
updateViewFromHash()
|
||||
}
|
||||
|
||||
document.addEventListener('timeupdate', event => {
|
||||
drawButton.href = "./?mode=draw" + formatHash(undefined, event.detail.period, event.detail.period, event.detail.variation)
|
||||
drawButton.href = "./?mode=draw" + formatHash(null, event.detail.period, event.detail.period, event.detail.variation)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -24,7 +24,15 @@
|
|||
<meta property="og:image:height" content="512">
|
||||
<meta property="og:image:alt" content="The r/place Atlas logo">
|
||||
<meta property="og:description" content="This is an atlas aiming to chart all the artworks created during the r/place April Fools event on Reddit in 2022. It is made with information to each artwork of the canvas provided by the community.">
|
||||
|
||||
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:creator" content="Place Atlas contributors (original by Roland Rytz)">
|
||||
<meta name="twitter:url" content="https://2022.place-atlas.stefanocoding.me/">
|
||||
<meta name="twitter:title" content="About - The 2022 r/place Atlas">
|
||||
<meta name="twitter:description" content="This is an atlas aiming to chart all the artworks created during the r/place April Fools event on Reddit in 2022. It is made with information to each artwork of the canvas provided by the community.">
|
||||
<meta name="twitter:image" content="https://2022.place-atlas.stefanocoding.me/_img/logo.png">
|
||||
<meta name="twitter:image:alt" content="The 2022 r/place Atlas logo">
|
||||
|
||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
|
||||
|
|
|
@ -24,7 +24,15 @@
|
|||
<meta property="og:image:height" content="512">
|
||||
<meta property="og:image:alt" content="The r/place Atlas logo">
|
||||
<meta property="og:description" content="An interactive map of Reddit's 2022 r/place, with information to each artwork of the canvas provided by the community.">
|
||||
|
||||
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:creator" content="Place Atlas contributors (original by Roland Rytz)">
|
||||
<meta name="twitter:url" content="https://2022.place-atlas.stefanocoding.me/">
|
||||
<meta name="twitter:title" content="The 2022 r/place Atlas">
|
||||
<meta name="twitter:description" content="An interactive map of Reddit's 2022 r/place, with information to each artwork of the canvas provided by the community.">
|
||||
<meta name="twitter:image" content="https://2022.place-atlas.stefanocoding.me/_img/logo.png">
|
||||
<meta name="twitter:image:alt" content="The 2022 r/place Atlas logo">
|
||||
|
||||
<!-- <meta name="google-site-verification" content="gZGHpBSMzffAbIn0qB8b00We6EwSGkDTfDoQVv-NWss"/> -->
|
||||
|
||||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1, maximum-scale=1, shrink-to-fit=no, viewport-fit=cover"> <!-- user-scalable=no -->
|
||||
|
|
Loading…
Reference in a new issue