Positioning Div relative to outer Div

1 day ago 2
ARTICLE AD BOX

My apologies if the title is not good.

I am on a group project making a DND map that will let the player move around pieces on the board.

It utilizes Jquery-UI for its draggable functions.

Currently I have the map at a fixed size, however it would be really nice if instead my pieces inside of the mapboard div and resize with the map, Meaning when the tab gets smaller by the user (or they have a smaller/different sized monitor) the pieces can move in the map along with it.

The closest similarity in how I want the map to function is: https://valoplant.gg/

My .cshtml

<div id="MapDiv"> <div class="map-board" id="map-board" style="background-image: url('@Model.MapImagePath'); background-size: 1500px 1000px; background-repeat: no-repeat; background-position: center; width: 1500px; height: 1000px;" data-role="dm"> @foreach (var token in Model.Tokens.Where(t => t.Piece?.PieceType?.Name != "Map" && (t.X != 0 || t.Y != 0))) { <div class="tokendiv" style="position: absolute; left: @(token.X)px; top: @(token.Y)px; z-index: @(token.ZIndex);"> <img src="@(string.IsNullOrEmpty(token.Piece?.ImagePath) ? "/images/default.png" : token.Piece.ImagePath)" class="draggable-token" style="height: 50px; width: 50px;" id="[email protected]" data-tokenid="@token.Id" onerror="this.onerror=null; this.src='/images/default.png';" /> </div> } </div> </div>

My JS:

const mapBoard = document.getElementById('map-board'); let isPlayerView = false; // Instantiates the broadcaster object for executing functions on the playerview side. const bc = new BroadcastChannel('map_channel'); // sets playerView to 'dm' or 'player' and then assigns isPlayerView to true if set to 'player' const playerView = mapBoard.dataset.role; //assigns isPlayerView to true if set to 'player' if (playerView === 'player') { isPlayerView = true; console.log('Player view set to true.'); bc.onmessage = (e) => { console.log(e); } } if (!isPlayerView) { // https://api.jqueryui.com/draggable/#event-create document.addEventListener('DOMContentLoaded', () => { // Dont be afraid of the dollar sign // JQuery selector. // Just grabs all the .draggable-token DOMS like a queryselectorall $('.draggable-token').draggable(draggablePieceInfo); // For every side-piece // My take for simplicity is to just give the user a popup // That they can select yes or no on. // It will make the piece on the map set it at a default 0x 0y and invisible to the player. // https://jqueryui.com/dialog/ document.querySelectorAll('.sidebar-piece').forEach(async (e) => { e.addEventListener('click', async (e) => { // E returns a pointer event so I need to get necessary data to work with the create token POST. const pieceId = e.srcElement.dataset.pieceid; // Gets the session ID form the uri const currentSessionId = window.sessionId; const x = 0; const y = 0; console.log(e); $('#dialog').dialog({ // This will prevent the user from interacting with background (map) when popup shows. modal: true, // Adding user button choices to the popup... buttons: [ { text: 'Yes', click: async () => { // Close the dialog. $('#dialog').dialog('close'); const response = await fetch('/Map/CreateToken', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ pieceId, sessionId: currentSessionId, X: x, Y: y, }), }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const result = await response.json(); console.log('Token created:', result); makeNewToken(result); }, }, { text: 'No', click: () => { // Close the dialog. $('#dialog').dialog('close'); }, }, ], }); document.getElementById('dialog').classList.remove('hidden'); console.log('Should show dialog...'); }); }); // For all the tokens give the right click event. document.querySelectorAll('.vangtokendiv').forEach((e) => { e.addEventListener('contextmenu', (e) => { e.preventDefault(); // console.log(e); // Get the source element and add my DM Toggle opacity. event.target.classList.toggle('dmOpacityToggle'); }); }); }); // Requires id of the token. const makeNewToken = (data) => { // Get the img element DOM in the sidebar. const sidebarPiece = document.querySelector( `[data-pieceid="${data.pieceImageID}"]`, ); // if we got it clone it and make it a normal draggable piece. if (sidebarPiece) { const tokenImg = sidebarPiece.cloneNode(true); tokenImg.id = `token-placed-${data.id}`; tokenImg.classList.remove('sidebar-piece'); tokenImg.classList.add('draggable-token'); tokenImg.dataset.tokenid = data.id; tokenImg.draggable = true; tokenImg.style.position = 'absolute'; tokenImg.style.left = `100px`; tokenImg.style.top = `100px`; tokenImg.style.zIndex = 99; mapBoard.appendChild(tokenImg); $(`#${tokenImg.id}`).draggable(draggablePieceInfo); // Send creation event to player // bc.postMessage({ tokenid: result.id, x: x.toFixed(0), y: y.toFixed(0), isVisible: true, action: 'tokenMoved' }); } else { console.log('Could not make the token!'); } }; const draggablePieceInfo = { containment: '#map-board', scroll: false, create: (event, ui) => { console.log('Token Created:', Date.now()); }, stop: (event, ui) => { console.log('Broadcast a message to the player view!'); console.log('Dropped at:', event.target.x, 'X'); console.log('Dropped at:', event.target.y, 'Y'); bc.postMessage("Broadcast the necessary info."); }, drag: (event, ui) => { console.log('A piece is dragging!'); // Put whatever functions here. }, }; }
Read Entire Article