JS - pixel-art-creator-02

revision:


pixel-art creator

pixel art maker

Choose grid size

grid height: 15
grid width: 15

Pick a color:


Mode:

PAINT

Design Canvas

(Click to paint or erase. Left mouse button for multi-tile action)

code:
            <div class="squares-bg">
                <div class="header flyItIn">
                    <h3>pixel art maker</h3>
                </div>
                <div class="gridContainer">
                    <div class="gridControl">
                        <h4>Choose grid size</h4>
                        <form id="sizePicker" name="gridSize">
                            <span class="gridSizeLabel">grid height:</span><span id="gridHeightDisplay"> 15</span>
                            <input type="range" id="inputHeight" class="slider" title="Set grid height" name="height" min="1" max= "50" value="15">
                            <br>
                            <span class="gridSizeLabel">grid width:</span><span id="gridWidthDisplay">  15</span>
                            <input type="range" id="inputWidth" class="slider" title="Set grid width" name="width" min="1" max="50" value="15">
                            <br>
                            <div class="gridCreateClear">
                                <input class="button" type="submit" id="createGrid" value="Create grid" name="submitGrid" title="Makes a grid of tiles using the values above">
                                <button class="button" type="button" id="clearGrid" value="Clear" title="Clears the colors from the grid so you can start over">
                                    Clear
                                </button>
                            </div>
                        </form>
                        <h4>Pick a color: </h4>
                        <input type="color" id="colorPicker" value="#ff0000" title="Set PAINT color">
                        <br>
                        <h4>Mode: </h4><span id="modeDisplay" class="paintOrErase"> PAINT</span>
                        <br>
                        <div id="mode">
                            <button id="paintBtn" class="button paint" title="Set mode to PAINT" type="button">
                                <i class="fas fa-paint-brush paint"></i>
                            </button>
                            <button id="eraseBtn" class="button erase" title="Set mode to ERASE" type="button">
                                <i class="fas fa-eraser erase"></i>
                            </button>
                        </div> <!--end mode div: for mode button listener -->
                    </div> <!-- end gridControl -->
                    <div id="gridCanvas" class="gridCanvas rotationTime">
                        <h4>Design Canvas</h4>
                        <table id="pixelCanvas" class="flyItIn2"></table>
                        <p id ="legend" class="noLegend"><em>(Click to paint or erase. Left mouse button for multi-tile action)</em></p>
                    </div> <!-- end gridCanvas -->
            </div> <!-- end cssGirdcontainer -->
        </div>
        <style>
            .squares-bg { width: 100%; height: 100%; color: white;}
            .squares-bg::before, .squares-bg::after {content: ""; width: 100%; height: 100%;  position: relative; top: 0; left: 0; pointer-events: none; z-index: -1;}
            .squares-bg::before {background-image: linear-gradient(black 50%, transparent 50%), linear-gradient(to right, grey 50%, black 50%);  background-size: 2vw 2vw;}
            .squares-bg::after {background-image: linear-gradient(black, transparent);}
            /* The grid classes are used for css grid layout.*/
            .gridContainer { display:grid; grid-template-areas: 'control canvas'; grid-template-columns: minmax(22vw, 22vw) minmax(50vw, 1fr); grid-template-rows: auto;  grid-gap: 1vw;}
            .gridControl {grid-area: control; height: 30vw; background: rgba(105, 105, 105, 0.85); border-radius: 0.7vw;  margin: 0 1.5vw 2vw 1.5vw; 
                box-shadow: 0.2vw 0.2vw 0.5vw rgba(77, 77, 77, 0.8);}
            .gridCanvas {grid-area: canvas; background: rgba(105, 105, 105, 0.85); border-radius: 0.7vw;  margin: 0 1.5vw 2vw 1.5vw;
                 box-shadow: 0.2vw 0.2vw 0.5vw rgba(77, 77, 77, 0.8);}
            h3 {font-family: 'Press Start 2P';font-size: 2vw;  color: dimgrey;  padding-top:1vw; text-shadow: 0.2vw 0.2vw 0.5vw red; margin: 0.5vw 0 0.75vw 0;}
            h4 {margin: 0.5vw 0 0.5vw;}
            h4:nth-of-type(2) {display: inline;}
            h4:nth-of-type(3) {display: inline; }
            table, tr, td {border: 0.1vw solid black; cursor: pointer;}
            table { border-collapse: collapse; background-color: white; margin: 0 auto; box-shadow: .2vw .2vw .4vw red;}
            tr {height: 2vw;}
            td {width: 2vw;}
            p {margin: 1vw 0 1vw; }
            .noLegend { display: none;}
            .legend {display: block;}
            .gridSizeLabel {font-size: 1.2vw;}
            .button {display: inline-block;margin-top: 0.5vw; padding: 0.7vw 2vw; background: transparent; font-size: 1.1vw; cursor: pointer; text-align: center; 
                text-shadow: 0.2vw .2vw .4vw #000000; outline: none; color: white; background-color: grey; border: none; border-radius: .5vw; box-shadow: 0 .3vw red;}
            .button:hover {background-color: dimgrey;}
            .button:active {  background-color: dimgrey; box-shadow: 0 .3vw lightcoral; transform: translateY(0.3vw);}
            #createGrid,  #paintBtn {  margin-right: 0.6vw;}
            input[type=color] { margin: 1.5vw 0 1vw 0.25vw; border: 0.1vw solid darkgray; background-color: grey; cursor: pointer;}
            /* Range input thumb and track styling: browser specific */
            input[type=range] {-webkit-appearance: none; width: 95%; margin: 1.6vw 0;  padding: 0;}
            input[type=range]:focus {outline: none;}
            input[type=range]::-webkit-slider-runnable-track {width: 100%; height: 1vw; cursor: pointer;  animate: 0.2s; 
                box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d; background: red; border-radius: .2vw; border: 0.05vw solid #010101;}
            input[type=range]::-webkit-slider-thumb {box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d; 
                border: .1vw solid black; height: 2vw; width: 0.7vw; border-radius: 0.3vw; background: grey; cursor: pointer; -webkit-appearance: none; margin-top: -0.6vw;}
            input[type=range]:hover::-webkit-slider-thumb {background: dimgrey;}
            input[type=range]:focus::-webkit-slider-runnable-track { background: red;}
            input[type=range]::-moz-range-track { width: 95%; height: 1vw; cursor: pointer; animate: 0.2s; box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d; 
                background: red; border-radius: 0.1vw; border: 0.02vw solid #010101;}
            input[type=range]::-moz-range-thumb {box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d; border: .1vw solid black; height: 2vw; 
                width: 0.7vw; border-radius: 0.3vw; background: grey; cursor: pointer;}
            input[type=range]:hover::-moz-range-thumb {background: dimgrey;}
            input[type=range]::-ms-track {width: 100%; height: 1vw; cursor: pointer; animate: 0.2s; background: transparent; 
                border-color: transparent; border-width: 1vw; color: transparent; margin: -0.4vw;}
            input[type=range]::-ms-fill-lower {background: red; border: 0.02vw solid #010101; border-radius: 0.26vw; box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d;}
            input[type=range]::-ms-fill-upper {background: red; border: 0.02vw solid #010101; border-radius: 0.26vw; box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d;}
            input[type=range]::-ms-thumb {box-shadow: .1vw .1vw .1vw black, 0vw 0vw .1vw #0d0d0d; border: .1vw solid black; height: 2vw; width: 0.7vw; 
                border-radius: 0.3vw; background: grey; cursor: pointer; margin: 0;}
            input[type=range]:focus::-ms-fill-lower {background: red;}
            input[type=range]::-ms-tooltip {display: none;}
            input[type=range]:focus::-ms-fill-upper {background: red;}
            input[type=range]:hover::-ms-thumb {background: dimgrey;}
            /* text fly in effect */
            .flyItIn {animation: flyin 1s ease forwards;  opacity: 0; transform: scale(2);filter: blur(0.4vw); }
             @keyframes flyin {
                to { filter: blur(0); transform: scale(1); opacity: 1;}
            }
            .flyItIn2 {animation: flyin2 1s ease forwards; opacity: 0;transform: scale(2); filter: blur(0.4vw);}
            @keyframes flyin2 {
                to {filter: blur(0); transform: scale(1); opacity: 1;}
            }
            /* rotates the Design Canvas div */
            .rotationTime {-webkit-transition: all 4s linear; -moz-transition: all 4s linear; -ms-transition: all 4s linear; -o-transition: all 4s linear;  transition: all 4s linear;}
            .rotateCanvas { -webkit-transform: rotateX(360deg) rotateY(360deg); -moz-transform: rotateX(360deg) rotateY(360deg); -ms-transform: rotateX(360deg) rotateY(360deg);
                -o-transform: rotateX(360deg) rotateY(360deg); transform: rotateX(360deg) rotateY(360deg); }
            /* make adjustments for smaller devices */
            @media (max-width: 700px) {
                    .gridContainer {grid-template-areas:'control' 'canvas'; grid-template-columns: 1fr;}
                    .squares-bg::before {background-size: 2vw 2vw;}
                    h3 {font-size: 1vw;}
                    .gridControl {margin: 0 1vw 1.5vw 1vw;}
                    .gridCanvas {margin: 0 1vw 1.5vw 1vw;}
                }
        </style>
        <script>
            // Create a grid that a user can color with clicks - allows grid size entry and color selection
            // When size is submitted by the user, call makeGrid()
    
            // Set the inital 'paint' changes happen in click event
            const PAINT = 'PAINT';
            const ERASE = 'ERASE';
            const theGridSize = document.forms.gridSize;
            const userColor = document.getElementById('colorPicker');
            const tileMode = document.getElementById('modeDisplay');
            const displayHeight = document.getElementById('gridHeightDisplay');
            const displayWidth = document.getElementById('gridWidthDisplay');
            const userHeight = document.getElementById('inputHeight');
            const userWidth = document.getElementById('inputWidth');
            
            const grid = document.getElementById('pixelCanvas');
            const gridCanvas = document.getElementById('gridCanvas');
            let gridTileMode = PAINT; 
           
            theGridSize.submitGrid.onclick = function makeGrid(event) {
                event.preventDefault();
                let mouseIsDown = false;
                const rows = userHeight.value;
                const columns = userWidth.value;
    
                while (grid.hasChildNodes()) {
                    grid.removeChild(grid.lastChild); 
                }
                //Build the grid row by row and then append to the table -  project rubrics requires use of for and while loops
    
                let tableRows = '';
                let r = 1;
                while (r <= rows) {
                    tableRows += '<tr>';
                    for (let c=1; c <= columns; c++) {
                            tableRows += '<td></td>';
                    }
                    tableRows += '</tr>';
                    r += 1;
                    } 
    
                grid.insertAdjacentHTML('afterbegin', tableRows); 
                document.getElementById('legend').className = "legend";
                grid.classList.toggle('flyItIn'); 
                grid.classList.toggle('flyItIn2'); 
                grid.addEventListener("click", function(event) {
                    event.preventDefault();
                    paintEraseTiles(event.target);
                });
                grid.addEventListener('mousedown', function(event) {
                    event.preventDefault();
                    mouseIsDown = event.which === 1 ? true : false;
                });
                document.addEventListener('mouseup', function(event) {
                    event.preventDefault();
                    mouseIsDown = false;
                });
                grid.addEventListener('mouseover', function(event) {
                    event.preventDefault();
                    if (mouseIsDown) {paintEraseTiles(event.target);}
                }); 
            };
            function paintEraseTiles(targetCell) {
                if (targetCell.nodeName === 'TD') {
                    targetCell.style.backgroundColor = gridTileMode === PAINT ? userColor.value : 'transparent';
                } else {
                    console.log("Nice try: " + targetCell.nodeName + " talk to the hand!");
                }
            }
            theGridSize.height.oninput = function (){
                displayHeight.innerHTML = ' ' + theGridSize.height.value;
            };
            theGridSize.width.oninput = function (){
                displayWidth.innerHTML = ' ' + theGridSize.width.value;
                // });
            };
            userColor.oninput = function (event){
                gridTileMode = PAINT;
                tileMode.innerHTML = ' ' + gridTileMode;
            };
            document.getElementById('clearGrid').addEventListener('click', function() {
                gridCanvas.classList.toggle('rotateCanvas'); // rotate the Design Canvas div
                let tiles = grid.getElementsByTagName('td');
                // grid.children().children().removeAttr("style");
                for(let i = 0; i <= tiles.length; i++) {
                    tiles[i].style.backgroundColor = 'transparent';
                }
            });
            document.getElementById('mode').addEventListener('click', function(event) {
                gridTileMode = event.target.className.indexOf('paint') >=0 ? PAINT : ERASE;
                // $('.paintOrErase').text(' ' + gridTileMode);
                tileMode.innerHTML = ' ' + gridTileMode;
            });
    
        </script>