mirror of
https://github.com/lospec/pixel-editor.git
synced 2023-08-10 21:12:51 +03:00
Finished implementing project loading and saving
This commit is contained in:
parent
2868363bb7
commit
caa81dde1c
@ -17,6 +17,7 @@ Suggestions / Planned features:
|
||||
- Snap brush preview to pixel grid
|
||||
- Move selection with arrows
|
||||
- Load palette from LPE file
|
||||
- Move colours in palette editor
|
||||
|
||||
- Custom color picker
|
||||
- custom code without dependencies
|
||||
|
@ -1,9 +1,11 @@
|
||||
|
||||
function createColorPalette(selectedPalette, fillBackground) {
|
||||
function createColorPalette(selectedPalette, fillBackground, deletePreviousPalette = true) {
|
||||
//remove current palette
|
||||
colors = document.getElementsByClassName('color-button');
|
||||
while (colors.length > 0) {
|
||||
colors[0].parentElement.remove();
|
||||
if (deletePreviousPalette) {
|
||||
colors = document.getElementsByClassName('color-button');
|
||||
while (colors.length > 0) {
|
||||
colors[0].parentElement.remove();
|
||||
}
|
||||
}
|
||||
|
||||
var lightestColor = '#000000';
|
||||
@ -31,9 +33,49 @@ function createColorPalette(selectedPalette, fillBackground) {
|
||||
|
||||
darkestColor = newColor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//set as current color
|
||||
currentLayer.context.fillStyle = darkestColor;
|
||||
}
|
||||
|
||||
function createPaletteFromLayers() {
|
||||
let colors = {};
|
||||
|
||||
for (let i=0; i<layers.length; i++) {
|
||||
if (layers[i].menuEntry != null) {
|
||||
let imageData = layers[i].context.getImageData(0, 0, layers[i].canvasSize[0], layers[i].canvasSize[1]).data;
|
||||
let dataLength = imageData.length;
|
||||
|
||||
for (let j=0; j<dataLength; j += 4) {
|
||||
if (!isPixelEmpty(imageData[j])) {
|
||||
let color = imageData[j]+','+imageData[j + 1]+','+imageData[j + 2];
|
||||
|
||||
if (!colors[color]) {
|
||||
colors[color] = {r:imageData[j],g:imageData[j + 1],b:imageData[j + 2]};
|
||||
|
||||
//don't allow more than 256 colors to be added
|
||||
if (Object.keys(colors).length >= settings.maxColorsOnImportedImage) {
|
||||
alert('The image loaded seems to have more than '+settings.maxColorsOnImportedImage+' colors.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(colors);
|
||||
|
||||
//create array out of colors object
|
||||
let colorPaletteArray = [];
|
||||
for (let color in colors) {
|
||||
if (colors.hasOwnProperty(color)) {
|
||||
colorPaletteArray.push('#'+rgbToHex(colors[color]));
|
||||
}
|
||||
}
|
||||
console.log('COLOR PALETTE ARRAY', colorPaletteArray);
|
||||
|
||||
//create palette form colors array
|
||||
createColorPalette(colorPaletteArray, false);
|
||||
}
|
@ -202,22 +202,27 @@ function closeMenu () {
|
||||
|
||||
function getProjectData() {
|
||||
// use a dictionary
|
||||
let dictionary = [];
|
||||
let dictionary = {};
|
||||
// sorting layers by increasing z-index
|
||||
let layersCopy = layers.slice();
|
||||
layersCopy.sort((a, b) => (a.canvas.style.zIndex > b.canvas.style.zIndex) ? 1 : -1);
|
||||
// store canvas size
|
||||
dictionary.push({key: "canvasWidth", value: currentLayer.canvasSize[0]});
|
||||
dictionary.push({key: "canvasHeight", value: currentLayer.canvasSize[1]});
|
||||
dictionary['canvasWidth'] = currentLayer.canvasSize[0];
|
||||
dictionary['canvasHeight'] = currentLayer.canvasSize[1];
|
||||
// store palette
|
||||
for (let i=0; i<currentPalette.length; i++) {
|
||||
dictionary.push({key: "color" + i, value: currentPalette[i]});
|
||||
dictionary["color" + i] = currentPalette[i];
|
||||
}
|
||||
|
||||
// Store number of layers
|
||||
dictionary["nLayers"] = layersCopy.length;
|
||||
|
||||
// store layers
|
||||
for (let i=0; i<layers.length; i++) {
|
||||
for (let i=0; i<layersCopy.length; i++) {
|
||||
// Only saving the layers the user has access to (no vfx, tmp or checkerboard layers)
|
||||
if (layers[i].menuEntry != null) {
|
||||
dictionary.push({key: "layer" + i, value: layers[i]});
|
||||
dictionary.push({key: "layer" + i + "ImageData",
|
||||
value: layers[i].canvas.toDataURL()
|
||||
});
|
||||
if (layersCopy[i].menuEntry != null) {
|
||||
dictionary["layer" + i] = layersCopy[i];
|
||||
dictionary["layer" + i + "ImageData"] = layersCopy[i].canvas.toDataURL();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,6 @@ class Layer {
|
||||
}
|
||||
|
||||
layerDragStart(element) {
|
||||
layerList.children[layerList.childElementCount - 2].setAttribute("draggable", "true");
|
||||
layerDragSource = this;
|
||||
element.dataTransfer.effectAllowed = 'move';
|
||||
element.dataTransfer.setData('text/html', this.id);
|
||||
@ -151,7 +150,6 @@ class Layer {
|
||||
|
||||
layerDragEnd(element) {
|
||||
this.classList.remove('layerdragover');
|
||||
layerList.children[layerList.childElementCount - 2].setAttribute("draggable", "false");
|
||||
}
|
||||
|
||||
// Resizes canvas
|
||||
@ -452,7 +450,7 @@ function renameLayer(event) {
|
||||
function moveLayers(toDropLayer, staticLayer, saveHistory = true) {
|
||||
let toDrop = getLayerByID(toDropLayer);
|
||||
let static = getLayerByID(staticLayer);
|
||||
let layerCopy = layers;
|
||||
let layerCopy = layers.slice();
|
||||
|
||||
let beforeToDrop = toDrop.menuEntry.nextElementSibling;
|
||||
let nMoved = 0;
|
||||
@ -547,6 +545,7 @@ function getLayerByID(id) {
|
||||
}
|
||||
|
||||
function addLayer(id, saveHistory = true) {
|
||||
// layers.length - 3
|
||||
let index = layers.length - 3;
|
||||
// Creating a new canvas
|
||||
let newCanvas = document.createElement("canvas");
|
||||
@ -583,4 +582,6 @@ function addLayer(id, saveHistory = true) {
|
||||
if (saveHistory) {
|
||||
new HistoryStateAddLayer(newLayer, index);
|
||||
}
|
||||
|
||||
return newLayer;
|
||||
}
|
@ -1,13 +1,19 @@
|
||||
document.getElementById('open-image-browse-holder').addEventListener('change', function () {
|
||||
let fileName = document.getElementById("open-image-browse-holder").value;
|
||||
let extension = fileName.substring(fileName.lastIndexOf('.')+1, fileName.length) || fileName;
|
||||
|
||||
if (this.files && this.files[0]) {
|
||||
if (extension == 'png' || extension == 'gif' || extension == 'lpe') {
|
||||
if (extension == 'lpe') {
|
||||
let file = this.files[0];
|
||||
let reader = new FileReader();
|
||||
|
||||
//make sure file is allowed filetype
|
||||
var fileContentType = this.files[0].type;
|
||||
console.log("File: " + fileContentType);
|
||||
reader.readAsText(file, "UTF-8");
|
||||
reader.onload = function (e) {
|
||||
let dictionary = JSON.parse(e.target.result);
|
||||
|
||||
if (fileContentType == 'image/png' || fileContentType == 'image/gif' || fileContentType == '.lpe') {
|
||||
if (fileContentType == '.lpe') {
|
||||
console.log("OK");
|
||||
newPixel(dictionary['canvasWidth'], dictionary['canvasHeight'], [], dictionary);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//load file
|
||||
@ -15,43 +21,12 @@ document.getElementById('open-image-browse-holder').addEventListener('change', f
|
||||
fileReader.onload = function(e) {
|
||||
var img = new Image();
|
||||
img.onload = function() {
|
||||
|
||||
//create a new pixel with the images dimentions
|
||||
newPixel(this.width, this.height, []);
|
||||
|
||||
//draw the image onto the canvas
|
||||
currentLayer.context.drawImage(img, 0, 0);
|
||||
|
||||
var colorPalette = {};
|
||||
var imagePixelData = currentLayer.context.getImageData(0,0,this.width, this.height).data;
|
||||
|
||||
var imagePixelDataLength = imagePixelData.length;
|
||||
|
||||
console.log(imagePixelData);
|
||||
for (var i = 0; i < imagePixelDataLength; i += 4) {
|
||||
var color = imagePixelData[i]+','+imagePixelData[i + 1]+','+imagePixelData[i + 2];
|
||||
if (!colorPalette[color]) {
|
||||
colorPalette[color] = {r:imagePixelData[i],g:imagePixelData[i + 1],b:imagePixelData[i + 2]};
|
||||
|
||||
//don't allow more than 256 colors to be added
|
||||
if (Object.keys(colorPalette).length >= settings.maxColorsOnImportedImage) {
|
||||
alert('The image loaded seems to have more than '+settings.maxColorsOnImportedImage+' colors.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create array out of colors object
|
||||
var colorPaletteArray = [];
|
||||
for (var color in colorPalette) {
|
||||
if( colorPalette.hasOwnProperty(color) ) {
|
||||
colorPaletteArray.push('#'+rgbToHex(colorPalette[color]));
|
||||
}
|
||||
}
|
||||
console.log('COLOR PALETTE ARRAY', colorPaletteArray);
|
||||
|
||||
//create palette form colors array
|
||||
createColorPalette(colorPaletteArray, false);
|
||||
createPaletteFromLayers();
|
||||
|
||||
//track google event
|
||||
ga('send', 'event', 'Pixel Editor Load', colorPalette.length, this.width+'/'+this.height); /*global ga*/
|
||||
@ -64,4 +39,4 @@ document.getElementById('open-image-browse-holder').addEventListener('change', f
|
||||
}
|
||||
else alert('Only .lpe project files, PNG and GIF files are allowed at this time.');
|
||||
}
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
let firstPixel = true;
|
||||
|
||||
function newPixel (width, height, palette) {
|
||||
function newPixel (width, height, palette, fileContent = null) {
|
||||
currentPalette = [];
|
||||
if (firstPixel) {
|
||||
layerList = document.getElementById("layers-menu");
|
||||
@ -74,7 +74,7 @@ function newPixel (width, height, palette) {
|
||||
|
||||
//add colors from selected palette
|
||||
var selectedPalette = getText('palette-button');
|
||||
if (selectedPalette != 'Choose a palette...') {
|
||||
if (selectedPalette != 'Choose a palette...' && fileContent == null) {
|
||||
|
||||
//if this palette isnt the one specified in the url, then reset the url
|
||||
if (!palettes[selectedPalette].specified)
|
||||
@ -82,26 +82,22 @@ function newPixel (width, height, palette) {
|
||||
|
||||
//fill the palette with specified palette
|
||||
createColorPalette(palettes[selectedPalette].colors,true);
|
||||
fillCheckerboard();
|
||||
}
|
||||
else {
|
||||
//this wasn't a specified palette, so reset the url
|
||||
history.pushState(null, null, '/pixel-editor/app');
|
||||
else if (fileContent == null) {
|
||||
//this wasn't a specified palette, so reset the url
|
||||
history.pushState(null, null, '/pixel-editor/app');
|
||||
|
||||
//generate default colors
|
||||
var fg = hslToRgb(Math.floor(Math.random()*255), 230,70);
|
||||
var bg = hslToRgb(Math.floor(Math.random()*255), 230,170);
|
||||
//generate default colors
|
||||
var fg = hslToRgb(Math.floor(Math.random()*255), 230,70);
|
||||
var bg = hslToRgb(Math.floor(Math.random()*255), 230,170);
|
||||
|
||||
//convert colors to hex
|
||||
var defaultForegroundColor = rgbToHex(fg.r,fg.g,fg.b);
|
||||
var defaultBackgroundColor = rgbToHex(bg.r,bg.g,bg.b);
|
||||
//convert colors to hex
|
||||
var defaultForegroundColor = rgbToHex(fg.r,fg.g,fg.b);
|
||||
var defaultBackgroundColor = rgbToHex(bg.r,bg.g,bg.b);
|
||||
|
||||
//add colors to paletee
|
||||
addColor(defaultForegroundColor).classList.add('selected');
|
||||
addColor(defaultBackgroundColor);
|
||||
|
||||
//fill background of canvas with bg color
|
||||
fillCheckerboard();
|
||||
//add colors to palette
|
||||
addColor(defaultForegroundColor).classList.add('selected');
|
||||
addColor(defaultBackgroundColor);
|
||||
|
||||
//set current drawing color as foreground color
|
||||
currentLayer.context.fillStyle = '#'+defaultForegroundColor;
|
||||
@ -109,6 +105,9 @@ function newPixel (width, height, palette) {
|
||||
selectedPalette = 'none';
|
||||
}
|
||||
|
||||
//fill background of canvas with bg color
|
||||
fillCheckerboard();
|
||||
|
||||
//reset undo and redo states
|
||||
undoStates = [];
|
||||
redoStates = [];
|
||||
@ -120,4 +119,43 @@ function newPixel (width, height, palette) {
|
||||
documentCreated = true;
|
||||
|
||||
firstPixel = false;
|
||||
|
||||
if (fileContent != null) {
|
||||
console.log(fileContent);
|
||||
for (let i=0; i<fileContent['nLayers']; i++) {
|
||||
let layerData = fileContent['layer' + i];
|
||||
let layerImage = fileContent['layer' + i + 'ImageData'];
|
||||
|
||||
if (layerData != null) {
|
||||
// Setting id
|
||||
let createdLayer = addLayer(layerData.id, false);
|
||||
// Setting name
|
||||
createdLayer.menuEntry.getElementsByTagName("p")[0].innerHTML = layerData.name;
|
||||
|
||||
// Adding the image (I can do that because they're sorted by increasing z-index)
|
||||
let img = new Image();
|
||||
img.onload = function() {
|
||||
createdLayer.context.drawImage(img, 0, 0);
|
||||
createdLayer.updateLayerPreview();
|
||||
|
||||
if (i == (fileContent['nLayers'] - 1)) {
|
||||
createPaletteFromLayers();
|
||||
}
|
||||
};
|
||||
|
||||
img.src = layerImage;
|
||||
|
||||
// Setting visibility and lock options
|
||||
if (!layerData.isVisible) {
|
||||
createdLayer.hide();
|
||||
}
|
||||
if (layerData.isLocked) {
|
||||
createdLayer.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deleting the default layer
|
||||
deleteLayer(false);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user