fixed merge

This commit is contained in:
Sam Keddy 2020-04-15 00:10:21 +00:00
commit f3ce09ac5a
45 changed files with 5409 additions and 4199 deletions

34
.eslintrc.json Normal file
View File

@ -0,0 +1,34 @@
{
"env": {
"browser": false,
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}

130
build.js
View File

@ -1,93 +1,59 @@
var fs = require('fs-extra');
var hbs = require('handlebars');
var glob = require("glob");
var sass = require("sass");
var path = require("path");
var gulp = require('gulp');
var include = require('gulp-include');
const fs = require('fs');
const path = require('path');
const gulp = require('gulp');
const include = require('gulp-include');
const hb = require('gulp-hb');
const sass = require('gulp-sass');
const rename = require('gulp-rename');
const BUILDDIR = './build';
const hb_svg = require('handlebars-helper-svg');
const BUILDDIR = process.argv[2] || './build/';
const SLUG = 'pixel-editor';
console.log('Building Pixel Editor');
hbs.registerHelper('svg', require('handlebars-helper-svg'));
require('hbs-register-helpers')(hbs,'./_ext/modules/hbs/helpers/**/*.js');
require('hbs-register-partials')(hbs,'./_ext/modules/hbs/_*.hbs');
//empty the build folder, or create it
fs.emptyDirSync(BUILDDIR);
function copy_images(){
gulp.src('./images/')
.pipe(gulp.dest(path.join(BUILDDIR, SLUG)));
}
function render_js(){
gulp.src('./js/*.js')
.pipe(include({includePaths: [
'_ext/scripts',
'js',
'!js/_*.js',
]}))
.on('error', console.log)
.pipe(gulp.dest(path.join(BUILDDIR, SLUG)));
}
//copy images
fs.copySync('./images','./build/'+SLUG);
function render_css(){
gulp.src('css/*.scss')
.pipe(sass({includePaths: ['css', '_ext/sass', '_ext/modules/css']}))
.pipe(gulp.dest(path.join(BUILDDIR, SLUG)));
}
//render js
gulp.src('./js/*.js')
.pipe(include({includePaths: [
'_ext/scripts',
'js',
'!js/_*.js',
]}))
.on('error', console.log)
.pipe(gulp.dest('build/'+SLUG));
function compile_page(){
gulp.src(path.join('./views/', SLUG + '.hbs'))
.pipe(hb({encoding: 'utf8'})
.partials('./_ext/modules/_*.hbs')
.helpers({ svg: hb_svg })
.helpers('./_ext/modules/hbs/helpers/**/*.js')
.data({
projectSlug: SLUG,
title: 'Lospec Pixel Editor',
layout: false,
}))
.pipe(rename('index.htm'))
.pipe(gulp.dest(BUILDDIR));
}
//render css
var sassFiles = glob.sync('css/*.scss');
sassFiles.forEach((s) => {
var f = sass.renderSync({file: s, outFile: 'test.css', includePaths: ['css', '_ext/sass', '_ext/modules/css']});
console.log('compiling:',path.basename(f.stats.entry))
fs.writeFileSync('build/'+SLUG+'/'+path.basename(f.stats.entry,'scss')+'css', f.css);
});
//compile page
var pageTemplate = hbs.compile(fs.readFileSync('./views/'+SLUG+'.hbs',{encoding: 'utf8'}));
var page = pageTemplate({
projectSlug: SLUG,
title: 'Lospec Pixel Editor',
layout: false,
});
//save output
fs.writeFileSync('./build/index.htm',page);
//server
const express = require('express');
const app = express();
//ROUTE - index.htm
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname+'/build/index.htm'), {}, function (err) {
if (err) console.log('error sending file',err);
else {
setTimeout(()=>{
console.log('closing server')
server.close();
process.exit();
},1000*10);
}
});
});
//ROUTE - other files
app.use(express.static(path.join(__dirname, 'build')));
//start server
var server = app.listen(3000, () => {
console.log('\nTemp server started at http://localhost:3000!');
//console.log('press ctrl+c to stop ');
var opn = require('opn');
// opens the url in the default browser
opn('http://localhost:3000');
});
// empty the build folder, or create it
fs.rmdirSync(BUILDDIR, { recursive: true });
fs.mkdirSync(BUILDDIR);
gulp.parallel(copy_images, render_js, render_css, compile_page)();

34
js/.eslintrc.json Normal file
View File

@ -0,0 +1,34 @@
{
"env": {
"browser": true,
"es6": true
},
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"indent": [
"error",
4,
{
"SwitchCase": 1
}
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}

View File

@ -2,48 +2,48 @@
//input hex color string
//returns list item element
function addColor (newColor) {
//add # at beginning if not present
if (newColor.charAt(0) != '#')
newColor = '#' + newColor;
//create list item
var listItem = document.createElement("li");
//create button
var button = document.createElement("button");
button.classList.add("color-button");
button.style.backgroundColor = newColor;
button.addEventListener("mouseup", clickedColor);
listItem.appendChild(button);
/*
//create input to hold color value
var colorValue = document.createElement("input");
colorValue.classList.add("color-value");
listItem.appendChild(colorValue);
*/
//insert new listItem element at the end of the colors menu (right before add button)
colorsMenu.insertBefore(listItem, colorsMenu.children[colorsMenu.children.length-1]);
//add jscolor functionality
initColor(button);
//add edit button
var editButtonTemplate = document.getElementsByClassName('color-edit-button')[0];
newEditButton = editButtonTemplate.cloneNode(true);
listItem.appendChild(newEditButton);
//when you click the edit button
on('click', newEditButton, function (event, button) {
//hide edit button
button.parentElement.lastChild.classList.add('hidden');
//show jscolor picker
button.parentElement.firstChild.jscolor.show();
});
return listItem;
}
//add # at beginning if not present
if (newColor.charAt(0) != '#')
newColor = '#' + newColor;
//create list item
var listItem = document.createElement('li');
//create button
var button = document.createElement('button');
button.classList.add('color-button');
button.style.backgroundColor = newColor;
button.addEventListener('mouseup', clickedColor);
listItem.appendChild(button);
/*
//create input to hold color value
var colorValue = document.createElement("input");
colorValue.classList.add("color-value");
listItem.appendChild(colorValue);
*/
//insert new listItem element at the end of the colors menu (right before add button)
colorsMenu.insertBefore(listItem, colorsMenu.children[colorsMenu.children.length-1]);
//add jscolor functionality
initColor(button);
//add edit button
var editButtonTemplate = document.getElementsByClassName('color-edit-button')[0];
newEditButton = editButtonTemplate.cloneNode(true);
listItem.appendChild(newEditButton);
//when you click the edit button
on('click', newEditButton, function (event, button) {
//hide edit button
button.parentElement.lastChild.classList.add('hidden');
//show jscolor picker
button.parentElement.firstChild.jscolor.show();
});
return listItem;
}

View File

