diff --git a/index.html b/index.html index de31418..ce7eaa7 100644 --- a/index.html +++ b/index.html @@ -18,12 +18,12 @@
-
name body
-
name eyes
-
name mouth
-
name arms
-
-
+
+
+
+
+
+
stats
@@ -46,4 +46,4 @@ - \ No newline at end of file + diff --git a/neomojimixer.css b/neomojimixer.css index df5a90d..39862d5 100644 --- a/neomojimixer.css +++ b/neomojimixer.css @@ -47,7 +47,7 @@ button#export { width: 250px; } -span.name { +#controls > div > .name { display: inline-block; width: 200px; text-align: center; diff --git a/neomojimixer.js b/neomojimixer.js index 4fa5b39..6a50a50 100644 --- a/neomojimixer.js +++ b/neomojimixer.js @@ -1,370 +1,323 @@ -//global variables +const NeomojiMixer = (function(NeomojiMixer) { + //global variables -//Arrays to hold the parts -let eyes = []; -let body = []; -let mouth = []; -let arms = []; + const color_names = [ + "blue", + "lightgrey", + "orange", + "red", + "white", + "yellow", + ]; + let selected_color = "blue"; + let color_change_callbacks = []; -//FOr all the different colours of the arms there will be each a own arraz -let arms_orange = []; -let arms_blue = []; -let arms_lightgrey = []; -let arms_red = []; -let arms_white = []; -let arms_yellow = []; + //shotnames for HTML elements to interact with -//Index to easily find when to roll back to the first/last element in the list -let inex_eyes = 0; -let index_body = 0; -let index_mouth = 0; -let index_arms = 0; -let index_color = 0; + const canvas = document.getElementById("canvas_export"); + const export_img = document.getElementById("imageExport"); + const neomoji_name = document.getElementById("fullNeomojiName"); -//shotnames for HTML elements to interact with + //Stats + const stats = document.getElementById("stats"); -//images -const body_image = document.getElementById("body_img"); -const eyes_image = document.getElementById("eyes_img"); -const mouth_image = document.getElementById("mouth_img"); -const arms_image = document.getElementById("arms_img"); - -const canvas = document.getElementById("canvas_export"); -const export_img = document.getElementById("imageExport"); -const neomoji_name = document.getElementById("fullNeomojiName"); - -//names -const body_name = document.getElementById("body_name"); -const eyes_name = document.getElementById("eyes_name"); -const mouth_name = document.getElementById("mouth_name"); -const arms_name = document.getElementById("arms_name"); - -//Stats -const stats = document.getElementById("stats"); - - -// Loading the JSON and getting all the available parts -async function getData() { - - fetch('./parts.json') - .then(function(response) { - return response.json(); - }) - .then(function(data) { - loadParts(data); - }) - .catch(function(error) { - console.log('An error occurred:', error); - }); -} - -function loadParts(parts) { - //Load parts into Arrays - parts.type.eyes.forEach(fillArrayEyes); - parts.type.body.forEach(fillArrayBody); - parts.type.mouth.forEach(fillArrayMouth); - parts.type.arms.forEach(fillArrayArms); - - //find the indexes of each part of the corresponding color and write those into the color arrays - fillArraysArms(); - - //Randomize initial view - randomize(); - - //Show little statistic - var sum = body.length + eyes.length + mouth.length + arms.length; - var variety = body.length * eyes.length * mouth.length * arms_orange.length; - - stats.innerHTML = "There are " + sum + " Elements available,
with " + new Intl.NumberFormat("de-DE").format(variety) + " possible combinations."; - - //Activate the buttons after everything is loaded in - document.getElementById("body_left").disabled = false; - document.getElementById("body_right").disabled = false; - document.getElementById("eyes_left").disabled = false; - document.getElementById("eyes_right").disabled = false; - document.getElementById("mouth_left").disabled = false; - document.getElementById("mouth_right").disabled = false; - document.getElementById("arms_left").disabled = false; - document.getElementById("arms_right").disabled = false; - document.getElementById("random").disabled = false; - document.getElementById("export").disabled = false; - -} - -function fillArrayEyes(item){ - let name = item.name; - let url = item.url; - eyes.push ([name, url]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1 -} - -function fillArrayBody(item){ - let name = item.name; - let url = item.url; - let color = item.color; - body.push ([name, url, color]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1 -} - -function fillArrayMouth(item){ - let name = item.name; - let url = item.url; - mouth.push ([name, url]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1 -} - -function fillArrayArms(item){ - let name = item.name; - let url = item.url; - let color = item.color; - arms.push ([name, url, color]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1 -} - -function fillArraysArms(){ - for (let i=0; i arms.selected_index; index_arms -> arms.entry_indices[arms.selected_index] + this.image_element = document.getElementById(name + "_img"); + this.name_element = document.getElementById(name + "_name"); + this.button_left = document.getElementById(name + "_left"); + this.button_right = document.getElementById(name + "_right"); + } + + PartHandler.prototype = { + fillArray: function(item) { + let name = item.name; + let url = item.url; + this.entries.push([name, url]); //Two dimensional array, Second dimension holds name on index 0 and url at index 1 + }, + fillIndices: function() { + for (let i = 0; i < this.entries.length; i++) { + this.entry_indices.push(i); //By default preserve index + } + }, + getSelectedEntry: function() { + return this.entries[this.entry_indices[this.selected_index]]; + }, + setIndex: function(index) { + const modulo = this.entry_indices.length; //Check if index is too big for the array + if (!modulo) { + this.selected_index = 0; //Error + } else { + index %= modulo; + if (index < 0) { + index += modulo; + } + this.selected_index = index; + } + this.redraw(); + }, + redraw: function() { + const entry = this.getSelectedEntry(); + this.image_element.src = "." + entry[1]; //Change URL of picture + //Change name in controls + this.updateOptions(); + this.name_element.selectedIndex = this.selected_index; + }, + onClickNext: function() { + this.setIndex(this.selected_index + 1); + }, + onClickPrev: function() { + this.setIndex(this.selected_index - 1); + }, + onChangeDropdown: function() { + this.setIndex(this.name_element.selectedIndex); + }, + activateControls: function() { + this.button_left.disabled = false; + this.button_right.disabled = false; + this.name_element.disabled = false; + }, + randomize: function() { + this.setIndex(Math.floor(Math.random() * this.entry_indices.length)); + }, + createExportImage: function() { + const entry = this.getSelectedEntry(); + let img = new Image(); + img.src = "." + entry[1]; + return img; + }, + updateOptions: function() { + const options = this.name_element.options; + for (let i = 0; i < this.entry_indices.length; i++) { + const index = this.entry_indices[i]; + const entry = this.entries[index]; + if (options.length > i && options[i].value == entry[0]) { + continue; + } else { + const option = new Option(entry[0], entry[0], false, this.selected_index == i); + if (this.name_element.length <= i) { + this.name_element.add(option); + } else { + this.name_element.remove(i); + this.name_element.add(option, i); + } + } + } + }, }; - - export_img.hidden = false; - neomoji_name.hidden = false; - document.getElementById("exportSaveMessage").hidden = false; -} + + function ColoredPartHandler(name) { + PartHandler.call(this, name); + //For all the different colours of the arms there will be each a own array + this.colored_indices = Object.create(null); + for (let i = 0; i < color_names.length; i++) { + this.colored_indices[color_names[i]] = []; + } + this.entry_indices = this.colored_indices[selected_color]; + const that = this; + color_change_callbacks.push(function() { + that.onColorChange(); + }); + } + + ColoredPartHandler.prototype = Object.assign(Object.create(PartHandler.prototype), { + constructor: PartHandler, + fillArray: function(item) { + let name = item.name; + let url = item.url; + let color = item.color; + this.entries.push([name, url, color]); //Two dimensional array, Second dimension holds name on index 0, url at index 1, and color at index 2 + }, + fillIndices: function() { + for (let i = 0; i < this.entries.length; i++) { + const color = this.entries[i][2]; + if (color == "") { + //All colors + for (let j in this.colored_indices) { + this.colored_indices[j].push(i); + } + } else { + const indices = this.colored_indices[color]; + if (indices == undefined) { + console.log("Cannot register " + this.name + " with unknown color: " + color); + } else { + indices.push(i); + } + } + } + }, + onColorChange: function() { + this.entry_indices = this.colored_indices[selected_color]; + this.redraw(); + }, + }); + + function BodyPartHandler(name) { + PartHandler.call(this, name); + } + + BodyPartHandler.prototype = Object.assign(Object.create(PartHandler.prototype), { + constructor: PartHandler, + fillArray: ColoredPartHandler.prototype.fillArray, + setIndex: function(index) { + const modulo = this.entry_indices.length; //Check if index is too big for the array + if (!modulo) { + this.selected_index = 0; //Error + } else { + index %= modulo; + if (index < 0) { + index += modulo; + } + this.selected_index = index; + } + this.redraw(); + const entry = this.getSelectedEntry(); + selected_color = entry[2]; //Global + onColorChange(); //Global + }, + }); + + const part_handlers = { + body: new BodyPartHandler("body"), + eyes: new PartHandler("eyes"), + mouth: new PartHandler("mouth"), + arms: new ColoredPartHandler("arms"), + }; + + + // Loading the JSON and getting all the available parts + async function getData() { + fetch('./parts.json') + .then(function(response) { + return response.json(); + }) + .then(function(data) { + loadParts(data); + }) + .catch(function(error) { + console.log('An error occurred:', error); + }); + } + + function loadParts(parts) { + //Load parts into Arrays + for (const i in part_handlers) { + parts.type[i].forEach(function(p) {part_handlers[i].fillArray(p);}); + } + + //find the indexes of each part of the corresponding color and write those into the color arrays + for (const i in part_handlers) { + part_handlers[i].fillIndices(); + } + + //Randomize initial view + randomize(); + + //Show little statistic + var sum = 0; + var variety = 1; + for (const i in part_handlers) { + sum += part_handlers[i].entries.length; + variety *= part_handlers[i].entry_indices.length; + } + + stats.innerHTML = "There are " + sum + " Elements available,
with " + new Intl.NumberFormat("de-DE").format(variety) + " possible combinations."; + + //Activate the buttons after everything is loaded in + for (const i in part_handlers) { + part_handlers[i].activateControls(); + } + document.getElementById("random").disabled = false; + document.getElementById("export").disabled = false; + + } + + function randomize() { //Randomize which parts are shown + for (const i in part_handlers) { + part_handlers[i].randomize(); + } + } + + function exportImage() { //Export image so it can be saved as one PNG + let ctx=canvas.getContext("2d"); + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + neomoji_name.value = part_handlers.body.getSelectedEntry()[0] + "_" + part_handlers.eyes.getSelectedEntry()[0] + "_" + part_handlers.mouth.getSelectedEntry()[0] + "_" + part_handlers.arms.getSelectedEntry()[0]; //Set name for the emoji to use as the image name and to show as shortcode + + let export_layers = [ + part_handlers.body.createExportImage(), + part_handlers.eyes.createExportImage(), + part_handlers.mouth.createExportImage(), + part_handlers.arms.createExportImage(), + ]; + + function layerCallback() { + while (export_layers.length) { + const layer = export_layers[0]; + if (!layer.complete) { + layer.onload = layerCallback; + return; //Wait to load + } + //Finished waiting + export_layers.shift() + ctx.drawImage(layer, 0, 0, 256, 256); + } + let img = canvas.toDataURL("image/png"); + export_img.src = img; + } + + setTimeout(layerCallback, 0); //Run asynchronously + + export_img.hidden = false; + neomoji_name.hidden = false; + document.getElementById("exportSaveMessage").hidden = false; + } + + NeomojiMixer.PartHandler = PartHandler; + NeomojiMixer.ColoredPartHandler = ColoredPartHandler; + NeomojiMixer.BodyPartHandler = BodyPartHandler; + + NeomojiMixer.color_names = color_names; + NeomojiMixer.color_change_callbacks = color_change_callbacks; + NeomojiMixer.part_handlers = part_handlers; + NeomojiMixer.onColorChange = onColorChange; + NeomojiMixer.getData = getData; + NeomojiMixer.loadParts = loadParts; + NeomojiMixer.randomize = randomize; + NeomojiMixer.exportImage = exportImage; + NeomojiMixer.canvas = canvas; + NeomojiMixer.export_img = export_img; + NeomojiMixer.neomoji_name = neomoji_name; + NeomojiMixer.stats = stats; + + Object.defineProperty(NeomojiMixer, 'selected_color', { + enumerable: true, + configurable: true, + get: function() { + return selected_color; + }, + set: function(value) { + selected_color = value; + onColorChange(); + }, + }); + + return NeomojiMixer; +})(window.NeomojiMixer || {}); + //Main Programm document.getElementById("noJSmessage").hidden = true; -getData(); \ No newline at end of file +NeomojiMixer.getData();