Skip to content

Commit

Permalink
Merge pull request #6 from karlyanelson/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
karlyanelson committed Dec 17, 2021
2 parents 34e4ee9 + f297cea commit b6ac4aa
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 36 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ A simple Dungeons and Dragons virtual tabletop. Upload a map and add customizabl

Everything is saved locally to your browser.

## Keyboard shortcuts

Click character pieces (or tab to them and press Space or Enter) to select them and press the arrow keys to move them around and scroll the window at the same time.

If you want to move the character pieces without scrolling the window, hold down "Shift" and use the arrow keys.

Press ESC to deselect all character pieces, or click off.

## Colophon

Built using Vanilla JS and [Reef](https://reefjs.com/).
Expand Down Expand Up @@ -38,7 +46,7 @@ npm install
Run locally:

```
npm run dev
npm run start
```

Build for production:
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"description": "↗️ [Go to the Site](https://dnd-map.netlify.app/)",
"browserslist": "> 0.5%, last 2 versions, not dead",
"scripts": {
"dev": "parcel src/index.html src/**/*.html",
"dev": "NODE_ENV=development parcel src/index.html src/**/*.html",
"start": "npm run dev",
"build": "parcel build src/index.html src/**/*.html",
"build": "NODE_ENV=production parcel build src/index.html src/**/*.html",
"clean": "rm -rf dist && rm -rf .parcel-cache"
},
"repository": {
Expand Down
15 changes: 12 additions & 3 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
run.</noscript
>
<main>
<a class="skip-to-content-link" href="#mapContainer">Skip to Content</a>
<div
id="mainControls"
class="
Expand All @@ -57,7 +58,7 @@
bg-opacity-95
dark:bg-opacity-95
rounded-lg
z-50
z-40
overflow-y-auto
w-80
shadow-soft
Expand Down Expand Up @@ -160,8 +161,16 @@ <h2 aria-live="polite" aria-atomic="true">
>Icons from
<a href="https://game-icons.net/">game-icons.net</a></span
>
</p>
<p class="my-2">
<a href="./contact">Give Feedback</a>

<span class="mx-1"></span>
<span><a href="./contact">Give Feedback</a></span>
<a
href="https://github.com/karlyanelson/dnd-map#keyboard-shortcuts"
target="_blank"
>Keyboard shortcuts</a
>
</p>
</footer>
</div>
Expand All @@ -179,7 +188,7 @@ <h2 aria-live="polite" aria-atomic="true">
bg-white bg-opacity-90
dark:bg-opacity-95
rounded-lg
z-50
z-40
content-row
shadow-soft
"
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import dropHandler from "./js/handlers/dropHandler";
import inputHandler from "./js/handlers/inputHandler";
import renderHandler from "./js/handlers/renderHandler";
import touchMoveHandler from "./js/handlers/touchMoveHandler";
import keydownHandler from "./js/handlers/keydownHandler";

(function () {
//// Inits
Expand Down Expand Up @@ -52,6 +53,8 @@ import touchMoveHandler from "./js/handlers/touchMoveHandler";

document.addEventListener("dragend", dragEndHandler, false);

document.addEventListener("keydown", keydownHandler, false);

window.addEventListener("storage", () => {
// When local storage changes in a different tab (ie: the settings page)
// refresh any other open dnd map tabs (ie: the map page)
Expand Down
35 changes: 21 additions & 14 deletions src/js/components/characterPiece.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,32 @@ export default function characterPiece(character, index) {
? ` box-shadow: 1px 1px 1px 2px black, 0px 0px 0px ${charAreaOfEffectRadius}px ${charAreaOfEffectColor}75; `
: "";

const charSelected = character.selected || false;

return `
<div
class='piece text-center inline-flex p-4 flex-col items-center cursor-grab hover:cursor-grab' draggable='true' id='${
character.id
}'
<button
class='piece-container text-center inline-flex p-0 flex-col items-center cursor-grab rounded-full hover:cursor-grab'
id='${character.id}'
data-character-piece
data-index='${index}'
draggable='true'
aria-grabbed='${character.dragged || charSelected}'
aria-dropeffect='${character.dragged || charSelected ? "move" : "none"}'
style='position:absolute; top: ${characterPosY}px; left: ${characterPosX}px;'
>
<div
class='bg-no-repeat bg-center rounded-full shadow-piece'
style='height:${characterSize}px; width:${characterSize}px; ${charAreaOfEffect} background-color:${charColor}; ${characterBGimg(
<div
class='bg-no-repeat bg-center rounded-full ${
charSelected ? "outline-dotted shadow-high-dark" : "shadow-piece"
}'
style='height:${characterSize}px; width:${characterSize}px; ${charAreaOfEffect} background-color:${charColor}; ${characterBGimg(
character
)}'
></div>
<span class='piece-label p-05 mt-1 bg-white bg-opacity-90 text-xs rounded tracking-wide text-black truncate max-w-20' style='top:${
characterSize * 1.15
}px;'>
${charName}
</span>
</div>
></div>
<span class='piece-label p-05 mt-1 bg-white bg-opacity-90 text-xs rounded tracking-wide text-black truncate max-w-20 absolute' style='top:${
characterSize + 4
}px;'>
${charName}
</span>
</button>
`;
}
18 changes: 15 additions & 3 deletions src/js/handlers/clickHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import zoomMap from "../utils/zoomMap";

export default function clickHandler(event) {
if (!event.target.closest("button")) {
DATA_STORE.data.characters.forEach((char) => (char.selected = false));
return;
}

let buttonTarget = event.target.closest("button");
const buttonTarget = event.target.closest("button");

if (buttonTarget.matches("[data-toggle-settings]")) {
DATA_STORE.data.settingsExpanded = DATA_STORE.data.settingsExpanded
Expand All @@ -20,15 +21,26 @@ export default function clickHandler(event) {
}

if (buttonTarget.matches("[data-toggle-character]")) {
let characterContainer = buttonTarget.closest(".characterListItem");
const characterContainer = buttonTarget.closest(".characterListItem");

if (characterContainer) {
let characterIndex = characterContainer.getAttribute("data-index");
const characterIndex = characterContainer.getAttribute("data-index");
let character = DATA_STORE.data.characters[characterIndex];
character.expanded = character.expanded ? false : true;
}
}

if (buttonTarget.matches("[data-character-piece]")) {
const characterIndex = buttonTarget.getAttribute("data-index");
let character = DATA_STORE.data.characters[characterIndex];

character.selected = character.selected ? false : true;
}

if (!buttonTarget.matches("[data-character-piece]")) {
DATA_STORE.data.characters.forEach((char) => (char.selected = false));
}

if (buttonTarget.matches("#addCharacter")) {
addCharacter();
}
Expand Down
9 changes: 9 additions & 0 deletions src/js/handlers/dragStartHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@ export default function dragStartHandler(event) {
if (!event.target.closest(".piece")) {
return;
}

event.target.style.opacity = 0.5;
DATA_STORE.data.draggedElemMouseOffsetX =
event.touches[0].target.offsetLeft;
DATA_STORE.data.draggedElemMouseOffsetY = event.touches[0].target.offsetTop;

const characterIndex = event.target.getAttribute("data-index");
const character = DATA_STORE.data.characters[characterIndex];
character.dragged = true;
} else {
event.target.style.opacity = 0.5;
event.dataTransfer.setData("text/plain", event.target.id);
DATA_STORE.data.draggedElemMouseOffsetX = event.offsetX;
DATA_STORE.data.draggedElemMouseOffsetY = event.offsetY;

event.target.style.cursor = "grabbing";

const characterIndex = event.target.getAttribute("data-index");
const character = DATA_STORE.data.characters[characterIndex];
character.dragged = true;
}
}
16 changes: 15 additions & 1 deletion src/js/handlers/dropHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function dropHandler(event) {

const character = DATA_STORE.data.characters[characterIndex];

character.dragged = true;
character.dragged = false;

if (event.type === "touchend") {
draggedElemPosX =
Expand All @@ -40,6 +40,20 @@ export default function dropHandler(event) {
draggedElemPosY = event.pageY - DATA_STORE.data.draggedElemMouseOffsetY;
}

const xDiff = draggedElemPosX - character.x;
const yDiff = draggedElemPosY - character.y;

const charactersSelected = DATA_STORE.data.characters.filter(
(character) => character.selected
);

if (charactersSelected.length > 0) {
charactersSelected.forEach((selectedCharacter) => {
selectedCharacter.x = (selectedCharacter.x + xDiff) / zoomRatio;
selectedCharacter.y = (selectedCharacter.y + yDiff) / zoomRatio;
});
}

character.x = draggedElemPosX / zoomRatio;
character.y = draggedElemPosY / zoomRatio;
}
30 changes: 30 additions & 0 deletions src/js/handlers/keydownHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import DATA_STORE from "../globals/store";

export default function keydownHandler(event) {
const charactersSelected = DATA_STORE.data.characters.filter(
(character) => character.selected
);

if (!charactersSelected.length) {
return;
}

console.log("i ran");

if (event.keyCode == "38") {
// up arrow
charactersSelected.forEach((char) => (char.y = char.y - 5));
} else if (event.keyCode == "40") {
// down arrow
charactersSelected.forEach((char) => (char.y = char.y + 5));
} else if (event.keyCode == "37") {
// left arrow
charactersSelected.forEach((char) => (char.x = char.x - 5));
} else if (event.keyCode == "39") {
// right arrow
charactersSelected.forEach((char) => (char.x = char.x + 5));
} else if (event.keyCode == "27") {
// ESC key
charactersSelected.forEach((char) => (char.selected = false));
}
}
1 change: 1 addition & 0 deletions src/js/utils/addCharacter.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function addCharacter(characterProps = {}) {
icon: characterProps.icon || "",
background: characterProps.background || "color", // options are: 'color', 'image', 'icon'
dragged: false,
selected: false,
expanded: true,
areaOfEffect: characterProps.areaOfEffect || false,
areaOfEffectRadius: characterProps.areaOfEffectRadius || 1,
Expand Down
1 change: 0 additions & 1 deletion src/js/utils/getDataFromStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import DATA_STORE from "../globals/store";
export default function getDataFromStorage(id) {
const storedData = localStorage.getItem(id);
const emptyData = {
// map: "https://i.imgur.com/KYVBIZd.jpeg",
map: null,
settingsExpanded: true,
pieceSize: 24,
Expand Down
3 changes: 2 additions & 1 deletion src/map/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
run.</noscript
>
<main>
<a class="skip-to-content-link" href="#mapContainer">Skip to Content</a>
<div
class="
map-controls
Expand All @@ -54,7 +55,7 @@
bg-white bg-opacity-90
dark:bg-opacity-95
rounded-lg
z-50
z-40
content-row
shadow-soft
"
Expand Down
23 changes: 23 additions & 0 deletions src/settings/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,29 @@ <h2 aria-live="polite" aria-atomic="true">
<div id="characterList"></div>
</section>
</div>

<footer class="text-xs text-center mb-6 mt-12">
<p>
Made by <a href="https://karlynelson.com/">Karly Nelson</a> using
<a href="https://reefjs.com/">ReefJS</a>
</p>
<p class="my-2">
<span
>Icons from
<a href="https://game-icons.net/">game-icons.net</a></span
>
</p>
<p class="my-2">
<a href="./contact">Give Feedback</a>

<span class="mx-1"></span>
<a
href="https://github.com/karlyanelson/dnd-map#keyboard-shortcuts"
target="_blank"
>Keyboard shortcuts</a
>
</p>
</footer>
</main>

<script type="module" src="../index.js"></script>
Expand Down
38 changes: 28 additions & 10 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,6 @@ textarea {
min-height: 80vh;
}

/* For Accessibility - see https://webaim.org/techniques/css/invisiblecontent/ */
.screenreader-only {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}

.contact a {
text-align: center;
display: inline-block;
Expand All @@ -243,6 +233,28 @@ textarea {
background-image: url(../static/assets/img/grid-light.png);
}

/* For Accessibility - see https://webaim.org/techniques/css/invisiblecontent/ */
.screenreader-only {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}

.skip-to-content-link {
@apply p-2 z-50 bg-white border-black text-black dark:bg-black dark:border-white dark:text-white;
left: 50%;
position: absolute;
transform: translateY(-100%);
transition: transform 0.3s;
}

.skip-to-content-link:focus {
transform: translateY(20%);
}

@media (prefers-color-scheme: dark) {
.no-map,
.grid-bg {
Expand Down Expand Up @@ -274,3 +286,9 @@ textarea {
.outline-custom {
outline: 1px auto #0961e4;
}

/* dotted: ["3px dotted white", "4px"], */

.outline-dotted {
outline: 3px dotted white;
}
Loading

0 comments on commit b6ac4aa

Please sign in to comment.