added pechatalka
This commit is contained in:
parent
62bfb5d569
commit
1bec4218b2
|
@ -0,0 +1,377 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name pechatalka.mjs
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Module with merch and print constructor for typrographies
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
* @public
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* import gallery from "https://codepen.io/mirzaev-sexy/pen/GgJbmQz.js";
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* {@link https://git.svoboda.works/mirzaev/pechatalka.mjs}
|
||||||
|
* {@link https://codepen.io/mirzaev-sexy/pen/GgJbmQz}
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @license http://www.wtfpl.net/ Do What The Fuck You Want To Public License
|
||||||
|
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||||||
|
*/
|
||||||
|
export default class pechatalka {
|
||||||
|
/**
|
||||||
|
* @name Wrap
|
||||||
|
*
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#wrap = document.getElementById("pechatalka");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Wrap (get)
|
||||||
|
*
|
||||||
|
* @return {HTMLElement}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get wrap() {
|
||||||
|
return this.#wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Canvas
|
||||||
|
*
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#canvas = document.getElementById("pechatalka")?.querySelector(".canvas");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Canvas (get)
|
||||||
|
*
|
||||||
|
* @return {HTMLElement}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get canvas() {
|
||||||
|
return this.#canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Result
|
||||||
|
*
|
||||||
|
* @type {HTMLElement}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#result = document.getElementById("pechatalka")?.querySelector(".result");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Result (get)
|
||||||
|
*
|
||||||
|
* @return {HTMLElement}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get result() {
|
||||||
|
return this.#result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Layers
|
||||||
|
*
|
||||||
|
* @type {Set}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#layers = new Set();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Layers (get)
|
||||||
|
*
|
||||||
|
* @return {Set}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get layers() {
|
||||||
|
return this.#layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cost
|
||||||
|
*
|
||||||
|
* @type {number}
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
#cost = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Cost (get)
|
||||||
|
*
|
||||||
|
* @return {number}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
get cost() {
|
||||||
|
return this.#cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Prices
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Prices for calculating the total cost
|
||||||
|
*
|
||||||
|
* @return {object}
|
||||||
|
*
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
prices = {
|
||||||
|
pin: {
|
||||||
|
image: 150
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Constructor
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Initialize the instance
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} wrap The wrap element
|
||||||
|
* @param {HTMLElement} canvas The canvas element
|
||||||
|
* @param {HTMLElement} result The result element
|
||||||
|
* @param {boolean} [inject=false] Write the instance into the wrap element?
|
||||||
|
*/
|
||||||
|
constructor(wrap, canvas, result, inject = false) {
|
||||||
|
if (wrap instanceof HTMLElement) {
|
||||||
|
// Initialized the wrap element
|
||||||
|
|
||||||
|
// Writing the wrap
|
||||||
|
this.#wrap = wrap;
|
||||||
|
|
||||||
|
// Writing the instance into the wrap element
|
||||||
|
if (inject) this.#wrap.pechatalka = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canvas instanceof HTMLElement) {
|
||||||
|
// Initialized the canvas element
|
||||||
|
|
||||||
|
// Writing the canvas
|
||||||
|
this.#canvas = canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result instanceof HTMLElement) {
|
||||||
|
// Initialized the result element
|
||||||
|
|
||||||
|
// Writing the result
|
||||||
|
this.#result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Moving
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Add moving for the target
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
moving(target) {
|
||||||
|
// Initializing the link to the canvas
|
||||||
|
const canvas = this.#canvas;
|
||||||
|
|
||||||
|
// Initializing the start moving cursor coordinates buffer
|
||||||
|
const from = { x: 0, y: 0 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Moving
|
||||||
|
*/
|
||||||
|
function moving(event) {
|
||||||
|
// Writing the X coordinate
|
||||||
|
target.style.left = event.clientX - from.x + "px";
|
||||||
|
|
||||||
|
// Writing the Y coordinate
|
||||||
|
target.style.top = event.clientY - from.y + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Restore
|
||||||
|
*/
|
||||||
|
function restore() {
|
||||||
|
// Restoring initial coordinates
|
||||||
|
target.style.top = target.style.left = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Start
|
||||||
|
*/
|
||||||
|
function start(event) {
|
||||||
|
if (event.button === 0) {
|
||||||
|
// Pressed the main mouse button (left by default)
|
||||||
|
|
||||||
|
// Writing the start moving cursor coordinates
|
||||||
|
[from.x, from.y] = [
|
||||||
|
event.clientX - (parseInt(target.style.left) || 0),
|
||||||
|
event.clientY - (parseInt(target.style.top) || 0)
|
||||||
|
];
|
||||||
|
|
||||||
|
// Initializing the event listener
|
||||||
|
window.addEventListener("mousemove", moving, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name End
|
||||||
|
*/
|
||||||
|
function end() {
|
||||||
|
// Initializing the event listener
|
||||||
|
window.removeEventListener("mousemove", moving, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializing event listeners
|
||||||
|
target.addEventListener("mousedown", start, false);
|
||||||
|
window.addEventListener("mouseup", end, false);
|
||||||
|
canvas.addEventListener("mouseleave", end, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Scaling
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Add resizing for the target
|
||||||
|
*
|
||||||
|
* 1. Resizing by changing the `scale` parameter disables the buttons visibility
|
||||||
|
* outside the cut borders (`overflow: fixed` did not work)
|
||||||
|
*
|
||||||
|
* 2. Resizing by changing the `width` parameter has problems with boundaries,
|
||||||
|
* that is it has movement glitches
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
* @param {string} [type='scale'] Type of scaling (scale, width)
|
||||||
|
*/
|
||||||
|
scaling(target, type = "scale") {
|
||||||
|
/**
|
||||||
|
* @name Scroll
|
||||||
|
*/
|
||||||
|
function scroll(event) {
|
||||||
|
if (type === "scale") {
|
||||||
|
// Scaling by changing scale
|
||||||
|
|
||||||
|
// Initializing new scale
|
||||||
|
let scale = (parseFloat(target.style.scale) || 1) + event.deltaY / 1000;
|
||||||
|
|
||||||
|
// Normalization and protection against out of scale boundaries
|
||||||
|
if (scale < 0.4) scale = 0.4;
|
||||||
|
else if (scale > 3) scale = 3;
|
||||||
|
|
||||||
|
// Writing the scale
|
||||||
|
target.style.scale = scale;
|
||||||
|
} else if (type === "width") {
|
||||||
|
// Scaling by changing width
|
||||||
|
|
||||||
|
// Initializing the zoom changing value
|
||||||
|
const change = event.deltaY / 2;
|
||||||
|
|
||||||
|
// Initializing width of the cut space
|
||||||
|
const cut = target.parentElement.offsetWidth;
|
||||||
|
|
||||||
|
// Initializing bounds for zooming
|
||||||
|
const bounds = {
|
||||||
|
minimum: cut / 2 - cut,
|
||||||
|
maximum: cut * 2 - cut
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initializing new scale
|
||||||
|
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 {
|
||||||
|
// The layer scale was changed
|
||||||
|
|
||||||
|
// Writing the X coordinate
|
||||||
|
target.style.left =
|
||||||
|
(parseInt(target.style.left) || 0) - change / 2 + "px";
|
||||||
|
|
||||||
|
// Writing the Y coordinate
|
||||||
|
target.style.top =
|
||||||
|
(parseInt(target.style.top) || 0) - change / 2 + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writing the scale
|
||||||
|
target.style.setProperty("--width-zoom", zoom + "px");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initializing the even listeners
|
||||||
|
target.addEventListener("wheel", scroll, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Image
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* Add the image into the canvas
|
||||||
|
*
|
||||||
|
* @param {File} file The file from input FileList
|
||||||
|
*/
|
||||||
|
image(file) {
|
||||||
|
// Initializing identifier
|
||||||
|
const identifier = this.#layers.entries.length ?? 1;
|
||||||
|
|
||||||
|
// Creating the layer <div> element
|
||||||
|
const layer = document.createElement("div");
|
||||||
|
layer.classList.add("layer");
|
||||||
|
layer.setAttribute("id", "pechatalka_layer_" + identifier);
|
||||||
|
|
||||||
|
// Creating the button <button> element
|
||||||
|
const button_delete = document.createElement("button");
|
||||||
|
button_delete.classList.add("delete", "rounded");
|
||||||
|
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
|
||||||
|
const trash = document.createElement("i");
|
||||||
|
trash.classList.add("icon", "trash");
|
||||||
|
|
||||||
|
// Creating the image <img> element
|
||||||
|
const image = document.createElement("img");
|
||||||
|
image.classList.add("rounded");
|
||||||
|
image.setAttribute("draggable", false);
|
||||||
|
image.setAttribute("src", URL.createObjectURL(file));
|
||||||
|
|
||||||
|
// Writing into the gallery
|
||||||
|
layer.appendChild(image);
|
||||||
|
button_delete.appendChild(trash);
|
||||||
|
layer.appendChild(button_delete);
|
||||||
|
this.#canvas.appendChild(layer);
|
||||||
|
|
||||||
|
// Adding to the total cost
|
||||||
|
this.#cost += this.prices.pin.image ?? 0;
|
||||||
|
|
||||||
|
// Writing the total cost into the document
|
||||||
|
this.#result.querySelector(".cost").innerText = this.#cost;
|
||||||
|
|
||||||
|
// Adding moving for the layer
|
||||||
|
this.moving(layer);
|
||||||
|
|
||||||
|
// Adding scaling for the layer
|
||||||
|
this.scaling(layer);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue