From 46aae06bd699b3ca396f7f5c750e1fb9fc9ff4bc Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Thu, 18 Aug 2022 02:17:23 -0400 Subject: Add transform to drags --- scripts/cards/card.js | 7 +++-- scripts/cards/deck.js | 24 ++++++++++++++--- scripts/cards/drag.js | 58 +++++++++++++++++++++++------------------ scripts/client.js | 3 +-- scripts/gui/lobby.js | 4 +-- scripts/gui/table.js | 71 ++++++++++++++++++++++++++++++++++++--------------- 6 files changed, 113 insertions(+), 54 deletions(-) (limited to 'scripts') 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(); + } } } } -- cgit v1.2.3