@ -1,59 +1,59 @@
//add color button
on('click', 'add-color-button', function(){
if (!documentCreated) return;
if (!documentCreated) return;
var colorCheckingStyle = `
var colorCheckingStyle = `
color: white;
background: #3c4cc2;
`;
var colorIsUnique = true
do {
//console.log('%cchecking for unique colors', colorCheckingStyle)
//generate random color
var hue = Math.floor(Math.random()*255);
var sat = 130+Math.floor(Math.random()*100);
var lit = 70+Math.floor(Math.random()*100);
var newColorRgb = hslToRgb(hue,sat,lit)
var newColor = rgbToHex(newColorRgb.r,newColorRgb.g,newColorRgb.b)
var newColorHex = newColor;
//check if color has been used before
colors = document.getElementsByClassName('color-button');
colorCheckingLoop: for (var i = 0; i < colors.length; i++) {
//console.log('%c'+newColorHex +' '+ colors[i].jscolor.toString(), colorCheckingStyle)
//if generated color matches this color
if (newColorHex == colors[i].jscolor.toString()) {
//console.log('%ccolor already exists', colorCheckingStyle)
//start loop again
colorIsUnique = false;
//exit
break colorCheckingLoop;
}
var colorIsUnique = true;
do {
//console.log('%cchecking for unique colors', colorCheckingStyle)
//generate random color
var hue = Math.floor(Math.random()*255);
var sat = 130+Math.floor(Math.random()*100);
var lit = 70+Math.floor(Math.random()*100);
var newColorRgb = hslToRgb(hue,sat,lit);
var newColor = rgbToHex(newColorRgb.r,newColorRgb.g,newColorRgb.b);
var newColorHex = newColor;
//check if color has been used before
colors = document.getElementsByClassName('color-button');
colorCheckingLoop: for (var i = 0; i < colors.length; i++) {
//console.log('%c'+newColorHex +' '+ colors[i].jscolor.toString(), colorCheckingStyle)
//if generated color matches this color
if (newColorHex == colors[i].jscolor.toString()) {
//console.log('%ccolor already exists', colorCheckingStyle)
//start loop again
colorIsUnique = false;
//exit
break colorCheckingLoop;
}
}
}
}
while (colorIsUnique == false);
//remove current color selection
document.querySelector("#colors-menu li.selected").classList.remove("selected");
//add new color and make it selected
var addedColor = addColor(newColor);
addedColor.classList.add('selected');
context.fillStyle = '#' + newColor;
//add history state
//saveHistoryState({type: 'addcolor', colorValue: addedColor.firstElementChild.jscolor.toString()});
new HistoryStateAddColor(addedColor.firstElementChild.jscolor.toString());
//show color picker
addedColor.firstElementChild.jscolor.show();
console.log("showing picker");
//hide edit button
addedColor.lastChild.classList.add('hidden');
}, false);
while (colorIsUnique == false);
//remove current color selection
document.querySelector('#colors-menu li.selected').classList.remove('selected');
//add new color and make it selected
var addedColor = addColor(newColor);
addedColor.classList.add('selected');
context.fillStyle = '#' + newColor;
//add history state
//saveHistoryState({type: 'addcolor', colorValue: addedColor.firstElementChild.jscolor.toString()});
new HistoryStateAddColor(addedColor.firstElementChild.jscolor.toString());
//show color picker
addedColor.firstElementChild.jscolor.show();
console.log('showing picker');
//hide edit button
addedColor.lastChild.classList.add('hidden');
}, false);

View File

@ -1,26 +0,0 @@
function changeTool (newToolName) {
console.log('changing tool to',newToolName)
var selectedTool = tool[newToolName];
// Ending any selection in progress
if (currentTool.name.includes("select") && !selectedTool.name.includes("select") && !selectionCanceled) {
endSelection();
}
//set tool and temp tje tje tpp;
currentTool = selectedTool;
currentToolTemp = selectedTool;
var tools = document.getElementById("tools-menu").children;
for (var i = 0; i < tools.length; i++) {
tools[i].classList.remove("selected");
}
//give the button of the selected tool the .selected class
document.getElementById(selectedTool.name+"-button").parentNode.classList.add("selected");
//change cursor
currentTool.updateCursor();
}

View File

@ -1,4 +1,3 @@
function changeZoom (layer, direction, cursorLocation) {
var oldWidth = canvasSize[0] * zoom;
var oldHeight = canvasSize[1] * zoom;
@ -29,4 +28,4 @@ function changeZoom (layer, direction, cursorLocation) {
// adjust brush size
currentTool.updateCursor();
}
}

View File

@ -1,20 +1,19 @@
/////=include libraries/bowser.js
function closeCompatibilityWarning () {
document.getElementById('compatibility-warning').style.visibility = 'hidden';
document.getElementById('compatibility-warning').style.visibility = 'hidden';
}
console.log('checking compatibility')
console.log('checking compatibility');
//check browser/version
if ( (bowser.msie && bowser.version < 11) ||
(bowser.firefox && bowser.version < 28) ||
(bowser.chrome && bowser.version < 29) ||
(bowser.msedge && bowser.version < 12) ||
(bowser.safari && bowser.version < 9) ||
(bowser.opera && bowser.version < 17) )
//show warning
document.getElementById('compatibility-warning').style.visibility = 'visible';
if ((bowser.msie && bowser.version < 11) ||
(bowser.firefox && bowser.version < 28) ||
(bowser.chrome && bowser.version < 29) ||
(bowser.msedge && bowser.version < 12) ||
(bowser.safari && bowser.version < 9) ||
(bowser.opera && bowser.version < 17) )
//show warning
document.getElementById('compatibility-warning').style.visibility = 'visible';
else alert(bowser.name+' '+bowser.version+' is fine!')
else alert(bowser.name+' '+bowser.version+' is fine!');

View File

@ -1,59 +1,59 @@
// This script contains all the functions used to manage the checkboard
// Setting current colour (each square has a different colour
var currentColor = firstCheckerBoardColor;
// Saving number of squares filled until now
var nSquaresFilled = 0;
function fillCheckerboard() {
// Getting checkerboard context
var context = checkerBoard.context;
// Cycling through the canvas (using it as a matrix)
for (var i=0; i<canvasSize[0] / checkerBoardSquareSize; i++) {
nSquaresFilled = 0;
for (var j=0; j<canvasSize[1] / checkerBoardSquareSize; j++) {
var rectX;
var rectY;
// Managing the not perfect squares (the ones at the sides if the canvas' sizes are not powers of checkerBoardSquareSize
if (i * checkerBoardSquareSize < canvasSize[0]) {
rectX = i * checkerBoardSquareSize;
}
else {
rectX = canvasSize[0];
}
if (j * checkerBoardSquareSize < canvasSize[1]) {
rectY = j * checkerBoardSquareSize;
}
else {
rectY = canvasSize[1];
}
// Selecting the colour
context.fillStyle = currentColor;
context.fillRect(rectX, rectY, checkerBoardSquareSize, checkerBoardSquareSize);
// Changing colour
changeCheckerboardColor();
nSquaresFilled++;
}
// If the number of filled squares was even, I change colour for the next column
if ((nSquaresFilled % 2) == 0) {
changeCheckerboardColor();
}
}
}
// Simply switches the checkerboard colour
function changeCheckerboardColor(isVertical) {
if (currentColor == firstCheckerBoardColor) {
currentColor = secondCheckerBoardColor;
} else if (currentColor == secondCheckerBoardColor) {
currentColor = firstCheckerBoardColor;
}
}
// This script contains all the functions used to manage the checkboard
// Setting current colour (each square has a different colour
var currentColor = firstCheckerBoardColor;
// Saving number of squares filled until now
var nSquaresFilled = 0;
function fillCheckerboard() {
// Getting checkerboard context
var context = checkerBoard.context;
// Cycling through the canvas (using it as a matrix)
for (var i=0; i<canvasSize[0] / checkerBoardSquareSize; i++) {
nSquaresFilled = 0;
for (var j=0; j<canvasSize[1] / checkerBoardSquareSize; j++) {
var rectX;
var rectY;
// Managing the not perfect squares (the ones at the sides if the canvas' sizes are not powers of checkerBoardSquareSize
if (i * checkerBoardSquareSize < canvasSize[0]) {
rectX = i * checkerBoardSquareSize;
}
else {
rectX = canvasSize[0];
}
if (j * checkerBoardSquareSize < canvasSize[1]) {
rectY = j * checkerBoardSquareSize;
}
else {
rectY = canvasSize[1];
}
// Selecting the colour
context.fillStyle = currentColor;
context.fillRect(rectX, rectY, checkerBoardSquareSize, checkerBoardSquareSize);
// Changing colour
changeCheckerboardColor();
nSquaresFilled++;
}
// If the number of filled squares was even, I change colour for the next column
if ((nSquaresFilled % 2) == 0) {
changeCheckerboardColor();
}
}
}
// Simply switches the checkerboard colour
function changeCheckerboardColor(isVertical) {
if (currentColor == firstCheckerBoardColor) {
currentColor = secondCheckerBoardColor;
} else if (currentColor == secondCheckerBoardColor) {
currentColor = firstCheckerBoardColor;
}
}

View File

@ -3,28 +3,25 @@ function clickedColor (e){
//left clicked color
if (e.which == 1) {
//remove current color selection
var selectedColor = document.querySelector("#colors-menu li.selected")
if (selectedColor) selectedColor.classList.remove("selected");
// remove current color selection
var selectedColor = document.querySelector('#colors-menu li.selected');
if (selectedColor) selectedColor.classList.remove('selected');
//set current color
currentLayer.context.fillStyle = this.style.backgroundColor;
currentGlobalColor = this.style.backgroundColor;
//make color selected
e.target.parentElement.classList.add('selected');
//right clicked color
} else if (e.which == 3) {
console.log('right clicked color button')
//hide edit color button (to prevent it from showing)
e.target.parentElement.lastChild.classList.add('hidden');
//show color picker
e.target.jscolor.show();
//set current color
currentLayer.context.fillStyle = this.style.backgroundColor;
currentGlobalColor = this.style.backgroundColor;
//make color selected
e.target.parentElement.classList.add('selected');
} else if (e.which == 3) { //right clicked color
console.log('right clicked color button');
//hide edit color button (to prevent it from showing)
e.target.parentElement.lastChild.classList.add('hidden');
//show color picker
e.target.jscolor.show();
}
}

View File

@ -3,92 +3,92 @@
document.getElementById('jscolor-hex-input').addEventListener('change', colorChanged, false);
on('input', 'jscolor-hex-input', function (e) {
//get hex value
var newColorHex = e.target.value.toLowerCase();
//if the color is not (yet) a valid hex color, exit this function and do nothing
if (/^[0-9a-f]{6}$/i.test(newColorHex) == false)
return;
//get currently editing color
var currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0];
//update the actual color picker to the inputted color
currentlyEditedColor.firstChild.jscolor.fromString(newColorHex);
colorChanged(e);
})
//get hex value
var newColorHex = e.target.value.toLowerCase();
//if the color is not (yet) a valid hex color, exit this function and do nothing
if (/^[0-9a-f]{6}$/i.test(newColorHex) == false)
return;
//get currently editing color
var currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0];
//update the actual color picker to the inputted color
currentlyEditedColor.firstChild.jscolor.fromString(newColorHex);
colorChanged(e);
});
//changes all of one color to another after being changed from color picker
function colorChanged(e) {
console.log('colorChanged()');
//get colors
var newColor = hexToRgb(e.target.value);
var oldColor = e.target.oldColor;
//save undo state
//saveHistoryState({type: 'colorchange', newColor: e.target.value, oldColor: rgbToHex(oldColor), canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])});
new HistoryStateEditColor(e.target.value.toLowerCase(), rgbToHex(oldColor));
//get the currently selected color
var currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0];
var duplicateColorWarning = document.getElementById("duplicate-color-warning");
console.log('colorChanged()');
//get colors
var newColor = hexToRgb(e.target.value);
var oldColor = e.target.oldColor;
//check if selected color already matches another color
colors = document.getElementsByClassName('color-button');
var colorCheckingStyle = "background: #bc60c4; color: white"
var newColorHex = e.target.value.toLowerCase();
//if the color is not a valid hex color, exit this function and do nothing
if (/^[0-9a-f]{6}$/i.test(newColorHex) == false)
return;
//loop through all colors in palette
for (var i = 0; i < colors.length; i++) {
//if generated color matches this color
if (newColorHex == colors[i].jscolor.toString()) {
//console.log('%ccolor already exists'+(colors[i].parentElement.classList.contains('jscolor-active')?' (but is the current color)':''), colorCheckingStyle);
//save undo state
//saveHistoryState({type: 'colorchange', newColor: e.target.value, oldColor: rgbToHex(oldColor), canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])});
new HistoryStateEditColor(e.target.value.toLowerCase(), rgbToHex(oldColor));
//if the color isnt the one that has the picker currently open
if (!colors[i].parentElement.classList.contains('jscolor-active')) {
//console.log('%cColor is duplicate', colorCheckingStyle)
//show the duplicate color warning
duplicateColorWarning.style.visibility = 'visible';
//shake warning icon
duplicateColorWarning.classList.remove('shake');
void duplicateColorWarning.offsetWidth;
duplicateColorWarning.classList.add('shake');
//exit function without updating color
//get the currently selected color
var currentlyEditedColor = document.getElementsByClassName('jscolor-active')[0];
var duplicateColorWarning = document.getElementById('duplicate-color-warning');
//check if selected color already matches another color
colors = document.getElementsByClassName('color-button');
var colorCheckingStyle = 'background: #bc60c4; color: white';
var newColorHex = e.target.value.toLowerCase();
//if the color is not a valid hex color, exit this function and do nothing
if (/^[0-9a-f]{6}$/i.test(newColorHex) == false)
return;
}
}
}
//if the color being edited has a duplicate color warning, remove it
duplicateColorWarning.style.visibility = 'hidden';
currentlyEditedColor.firstChild.jscolor.fromString(newColorHex)
replaceAllOfColor(oldColor, newColor);
//set new old color to changed color
e.target.oldColor = newColor;
//if this is the current color, update the drawing color
if (e.target.colorElement.parentElement.classList.contains('selected')) {
//console.log('this color is the current color');
context.fillStyle = currentColor;
}
/* this is wrong and bad
if (settings.switchToChangedColor) {
}*/
//loop through all colors in palette
for (var i = 0; i < colors.length; i++) {
//if generated color matches this color
if (newColorHex == colors[i].jscolor.toString()) {
// console.log('%ccolor already exists'+(colors[i].parentElement.classList.contains('jscolor-active')?' (but is the current color)':''), colorCheckingStyle);
//if the color isnt the one that has the picker currently open
if (!colors[i].parentElement.classList.contains('jscolor-active')) {
// console.log('%cColor is duplicate', colorCheckingStyle);
//show the duplicate color warning
duplicateColorWarning.style.visibility = 'visible';
//shake warning icon
duplicateColorWarning.classList.remove('shake');
void duplicateColorWarning.offsetWidth;
duplicateColorWarning.classList.add('shake');
//exit function without updating color
return;
}
}
}
//if the color being edited has a duplicate color warning, remove it
duplicateColorWarning.style.visibility = 'hidden';
currentlyEditedColor.firstChild.jscolor.fromString(newColorHex);
replaceAllOfColor(oldColor, newColor);
//set new old color to changed color
e.target.oldColor = newColor;
//if this is the current color, update the drawing color
if (e.target.colorElement.parentElement.classList.contains('selected')) {
// console.log('this color is the current color');
context.fillStyle = currentColor;
}
/* this is wrong and bad
if (settings.switchToChangedColor) {
}*/
}

View File

@ -1,22 +1,21 @@
on('click', 'create-button', function (){
var width = getValue('size-width');
var height = getValue('size-height');
newPixel(width,height,'asdfg');
document.getElementById('new-pixel-warning').style.display = 'block';
//get selected palette name
var selectedPalette = getText('palette-button');
if (selectedPalette == 'Choose a palette...')
selectedPalette = 'none';
//track google event
var width = getValue('size-width');
var height = getValue('size-height');
newPixel(width,height,'asdfg');
document.getElementById('new-pixel-warning').style.display = 'block';
//get selected palette name
var selectedPalette = getText('palette-button');
if (selectedPalette == 'Choose a palette...')
selectedPalette = 'none';
//track google event
ga('send', 'event', 'Pixel Editor New', selectedPalette, width+'/'+height); /*global ga*/
//reset new form
setValue('size-width', 64);
setValue('size-height', 64);
setText('palette-button', 'Choose a palette...');
setText('preset-button', 'Choose a preset...');
});
//reset new form
setValue('size-width', 64);
setValue('size-height', 64);
setText('palette-button', 'Choose a palette...');
setText('preset-button', 'Choose a preset...');
});

View File

@ -1,45 +1,45 @@
function createColorPalette(selectedPalette, fillBackground) {
//remove current palette
colors = document.getElementsByClassName('color-button');
while (colors.length > 0) {
colors[0].parentElement.remove();
}
var lightestColor = '#000000';
var darkestColor = '#ffffff';
for (var i = 0; i < selectedPalette.length; i++) {
var newColor = selectedPalette[i];
var newColorElement = addColor(newColor);
//remove current palette
colors = document.getElementsByClassName('color-button');
while (colors.length > 0) {
colors[0].parentElement.remove();
}
var newColorHex = hexToRgb(newColor);
var lightestColor = '#000000';
var darkestColor = '#ffffff';
var lightestColorHex = hexToRgb(lightestColor);
if (newColorHex.r + newColorHex.g + newColorHex.b > lightestColorHex.r + lightestColorHex.g + lightestColorHex.b)
lightestColor = newColor;
for (var i = 0; i < selectedPalette.length; i++) {
var newColor = selectedPalette[i];
var newColorElement = addColor(newColor);
var darkestColorHex = hexToRgb(darkestColor);
if (newColorHex.r + newColorHex.g + newColorHex.b < darkestColorHex.r + darkestColorHex.g + darkestColorHex.b) {
//remove current color selection
var selectedColor = document.querySelector("#colors-menu li.selected")
if (selectedColor) selectedColor.classList.remove("selected");
//set as current color
newColorElement.classList.add('selected');
darkestColor = newColor;
}
}
//fill bg with lightest color
if (fillBackground) {
currentLayer.context.fillStyle = lightestColor;
currentLayer.context.fillRect(0, 0, canvasSize[0], canvasSize[1]);
}
//set as current color
currentLayer.context.fillStyle = darkestColor;
}
var newColorHex = hexToRgb(newColor);
var lightestColorHex = hexToRgb(lightestColor);
if (newColorHex.r + newColorHex.g + newColorHex.b > lightestColorHex.r + lightestColorHex.g + lightestColorHex.b)
lightestColor = newColor;
var darkestColorHex = hexToRgb(darkestColor);
if (newColorHex.r + newColorHex.g + newColorHex.b < darkestColorHex.r + darkestColorHex.g + darkestColorHex.b) {
//remove current color selection
var selectedColor = document.querySelector('#colors-menu li.selected');
if (selectedColor) selectedColor.classList.remove('selected');
//set as current color
newColorElement.classList.add('selected');
darkestColor = newColor;
}
}
//fill bg with lightest color
if (fillBackground) {
currentLayer.context.fillStyle = lightestColor;
currentLayer.context.fillRect(0, 0, canvasSize[0], canvasSize[1]);
}
//set as current color
currentLayer.context.fillStyle = darkestColor;
}

View File

@ -3,82 +3,82 @@
//called when the delete button is pressed on color picker
//input color button or hex string
function deleteColor (color) {
const logStyle = 'background: #913939; color: white; padding: 5px;';
//console.log('%c'+'deleting color', logStyle);
//if color is a string, then find the corresponding button
if (typeof color === 'string') {
console.log('trying to find ',color)
//get all colors in palette
colors = document.getElementsByClassName('color-button');
//loop through colors
for (var i = 0; i < colors.length; i++) {
console.log(color,'=',colors[i].jscolor.toString())
if (color == colors[i].jscolor.toString()) {
console.log('match')
//set color to the color button
color = colors[i];
console.log('found color', color);
//exit loop
break;
}
}
//if the color wasn't found
if (typeof color === 'string') {
console.log('color not found');
//exit function
return;
}
}
//hide color picker
color.jscolor.hide();
//find lightest color in palette
var colors = document.getElementsByClassName('color-button');
var lightestColor = [0,null];
for (var i = 0; i < colors.length; i++) {
//get colors lightness
var lightness = rgbToHsl(colors[i].jscolor.toRgb()).l;
//console.log('%c'+lightness, logStyle)
//if not the color we're deleting
if (colors[i] != color) {
//if lighter than the current lightest, set as the new lightest
if (lightness > lightestColor[0]) {
lightestColor[0] = lightness;
lightestColor[1] = colors[i];
}
}
}
//console.log('%c'+'replacing with lightest color: '+lightestColor[1].jscolor.toString(), logStyle)
//replace deleted color with lightest color
replaceAllOfColor(color.jscolor.toString(),lightestColor[1].jscolor.toString());
//if the color you are deleting is the currently selected color
if (color.parentElement.classList.contains('selected')) {
//console.log('%c'+'deleted color is currently selected', logStyle);
//set current color TO LIGHTEST COLOR
lightestColor[1].parentElement.classList.add('selected');
currentLayer.context.fillStyle = '#'+lightestColor[1].jscolor.toString();
}
//delete the element
colorsMenu.removeChild(color.parentElement);
const logStyle = 'background: #913939; color: white; padding: 5px;';
}
//console.log('%c'+'deleting color', logStyle);
//if color is a string, then find the corresponding button
if (typeof color === 'string') {
console.log('trying to find ',color);
//get all colors in palette
colors = document.getElementsByClassName('color-button');
//loop through colors
for (var i = 0; i < colors.length; i++) {
console.log(color,'=',colors[i].jscolor.toString());
if (color == colors[i].jscolor.toString()) {
console.log('match');
//set color to the color button
color = colors[i];
console.log('found color', color);
//exit loop
break;
}
}
//if the color wasn't found
if (typeof color === 'string') {
console.log('color not found');
//exit function
return;
}
}
//hide color picker
color.jscolor.hide();
//find lightest color in palette
var colors = document.getElementsByClassName('color-button');
var lightestColor = [0,null];
for (var i = 0; i < colors.length; i++) {
//get colors lightness
var lightness = rgbToHsl(colors[i].jscolor.toRgb()).l;
//console.log('%c'+lightness, logStyle)
//if not the color we're deleting
if (colors[i] != color) {
//if lighter than the current lightest, set as the new lightest
if (lightness > lightestColor[0]) {
lightestColor[0] = lightness;
lightestColor[1] = colors[i];
}
}
}
//console.log('%c'+'replacing with lightest color: '+lightestColor[1].jscolor.toString(), logStyle)
//replace deleted color with lightest color
replaceAllOfColor(color.jscolor.toString(),lightestColor[1].jscolor.toString());
//if the color you are deleting is the currently selected color
if (color.parentElement.classList.contains('selected')) {
//console.log('%c'+'deleted color is currently selected', logStyle);
//set current color TO LIGHTEST COLOR
lightestColor[1].parentElement.classList.add('selected');
currentLayer.context.fillStyle = '#'+lightestColor[1].jscolor.toString();
}
//delete the element
colorsMenu.removeChild(color.parentElement);
}

View File

@ -1,36 +1,36 @@
function showDialogue (dialogueName, trackEvent) {
if (typeof trackEvent === 'undefined') trackEvent = true;
dialogueOpen = true;
popUpContainer.style.display = 'block';
document.getElementById(dialogueName).style.display = 'block';
dialogueOpen = true;
popUpContainer.style.display = 'block';
document.getElementById(dialogueName).style.display = 'block';
//track google event
if (trackEvent)
ga('send', 'event', 'Palette Editor Dialogue', dialogueName); /*global ga*/
}
function closeDialogue () {
popUpContainer.style.display = 'none';
var popups = popUpContainer.children;
for (var i = 0; i < popups.length; i++) {
popups[i].style.display = 'none';
}
dialogueOpen = false;
popUpContainer.style.display = 'none';
var popups = popUpContainer.children;
for (var i = 0; i < popups.length; i++) {
popups[i].style.display = 'none';
}
dialogueOpen = false;
}
popUpContainer.addEventListener("click", function (e) {
if (e.target == popUpContainer)
closeDialogue();
popUpContainer.addEventListener('click', function (e) {
if (e.target == popUpContainer)
closeDialogue();
});
//add click handlers for all cancel buttons
var cancelButtons = popUpContainer.getElementsByClassName('close-button');
for (var i = 0; i < cancelButtons.length; i++) {
cancelButtons[i].addEventListener('click', function () {
closeDialogue();
});
}
cancelButtons[i].addEventListener('click', function () {
closeDialogue();
});
}

View File

@ -52,4 +52,4 @@ function lineOnLayer(x0,y0,x1,y1, brushSize, context) {
if (e2 >-dy) {err -=dy; x0+=sx;}
if (e2 < dx) {err +=dx; y0+=sy;}
}
}
}

View File

@ -1,18 +1,18 @@
var mainMenuItems = document.getElementById("main-menu").children;
var mainMenuItems = document.getElementById('main-menu').children;
//for each button in main menu (starting at 1 to avoid logo)
for (var i = 1; i < mainMenuItems.length; i++) {
//get the button that's in the list item
var menuItem = mainMenuItems[i];
var menuButton = menuItem.children[0];
//get the button that's in the list item
var menuItem = mainMenuItems[i];
var menuButton = menuItem.children[0];
console.log(mainMenuItems)
console.log(mainMenuItems);
//when you click a main menu items button
on('click', menuButton, function (e, button) {
console.log('parent ', button.parentElement)
select(button.parentElement);
console.log('parent ', button.parentElement);
select(button.parentElement);
});
var subMenu = menuItem.children[1];
@ -23,114 +23,114 @@ for (var i = 1; i < mainMenuItems.length; i++) {
//when you click an item within a menu button
for (var j = 0; j < subMenuItems.length; j++) {
var subMenuItem = subMenuItems[j];
var subMenuButton = subMenuItem.children[0];
var subMenuItem = subMenuItems[j];
var subMenuButton = subMenuItem.children[0];
subMenuButton.addEventListener("click", function (e) {
subMenuButton.addEventListener('click', function (e) {
switch(this.textContent) {
switch(this.textContent) {
//File Menu
case 'New':
showDialogue('new-pixel');
break;
case 'Open':
//File Menu
case 'New':
showDialogue('new-pixel');
break;
case 'Open':
//if a document exists
if (documentCreated) {
//check if the user wants to overwrite
if (confirm('Opening a pixel will discard your current one. Are you sure you want to do that?'))
//open file selection dialog
document.getElementById("open-image-browse-holder").click();
}
else
//open file selection dialog
document.getElementById("open-image-browse-holder").click();
//if a document exists
if (documentCreated) {
//check if the user wants to overwrite
if (confirm('Opening a pixel will discard your current one. Are you sure you want to do that?'))
//open file selection dialog
document.getElementById('open-image-browse-holder').click();
}
else
//open file selection dialog
document.getElementById('open-image-browse-holder').click();
break;
break;
case 'Save as...':
if (documentCreated) {
case 'Save as...':
if (documentCreated) {
//create name
var selectedPalette = getText('palette-button');
if (selectedPalette != 'Choose a palette...'){
var paletteAbbreviation = palettes[selectedPalette].abbreviation;
var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.png';
} else {
var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.png';
selectedPalette = 'none';
}
//create name
var selectedPalette = getText('palette-button');
if (selectedPalette != 'Choose a palette...'){
var paletteAbbreviation = palettes[selectedPalette].abbreviation;
var fileName = 'pixel-'+paletteAbbreviation+'-'+canvasSize[0]+'x'+canvasSize[1]+'.png';
} else {
var fileName = 'pixel-'+canvasSize[0]+'x'+canvasSize[1]+'.png';
selectedPalette = 'none';
}
//set download link
var linkHolder = document.getElementById("save-image-link-holder");
linkHolder.href = canvas.toDataURL();
linkHolder.download = fileName;
//set download link
var linkHolder = document.getElementById('save-image-link-holder');
linkHolder.href = canvas.toDataURL();
linkHolder.download = fileName;
linkHolder.click();
linkHolder.click();
//track google event
//track google event
ga('send', 'event', 'Pixel Editor Save', selectedPalette, canvasSize[0]+'/'+canvasSize[1]); /*global ga*/
}
}
break;
break;
case 'Exit':
case 'Exit':
console.log('exit')
//if a document exists, make sure they want to delete it
if (documentCreated) {
console.log('exit');
//if a document exists, make sure they want to delete it
if (documentCreated) {
//ask user if they want to leave
if (confirm('Exiting will discard your current pixel. Are you sure you want to do that?'))
//skip onbeforeunload prompt
window.onbeforeunload = null;
else
e.preventDefault();
}
//ask user if they want to leave
if (confirm('Exiting will discard your current pixel. Are you sure you want to do that?'))
//skip onbeforeunload prompt
window.onbeforeunload = null;
else
e.preventDefault();
}
break;
//Edit Menu
case 'Undo':
undo();
break;
case 'Redo':
redo();
break;
break;
//Edit Menu
case 'Undo':
undo();
break;
case 'Redo':
redo();
break;
//Palette Menu
case 'Add color':
addColor('#eeeeee');
break;
//Help Menu
case 'Settings':
//Palette Menu
case 'Add color':
addColor('#eeeeee');
break;
//Help Menu
case 'Settings':
//fill form with current settings values
setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates);
//fill form with current settings values
setValue('setting-numberOfHistoryStates', settings.numberOfHistoryStates);
showDialogue('settings');
break;
//Help Menu
case 'Help':
showDialogue('help');
break;
case 'About':
showDialogue('about');
break;
case 'Changelog':
showDialogue('changelog');
break;
}
showDialogue('settings');
break;
//Help Menu
case 'Help':
showDialogue('help');
break;
case 'About':
showDialogue('about');
break;
case 'Changelog':
showDialogue('changelog');
break;
}
closeMenu();
});
}
closeMenu();
});
}
}
function closeMenu () {
//remove .selected class from all menu buttons
for (var i = 0; i < mainMenuItems.length; i++) {
deselect(mainMenuItems[i]);
}
}
//remove .selected class from all menu buttons
for (var i = 0; i < mainMenuItems.length; i++) {
deselect(mainMenuItems[i]);
}
}

View File

@ -1,110 +1,110 @@
function fill(cursorLocation) {
//changes a pixels color
function colorPixel(tempImage, pixelPos, fillColor) {
//console.log('colorPixel:',pixelPos);
tempImage.data[pixelPos] = fillColor.r;
tempImage.data[pixelPos + 1] = fillColor.g;
tempImage.data[pixelPos + 2] = fillColor.b;
tempImage.data[pixelPos + 3] = 255;
/*
tempImage.data[pixelPos] = fillColor.r;
tempImage.data[pixelPos + 1] = fillColor.g;
tempImage.data[pixelPos + 2] = fillColor.b;
*/
}
//change x y to color value passed from the function and use that as the original color
function matchStartColor(tempImage, pixelPos, color) {
//console.log('matchPixel:',x,y)
var r = tempImage.data[pixelPos];
var g = tempImage.data[pixelPos + 1];
var b = tempImage.data[pixelPos + 2];
//console.log(r == color[0] && g == color[1] && b == color[2]);
return (r == color[0] && g == color[1] && b == color[2]);
}
//save history state
new HistoryStateEditCanvas();
//saveHistoryState({type: 'canvas', canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])});
//console.log('filling at '+ Math.floor(cursorLocation[0]/zoom) + ','+ Math.floor(cursorLocation[1]/zoom));
//temporary image holds the data while we change it
var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
//changes a pixels color
function colorPixel(tempImage, pixelPos, fillColor) {
//console.log('colorPixel:',pixelPos);
tempImage.data[pixelPos] = fillColor.r;
tempImage.data[pixelPos + 1] = fillColor.g;
tempImage.data[pixelPos + 2] = fillColor.b;
tempImage.data[pixelPos + 3] = 255;
/*
tempImage.data[pixelPos] = fillColor.r;
tempImage.data[pixelPos + 1] = fillColor.g;
tempImage.data[pixelPos + 2] = fillColor.b;
*/
}
//this is an array that holds all of the pixels at the top of the cluster
var topmostPixelsArray = [[Math.floor(cursorLocation[0]/zoom), Math.floor(cursorLocation[1]/zoom)]];
//console.log('topmostPixelsArray:',topmostPixelsArray)
//change x y to color value passed from the function and use that as the original color
function matchStartColor(tempImage, pixelPos, color) {
//console.log('matchPixel:',x,y)
//the offset of the pixel in the temp image data to start with
var startingPosition = (topmostPixelsArray[0][1] * canvasSize[0] + topmostPixelsArray[0][0]) * 4;
var r = tempImage.data[pixelPos];
var g = tempImage.data[pixelPos + 1];
var b = tempImage.data[pixelPos + 2];
//console.log(r == color[0] && g == color[1] && b == color[2]);
return (r == color[0] && g == color[1] && b == color[2]);
}
//the color of the cluster that is being filled
var clusterColor = [tempImage.data[startingPosition],tempImage.data[startingPosition+1],tempImage.data[startingPosition+2]];
//save history state
new HistoryStateEditCanvas();
//saveHistoryState({type: 'canvas', canvas: context.getImageData(0, 0, canvasSize[0], canvasSize[1])});
//console.log('filling at '+ Math.floor(cursorLocation[0]/zoom) + ','+ Math.floor(cursorLocation[1]/zoom));
//the new color to fill with
var fillColor = hexToRgb(currentLayer.context.fillStyle);
//temporary image holds the data while we change it
var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
//if you try to fill with the same color that's already there, exit the function
if (clusterColor[0] == fillColor.r &&
clusterColor[1] == fillColor.g &&
clusterColor[2] == fillColor.b )
return;
//this is an array that holds all of the pixels at the top of the cluster
var topmostPixelsArray = [[Math.floor(cursorLocation[0]/zoom), Math.floor(cursorLocation[1]/zoom)]];
//console.log('topmostPixelsArray:',topmostPixelsArray)
//loop until there are no more values left in this array
while (topmostPixelsArray.length) {
var reachLeft, reachRight;
//the offset of the pixel in the temp image data to start with
var startingPosition = (topmostPixelsArray[0][1] * canvasSize[0] + topmostPixelsArray[0][0]) * 4;
//move the most recent pixel from the array and set it as our current working pixels
var currentPixel = topmostPixelsArray.pop();
//the color of the cluster that is being filled
var clusterColor = [tempImage.data[startingPosition],tempImage.data[startingPosition+1],tempImage.data[startingPosition+2]];
//set the values of this pixel to x/y variables just for readability
var x = currentPixel[0];
var y = currentPixel[1];
//the new color to fill with
var fillColor = hexToRgb(currentLayer.context.fillStyle);
//this variable holds the index of where the starting values for the current pixel are in the data array
//we multiply the number of rows down (y) times the width of each row, then add x. at the end we multiply by 4 because
//each pixel has 4 values, rgba
var pixelPos = (y * canvasSize[0] + x) * 4;
//if you try to fill with the same color that's already there, exit the function
if (clusterColor[0] == fillColor.r &&
clusterColor[1] == fillColor.g &&
clusterColor[2] == fillColor.b )
return;
//move up in the image until you reach the top or the pixel you hit was not the right color
while (y-- >= 0 && matchStartColor(tempImage, pixelPos, clusterColor)) {
pixelPos -= canvasSize[0] * 4;
}
pixelPos += canvasSize[0] * 4;
++y;
reachLeft = false;
reachRight = false;
while (y++ < canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) {
colorPixel(tempImage, pixelPos, fillColor);
if (x > 0) {
if (matchStartColor(tempImage, pixelPos - 4, clusterColor)) {
if (!reachLeft) {
topmostPixelsArray.push([x - 1, y]);
reachLeft = true;
}
}
else if (reachLeft) {
reachLeft = false;
}
}
//loop until there are no more values left in this array
while (topmostPixelsArray.length) {
var reachLeft, reachRight;
if (x < canvasSize[0] - 1) {
if (matchStartColor(tempImage, pixelPos + 4, clusterColor)) {
if (!reachRight) {
topmostPixelsArray.push([x + 1, y]);
reachRight = true;
}
}
else if (reachRight) {
reachRight = false;
}
}
//move the most recent pixel from the array and set it as our current working pixels
var currentPixel = topmostPixelsArray.pop();
pixelPos += canvasSize[0] * 4;
}
}
//set the values of this pixel to x/y variables just for readability
var x = currentPixel[0];
var y = currentPixel[1];
//this variable holds the index of where the starting values for the current pixel are in the data array
//we multiply the number of rows down (y) times the width of each row, then add x. at the end we multiply by 4 because
//each pixel has 4 values, rgba
var pixelPos = (y * canvasSize[0] + x) * 4;
//move up in the image until you reach the top or the pixel you hit was not the right color
while (y-- >= 0 && matchStartColor(tempImage, pixelPos, clusterColor)) {
pixelPos -= canvasSize[0] * 4;
}
pixelPos += canvasSize[0] * 4;
++y;
reachLeft = false;
reachRight = false;
while (y++ < canvasSize[1] - 1 && matchStartColor(tempImage, pixelPos, clusterColor)) {
colorPixel(tempImage, pixelPos, fillColor);
if (x > 0) {
if (matchStartColor(tempImage, pixelPos - 4, clusterColor)) {
if (!reachLeft) {
topmostPixelsArray.push([x - 1, y]);
reachLeft = true;
}
}
else if (reachLeft) {
reachLeft = false;
}
}
if (x < canvasSize[0] - 1) {
if (matchStartColor(tempImage, pixelPos + 4, clusterColor)) {
if (!reachRight) {
topmostPixelsArray.push([x + 1, y]);
reachRight = true;
}
}
else if (reachRight) {
reachRight = false;
}
}
pixelPos += canvasSize[0] * 4;
}
}
currentLayer.context.putImageData(tempImage, 0, 0);
//console.log('done filling')
}
//console.log('done filling')
}

View File

@ -1,21 +1,21 @@
//get cursor position relative to canvas
function getCursorPosition(e) {
var x;
var y;
var x;
var y;
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
x -= canvas.offsetLeft;
y -= canvas.offsetTop;
x -= canvas.offsetLeft;
y -= canvas.offsetTop;
return [x,y];
return [x,y];
}
// TODO: apply the function below to every getCursorPosition call
@ -24,20 +24,20 @@ function getCursorPosition(e) {
//get cursor position relative to canvas
function getCursorPositionRelative(e, layer) {
var x;
var y;
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
var x;
var y;
x -= layer.canvas.offsetLeft;
y -= layer.canvas.offsetTop;
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
return [x,y];
}
x -= layer.canvas.offsetLeft;
y -= layer.canvas.offsetTop;
return [x,y];
}

View File

@ -5,194 +5,194 @@ const undoLogStyle = 'background: #87ff1c; color: black; padding: 5px;';
//prototype for undoing canvas changes
function HistoryStateEditCanvas () {
this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
this.undo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
this.canvas = currentCanvas;
redoStates.push(this);
}
this.redo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
this.canvas = currentCanvas;
undoStates.push(this);
}
//add self to undo array
saveHistoryState(this);
this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
this.undo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
this.canvas = currentCanvas;
redoStates.push(this);
};
this.redo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
this.canvas = currentCanvas;
undoStates.push(this);
};
//add self to undo array
saveHistoryState(this);
}
//prototype for undoing added colors
function HistoryStateAddColor (colorValue) {
this.colorValue = colorValue;
this.undo = function () {
redoStates.push(this);
deleteColor(this.colorValue);
}
this.redo = function () {
addColor(this.colorValue);
undoStates.push(this);
}
//add self to undo array
saveHistoryState(this);
this.colorValue = colorValue;
this.undo = function () {
redoStates.push(this);
deleteColor(this.colorValue);
};
this.redo = function () {
addColor(this.colorValue);
undoStates.push(this);
};
//add self to undo array
saveHistoryState(this);
}
//prototype for undoing deleted colors
function HistoryStateDeleteColor (colorValue) {
this.colorValue = colorValue;
this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
this.undo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
addColor(this.colorValue);
this.canvas = currentCanvas;
redoStates.push(this);
}
this.redo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
deleteColor(this.colorValue);
this.canvas = currentCanvas;
undoStates.push(this);
}
//add self to undo array
saveHistoryState(this);
this.colorValue = colorValue;
this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
this.undo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
addColor(this.colorValue);
this.canvas = currentCanvas;
redoStates.push(this);
};
this.redo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
deleteColor(this.colorValue);
this.canvas = currentCanvas;
undoStates.push(this);
};
//add self to undo array
saveHistoryState(this);
}
//prototype for undoing colors edits
function HistoryStateEditColor (newColorValue, oldColorValue) {
this.newColorValue = newColorValue;
this.oldColorValue = oldColorValue;
this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
this.undo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
//find new color in palette and change it back to old color
var colors = document.getElementsByClassName('color-button');
for (var i = 0; i < colors.length; i++) {
console.log(newColorValue, '==', colors[i].jscolor.toString())
if (newColorValue == colors[i].jscolor.toString()) {
colors[i].jscolor.fromString(oldColorValue);
break;
}
}
this.canvas = currentCanvas;
redoStates.push(this);
}
this.redo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
//find old color in palette and change it back to new color
var colors = document.getElementsByClassName('color-button');
for (var i = 0; i < colors.length; i++) {
console.log(oldColorValue, '==', colors[i].jscolor.toString())
if (oldColorValue == colors[i].jscolor.toString()) {
colors[i].jscolor.fromString(newColorValue);
break;
}
}
this.canvas = currentCanvas;
undoStates.push(this);
}
//add self to undo array
saveHistoryState(this);
this.newColorValue = newColorValue;
this.oldColorValue = oldColorValue;
this.canvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
this.undo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
//find new color in palette and change it back to old color
var colors = document.getElementsByClassName('color-button');
for (var i = 0; i < colors.length; i++) {
console.log(newColorValue, '==', colors[i].jscolor.toString());
if (newColorValue == colors[i].jscolor.toString()) {
colors[i].jscolor.fromString(oldColorValue);
break;
}
}
this.canvas = currentCanvas;
redoStates.push(this);
};
this.redo = function () {
var currentCanvas = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
currentLayer.context.putImageData(this.canvas, 0, 0);
//find old color in palette and change it back to new color
var colors = document.getElementsByClassName('color-button');
for (var i = 0; i < colors.length; i++) {
console.log(oldColorValue, '==', colors[i].jscolor.toString());
if (oldColorValue == colors[i].jscolor.toString()) {
colors[i].jscolor.fromString(newColorValue);
break;
}
}
this.canvas = currentCanvas;
undoStates.push(this);
};
//add self to undo array
saveHistoryState(this);
}
//rename to add undo state
function saveHistoryState (state) {
console.log('%csaving history state', undoLogStyle)
console.log(state)
console.log('%csaving history state', undoLogStyle);
console.log(state);
//get current canvas data and save to undoStates array
undoStates.push(state);
//limit the number of states to settings.numberOfHistoryStates
if (undoStates.length > settings.numberOfHistoryStates) {
undoStates = undoStates.splice(-settings.numberOfHistoryStates, settings.numberOfHistoryStates);
}
//there is now definitely at least 1 undo state, so the button shouldnt be disabled
document.getElementById('undo-button').classList.remove('disabled');
//there should be no redoStates after an undoState is saved
redoStates = [];
console.log(undoStates)
console.log(redoStates)
//get current canvas data and save to undoStates array
undoStates.push(state);
//limit the number of states to settings.numberOfHistoryStates
if (undoStates.length > settings.numberOfHistoryStates) {
undoStates = undoStates.splice(-settings.numberOfHistoryStates, settings.numberOfHistoryStates);
}
//there is now definitely at least 1 undo state, so the button shouldnt be disabled
document.getElementById('undo-button').classList.remove('disabled');
//there should be no redoStates after an undoState is saved
redoStates = [];
console.log(undoStates);
console.log(redoStates);
}
function undo () {
console.log('%cundo', undoLogStyle);
//if there are any states saved to undo
if (undoStates.length > 0) {
console.log('%cundo', undoLogStyle);
document.getElementById('redo-button').classList.remove('disabled');
//get state
var undoState = undoStates[undoStates.length-1];
console.log(undoState);
//restore the state
undoState.undo();
//remove from the undo list
undoStates.splice(undoStates.length-1,1);
//if theres none left to undo, disable the option
if (undoStates.length == 0)
document.getElementById('undo-button').classList.add('disabled');
}
console.log(undoStates)
console.log(redoStates)
//if there are any states saved to undo
if (undoStates.length > 0) {
document.getElementById('redo-button').classList.remove('disabled');
//get state
var undoState = undoStates[undoStates.length-1];
console.log(undoState);
//restore the state
undoState.undo();
//remove from the undo list
undoStates.splice(undoStates.length-1,1);
//if theres none left to undo, disable the option
if (undoStates.length == 0)
document.getElementById('undo-button').classList.add('disabled');
}
console.log(undoStates);
console.log(redoStates);
}
function redo () {
console.log('%credo', undoLogStyle);
console.log('%credo', undoLogStyle);
if (redoStates.length > 0) {
if (redoStates.length > 0) {
//enable undo button
document.getElementById('undo-button').classList.remove('disabled');
//get state
var redoState = redoStates[redoStates.length-1];
console.log(redoState);
//restore the state
redoState.redo();
//remove from redo array
redoStates.splice(redoStates.length-1,1);
//if theres none left to redo, disable the option
if (redoStates.length == 0)
document.getElementById('redo-button').classList.add('disabled');
}
console.log(undoStates)
console.log(redoStates)
}
//enable undo button
document.getElementById('undo-button').classList.remove('disabled');
//get state
var redoState = redoStates[redoStates.length-1];
console.log(redoState);
//restore the state
redoState.redo();
//remove from redo array
redoStates.splice(redoStates.length-1,1);
//if theres none left to redo, disable the option
if (redoStates.length == 0)
document.getElementById('redo-button').classList.add('disabled');
}
console.log(undoStates);
console.log(redoStates);
}

View File

@ -1,15 +1,15 @@
var spacePressed = false;
function KeyPress(e) {
var keyboardEvent = window.event? event : e;
var keyboardEvent = window.event? event : e;
//if the user is typing in an input field, ignore these hotkeys
if (document.activeElement.tagName == 'INPUT') return;
//if the user is typing in an input field, ignore these hotkeys
if (document.activeElement.tagName == 'INPUT') return;
//if no document has been created yet,
//orthere is a dialog box open
//ignore hotkeys
if (!documentCreated || dialogueOpen) return;
//if no document has been created yet,
//orthere is a dialog box open
//ignore hotkeys
if (!documentCreated || dialogueOpen) return;
//
if (e.key === "Escape") {

View File

@ -1,23 +1,23 @@
//format a color button
function initColor (colorElement) {
//console.log('initColor()');
//console.log(document.getElementById('jscolor-hex-input'))
//add jscolor picker for this color
colorElement.jscolor = new jscolor(colorElement.parentElement, {
valueElement: null, //if you dont set this to null, it turns the button (colorElement) into text, we set it when you open the picker
styleElement: colorElement,
width:151,
position: 'left',
padding:0,
borderWidth:14,
borderColor: '#332f35',
backgroundColor: '#332f35',
insetColor: 'transparent',
value: colorElement.style.backgroundColor,
deleteButton: true,
});
//console.log('initColor()');
//console.log(document.getElementById('jscolor-hex-input'))
//add jscolor picker for this color
colorElement.jscolor = new jscolor(colorElement.parentElement, {
valueElement: null, //if you dont set this to null, it turns the button (colorElement) into text, we set it when you open the picker
styleElement: colorElement,
width:151,
position: 'left',
padding:0,
borderWidth:14,
borderColor: '#332f35',
backgroundColor: '#332f35',
insetColor: 'transparent',
value: colorElement.style.backgroundColor,
deleteButton: true,
});
}

File diff suppressed because it is too large Load Diff

View File

@ -15,9 +15,9 @@
* @param canvas HTML canvas element
*/
function Layer(width, height, canvas) {
this.canvasSize = [width, height],
this.canvas = canvas,
this.context = this.canvas.getContext("2d"),
this.canvasSize = [width, height];
this.canvas = canvas;
this.context = this.canvas.getContext('2d');
// Initializes the canvas
this.initialize = function() {
var maxHorizontalZoom = Math.floor(window.innerWidth/this.canvasSize[0]*0.75);
@ -38,10 +38,10 @@ function Layer(width, height, canvas) {
//center canvas in window
this.canvas.style.left = 64+canvasView.clientWidth/2-(this.canvasSize[0]*zoom/2)+'px';
this.canvas.style.top = 48+canvasView.clientHeight/2-(this.canvasSize[1]*zoom/2)+'px';
this.context.imageSmoothingEnabled = false;
this.context.mozImageSmoothingEnabled = false;
},
};
// Resizes canvas
this.resize = function() {
let newWidth = (this.canvas.width * zoom) + 'px';
@ -49,7 +49,7 @@ function Layer(width, height, canvas) {
this.canvas.style.width = newWidth;
this.canvas.style.height = newHeight;
},
};
// Copies the otherCanvas' position and size
this.copyData = function(otherCanvas) {
this.canvas.style.width = otherCanvas.canvas.style.width;
@ -57,5 +57,5 @@ function Layer(width, height, canvas) {
this.canvas.style.left = otherCanvas.canvas.style.left;
this.canvas.style.top = otherCanvas.canvas.style.top;
}
}
};
}

View File

@ -1,61 +1,61 @@
document.getElementById('open-image-browse-holder').addEventListener('change', function () {
if (this.files && this.files[0]) {
//make sure file is allowed filetype
var fileContentType = this.files[0].type;
if (fileContentType == 'image/png' || fileContentType == 'image/gif') {
//load file
var fileReader = new FileReader();
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);
//track google event
ga('send', 'event', 'Pixel Editor Load', colorPalette.length, this.width+'/'+this.height); /*global ga*/
if (this.files && this.files[0]) {
};
img.src = e.target.result;
};
fileReader.readAsDataURL(this.files[0]);
}
else alert('Only PNG and GIF files are allowed at this time.');
}
});
//make sure file is allowed filetype
var fileContentType = this.files[0].type;
if (fileContentType == 'image/png' || fileContentType == 'image/gif') {
//load file
var fileReader = new FileReader();
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);
//track google event
ga('send', 'event', 'Pixel Editor Load', colorPalette.length, this.width+'/'+this.height); /*global ga*/
};
img.src = e.target.result;
};
fileReader.readAsDataURL(this.files[0]);
}
else alert('Only PNG and GIF files are allowed at this time.');
}
});

View File

@ -1,50 +1,50 @@
//this is called when a user picks a file after selecting "load palette" from the new pixel dialogue
document.getElementById('load-palette-browse-holder').addEventListener('change', function () {
if (this.files && this.files[0]) {
//make sure file is allowed filetype
var fileContentType = this.files[0].type;
if (fileContentType == 'image/png' || fileContentType == 'image/gif') {
//load file
var fileReader = new FileReader();
fileReader.onload = function(e) {
var img = new Image();
img.onload = function() {
//draw image onto the temporary canvas
var loadPaletteCanvas = document.getElementById("load-palette-canvas-holder");
var loadPaletteContext = loadPaletteCanvas.getContext("2d");
loadPaletteCanvas.width = img.width;
loadPaletteCanvas.height = img.height;
loadPaletteContext.drawImage(img, 0, 0);
//create array to hold found colors
var colorPalette = [];
var imagePixelData = loadPaletteContext.getImageData(0,0,this.width, this.height).data;
console.log(imagePixelData)
//loop through pixels looking for colors to add to palette
for (var i = 0; i < imagePixelData.length; i += 4) {
var color = '#'+rgbToHex(imagePixelData[i],imagePixelData[i + 1],imagePixelData[i + 2]);
if (colorPalette.indexOf(color) == -1) {
colorPalette.push(color);
}
}
//add to palettes so that it can be loaded when they click okay
palettes['Loaded palette'] = {};
palettes['Loaded palette'].colors = colorPalette;
setText('palette-button', 'Loaded palette');
};
img.src = e.target.result;
};
fileReader.readAsDataURL(this.files[0]);
}
else alert('Only PNG and GIF files are supported at this time.');
}
});
if (this.files && this.files[0]) {
//make sure file is allowed filetype
var fileContentType = this.files[0].type;
if (fileContentType == 'image/png' || fileContentType == 'image/gif') {
//load file
var fileReader = new FileReader();
fileReader.onload = function(e) {
var img = new Image();
img.onload = function() {
//draw image onto the temporary canvas
var loadPaletteCanvas = document.getElementById('load-palette-canvas-holder');
var loadPaletteContext = loadPaletteCanvas.getContext('2d');
loadPaletteCanvas.width = img.width;
loadPaletteCanvas.height = img.height;
loadPaletteContext.drawImage(img, 0, 0);
//create array to hold found colors
var colorPalette = [];
var imagePixelData = loadPaletteContext.getImageData(0,0,this.width, this.height).data;
console.log(imagePixelData);
//loop through pixels looking for colors to add to palette
for (var i = 0; i < imagePixelData.length; i += 4) {
var color = '#'+rgbToHex(imagePixelData[i],imagePixelData[i + 1],imagePixelData[i + 2]);
if (colorPalette.indexOf(color) == -1) {
colorPalette.push(color);
}
}
//add to palettes so that it can be loaded when they click okay
palettes['Loaded palette'] = {};
palettes['Loaded palette'].colors = colorPalette;
setText('palette-button', 'Loaded palette');
};
img.src = e.target.result;
};
fileReader.readAsDataURL(this.files[0]);
}
else alert('Only PNG and GIF files are supported at this time.');
}
});

View File

@ -118,14 +118,35 @@ window.addEventListener("mouseup", function (mouseEvent) {
if (mouseEvent.which == 1){
mode = "in";
}
else if (mouseEvent.which == 3){
mode = "out";
}
else if (currentTool == 'fill' && mouseEvent.target.className == 'drawingCanvas') {
console.log('filling');
//if you clicked on anything but the canvas, do nothing
if (!mouseEvent.target == currentLayer.canvas) return;
//get cursor postion
var cursorLocation = getCursorPosition(mouseEvent);
//offset to match cursor point
cursorLocation[0] += 2;
cursorLocation[1] += 12;
//fill starting at the location
fill(cursorLocation);
}
else if (currentTool == 'zoom' && mouseEvent.target.className == 'drawingCanvas') {
let mode;
if (mouseEvent.which == 1){
mode = 'in';
}
else if (mouseEvent.which == 3){
mode = 'out';
}
changeZoom(layers[0], mode, getCursorPosition(mouseEvent));
for (let i=1; i<layers.length; i++) {
layers[i].copyData(layers[0]);
layers[i].copyData(layers[0]);
}
}
else if (currentTool.name == 'rectselect' && isRectSelecting) {
@ -143,6 +164,19 @@ window.addEventListener("mouseup", function (mouseEvent) {
}, false);
function setPreviewPosition(preview, cursor, size){
preview.style.left = (
currentLayer.canvas.offsetLeft
+ Math.floor(cursor[0]/zoom) * zoom
- Math.floor(size / 2) * zoom
) + 'px';
preview.style.top = (
currentLayer.canvas.offsetTop
+ Math.floor(cursor[1]/zoom) * zoom
- Math.floor(size / 2) * zoom
) + 'px';
}
// OPTIMIZABLE: redundant || mouseEvent.target.className in currentTool ifs
@ -231,7 +265,7 @@ function draw (mouseEvent) {
else if (currentTool.name == 'pan' && dragging) {
// Setting first layer position
setCanvasOffset(layers[0].canvas, layers[0].canvas.offsetLeft + (cursorLocation[0] - lastPos[0]), layers[0].canvas.offsetTop + (cursorLocation[1] - lastPos[1]));
// Copying that position to the other layers
// Copying that position to the other layers
for (let i=1; i<layers.length; i++) {
layers[i].copyData(layers[0]);
}
@ -248,8 +282,8 @@ function draw (mouseEvent) {
var colorLightness = Math.max(selectedColor[0],selectedColor[1],selectedColor[2]);
//for the darkest 50% of colors, change the eyedropper preview to dark mode
if (colorLightness>127) eyedropperPreview.classList.remove('dark');
else eyedropperPreview.classList.add('dark');
if (colorLightness>127) eyedropperPreview.classList.remove('dark');
else eyedropperPreview.classList.add('dark');
}
else if (currentTool.name == 'resizebrush' && dragging) {
//get new brush size based on x distance from original clicking location
@ -319,10 +353,10 @@ function draw (mouseEvent) {
// Updating the cursor (move if inside rect, cross if not)
currentTool.updateCursor();
// If I'm dragging, I move the preview
if (dragging && cursorInSelectedArea()) {
updateMovePreview(mouseEvent);
}
// If I'm dragging, I move the preview
if (dragging && cursorInSelectedArea()) {
updateMovePreview(mouseEvent);
}
}
}
@ -334,17 +368,17 @@ canvasView.addEventListener("wheel", function(mouseEvent){
if (mouseEvent.deltaY < 0){
mode = 'in';
}
else if (mouseEvent.deltaY > 0) {
mode = 'out';
else if (mouseEvent.deltaY > 0) {
mode = 'out';
}
// Changing zoom and position of the first layer
changeZoom(layers[0], mode, getCursorPosition(mouseEvent))
changeZoom(layers[0], mode, getCursorPosition(mouseEvent));
for (let i=1; i<layers.length; i++) {
// Copying first layer's data into the other layers
// Copying first layer's data into the other layers
layers[i].copyData(layers[0]);
}
}
});
});

View File

@ -7,66 +7,66 @@ var firstTimeMove = true;
// TODO: move with arrows
function updateMovePreview(mouseEvent) {
// ISSUE
selectionCanceled = false;
// ISSUE
selectionCanceled = false;
if (firstTimeMove) {
cutSelection(mouseEvent);
}
if (firstTimeMove) {
cutSelection(mouseEvent);
}
firstTimeMove = false;
firstTimeMove = false;
lastMousePos = getCursorPosition(mouseEvent);
// clear the entire tmp layer
TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height);
// put the image data with offset
TMPLayer.context.putImageData(
imageDataToMove,
Math.round(lastMousePos[0] / zoom - imageDataToMove.width / 2),
Math.round(lastMousePos[1] / zoom - imageDataToMove.height / 2));
lastMousePos = getCursorPosition(mouseEvent);
// clear the entire tmp layer
TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height);
// put the image data with offset
TMPLayer.context.putImageData(
imageDataToMove,
Math.round(lastMousePos[0] / zoom - imageDataToMove.width / 2),
Math.round(lastMousePos[1] / zoom - imageDataToMove.height / 2));
lastMovePos = lastMousePos;
moveSelection(lastMousePos[0] / zoom, lastMousePos[1] / zoom, imageDataToMove.width, imageDataToMove.height)
lastMovePos = lastMousePos;
moveSelection(lastMousePos[0] / zoom, lastMousePos[1] / zoom, imageDataToMove.width, imageDataToMove.height);
}
function endSelection() {
TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height);
VFXLayer.context.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height);
TMPLayer.context.clearRect(0, 0, TMPLayer.canvas.width, TMPLayer.canvas.height);
VFXLayer.context.clearRect(0, 0, VFXLayer.canvas.width, VFXLayer.canvas.height);
if (imageDataToMove !== undefined) {
let underlyingImageData = currentLayer.context.getImageData(startX, startY, endX - startX, endY - startY);
if (imageDataToMove !== undefined) {
let underlyingImageData = currentLayer.context.getImageData(startX, startY, endX - startX, endY - startY);
for (let i=0; i<underlyingImageData.data.length; i+=4) {
let currentMovePixel = [
imageDataToMove.data[i], imageDataToMove.data[i+1],
imageDataToMove.data[i+2], imageDataToMove.data[i+3]
];
for (let i=0; i<underlyingImageData.data.length; i+=4) {
let currentMovePixel = [
imageDataToMove.data[i], imageDataToMove.data[i+1],
imageDataToMove.data[i+2], imageDataToMove.data[i+3]
];
let currentUnderlyingPixel = [
underlyingImageData.data[i], underlyingImageData.data[i+1],
underlyingImageData.data[i+2], underlyingImageData.data[i+3]
];
let currentUnderlyingPixel = [
underlyingImageData.data[i], underlyingImageData.data[i+1],
underlyingImageData.data[i+2], underlyingImageData.data[i+3]
];
if (isPixelEmpty(currentMovePixel)) {
if (!isPixelEmpty(underlyingImageData)) {
imageDataToMove.data[i] = currentUnderlyingPixel[0];
imageDataToMove.data[i+1] = currentUnderlyingPixel[1];
imageDataToMove.data[i+2] = currentUnderlyingPixel[2];
imageDataToMove.data[i+3] = currentUnderlyingPixel[3];
}
}
}
if (isPixelEmpty(currentMovePixel)) {
if (!isPixelEmpty(underlyingImageData)) {
imageDataToMove.data[i] = currentUnderlyingPixel[0];
imageDataToMove.data[i+1] = currentUnderlyingPixel[1];
imageDataToMove.data[i+2] = currentUnderlyingPixel[2];
imageDataToMove.data[i+3] = currentUnderlyingPixel[3];
}
}
}
if (lastMovePos !== undefined) {
currentLayer.context.putImageData(
imageDataToMove,
Math.round(lastMovePos[0] / zoom - imageDataToMove.width / 2),
Math.round(lastMovePos[1] / zoom - imageDataToMove.height / 2));
}
}
if (lastMovePos !== undefined) {
currentLayer.context.putImageData(
imageDataToMove,
Math.round(lastMovePos[0] / zoom - imageDataToMove.width / 2),
Math.round(lastMovePos[1] / zoom - imageDataToMove.height / 2));
}
}
selectionCanceled = true;
isRectSelecting = false;
firstTimeMove = true;
imageDataToMove = undefined;
selectionCanceled = true;
isRectSelecting = false;
firstTimeMove = true;
imageDataToMove = undefined;
}

View File

@ -1,5 +1,5 @@
function newPixel (width, height, palette) {
// Setting the current layer
// Setting the current layer
currentLayer = new Layer(width, height, canvas);
currentLayer.initialize();
@ -80,4 +80,4 @@ function newPixel (width, height, palette) {
document.getElementById('save-as-button').classList.remove('disabled');
documentCreated = true;
}
}

View File

@ -9,4 +9,4 @@ window.onload = function(){
else
//otherwise show the new pixel dialog
showDialogue('new-pixel', false);
};
};

View File

@ -1,7 +1,7 @@
//prevent user from leaving page with unsaved data
window.onbeforeunload = function() {
if (documentCreated)
return 'You will lose your pixel if it\'s not saved!';
else return;
}
if (documentCreated)
return 'You will lose your pixel if it\'s not saved!';
else return;
};

View File

@ -1,62 +1,62 @@
//populate palettes list in new pixel menu
Object.keys(palettes).forEach(function(paletteName,index) {
var palettesMenu = document.getElementById("palette-menu");
var palettesMenu = document.getElementById('palette-menu');
//create button
var button = document.createElement("button");
var button = document.createElement('button');
button.appendChild(document.createTextNode(paletteName));
//insert new element
palettesMenu.appendChild(button);
//if the palette was specified by the user, change the dropdown to it
if (palettes[paletteName].specified == true) {
setText('palette-button', paletteName);
//Show empty palette option
document.getElementById('no-palette-button').style.display = 'block';
}
on('click', button, function() {
//insert new element
palettesMenu.appendChild(button);
//hide the dropdown menu
deselect('palette-menu');
deselect('palette-button');
//show empty palette option
document.getElementById('no-palette-button').style.display = 'block';
//set the text of the dropdown to the newly selected preset
setText('palette-button', paletteName);
});
//if the palette was specified by the user, change the dropdown to it
if (palettes[paletteName].specified == true) {
setText('palette-button', paletteName);
//Show empty palette option
document.getElementById('no-palette-button').style.display = 'block';
}
on('click', button, function() {
//hide the dropdown menu
deselect('palette-menu');
deselect('palette-button');
//show empty palette option
document.getElementById('no-palette-button').style.display = 'block';
//set the text of the dropdown to the newly selected preset
setText('palette-button', paletteName);
});
});
//select no palette
on('click', 'no-palette-button', function () {
document.getElementById('no-palette-button').style.display = 'none';
setText('palette-button', 'Choose a palette...');
document.getElementById('no-palette-button').style.display = 'none';
setText('palette-button', 'Choose a palette...');
});
//select load palette
on('click', 'load-palette-button', function () {
document.getElementById("load-palette-browse-holder").click();
document.getElementById('load-palette-browse-holder').click();
});
on('click', 'palette-button', function (e){
toggle('palette-button');
toggle('palette-menu');
deselect('preset-button');
deselect('preset-menu');
e.stopPropagation();
toggle('palette-button');
toggle('palette-menu');
deselect('preset-button');
deselect('preset-menu');
e.stopPropagation();
});
on('click', 'new-pixel', function (){
deselect('preset-button');
deselect('preset-menu');
deselect('palette-button');
deselect('palette-menu');
});
deselect('preset-button');
deselect('preset-menu');
deselect('palette-button');
deselect('palette-menu');
});

View File

@ -1,7 +1,7 @@
function isPixelEmpty(pixel) {
if ((pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) || pixel[3] == 0) {
return true;
}
if ((pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) || pixel[3] == 0) {
return true;
}
return false;
return false;
}

View File

@ -1,64 +1,64 @@
//prests
var presets = {
'Gameboy Color': {
width: 240,
height: 203,
palette: 'Gameboy Color'
},
'PICO-8': {
width: 128,
height: 128,
palette: 'PICO-8',
},
'Commodore 64': {
width: 40,
height: 80,
palette: 'Commodore 64'
}
'Gameboy Color': {
width: 240,
height: 203,
palette: 'Gameboy Color'
},
'PICO-8': {
width: 128,
height: 128,
palette: 'PICO-8',
},
'Commodore 64': {
width: 40,
height: 80,
palette: 'Commodore 64'
}
};
//populate preset list in new pixel menu
Object.keys(presets).forEach(function(presetName,index) {
var presetsMenu = document.getElementById("preset-menu");
var presetsMenu = document.getElementById('preset-menu');
//create button
var button = document.createElement("button");
var button = document.createElement('button');
button.appendChild(document.createTextNode(presetName));
//insert new element
presetsMenu.appendChild(button);
//add click event listener
on('click', button, function() {
//change dimentions on new pixel form
setValue('size-width', presets[presetName].width);
setValue('size-height', presets[presetName].height);
//insert new element
presetsMenu.appendChild(button);
//set the text of the dropdown to the newly selected preset
setText('palette-button', presets[presetName].palette);
//add click event listener
on('click', button, function() {
//hide the dropdown menu
deselect('preset-menu');
deselect('preset-button');
//change dimentions on new pixel form
setValue('size-width', presets[presetName].width);
setValue('size-height', presets[presetName].height);
//set the text of the dropdown to the newly selected preset
setText('preset-button', presetName);
});
//set the text of the dropdown to the newly selected preset
setText('palette-button', presets[presetName].palette);
//hide the dropdown menu
deselect('preset-menu');
deselect('preset-button');
//set the text of the dropdown to the newly selected preset
setText('preset-button', presetName);
});
});
on('click', 'preset-button', function (e){
//open or close the preset menu
toggle('preset-button');
toggle('preset-menu');
//close the palette menu
deselect('palette-button');
deselect('palette-menu');
//stop the click from propogating to the parent element
e.stopPropagation();
//open or close the preset menu
toggle('preset-button');
toggle('preset-menu');
//close the palette menu
deselect('palette-button');
deselect('palette-menu');
//stop the click from propogating to the parent element
e.stopPropagation();
});

View File

@ -5,34 +5,34 @@ let endX;
let endY;
function startRectSelection(mouseEvent) {
// Saving the canvas
new HistoryStateEditCanvas();
// Putting the vfx layer on top of everything
VFXCanvas.style.zIndex = MAX_Z_INDEX;
// Saving the canvas
new HistoryStateEditCanvas();
// Putting the vfx layer on top of everything
VFXCanvas.style.zIndex = MAX_Z_INDEX;
// Saving the start coords of the rect
let cursorPos = getCursorPosition(mouseEvent);
startX = Math.round(cursorPos[0] / zoom) - 0.5;
startY = Math.round(cursorPos[1] / zoom) - 0.5;
// Saving the start coords of the rect
let cursorPos = getCursorPosition(mouseEvent);
startX = Math.round(cursorPos[0] / zoom) - 0.5;
startY = Math.round(cursorPos[1] / zoom) - 0.5;
// Avoiding external selections
if (startX < 0) {
startX = 0;
}
else if (startX > currentLayer.canvas.width) {
startX = currentLayer.canvas.width;
}
// Avoiding external selections
if (startX < 0) {
startX = 0;
}
else if (startX > currentLayer.canvas.width) {
startX = currentLayer.canvas.width;
}
if (startY < 0) {
startY = 0;
}
else if (startY > currentLayer.canvas.height) {
startY = currentLayer.canvas.height;
}
if (startY < 0) {
startY = 0;
}
else if (startY > currentLayer.canvas.height) {
startY = currentLayer.canvas.height;
}
// Drawing the rect
drawRect(startX, startY);
selectionCanceled = false;
// Drawing the rect
drawRect(startX, startY);
selectionCanceled = false;
}
function updateRectSelection(mouseEvent) {
@ -81,71 +81,71 @@ function cutSelection(mouseEvent) {
// Moving those pixels from the current layer to the tmp layer
TMPLayer.context.putImageData(imageDataToMove, startX + 1, startY);
//originalDataPosition = [currentPos[0], currentPos[1]];
//originalDataPosition = [currentPos[0], currentPos[1]];
}
function drawRect(x, y) {
// Getting the vfx context
let vfxContext = VFXCanvas.getContext("2d");
// Getting the vfx context
let vfxContext = VFXCanvas.getContext('2d');
// Clearing the vfx canvas
vfxContext.clearRect(0, 0, VFXCanvas.width, VFXCanvas.height);
vfxContext.lineWidth = 1;
vfxContext.strokeStyle = "black";
vfxContext.setLineDash([4]);
// Clearing the vfx canvas
vfxContext.clearRect(0, 0, VFXCanvas.width, VFXCanvas.height);
vfxContext.lineWidth = 1;
vfxContext.strokeStyle = 'black';
vfxContext.setLineDash([4]);
// Drawing the rect
vfxContext.beginPath();
vfxContext.rect(startX, startY, x - startX, y - startY);
// Drawing the rect
vfxContext.beginPath();
vfxContext.rect(startX, startY, x - startX, y - startY);
vfxContext.stroke();
vfxContext.stroke();
// TODO: make the rect blink from black to white in case of dark backgrounds
// TODO: make the rect blink from black to white in case of dark backgrounds
}
function applyChanges() {
VFXCanvas.style.zIndex = MIN_Z_INDEX;
VFXCanvas.style.zIndex = MIN_Z_INDEX;
}
// Checks whether the pointer is inside the selected area or not
function cursorInSelectedArea() {
let cursorPos = getCursorPosition(currentMouseEvent);
let x = cursorPos[0] / zoom;
let y = cursorPos[1] / zoom;
let cursorPos = getCursorPosition(currentMouseEvent);
let x = cursorPos[0] / zoom;
let y = cursorPos[1] / zoom;
let leftX = Math.min(startX, endX);
let rightX = Math.max(startX, endX);
let topY = Math.max(startY, endY);
let bottomY = Math.min(startY, endY);
let leftX = Math.min(startX, endX);
let rightX = Math.max(startX, endX);
let topY = Math.max(startY, endY);
let bottomY = Math.min(startY, endY);
if (leftX <= x && x <= rightX) {
if (bottomY <= y && y <= topY) {
return true;
}
if (leftX <= x && x <= rightX) {
if (bottomY <= y && y <= topY) {
return true;
}
return false;
}
return false;
}
return false;
return false;
}
function moveSelection(x, y, width, height) {
// Getting the vfx context
let vfxContext = VFXCanvas.getContext("2d");
// Getting the vfx context
let vfxContext = VFXCanvas.getContext('2d');
// Clearing the vfx canvas
vfxContext.clearRect(0, 0, VFXCanvas.width, VFXCanvas.height);
vfxContext.lineWidth = 1;
vfxContext.setLineDash([4]);
// Clearing the vfx canvas
vfxContext.clearRect(0, 0, VFXCanvas.width, VFXCanvas.height);
vfxContext.lineWidth = 1;
vfxContext.setLineDash([4]);
startX = Math.round(Math.round(x) - Math.round(width / 2)) + 0.5;
startY = Math.round(Math.round(y) - Math.round(height / 2)) + 0.5;
endX = startX + Math.round(width);
endY = startY + Math.round(height);
startX = Math.round(Math.round(x) - Math.round(width / 2)) + 0.5;
startY = Math.round(Math.round(y) - Math.round(height / 2)) + 0.5;
endX = startX + Math.round(width);
endY = startY + Math.round(height);
// Drawing the rect
vfxContext.beginPath();
vfxContext.rect(startX, startY, width, height);
// Drawing the rect
vfxContext.beginPath();
vfxContext.rect(startX, startY, width, height);
vfxContext.stroke();
vfxContext.stroke();
}

View File

@ -12,17 +12,17 @@ let endRectY;
function startRectDrawing(mouseEvent) {
// Putting the vfx layer on top of everything
VFXCanvas.style.zIndex = MAX_Z_INDEX;
// Updating flag
isDrawingRect = true;
// Putting the vfx layer on top of everything
VFXCanvas.style.zIndex = MAX_Z_INDEX;
// Updating flag
isDrawingRect = true;
// Saving the start coords of the rect
let cursorPos = getCursorPosition(mouseEvent);
startRectX = Math.round(cursorPos[0] / zoom) - 0.5;
startRectY = Math.round(cursorPos[1] / zoom) - 0.5;
// Saving the start coords of the rect
let cursorPos = getCursorPosition(mouseEvent);
startRectX = Math.floor(cursorPos[0] / zoom) + 0.5;
startRectY = Math.floor(cursorPos[1] / zoom) + 0.5;
drawRectangle(startRectX, startRectY);
drawRectangle(startRectX, startRectY);
}
function updateRectDrawing(mouseEvent) {
@ -101,20 +101,20 @@ function drawRectangle(x, y) {
vfxContext.setLineDash([]);
vfxContext.stroke();
vfxContext.stroke();
}
function setRectToolSvg() {
if (drawMode == 'empty') {
emptySVG.setAttribute("display", "visible");
fullSVG.setAttribute("display", "none");
}
else {
emptySVG.setAttribute("display", "none");
fullSVG.setAttribute("display", "visible");
}
if (drawMode == 'empty') {
emptySVG.setAttribute('display', 'visible');
fullSVG.setAttribute('display', 'none');
}
else {
emptySVG.setAttribute('display', 'none');
fullSVG.setAttribute('display', 'visible');
}
}
function applyChanges() {
VFXCanvas.style.zIndex = MIN_Z_INDEX;
}
VFXCanvas.style.zIndex = MIN_Z_INDEX;
}

View File

@ -1,25 +1,25 @@
//replaces all of a single color on the canvas with a different color
//input two rgb color objects {r:0,g:0,b:0}
function replaceAllOfColor (oldColor, newColor) {
//convert strings to objects if nessesary
if (typeof oldColor === 'string') oldColor = hexToRgb(oldColor);
if (typeof newColor === 'string') newColor = hexToRgb(newColor);
//create temporary image from canvas to search through
var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
//loop through all pixels
for (var i=0;i<tempImage.data.length;i+=4) {
//check if pixel matches old color
if(tempImage.data[i]==oldColor.r && tempImage.data[i+1]==oldColor.g && tempImage.data[i+2]==oldColor.b){
//change to new color
tempImage.data[i]=newColor.r;
tempImage.data[i+1]=newColor.g;
tempImage.data[i+2]=newColor.b;
}
}
//put temp image back onto canvas
currentLayer.context.putImageData(tempImage,0,0);
}
//convert strings to objects if nessesary
if (typeof oldColor === 'string') oldColor = hexToRgb(oldColor);
if (typeof newColor === 'string') newColor = hexToRgb(newColor);
//create temporary image from canvas to search through
var tempImage = currentLayer.context.getImageData(0, 0, canvasSize[0], canvasSize[1]);
//loop through all pixels
for (var i=0;i<tempImage.data.length;i+=4) {
//check if pixel matches old color
if(tempImage.data[i]==oldColor.r && tempImage.data[i+1]==oldColor.g && tempImage.data[i+2]==oldColor.b){
//change to new color
tempImage.data[i]=newColor.r;
tempImage.data[i+1]=newColor.g;
tempImage.data[i+2]=newColor.b;
}
}
//put temp image back onto canvas
currentLayer.context.putImageData(tempImage,0,0);
}

View File

@ -1,23 +1,23 @@
function setCanvasOffset (canvas, offsetLeft, offsetTop) {
//horizontal offset
var minXOffset = -canvasSize[0]*zoom+ 164;
var maxXOffset = window.innerWidth - 148;
if (offsetLeft < minXOffset)
canvas.style.left = minXOffset +'px';
else if (offsetLeft > maxXOffset)
canvas.style.left = maxXOffset +'px';
else
canvas.style.left = offsetLeft +'px';
//vertical offset
var minYOffset = -canvasSize[1]*zoom + 164;
var maxYOffset = window.innerHeight-100;
if (offsetTop < minYOffset)
canvas.style.top = minYOffset +'px';
else if (offsetTop > maxYOffset)
canvas.style.top = maxYOffset +'px';
else
canvas.style.top = offsetTop +'px';
}
//horizontal offset
var minXOffset = -canvasSize[0]*zoom+ 164;
var maxXOffset = window.innerWidth - 148;
if (offsetLeft < minXOffset)
canvas.style.left = minXOffset +'px';
else if (offsetLeft > maxXOffset)
canvas.style.left = maxXOffset +'px';
else
canvas.style.left = offsetLeft +'px';
//vertical offset
var minYOffset = -canvasSize[1]*zoom + 164;
var maxYOffset = window.innerHeight-100;
if (offsetTop < minYOffset)
canvas.style.top = minYOffset +'px';
else if (offsetTop > maxYOffset)
canvas.style.top = maxYOffset +'px';
else
canvas.style.top = offsetTop +'px';
}

View File

@ -1,45 +1,45 @@
var settings;
if (!Cookies.enabled) {
document.getElementById('cookies-disabled-warning').style.display = 'block';
document.getElementById('cookies-disabled-warning').style.display = 'block';
}
//try to load settings from cookie
var settingsFromCookie = Cookies.get('pixelEditorSettings');
if(!settingsFromCookie) {
console.log('settings cookie not found')
settings = {
switchToChangedColor: true,
enableDynamicCursorOutline: true, //unused - performance
enableBrushPreview: true, //unused - performance
enableEyedropperPreview: true, //unused - performance
numberOfHistoryStates: 20,
maxColorsOnImportedImage: 128
};
console.log('settings cookie not found');
settings = {
switchToChangedColor: true,
enableDynamicCursorOutline: true, //unused - performance
enableBrushPreview: true, //unused - performance
enableEyedropperPreview: true, //unused - performance
numberOfHistoryStates: 20,
maxColorsOnImportedImage: 128
};
}
else{
console.log('settings cookie found');
console.log(settingsFromCookie);
var settings = JSON.parse(settingsFromCookie);
console.log('settings cookie found');
console.log(settingsFromCookie);
var settings = JSON.parse(settingsFromCookie);
}
console.log(settings);
//on clicking the save button in the settings dialog
on('click', 'save-settings', function (){
//check if values are valid
if (isNaN(getValue('setting-numberOfHistoryStates'))) {
alert('Invalid value for numberOfHistoryStates')
return;
}
//save new settings to settings object
settings.numberOfHistoryStates = getValue('setting-numberOfHistoryStates');
//save settings object to cookie
var cookieValue = JSON.stringify(settings);
Cookies.set('pixelEditorSettings', cookieValue, { expires: Infinity });
//close window
closeDialogue();
});
//check if values are valid
if (isNaN(getValue('setting-numberOfHistoryStates'))) {
alert('Invalid value for numberOfHistoryStates');
return;
}
//save new settings to settings object
settings.numberOfHistoryStates = getValue('setting-numberOfHistoryStates');
//save settings object to cookie
var cookieValue = JSON.stringify(settings);
Cookies.set('pixelEditorSettings', cookieValue, { expires: Infinity });
//close window
closeDialogue();
});

View File

@ -31,7 +31,7 @@ on('click',"eraser-smaller-button", function(e){
}, false);
// rectangle
on('click',"rectangle-button", function(){
on('click','rectangle-button', function(){
// If the user clicks twice on the button, they change the draw mode
if (currentTool.name == 'rectangle') {
if (drawMode == 'empty') {
@ -80,8 +80,8 @@ on('click',"zoom-button", function(){
}, false);
//zoom in button
on('click',"zoom-in-button", function(){
//changeZoom('in',[window.innerWidth/2-canvas.offsetLeft,window.innerHeight/2-canvas.offsetTop]);
on('click','zoom-in-button', function(){
//changeZoom('in',[window.innerWidth/2-canvas.offsetLeft,window.innerHeight/2-canvas.offsetTop]);
changeZoom(layers[0],'in', [canvasSize[0] * zoom / 2, canvasSize[1] * zoom / 2]);
for (let i=1; i<layers.length; i++) {
@ -90,7 +90,7 @@ on('click',"zoom-in-button", function(){
}, false);
//zoom out button
on('click',"zoom-out-button", function(){
on('click','zoom-out-button', function(){
changeZoom(layers[0],'out',[canvasSize[0]*zoom/2,canvasSize[1]*zoom/2]);
for (let i=1; i<layers.length; i++) {
@ -103,4 +103,4 @@ on('click', "rectselect-button", function(){
tool.rectselect.switchTo();
}, false);
/*global on */
/*global on */

View File

@ -33,4 +33,4 @@ Tool.prototype.updateCursor = function () {
}
}
/*global Tool, dragging, canvasView, brushPreview, canMoveSelection, cursorInSelectedArea, eyedropperPreview, zoom, currentTool */
/*global Tool, dragging, canvasView, brushPreview, canMoveSelection, cursorInSelectedArea, eyedropperPreview, zoom, currentTool */

View File

@ -13,7 +13,7 @@ var secondCheckerBoardColor = 'rgba(204, 200, 206, 1)';
// Square size for the checkerboard
var checkerBoardSquareSize = 16;
// Checkerboard canvas
var checkerBoardCanvas = document.getElementById("checkerboard");
var checkerBoardCanvas = document.getElementById('checkerboard');
//common elements
var brushPreview = document.getElementById("brush-preview");
@ -24,8 +24,8 @@ var colorsMenu = document.getElementById("colors-menu");
var popUpContainer = document.getElementById("pop-up-container");
// main canvas
var canvas = document.getElementById("pixel-canvas");
var context = canvas.getContext("2d");
var canvas = document.getElementById('pixel-canvas');
var context = canvas.getContext('2d');
var currentGlobalColor;
// Layers
@ -36,9 +36,9 @@ var currentLayer;
// VFX layer used to draw previews of the selection and things like that
var VFXLayer;
// VFX canvas
var VFXCanvas = document.getElementById("vfx-canvas");
var VFXCanvas = document.getElementById('vfx-canvas');
// TMP layer
var TMPLayer;
// TMP canvas
var TMPCanvas = document.getElementById("tmp-canvas");
var TMPCanvas = document.getElementById('tmp-canvas');

2813
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,21 +4,22 @@
"description": "Online pixel art creation tool",
"main": "build.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"build": "node ./build.js ./build",
"serve": "node ./server.js ./build 3000",
"test": "npm run build && npm run serve"
},
"author": "Lospec",
"license": "ISC",
"dependencies": {
"express": "^4.16.4",
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"gulp": "^4.0.0",
"gulp": "^4.0.2",
"gulp-hb": "^8.0.0",
"gulp-include": "^2.3.1",
"gulp-rename": "^2.0.0",
"gulp-sass": "^4.0.2",
"handlebars-helper-svg": "git+https://bitbucket.org/skeddles/npm-handlebars-helper-svg-lospec-open-source.git",
"hbs": "^4.0.3",
"hbs-register-helpers": "git+https://skeddles@bitbucket.org/skeddles/hbs-register-helpers.git",
"hbs-register-partials": "git+https://skeddles@bitbucket.org/skeddles/hbs-register-partials.git",
"opn": "^6.0.0",
"open": "^6.0.0",
"sass": "^1.17.3"
}
}

37
server.js Normal file
View File

@ -0,0 +1,37 @@
const path = require('path');
const express = require('express');
const app = express();
const BUILDDIR = process.argv[2] || './build';
const PORT = process.argv[3] || 3000;
//ROUTE - index.htm
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, BUILDDIR, 'index.htm'), {}, function (err) {
if(err){
console.log('error sending file',err);
} else {
setTimeout(()=>{
console.log('closing server');
server.close();
process.exit();
},1000*10);
}
});
});
//ROUTE - other files
app.use(express.static(path.join(__dirname, BUILDDIR)));
//start server
var server = app.listen(PORT, () => {
console.log(`\nTemp server started at http://localhost:${PORT}!`);
//console.log('press ctrl+c to stop ');
var opn = require('open');
// opens the url in the default browser
opn(`http://localhost:${PORT}`);
});