#javascript #html #css #canvas
#javascript #HTML #css #холст
Вопрос:
Я создаю pixel art Maker, и у меня отключена большая часть функциональности; однако я хочу, чтобы пользователи могли сохранять и загружать свои проекты, созданные на странице. Я использовал сетку divs для шаблона, но во всех примерах сохранения и загрузки, которые я видел, использовался элемент canvas. Есть ли какой-нибудь способ сделать это с моим дизайном, или мне нужно переделать его с помощью canvas?
let canvas = document.querySelector('.canvas');
let button = document.querySelector('button');
let high;
let wide;
let color = document.querySelector('.colorChoice').value;
//create cell listeners
function listenCells() {
let cell = document.querySelectorAll('.grid-square');
cell.forEach((cell) => {
cell.addEventListener('click', function() {
cell.style.backgroundColor = color;
});
});
}
//Check for updated color picker
function onChangeColor() {
color = this.value;
}
document.querySelector('.colorChoice').addEventListener("change", onChangeColor);
//function to build the grid based on user input
function createGrid(height = 25, width = 25) {
canvas.innerHTML = '';
for (let i = 0; i < height; i ) {
let row = document.createElement('div');
row.classList.add('row');
canvas.appendChild(row);
for (let j = 0; j < width; j ) {
let cell = document.createElement('div');
cell.classList.add('grid-square');
row.appendChild(cell);
}
}
listenCells();
}
//listens for input of rows and columns
button.addEventListener('click', function() {
high = parseInt(document.querySelector('.column-input').value);
wide = parseInt(document.querySelector('.row-input').value);
if (Number.isNaN(high) || Number.isNaN(wide)) {
createGrid();
} else {
createGrid(wide, high);
}
});
//Default grid built on load
window.onload = createGrid(25, 25);
/* import pixel font for navbar */
@import url('https://fonts.googleapis.com/css2?family=Press Start 2Pamp;display=swap');
.grid-square {
height: 12px;
width: 12px;
border: 1px black solid;
flex-shrink: 0;
}
.row {
display: flex;
justify-content: center;
flex-wrap: nowrap;
}
.canvas {
max-height: inherit;
max-width: 75%;
}
body {
font-family: 'Press Start 2P', cursive;
}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="styles/style.css">
<title>Pixel Art Maker</title>
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-dark bg-dark">
<span class="navbar-brand mb-0 h1 mx-auto">Pixel Art Maker</span>
</nav>
<!-- Container to put grid in -->
<div class="container shadow p-3 mb-5 bg-white rounded mt-5 main">
<div class="container canvas d-flex-inline">
</div>
<form class="d-flex-inline w-50 mx-auto mt-4">
<div class="d-flex">
<div class="form-group w-25 ml-auto mr-2">
<label class="d-block text-center" for="gridRows">Rows</label>
<input type="number" class="form-control row-input" id="gridRows">
</div>
<div class="form-group w-25 mr-auto ml-2">
<label class="d-block text-center" for="gridColumns">Columns</label>
<input type="number" class="form-control column-input" id="gridColumns">
</div>
</div>
</form>
<div class="form-group w-25 mx-auto">
<button type="submit" class="btn btn-primary w-100">Submit</button>
</div>
<form class="d-flex-inline w-50 mx-auto">
<div class="form-group w-25 mx-auto">
<label for="color">Color</label>
<input type="color" class="form-control colorChoice" id="color">
</div>
</form>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS, then local JS -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C OGpamoFVy38MVBnE IbbVYUew OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU 6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV rV" crossorigin="anonymous"></script>
<script src="scripts/script.js"></script>
</body>
</html>
PS Я использую обычный JavaScript, без jQuery
Комментарии:
1. Вы можете вызвать
canvas.toDataURL();
, чтобы получить URL-адрес, который имеет представление изображения. Этот URL-адрес можно сохранитьlocalStorage
.2. Вам обязательно следует перейти на дизайн canvas. Вы должны создать свои функции рисования, чтобы принимать аргументы, которые могут воссоздавать те же рисунки, которые ваш клиент создает в графическом интерфейсе. Есть несколько способов сохранить вещи;
localStorage
например, в вашем браузереlocalStorage.data = JSON.stringify(jsonObjectHere);
и на самом сервере, которые я бы рекомендовал, если у вашего клиента есть учетная запись в вашей системе (нужно выполнить много работы правильно) .3. Понимая, что вы используете сетку
<div>
, они могут быть сериализованы до массива объектов javascript со свойствами размеров и положения, содержимого, базовых стилей и т. Д., Если это то, что вам нужно. Затем этот массив может быть отправлен на сервер или сохранен локально. При наличии достаточного количества свойств в каждом объекте, когда вам нужно загрузить его снова, вы создаете элементы для каждого объекта и вставляете в dom. Не уверен, почему вы не использовали бы canvas для всего этого4. Просто сохраните координаты в карте цветов и сохраните все как JSON. И в отличие от всех других предыдущих комментариев, я вижу очень веские причины не использовать холст здесь: рисование сетки на холсте означает, что у вас на самом деле должен быть холст в 12 раз больше, чем пиксельная графика, если вы хотите удалить эту сетку при экспорте, это означает, что вам нужно все перерисовать и т.д. Логика событий указателей была бы намного сложнее и т. Д. Сохранение divs в качестве элементов управления кажется мне разумным, если вам нужен вывод в формате png, вы всегда можете нарисовать только это на холсте.
Ответ №1:
Вы не предлагаете подробностей о able to save and load
so, поэтому я бы выбрал SVG…
Если вы никогда не слышали о SVG, вам следует немного почитать:
https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
Вот пример того, как будет выглядеть сохраненный документ:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1" baseProfile="full"
height="80px" width="440px">
<defs/>
<rect fill="rgb(105,10,255)" height="40px" width="40px" x="40px" y="0px"/>
<rect fill="rgb(135,20,245)" height="40px" width="40px" x="80px" y="0px"/>
<rect fill="rgb(165,30,235)" height="40px" width="40px" x="120px" y="0px"/>
<rect fill="rgb(195,40,225)" height="40px" width="40px" x="160px" y="0px"/>
<rect fill="rgb(205,50,215)" height="40px" width="40px" x="200px" y="0px"/>
<rect fill="rgb(215,60,205)" height="40px" width="40px" x="240px" y="0px"/>
<rect fill="rgb(225,70,195)" height="40px" width="40px" x="280px" y="0px"/>
<rect fill="rgb(235,80,165)" height="40px" width="40px" x="320px" y="0px"/>
<rect fill="rgb(245,90,135)" height="40px" width="40px" x="360px" y="0px"/>
<rect fill="rgb(255,10,105)" height="40px" width="40px" x="400px" y="0px"/>
<rect fill="rgb(105,255,10)" height="40px" width="40px" x="40px" y="40px"/>
<rect fill="rgb(135,245,20)" height="40px" width="40px" x="80px" y="40px"/>
<rect fill="rgb(165,235,30)" height="40px" width="40px" x="120px" y="40px"/>
<rect fill="rgb(195,225,40)" height="40px" width="40px" x="160px" y="40px"/>
<rect fill="rgb(205,215,50)" height="40px" width="40px" x="200px" y="40px"/>
<rect fill="rgb(215,205,60)" height="40px" width="40px" x="240px" y="40px"/>
<rect fill="rgb(225,195,70)" height="40px" width="40px" x="280px" y="40px"/>
<rect fill="rgb(235,165,80)" height="40px" width="40px" x="320px" y="40px"/>
<rect fill="rgb(245,135,90)" height="40px" width="40px" x="360px" y="40px"/>
<rect fill="rgb(255,105,10)" height="40px" width="40px" x="400px" y="40px"/>
</svg>
Конечно, это всего лишь небольшая выборка, состоящая всего из двух строк.
У вас будет по одному rect
на каждый определенный вами пиксель.