summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Gunger <kgunger12@gmail.com>2022-08-18 02:17:23 -0400
committerKyle Gunger <kgunger12@gmail.com>2022-08-18 02:17:23 -0400
commit46aae06bd699b3ca396f7f5c750e1fb9fc9ff4bc (patch)
tree92a7c7179a568d0095c2fff3c14d20437c1acd8b
parent4efae60183feb616c3dec7698a6a2fe4351b71c7 (diff)
Add transform to drags
-rw-r--r--client.html2
-rw-r--r--scripts/cards/card.js7
-rw-r--r--scripts/cards/deck.js24
-rw-r--r--scripts/cards/drag.js58
-rw-r--r--scripts/client.js3
-rw-r--r--scripts/gui/lobby.js4
-rw-r--r--scripts/gui/table.js71
-rw-r--r--styles/client/card.css29
8 files changed, 139 insertions, 59 deletions
diff --git a/client.html b/client.html
index 26f3c18..f1871f7 100644
--- a/client.html
+++ b/client.html
@@ -47,7 +47,7 @@
<body>
<div class="table" state="closed">
-
+ <drag></drag>
</div>
<div class="topbar" style="height: auto;">
diff --git a/scripts/cards/card.js b/scripts/cards/card.js
index 53e9861..352f2b3 100644
--- a/scripts/cards/card.js
+++ b/scripts/cards/card.js
@@ -7,7 +7,7 @@ const CardPos = ["top", "topl", "topr", "mid", "midt", "midb", "bot", "botl", "b
// Every card should have a deck.
// Use deck.appendCard, deck.prependCard, or deck.addCardAt to make a card visible
class Card {
- constructor (id, data)
+ constructor (id, deck, data)
{
this.e = document.createElement("card");
this.generateElements(data);
@@ -16,6 +16,7 @@ class Card {
this.e.card = this;
this.id = id;
+ this.deck = deck;
}
// Generate a card with basic text only
@@ -125,6 +126,8 @@ class Card {
{
this.e.style.setProperty("--left", "0px");
this.e.style.setProperty("--top", "0px");
+ this.e.style.setProperty("--irot", "0");
+ this.e.style.setProperty("--iscale", "1");
}
resetPosInstant()
@@ -136,6 +139,6 @@ class Card {
}
getDeck() {
- return this.e.parentElement.deck;
+ return this.deck;
}
}
diff --git a/scripts/cards/deck.js b/scripts/cards/deck.js
index b1c7fd2..3ed94ff 100644
--- a/scripts/cards/deck.js
+++ b/scripts/cards/deck.js
@@ -64,6 +64,15 @@ class Deck {
updatePos()
{
+ let cb = this.e.getBoundingClientRect();
+
+ if(cb.width >= window.innerWidth)
+ this.e.className = "maxw";
+ else if (cb.height >= window.innerHeight)
+ this.e.className = "maxh";
+ else
+ this.e.className = "";
+
let len = this.cards.length - 1;
for(let i in this.cards)
this.cards[i].setPos(len-i);
@@ -77,6 +86,7 @@ class Deck {
}
this.cards.push(card);
this.e.appendChild(card.e);
+ card.deck = this.getID();
this.updatePos();
return true;
}
@@ -89,14 +99,14 @@ class Deck {
this.cards.unshift(card);
this.e.prepend(card.e);
card.setPos(this.cards.length - 1);
+ card.deck = this.getID();
this.updateCount();
return true;
}
addCardAt(card, index)
{
- if(index < 0 || index > this.cards.length)
- return
+ index = Math.min(Math.max(index, 0), this.cards.length);
if(index == 0) {
this.prependCard(card);
@@ -106,6 +116,7 @@ class Deck {
let temp = this.cards.slice(0, index);
temp[temp.length - 1].e.after(card.e);
this.cards.unshift(card);
+ card.deck = this.getID();
for(let i = temp.length - 1; i >= 0; i--)
this.cards.unshift(temp[i]);
@@ -135,7 +146,6 @@ class Deck {
if(index < 0 || index >= this.cards.length)
return
- this.e.removeChild(this.cards[index].e);
let c = this.cards.splice(index, 1)[0];
this.updatePos();
@@ -174,6 +184,14 @@ class Deck {
return (x > rect.left && x < rect.right && y > rect.top && y < rect.bottom)
}
+ dist(x, y)
+ {
+ let rect = this.e.getBoundingClientRect();
+ let mx = rect.left + (rect.right - rect.left) / 2;
+ let my = rect.top + (rect.bottom - rect.top) / 2;
+ return Math.sqrt((mx - x)**2 + (my - y)**2);
+ }
+
checkCard (el)
{
for(let c of this.cards)
diff --git a/scripts/cards/drag.js b/scripts/cards/drag.js
index ec82ade..0805556 100644
--- a/scripts/cards/drag.js
+++ b/scripts/cards/drag.js
@@ -5,7 +5,7 @@ class MultiDrag extends EventTarget {
drag = [];
mouse = [null, null];
- constructor(ret = false) {
+ constructor(root, ret = false) {
super();
window.addEventListener("mousemove", this.update.bind(this));
@@ -15,26 +15,32 @@ class MultiDrag extends EventTarget {
//window.addEventListener("touchend", this.stopDraggingAll.bind(this));
//window.addEventListener("touchcancel", this.stopDraggingAll.bind(this));
+ this.root = root;
this.ret = ret;
+ this.transform = ()=>{return [0.0, 1.0];};
}
- addDragEl(el, ox, oy, px, py, pt) {
+ addDragEl(el, px, py) {
if(this.del)
return;
- el.style.transitionDuration = "0s";
+ el.className = "instant";
let push = {
e: el,
- osx: ox,
- osy: oy,
- ptd: pt
+ ep: el.parentElement,
+ ex: el.getBoundingClientRect().left,
+ ey: el.getBoundingClientRect().top,
+ px: px,
+ py: py
};
- if(this.ret) {
- push.prx = px;
- push.pry = py;
- }
+ let t = this.transform(px, py);
+ this.root.appendChild(el);
+ el.style.setProperty("--left", push.ex + "px");
+ el.style.setProperty("--top", push.ey + "px");
+ el.style.setProperty("--irot", t[0]);
+ el.style.setProperty("--iscale", t[1]);
this.drag.push(push);
@@ -60,14 +66,7 @@ class MultiDrag extends EventTarget {
let cap = new Event("dragstart");
- cap.drag = this.addDragEl(
- e.target,
- e.pageX - parseInt(e.target.style.getPropertyValue("--left")),
- e.pageY - parseInt(e.target.style.getPropertyValue("--top")),
- e.target.style.left,
- e.target.style.top,
- e.target.style.transitionDuration
- );
+ cap.drag = this.addDragEl(e.target, e.pageX, e.pageY);
this.dispatchEvent(cap);
}
@@ -85,11 +84,12 @@ class MultiDrag extends EventTarget {
cap.x = this.mouse[0];
cap.y = this.mouse[1];
- this.drag[i].e.style.transitionDuration = this.drag[i].ptd;
+ this.drag[i].e.className = "";
if(this.ret) {
- this.drag[i].e.style.setProperty("--left", this.drag[i].prx + "px");
- this.drag[i].e.style.setProperty("--top", this.drag[i].pry + "px");
+ this.drag[i].e.style.setProperty("--left", "0px");
+ this.drag[i].e.style.setProperty("--top", "0px");
+ this.drag[i].ep.appendChild(this.drag[i].e);
}
cap.drag = this.drag.splice(i, 1);
@@ -123,8 +123,9 @@ class MultiDrag extends EventTarget {
this.drag[0].e.style.transitionDuration = this.drag[0].ptd;
if(this.ret) {
- this.drag[0].e.style.setProperty("--left", this.drag[0].prx + "px");
- this.drag[0].e.style.setProperty("--top", this.drag[0].pry + "px");
+ this.drag[0].e.style.setProperty("--left", "0px");
+ this.drag[0].e.style.setProperty("--top", "0px");
+ this.drag[0].ep.appendChild(this.drag[0].e);
}
cap.drag.push(this.drag.shift());
@@ -136,12 +137,19 @@ class MultiDrag extends EventTarget {
}
update(e) {
+ if(this.drag.length == 0)
+ return;
+
this.mouse[0] = e.pageX;
this.mouse[1] = e.pageY;
+ let t = this.transform(this.mouse[0], this.mouse[1]);
for (let i = 0; i < this.drag.length && !this.del; i++) {
- this.drag[i].e.style.setProperty("--left", e.pageX - this.drag[i].osx + "px");
- this.drag[i].e.style.setProperty("--top", e.pageY - this.drag[i].osy + "px");
+ let d = this.drag[i];
+ d.e.style.setProperty("--left", (e.pageX - d.px) + d.ex + "px");
+ d.e.style.setProperty("--top", (e.pageY - d.py) + d.ey + "px");
+ d.e.style.setProperty("--irot", t[0]);
+ d.e.style.setProperty("--iscale", t[1]);
}
}
diff --git a/scripts/client.js b/scripts/client.js
index d5a9616..f030859 100644
--- a/scripts/client.js
+++ b/scripts/client.js
@@ -57,9 +57,8 @@ class Client{
this.lobby = new Lobby(document.getElementsByClassName("lobby")[0], this.socket);
this.lobby.setState("Connecting", "loading", this.socket.server);
-
- this.drag = new MultiDrag();
+ this.drag = new MultiDrag(document.getElementsByTagName("drag")[0]);
this.table = new Table(document.getElementsByClassName("table")[0], this.drag, this.socket);
this.chat = new Chat(document.getElementsByClassName("chat")[0], this.socket);
diff --git a/scripts/gui/lobby.js b/scripts/gui/lobby.js
index a32c47f..f790a31 100644
--- a/scripts/gui/lobby.js
+++ b/scripts/gui/lobby.js
@@ -158,7 +158,6 @@ class Lobby {
while (this.e.games.firstChild != null) {
this.e.games.removeChild(this.e.games.firstChild)
}
- console.log("eheh")
for (let i of data.games) {
if(typeof i != "object")
@@ -207,7 +206,7 @@ class Lobby {
// Called when a new public game is removed on the server
// { data string } the uuid of the game to delete
deleteGame (data) {
-
+ delete this.games[data];
}
// Called when the client wants to toggle the new game screen
@@ -240,6 +239,7 @@ class Lobby {
while (this.e.games.firstElementChild != null) {
this.e.games.removeChild(this.e.games.firstElementChild)
}
+ this.games = {};
this.setState("Connecting", "loading", this.e.addr.innerText);
this.init = false;
diff --git a/scripts/gui/table.js b/scripts/gui/table.js
index f17abb1..51ed4b3 100644
--- a/scripts/gui/table.js
+++ b/scripts/gui/table.js
@@ -1,12 +1,13 @@
'use strict';
-const TABLE_RPC = ["newDeck", "newCard", "deleteDeck", "deleteCard", "moveByID", "swapCard"]
+const TABLE_RPC = ["newDeck", "newCard", "deleteDeck", "deleteCard", "moveCard", "swapCard"]
// Table represents and manages the actual game. It accepts inputs from the server and tries to query the server when the player makes a move.
class Table{
constructor(e, drag, socket) {
this.root = e;
this.drag = drag;
+ this.drag.transform = this.getTransform.bind(this);
drag.addEventListener("dragstart", (e) => {console.log(e)});
drag.addEventListener("dragstop", this.dragMsg.bind(this));
@@ -57,8 +58,11 @@ class Table{
// Should reset all internal objects and delete all dangling decks and cards.
reset ()
{
- while(this.root.firstElementChild != null)
- this.root.firstElementChild.remove();
+ for (let e of this.root.children) {
+ if(e.tagName !== "DRAG") {
+ e.remove();
+ }
+ }
this.decks = {};
this.cards = {};
@@ -117,29 +121,32 @@ class Table{
// Move a card from one deck to another
// {data object} data from the server
- // {data.cardID any} ID of the card to move
- // {data.deckID any} ID of the deck to move the card to
+ // {data.card any} ID of the card to move
+ // {data.deck any} ID of the deck to move the card to
// {data.index number} card index in the new deck
- moveByID(data)
+ moveCard(data)
{
- this.cards[data.cardID].getDeck().removeCardByID(data.cardID);
- this.decks[data.deckID].addCardAt(this.cards[data.cardID], data.index);
+ let c = this.cards[data.card];
+ this.decks[c.getDeck()].removeCardByID(data.card);
+ this.decks[data.deck].addCardAt(c, data.index);
+ c.resetPos();
+ c.e.className = "";
}
// Swap card data with new data
// {data object} data from the server
- // {data.cardID any} ID of the card to swap
- // {data.newID any} New ID for the card
+ // {data.card any} ID of the card to swap
+ // {data.id any} New ID for the card
// {data.data object} visualization data
swapCard(data)
{
// Can't swap a card into a an id of a pre-existing card.
- if (this.cards[data.newID] != null) {
+ if (this.cards[data.id] != null) {
return false;
}
- this.cards[data.newID] = this.cards[data.cardID];
- delete this.cards[data.cardID];
- this.cards[data.newID].generateElements(data.data);
+ this.cards[data.id] = this.cards[data.card];
+ delete this.cards[data.card];
+ this.cards[data.id].generateElements(data.data);
}
@@ -162,6 +169,27 @@ class Table{
this.socket.send("move", {card: cardID, deck: deckID, index: index});
}
+ getTransform(x, y)
+ {
+ let rot = 0, scale = 0, dtot = 0;
+
+ for(let d in this.decks ) {
+ let r = parseFloat(this.decks[d].e.style.getPropertyValue("--rot"));
+ let s = parseFloat(this.decks[d].e.style.getPropertyValue("--scale"));
+
+ //
+ //TODO: Some code to properly weight the importance of scale and rotation
+ // Hopefully this can be done in one pass
+ let f = 1/this.decks[d].dist(x, y);
+ let tot = dtot + f;
+ rot = rot*(dtot/tot) + r*(f/tot);
+ scale = scale*(dtot/tot) + s*(f/tot);
+ dtot += tot;
+ }
+
+ return [rot, scale];
+ }
+
// DRAG DEBUGGING
@@ -177,15 +205,18 @@ class Table{
if(event.drag.length < 1)
return;
- let c = event.drag[0].e.card;
+ let c = event.drag[0];
let d = this.checkDeck(event.x, event.y);
- if(c !== null)
+ if(c.e.card !== null)
{
- if(d !== null && !this.decks[d].hasCard(c.id))
- this.checkMove(c.id, d);
- else
- c.resetPos();
+ let id = c.e.card.id;
+ if(d !== null && !this.decks[d].hasCard(id))
+ this.checkMove(id, d);
+ else {
+ c.ep.appendChild(c.e)
+ c.e.card.resetPos();
+ }
}
}
}
diff --git a/styles/client/card.css b/styles/client/card.css
index 7b63b41..6e4121e 100644
--- a/styles/client/card.css
+++ b/styles/client/card.css
@@ -1,3 +1,13 @@
+drag {
+ position:absolute;
+ display:contents;
+ overflow: visible;
+ width: 0;
+ height: 0;
+ top:0;
+ left:0;
+}
+
.instant {
transition-duration: 0s;
}
@@ -20,8 +30,9 @@ card
box-sizing: border-box;
font-size: small;
- left: calc(var(--left) / var(--scale));
- top: calc(var(--top) / var(--scale));
+ left: var(--left);
+ top: var(--top);
+ transform: scale(var(--iscale)) rotate(var(--irot));
z-index: 3;
}
@@ -130,8 +141,7 @@ cimage
flex: 1;
}
-card[drag=true]
-{
+drag > card {
z-index: 4;
}
@@ -157,6 +167,17 @@ deck {
border: 3px solid var(--deck-shadow);
box-sizing: border-box;
+ max-height: 100vh;
+ max-width: 100vw;
+ overflow: auto;
+}
+
+.maxw {
+ left: 0 !important;
+}
+
+.maxh {
+ top: 0 !important;
}
deck:hover {