layer class, events, injected parameters
This commit is contained in:
@@ -1 +1 @@
|
|||||||
"use strict";export default class pechatalka{#wrap=document.getElementById("pechatalka");get wrap(){return this.#wrap}#canvas=document.getElementById("pechatalka")?.querySelector(".canvas");get canvas(){return this.#canvas}#result=document.getElementById("pechatalka")?.querySelector(".result");get result(){return this.#result}#layers=new Set();get layers(){return this.#layers}#cost=0;get cost(){return this.#cost}prices={pin:{image:150}};constructor(wrap,canvas,result,inject=false){if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.pechatalka=this}}if(canvas instanceof HTMLElement){this.#canvas=canvas}if(result instanceof HTMLElement){this.#result=result}}moving(target){const canvas=this.#canvas;const from={x:0,y:0};function moving(event){target.style.left=event.clientX-from.x+"px";target.style.top=event.clientY-from.y+"px"}function restore(){target.style.top=target.style.left=null}function start(event){if(event.button===0){[from.x,from.y]=[event.clientX-(parseInt(target.style.left)||0),event.clientY-(parseInt(target.style.top)||0)];window.addEventListener("mousemove",moving,true)}}function end(){window.removeEventListener("mousemove",moving,true)}target.addEventListener("mousedown",start,false);window.addEventListener("mouseup",end,false);canvas.addEventListener("mouseleave",end,false)}scaling(target,type="scale"){function scroll(event){if(type==="scale"){let scale=(parseFloat(target.style.scale)||1)+event.deltaY/1000;if(scale<0.4){scale=0.4}else if(scale>3){scale=3}target.style.scale=scale}else if(type==="width"){const change=event.deltaY/2;const cut=target.parentElement.offsetWidth;const bounds={minimum:cut/2-cut,maximum:cut*2-cut};let zoom=(parseFloat(target.style.getPropertyValue("--width-zoom"))||0)+change;if(zoom<bounds.minimum){zoom=bounds.minimum}else if(zoom>bounds.maximum){zoom=bounds.maximum}else{target.style.left=(parseInt(target.style.left)||0)-change/2+"px";target.style.top=(parseInt(target.style.top)||0)-change/2+"px"}target.style.setProperty("--width-zoom",zoom+"px")}}target.addEventListener("wheel",scroll,false)}image(file){const identifier=this.#layers.entries.length??1;const layer=document.createElement("div");layer.classList.add("layer");layer.setAttribute("id","pechatalka_layer_"+identifier);const button_delete=document.createElement("button");button_delete.classList.add("delete","rounded");button_delete.addEventListener("click",(event)=>{layer.remove();this.#cost-=this.prices.pin.image??0;this.#result.querySelector(".cost").innerText=this.#cost});const trash=document.createElement("i");trash.classList.add("icon","trash");const image=document.createElement("img");image.classList.add("rounded");image.setAttribute("draggable",false);image.setAttribute("src",URL.createObjectURL(file));layer.appendChild(image);button_delete.appendChild(trash);layer.appendChild(button_delete);this.#canvas.appendChild(layer);this.#cost+=this.prices.pin.image??0;this.#result.querySelector(".cost").innerText=this.#cost;this.moving(layer);this.scaling(layer)}}
|
"use strict";export default class pechatalka{#wrap=document.getElementById("pechatalka");get wrap(){return this.#wrap}#canvas=document.getElementById("pechatalka")?.querySelector(".canvas");get canvas(){return this.#canvas}#result=document.getElementById("pechatalka")?.querySelector(".result");get result(){return this.#result}#layers=new Set();get layers(){return this.#layers}#preset=new Map();get preset(){return this.#preset}#cost=0;set cost(value){if(typeof value==="number"){const from=this.#cost;this.#cost=value;if(this.#cost<0){this.#cost=0}this.#events.get("cost")?.get("changed")(this.#cost,from)}}get cost(){return this.#cost}prices={pin:{image:150}};#events=new Map([["layers",new Map([["create",(layer)=>{}]])],["cost",new Map([["changed",(to,from)=>{}]])]]);get events(){return this.#events}constructor(wrap,canvas,result,preset,inject=false){if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.pechatalka=this}}if(canvas instanceof HTMLElement){this.#canvas=canvas}if(result instanceof HTMLElement){this.#result=result}if(preset instanceof Map){this.#preset=preset}}global(name,value=null,preset=false){if(typeof name==="string"){for(const layer of this.#layers){layer.set(name,value)}if(preset){this.#preset.set(name,value)}}}moving(layer){const from={x:0,y:0};function moving(event){layer.wrap.style.left=event.clientX-from.x+"px";layer.wrap.style.top=event.clientY-from.y+"px"}function restore(){layer.wrap.style.top=layer.wrap.style.left=null}function start(event){if(event.button===0){[from.x,from.y]=[event.clientX-(parseInt(layer.wrap.style.left)||0),event.clientY-(parseInt(layer.wrap.style.top)||0)];window.addEventListener("mousemove",moving,true)}}function end(){window.removeEventListener("mousemove",moving,true)}layer.wrap.addEventListener("mousedown",start,false);window.addEventListener("mouseup",end,false);this.#canvas.addEventListener("mouseleave",end,false)}scaling(layer,type="scale"){function scroll(event){if(type==="scale"){let scale=(parseFloat(layer.wrap.style.scale)||1)+event.deltaY/1000;if(scale<0.4){scale=0.4}else if(scale>3){scale=3}layer.wrap.style.scale=scale}else if(type==="width"){const change=event.deltaY/1.5;const cut=target.parentElement.offsetWidth;const bounds={minimum:cut/1.5-cut,maximum:cut*1.5-cut};let zoom=(parseFloat(layer.wrap.style.getPropertyValue("--width-zoom"))||0)+change;if(zoom<bounds.minimum){zoom=bounds.minimum}else if(zoom>bounds.maximum){zoom=bounds.maximum}else{layer.wrap.style.left=(parseInt(layer.wrap.style.left)||0)-change/2+"px";layer.wrap.style.top=(parseInt(layer.wrap.style.top)||0)-change/2+"px"}layer.wrap.style.setProperty("--width-zoom",zoom+"px")}}layer.wrap.addEventListener("wheel",scroll,false)}image(file,cost=0){const identifier=this.#layers.size+1;const wrap=document.createElement("div");wrap.classList.add("layer");wrap.setAttribute("id","pechatalka_layer_"+identifier);const button_delete=document.createElement("button");button_delete.classList.add("delete");const trash=document.createElement("i");trash.classList.add("icon","trash");const image=document.createElement("img");image.setAttribute("draggable",false);image.setAttribute("src",URL.createObjectURL(file));wrap.appendChild(image);button_delete.appendChild(trash);wrap.appendChild(button_delete);this.#canvas.appendChild(wrap);const instance=new layer("image",cost,wrap,image,{delete:button_delete},this.#preset,);this.#layers.add(instance);this.#events.get("layers")?.get("create")(instance);this.cost+=instance.cost;this.moving(instance);this.scaling(instance);button_delete.addEventListener("click",(event)=>{instance.wrap.remove();this.#layers.delete(instance);this.cost-=instance.cost})}}export class layer{#type;set type(value){const types=new Set(["image","film"]);if(types.has(value)){this.#type=value}}get type(){return this.#type}#cost=0;set cost(value){if(typeof value==="number"){const from=this.#cost;this.#cost=value;if(this.#cost<0){this.#cost=0}this.#events.get("cost")?.get("changed")(from,this.#cost)}}get cost(){return this.#cost}#wrap;get wrap(){return this.#wrap}#content;get content(){return this.#content}#buttons=new Map();get buttons(){return this.#buttons}#events=new Map([["cost",new Map([["changed",(to,from)=>{}]])]]);get events(){return this.#events}constructor(type,cost,wrap,content,buttons,preset,inject=false){this.type=type;if(typeof this.#type==="string"){this.cost=cost;if(wrap instanceof HTMLElement){this.#wrap=wrap;if(inject){this.#wrap.layer=this}}if(content instanceof HTMLElement){this.#content=content}if(buttons instanceof Object){for(const[name,element]of Object.entries(buttons)){this.#buttons.set(name,element)}}for(const[name,value]of preset.entries()){this[name]=value}}}set(name,value){const from=this[name];this[name]=value;this.#events.get(name)?.get("set")(this[name],from);return this[name]}toggle(name){this[name]=!this[name]??true;this.#events.get(name)?.get("toggle")(this[name]);return this[name]}}
|
||||||
|
565
pechatalka.mjs
565
pechatalka.mjs
@@ -107,18 +107,78 @@ export default class pechatalka {
|
|||||||
return this.#layers;
|
return this.#layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Preset
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Registry of parameters that will be write into created layers
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#preset = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Preset (get)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Registry of parameters that will be write into created layers
|
||||||
|
*
|
||||||
|
* @return {Map}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get preset() {
|
||||||
|
return this.#preset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Cost
|
* @name Cost
|
||||||
*
|
*
|
||||||
|
* @description
|
||||||
|
* The total cost
|
||||||
|
*
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*
|
*
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
#cost = 0;
|
#cost = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cost (set)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The total cost
|
||||||
|
*
|
||||||
|
* @return {number}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
set cost(value) {
|
||||||
|
if (typeof value === "number") {
|
||||||
|
// Validated the value
|
||||||
|
|
||||||
|
// Initializing the deprecated cost
|
||||||
|
const from = this.#cost;
|
||||||
|
|
||||||
|
// Writing the value
|
||||||
|
this.#cost = value;
|
||||||
|
|
||||||
|
// Filtering by the minimal value
|
||||||
|
if (this.#cost < 0) this.#cost = 0;
|
||||||
|
|
||||||
|
// Processing the `cost changed` event function
|
||||||
|
this.#events.get("cost")?.get("changed")(this.#cost, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Cost (get)
|
* @name Cost (get)
|
||||||
*
|
*
|
||||||
|
* @description
|
||||||
|
* The total cost
|
||||||
|
*
|
||||||
* @return {number}
|
* @return {number}
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
@@ -139,22 +199,46 @@ export default class pechatalka {
|
|||||||
*/
|
*/
|
||||||
prices = {
|
prices = {
|
||||||
pin: {
|
pin: {
|
||||||
image: 150
|
image: 150,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Events
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#events = new Map([
|
||||||
|
["layers", new Map([["create", (layer) => {}]])],
|
||||||
|
["cost", new Map([["changed", (to, from) => {}]])],
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Events (get)
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get events() {
|
||||||
|
return this.#events;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Constructor
|
* @name Constructor
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Initialize the instance
|
* Initialize the instance of Pechatalka
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} wrap The wrap element
|
* @param {HTMLElement} wrap The wrap element
|
||||||
* @param {HTMLElement} canvas The canvas element
|
* @param {HTMLElement} canvas The canvas element
|
||||||
* @param {HTMLElement} result The result element
|
* @param {HTMLElement} result The result element
|
||||||
|
* @param {(Map|null)} [preset=null] Preset parameters for layers
|
||||||
* @param {boolean} [inject=false] Write the instance into the wrap element?
|
* @param {boolean} [inject=false] Write the instance into the wrap element?
|
||||||
*/
|
*/
|
||||||
constructor(wrap, canvas, result, inject = false) {
|
constructor(wrap, canvas, result, preset, inject = false) {
|
||||||
if (wrap instanceof HTMLElement) {
|
if (wrap instanceof HTMLElement) {
|
||||||
// Initialized the wrap element
|
// Initialized the wrap element
|
||||||
|
|
||||||
@@ -178,20 +262,54 @@ export default class pechatalka {
|
|||||||
// Writing the result
|
// Writing the result
|
||||||
this.#result = result;
|
this.#result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preset instanceof Map) {
|
||||||
|
// Received the preset registry
|
||||||
|
|
||||||
|
// Writing the preset registry
|
||||||
|
this.#preset = preset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Global
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Write the parameter into all layers
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {(Object|string|number|boolean|null)} [value=null] Value of the parameter
|
||||||
|
* @param {boolean} [preset=false] Reinitialize the parameter in the preset registry?
|
||||||
|
*/
|
||||||
|
global(name, value = null, preset = false) {
|
||||||
|
if (typeof name === "string") {
|
||||||
|
// Received required arguments
|
||||||
|
|
||||||
|
for (const layer of this.#layers) {
|
||||||
|
// Iterating over layers
|
||||||
|
|
||||||
|
// Reinitializing the layer parameter
|
||||||
|
layer.set(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preset) {
|
||||||
|
// Requested to reinitialize the parameter in the preset registry
|
||||||
|
|
||||||
|
// Writing the parameter into the preset registry
|
||||||
|
this.#preset.set(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Moving
|
* @name Moving
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Add moving for the target
|
* Add moving for the layer
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} target
|
* @param {layer} layer
|
||||||
*/
|
*/
|
||||||
moving(target) {
|
moving(layer) {
|
||||||
// Initializing the link to the canvas
|
|
||||||
const canvas = this.#canvas;
|
|
||||||
|
|
||||||
// Initializing the start moving cursor coordinates buffer
|
// Initializing the start moving cursor coordinates buffer
|
||||||
const from = { x: 0, y: 0 };
|
const from = { x: 0, y: 0 };
|
||||||
|
|
||||||
@@ -200,10 +318,10 @@ export default class pechatalka {
|
|||||||
*/
|
*/
|
||||||
function moving(event) {
|
function moving(event) {
|
||||||
// Writing the X coordinate
|
// Writing the X coordinate
|
||||||
target.style.left = event.clientX - from.x + "px";
|
layer.wrap.style.left = event.clientX - from.x + "px";
|
||||||
|
|
||||||
// Writing the Y coordinate
|
// Writing the Y coordinate
|
||||||
target.style.top = event.clientY - from.y + "px";
|
layer.wrap.style.top = event.clientY - from.y + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,7 +329,7 @@ export default class pechatalka {
|
|||||||
*/
|
*/
|
||||||
function restore() {
|
function restore() {
|
||||||
// Restoring initial coordinates
|
// Restoring initial coordinates
|
||||||
target.style.top = target.style.left = null;
|
layer.wrap.style.top = layer.wrap.style.left = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,8 +341,8 @@ export default class pechatalka {
|
|||||||
|
|
||||||
// Writing the start moving cursor coordinates
|
// Writing the start moving cursor coordinates
|
||||||
[from.x, from.y] = [
|
[from.x, from.y] = [
|
||||||
event.clientX - (parseInt(target.style.left) || 0),
|
event.clientX - (parseInt(layer.wrap.style.left) || 0),
|
||||||
event.clientY - (parseInt(target.style.top) || 0)
|
event.clientY - (parseInt(layer.wrap.style.top) || 0),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Initializing the event listener
|
// Initializing the event listener
|
||||||
@@ -241,16 +359,16 @@ export default class pechatalka {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initializing event listeners
|
// Initializing event listeners
|
||||||
target.addEventListener("mousedown", start, false);
|
layer.wrap.addEventListener("mousedown", start, false);
|
||||||
window.addEventListener("mouseup", end, false);
|
window.addEventListener("mouseup", end, false);
|
||||||
canvas.addEventListener("mouseleave", end, false);
|
this.#canvas.addEventListener("mouseleave", end, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Scaling
|
* @name Scaling
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Add resizing for the target
|
* Add resizing for the layer
|
||||||
*
|
*
|
||||||
* 1. Resizing by changing the `scale` parameter disables the buttons visibility
|
* 1. Resizing by changing the `scale` parameter disables the buttons visibility
|
||||||
* outside the cut borders (`overflow: fixed` did not work)
|
* outside the cut borders (`overflow: fixed` did not work)
|
||||||
@@ -258,10 +376,10 @@ export default class pechatalka {
|
|||||||
* 2. Resizing by changing the `width` parameter has problems with boundaries,
|
* 2. Resizing by changing the `width` parameter has problems with boundaries,
|
||||||
* that is it has movement glitches
|
* that is it has movement glitches
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} target
|
* @param {layer} layer
|
||||||
* @param {string} [type='scale'] Type of scaling (scale, width)
|
* @param {string} [type='scale'] Type of scaling (scale, width)
|
||||||
*/
|
*/
|
||||||
scaling(target, type = "scale") {
|
scaling(layer, type = "scale") {
|
||||||
/**
|
/**
|
||||||
* @name Scroll
|
* @name Scroll
|
||||||
*/
|
*/
|
||||||
@@ -270,32 +388,34 @@ export default class pechatalka {
|
|||||||
// Scaling by changing scale
|
// Scaling by changing scale
|
||||||
|
|
||||||
// Initializing new scale
|
// Initializing new scale
|
||||||
let scale = (parseFloat(target.style.scale) || 1) + event.deltaY / 1000;
|
let scale = (parseFloat(layer.wrap.style.scale) || 1) +
|
||||||
|
event.deltaY / 1000;
|
||||||
|
|
||||||
// Normalization and protection against out of scale boundaries
|
// Normalization and protection against out of scale boundaries
|
||||||
if (scale < 0.4) scale = 0.4;
|
if (scale < 0.4) scale = 0.4;
|
||||||
else if (scale > 3) scale = 3;
|
else if (scale > 3) scale = 3;
|
||||||
|
|
||||||
// Writing the scale
|
// Writing the scale
|
||||||
target.style.scale = scale;
|
layer.wrap.style.scale = scale;
|
||||||
} else if (type === "width") {
|
} else if (type === "width") {
|
||||||
// Scaling by changing width
|
// Scaling by changing width
|
||||||
|
|
||||||
// Initializing the zoom changing value
|
// Initializing the zoom changing value
|
||||||
const change = event.deltaY / 2;
|
const change = event.deltaY / 1.5;
|
||||||
|
|
||||||
// Initializing width of the cut space
|
// Initializing width of the cut space
|
||||||
const cut = target.parentElement.offsetWidth;
|
const cut = target.parentElement.offsetWidth;
|
||||||
|
|
||||||
// Initializing bounds for zooming
|
// Initializing bounds for zooming
|
||||||
const bounds = {
|
const bounds = {
|
||||||
minimum: cut / 2 - cut,
|
minimum: cut / 1.5 - cut,
|
||||||
maximum: cut * 2 - cut
|
maximum: cut * 1.5 - cut,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initializing new scale
|
// Initializing new scale
|
||||||
let zoom =
|
let zoom =
|
||||||
(parseFloat(target.style.getPropertyValue("--width-zoom")) || 0) +
|
(parseFloat(layer.wrap.style.getPropertyValue("--width-zoom")) ||
|
||||||
|
0) +
|
||||||
change;
|
change;
|
||||||
|
|
||||||
if (zoom < bounds.minimum) zoom = bounds.minimum;
|
if (zoom < bounds.minimum) zoom = bounds.minimum;
|
||||||
@@ -304,53 +424,46 @@ export default class pechatalka {
|
|||||||
// The layer scale was changed
|
// The layer scale was changed
|
||||||
|
|
||||||
// Writing the X coordinate
|
// Writing the X coordinate
|
||||||
target.style.left =
|
layer.wrap.style.left = (parseInt(layer.wrap.style.left) || 0) -
|
||||||
(parseInt(target.style.left) || 0) - change / 2 + "px";
|
change / 2 +
|
||||||
|
"px";
|
||||||
|
|
||||||
// Writing the Y coordinate
|
// Writing the Y coordinate
|
||||||
target.style.top =
|
layer.wrap.style.top = (parseInt(layer.wrap.style.top) || 0) -
|
||||||
(parseInt(target.style.top) || 0) - change / 2 + "px";
|
change / 2 +
|
||||||
|
"px";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writing the scale
|
// Writing the scale
|
||||||
target.style.setProperty("--width-zoom", zoom + "px");
|
layer.wrap.style.setProperty("--width-zoom", zoom + "px");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializing the even listeners
|
// Initializing the even listeners
|
||||||
target.addEventListener("wheel", scroll, false);
|
layer.wrap.addEventListener("wheel", scroll, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Image
|
* @name Image
|
||||||
*
|
*
|
||||||
* @description
|
* @description
|
||||||
* Add the image into the canvas
|
* Generate and write the image into the canvas
|
||||||
*
|
*
|
||||||
* @param {File} file The file from input FileList
|
* @param {File} file The file from input FileList
|
||||||
|
* @param {number} [cost=0] The layer cost
|
||||||
*/
|
*/
|
||||||
image(file) {
|
image(file, cost = 0) {
|
||||||
// Initializing identifier
|
// Initializing identifier
|
||||||
const identifier = this.#layers.entries.length ?? 1;
|
const identifier = this.#layers.size + 1;
|
||||||
|
|
||||||
// Creating the layer <div> element
|
// Creating the layer wrap <div> element
|
||||||
const layer = document.createElement("div");
|
const wrap = document.createElement("div");
|
||||||
layer.classList.add("layer");
|
wrap.classList.add("layer");
|
||||||
layer.setAttribute("id", "pechatalka_layer_" + identifier);
|
wrap.setAttribute("id", "pechatalka_layer_" + identifier);
|
||||||
|
|
||||||
// Creating the button <button> element
|
// Creating the button <button> element
|
||||||
const button_delete = document.createElement("button");
|
const button_delete = document.createElement("button");
|
||||||
button_delete.classList.add("delete", "rounded");
|
button_delete.classList.add("delete");
|
||||||
button_delete.addEventListener("click", (event) => {
|
|
||||||
// Deleting the wrap
|
|
||||||
layer.remove();
|
|
||||||
|
|
||||||
// Removing from the total cost
|
|
||||||
this.#cost -= this.prices.pin.image ?? 0;
|
|
||||||
|
|
||||||
// Writing the total cost into the document
|
|
||||||
this.#result.querySelector(".cost").innerText = this.#cost;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Creating the trash icon <i> element
|
// Creating the trash icon <i> element
|
||||||
const trash = document.createElement("i");
|
const trash = document.createElement("i");
|
||||||
@@ -358,26 +471,358 @@ export default class pechatalka {
|
|||||||
|
|
||||||
// Creating the image <img> element
|
// Creating the image <img> element
|
||||||
const image = document.createElement("img");
|
const image = document.createElement("img");
|
||||||
image.classList.add("rounded");
|
|
||||||
image.setAttribute("draggable", false);
|
image.setAttribute("draggable", false);
|
||||||
image.setAttribute("src", URL.createObjectURL(file));
|
image.setAttribute("src", URL.createObjectURL(file));
|
||||||
|
|
||||||
// Writing into the gallery
|
// Writing into the gallery
|
||||||
layer.appendChild(image);
|
wrap.appendChild(image);
|
||||||
button_delete.appendChild(trash);
|
button_delete.appendChild(trash);
|
||||||
layer.appendChild(button_delete);
|
wrap.appendChild(button_delete);
|
||||||
this.#canvas.appendChild(layer);
|
this.#canvas.appendChild(wrap);
|
||||||
|
|
||||||
|
// Initializing the layer instance
|
||||||
|
const instance = new layer(
|
||||||
|
"image",
|
||||||
|
cost,
|
||||||
|
wrap,
|
||||||
|
image,
|
||||||
|
{
|
||||||
|
delete: button_delete,
|
||||||
|
},
|
||||||
|
this.#preset,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Writing into the layers registry
|
||||||
|
this.#layers.add(instance);
|
||||||
|
|
||||||
|
// Processing the `layer create` event function
|
||||||
|
this.#events.get("layers")?.get("create")(instance);
|
||||||
|
|
||||||
// Adding to the total cost
|
// Adding to the total cost
|
||||||
this.#cost += this.prices.pin.image ?? 0;
|
this.cost += instance.cost;
|
||||||
|
|
||||||
// Writing the total cost into the document
|
|
||||||
this.#result.querySelector(".cost").innerText = this.#cost;
|
|
||||||
|
|
||||||
// Adding moving for the layer
|
// Adding moving for the layer
|
||||||
this.moving(layer);
|
this.moving(instance);
|
||||||
|
|
||||||
// Adding scaling for the layer
|
// Adding scaling for the layer
|
||||||
this.scaling(layer);
|
this.scaling(instance);
|
||||||
|
|
||||||
|
// Initializing the event listener function
|
||||||
|
button_delete.addEventListener("click", (event) => {
|
||||||
|
// Deleting the layer root element
|
||||||
|
instance.wrap.remove();
|
||||||
|
|
||||||
|
// Deleting from the layer registry
|
||||||
|
this.#layers.delete(instance);
|
||||||
|
|
||||||
|
// Substraction from the total cost
|
||||||
|
this.cost -= instance.cost;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class layer {
|
||||||
|
/**
|
||||||
|
* @name Type
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layr type
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Type (set)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layr type
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
set type(value) {
|
||||||
|
// Initializing types of layers
|
||||||
|
const types = new Set(["image", "film"]);
|
||||||
|
|
||||||
|
// Writing the value
|
||||||
|
if (types.has(value)) this.#type = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Type (get)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layr type
|
||||||
|
*
|
||||||
|
* @return {string}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get type() {
|
||||||
|
// Exit (success)
|
||||||
|
return this.#type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cost
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layr cost
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#cost = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cost (set)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer cost
|
||||||
|
*
|
||||||
|
* @return {number}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
set cost(value) {
|
||||||
|
if (typeof value === "number") {
|
||||||
|
// Validated the value
|
||||||
|
|
||||||
|
// Initializing the deprecated cost
|
||||||
|
const from = this.#cost;
|
||||||
|
|
||||||
|
// Writing the value
|
||||||
|
this.#cost = value;
|
||||||
|
|
||||||
|
// Filtering by the minimal value
|
||||||
|
if (this.#cost < 0) this.#cost = 0;
|
||||||
|
|
||||||
|
// Processing the `cost changed` event function
|
||||||
|
this.#events.get("cost")?.get("changed")(from, this.#cost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cost (get)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer cost
|
||||||
|
*
|
||||||
|
* @return {number}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get cost() {
|
||||||
|
return this.#cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Wrap
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer root element
|
||||||
|
*
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#wrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Wrap (get)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer root element
|
||||||
|
*
|
||||||
|
* @return {HTMLElement}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get wrap() {
|
||||||
|
return this.#wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Content
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer target content element
|
||||||
|
*
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Content (get)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer target content element
|
||||||
|
*
|
||||||
|
* @return {HTMLElement}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get content() {
|
||||||
|
return this.#content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Buttons
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer buttons elements registry
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#buttons = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Buttons (get)
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* The layer buttons elements registry
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get buttons() {
|
||||||
|
return this.#buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Events
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#events = new Map([
|
||||||
|
["cost", new Map([["changed", (to, from) => {}]])],
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Events (get)
|
||||||
|
*
|
||||||
|
* @type {Map}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get events() {
|
||||||
|
return this.#events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Constructor
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Initialize the instance of the layer
|
||||||
|
*
|
||||||
|
* @param {string} type The layer type
|
||||||
|
* @param {number} cost The layer cost
|
||||||
|
* @param {HTMLElement} wrap The layer root element
|
||||||
|
* @param {HTMLElement} content The layer target content element
|
||||||
|
* @param {object} buttons The layer buttons elements
|
||||||
|
* @param {Map} preset Preset parameters
|
||||||
|
* @param {boolean} [inject=false] Write the instance into the element?
|
||||||
|
*/
|
||||||
|
constructor(type, cost, wrap, content, buttons, preset, inject = false) {
|
||||||
|
// Writing the layer type
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
if (typeof this.#type === "string") {
|
||||||
|
// Initialized the layer type
|
||||||
|
|
||||||
|
// Writing the layer cost
|
||||||
|
this.cost = cost;
|
||||||
|
|
||||||
|
if (wrap instanceof HTMLElement) {
|
||||||
|
// Received the layer root element
|
||||||
|
|
||||||
|
// Writing the layer root element
|
||||||
|
this.#wrap = wrap;
|
||||||
|
|
||||||
|
// Writing the instance into the layer root element
|
||||||
|
if (inject) this.#wrap.layer = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content instanceof HTMLElement) {
|
||||||
|
// Received the layer target content element
|
||||||
|
|
||||||
|
// Writing the layer target content element
|
||||||
|
this.#content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttons instanceof Object) {
|
||||||
|
// Received the layer buttons elements
|
||||||
|
|
||||||
|
for (const [name, element] of Object.entries(buttons)) {
|
||||||
|
// Iterating over the layers buttons elements
|
||||||
|
|
||||||
|
// Writing into the layer buttons registry
|
||||||
|
this.#buttons.set(name, element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [name, value] of preset.entries()) {
|
||||||
|
// Iterating over preset parameters
|
||||||
|
|
||||||
|
// Writing the parameter
|
||||||
|
this[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Set
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Set the parameter value
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
* @param {(Object|string|number|boolean|null)} value Value of the parameter
|
||||||
|
*
|
||||||
|
* @return {boolean} The new parameter value
|
||||||
|
*/
|
||||||
|
set(name, value) {
|
||||||
|
// Initializing the old parameter value
|
||||||
|
const from = this[name];
|
||||||
|
|
||||||
|
// Writing the value
|
||||||
|
this[name] = value;
|
||||||
|
|
||||||
|
// Processing the parameter `set` event function
|
||||||
|
this.#events.get(name)?.get("set")(this[name], from);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return this[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Toggle
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Toggle the parameter valu
|
||||||
|
*
|
||||||
|
* @param {string} name Name of the parameter
|
||||||
|
*
|
||||||
|
* @return {boolean} The new parameter value
|
||||||
|
*/
|
||||||
|
toggle(name) {
|
||||||
|
// Writing the value
|
||||||
|
this[name] = !this[name] ?? true;
|
||||||
|
|
||||||
|
// Processing the parameter `toggle` event function
|
||||||
|
this.#events.get(name)?.get("toggle")(this[name]);
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return this[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user