Shifting Position Within A Grid


by Jeremy Caudle
code

Today I wanted to see how easy would it be to move an element around on a grid using arrows keys and buttons for touchscreen devices. Turns out it is a bit trickier than I anticipated in terms of tracking the correct values, but I was able to eventually get something working with some code I put to use in my style customizer prototype. I manipulated CSS variables/custom properties to update the position of the yellow square within the grid. I wonder what I'll be able to build on top of this in the future.

View the code:

HTML and JS
<section class="display">
            <div class="bg-tile"></div>

            <div class="active-sprite-tile"></div>
        </section>
        <section class="button-block">
            <button id="upButton">Up</button>
            <button id="downButton">Down</button>
            <button id="leftButton">Left</button>
            <button id="rightButton">Right</button>
        </section>
        <script>
            /*** Variables ***/
            const playerTile = document.querySelector('.active-sprite-tile');
            console.log(playerTile);
            let playerTileRowStart = 1;
            let playerTileRowEnd = 1;
            let playerTileColumnStart = 1;
            let playerTileColumnEnd = 1;
            let root = document.documentElement;

            /*** Functions ***/

            /* Key logging function from MDN */
            function logKey(e) {
                console.log(` ${e.key}`);
            }

            function updatePlayerPosition() {
                root.style.setProperty('--player-row-start', playerTileRowStart);
                root.style.setProperty('--player-row-end', playerTileRowEnd);
                root.style.setProperty('--player-column-start', playerTileColumnStart);
                root.style.setProperty('--player-column-end', playerTileColumnEnd);
                console.log(`Column: ${root.style.getPropertyValue('--player-column-start')} / ${root.style.getPropertyValue('--player-column-end')}, Row: ${root.style.getPropertyValue('--player-row-start')} / ${root.style.getPropertyValue('--player-row-end')} `);
            }
            
            function playerMoveDown() {
                playerTileRowStart++;
                playerTileRowEnd++;
                updatePlayerPosition();                    
            }

            function playerMoveUp() {
                playerTileRowStart--;
                playerTileRowEnd--;
                updatePlayerPosition();                  
            }

            function playerMoveLeft() {
                playerTileColumnStart--;
                playerTileColumnEnd--;
                updatePlayerPosition();                  
            }

            function playerMoveRight() {
                playerTileColumnStart++;
                playerTileColumnEnd++;
                updatePlayerPosition();                 
            }


            /*** Events ***/
            document.addEventListener('keydown', (e) => {
                logKey(e);
                let keyPressed = e.key;
                if (keyPressed == 'ArrowDown') {
                    playerMoveDown();
                } else if (keyPressed == 'ArrowUp') {
                    playerMoveUp();
                } else if (keyPressed == 'ArrowLeft') {
                    playerMoveLeft();
                } else if (keyPressed == 'ArrowRight') {
                    playerMoveRight();
                }
                logKey(e);
            });

            downButton.addEventListener('click', playerMoveDown);
            upButton.addEventListener('click', playerMoveUp);
            leftButton.addEventListener('click', playerMoveLeft);
            rightButton.addEventListener('click', playerMoveRight);

        </script>
CSS
:root {
            --player-row-start: 1;
            --player-row-end: 1;
            --player-column-start: 1;
            --player-column-end: 1;
            }
            
            html { box-sizing: border-box; z-index: 0; }
            html * { box-sizing: inherit; }

            section.display {
                width: 256px;
                height: 256px;
                margin: 2rem auto;
                background-color: gray;
            }

            .bg-tile {
                background-color: darkgreen;
                width:100%;
                height:100%;
                grid-column: 1 / 9;
                grid-row: 1 / 9;
            }

            .active-sprite-tile {
                background-color: yellow;
                width:100%;
                height:100%;
            }

            .button-block button {
                    min-height: 44px;
                    border-radius: 50%;
                    padding: .5rem;
                    min-width: 7ch;
                    border: none;
                    background-color: #444;
                    color: #dedede;
                }
            
            @supports (display: flex) {
                .button-block {
                    display: flex;
                    justify-content: space-evenly;
                    max-width: 256px;
                    margin: 1rem auto;
                }
                .button-block button {
                    min-height: 44px;
                    padding: .5rem;
                }
            }

            @supports (display: grid) {
                section.display {
                    display: grid;
                    grid-template-columns: repeat(8, 1fr);
                    grid-template-rows: repeat(8, 1fr);
                    gap:0;
                }  

                .active-sprite-tile {
                    grid-row-start: var(--player-row-start, 1);
                    grid-row-end: var(--player-row-end, 1);
                    grid-column-start: var(--player-column-start, 1);
                    grid-column-end: var(--player-column-end, 1);
                } 
            }