Created
October 2, 2020 20:33
-
-
Save scorredoira/b9a12db70a9c311b868ac87599632973 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace UI { | |
const subtitle = T("@@or drop a file to upload") | |
interface Position { | |
x: number | |
y: number | |
} | |
interface Bounds { | |
left: number | |
top: number | |
right: number | |
bottom: number | |
} | |
export class Imagedrop extends S.Control { | |
private subtitleRow: HTMLElement | |
private input: HTMLInputElement | |
private overlay: HTMLElement | |
private draggingElement: string | |
private mouseStart: Position | |
private startBounds: Bounds | |
private cropLayer: HTMLElement | |
private cropperBounds: Bounds | |
data: string | |
constructor() { | |
super(S.create("div", "ui-imagedrop")) | |
// this.data = DATA | |
// this.startCrop() | |
} | |
private addDropEvents(element: HTMLElement) { | |
element.addEventListener("dragover", e => this.onDragover(e)) | |
element.addEventListener("dragenter", e => this.onDragenter(e)) | |
element.addEventListener("dragleave", e => this.onDragleave(e)) | |
element.addEventListener("drop", e => this.onDrop(e)) | |
} | |
private _url: string; | |
public get url(): string { | |
return this._url; | |
} | |
public set url(v: string) { | |
this._url = v; | |
this.render() | |
} | |
render() { | |
if (this.building) { | |
return | |
} | |
if (!this.data && !this._url) { | |
this.renderEmpty() | |
return | |
} | |
// this.overlay = S.create("div", "overlay", this.element) | |
// this.overlay.style.backgroundImage = "url(" + this.data || this.url + ")" | |
} | |
private renderEmpty() { | |
this.clear() | |
this.element.classList.remove("crop") | |
this.element.classList.add("empty") | |
this.input = S.createInput("file", "inputFile", this.element) | |
this.input.accept = ".gif,.jpg,.jpeg,.png" | |
this.input.addEventListener("input", e => this.onFilePicked()) | |
this.addDropEvents(this.element) | |
let icon = getIcon("photo", 50, 50) | |
let row = S.create("div", "row", this.element, icon) | |
this.addDropEvents(row) | |
let button = new Button(T("@@Add file")) | |
button.click = () => this.input.click() | |
this.appendChild(button) | |
row = S.create("div", "row", this.element, button.element) | |
this.addDropEvents(row) | |
this.subtitleRow = S.create("div", "row subtitle", this.element, subtitle) | |
this.addDropEvents(this.subtitleRow) | |
} | |
private onDragover(e: DragEvent) { | |
e.preventDefault() | |
e.stopPropagation() | |
} | |
private onDragenter(e: DragEvent) { | |
e.preventDefault() | |
e.stopPropagation() | |
this.element.classList.add("dragover") | |
} | |
private onDragleave(e: DragEvent) { | |
e.preventDefault() | |
e.stopPropagation() | |
this.element.classList.remove("dragover") | |
} | |
private onDrop(e: DragEvent) { | |
// Prevent default behavior (Prevent file from being opened) | |
e.preventDefault() | |
e.stopPropagation() | |
this.element.classList.remove("dragover") | |
this.onFileSelected(e.dataTransfer.files[0]) | |
e.dataTransfer.clearData() | |
} | |
private onFilePicked() { | |
this.onFileSelected(this.input.files[0]) | |
this.input.files = null | |
} | |
private onFileSelected(f: File) { | |
const reader = new FileReader(); | |
reader.readAsDataURL(f) | |
reader.onload = () => { | |
this.data = reader.result.toString() | |
this.dispatchEvent(new CustomEvent("input", { detail: f })) | |
this.startCrop() | |
} | |
} | |
private startCrop() { | |
this.clear() | |
this.element.classList.add("crop") | |
this.element.classList.remove("empty") | |
let img = S.create("img", null, this.element) | |
img.addEventListener("load", () => this.showCropper()) | |
img.src = this.data | |
} | |
private showCropper() { | |
this.cropLayer = S.create("div", "cropLayer", this.element) | |
this.cropLayer.addEventListener("mouseup", () => this.stopDragging()) | |
//this.cropLayer.addEventListener("mouseleave", () => this.stopDragging()) | |
this.cropLayer.addEventListener("mousemove", e => this.onMouseMove(e)) | |
this.cropperBounds = { | |
left: 20, | |
right: 20, | |
top: 20, | |
bottom: 20 | |
} | |
this.adjustGrid() | |
let top = S.create("div", "cover", this.cropLayer) | |
top.style.gridColumn = "span 3" | |
S.create("div", "cover", this.cropLayer) | |
let cropper = S.create("div", "cropper", this.cropLayer) | |
S.create("div", "cover", this.cropLayer) | |
let bottom = S.create("div", "cover", this.cropLayer) | |
bottom.style.gridColumn = "span 3" | |
let leftTop = S.create("div", "handle leftTop", cropper) | |
let rightTop = S.create("div", "handle rightTop", cropper) | |
let leftBottom = S.create("div", "handle leftBottom", cropper) | |
let rightBottom = S.create("div", "handle rightBottom", cropper) | |
cropper.addEventListener("mousedown", e => this.startDragging(e, "cropper")) | |
leftTop.addEventListener("mousedown", e => this.startDragging(e, "leftTop")) | |
rightTop.addEventListener("mousedown", e => this.startDragging(e, "rightTop")) | |
leftBottom.addEventListener("mousedown", e => this.startDragging(e, "leftBottom")) | |
rightBottom.addEventListener("mousedown", e => this.startDragging(e, "rightBottom")) | |
} | |
private startDragging(e: MouseEvent, source: string) { | |
if (e.button != 0) { | |
return | |
} | |
e.stopPropagation() | |
this.draggingElement = source | |
this.mouseStart = { x: e.x, y: e.y } | |
this.startBounds = { | |
left: this.cropperBounds.left, | |
right: this.cropperBounds.right, | |
top: this.cropperBounds.top, | |
bottom: this.cropperBounds.bottom, | |
} | |
} | |
private stopDragging() { | |
this.mouseStart = null | |
this.startBounds = null | |
console.log(this.getCropBounds()) | |
} | |
private onMouseMove(e: MouseEvent) { | |
if (e.buttons != 1) { | |
// not clicked | |
return | |
} | |
let x = e.x - this.mouseStart.x | |
let y = e.y - this.mouseStart.y | |
let isCropper | |
switch (this.draggingElement) { | |
case "cropper": | |
isCropper = true | |
this.cropperBounds.left = this.startBounds.left + x | |
this.cropperBounds.right = this.startBounds.right - x | |
this.cropperBounds.top = this.startBounds.top + y | |
this.cropperBounds.bottom = this.startBounds.bottom - y | |
break | |
case "leftTop": | |
this.cropperBounds.left = this.startBounds.left + x | |
this.cropperBounds.top = this.startBounds.top + y | |
break | |
case "leftBottom": | |
this.cropperBounds.left = this.startBounds.left + x | |
this.cropperBounds.bottom = this.startBounds.bottom - y | |
break | |
case "rightTop": | |
this.cropperBounds.right = this.startBounds.right - x | |
this.cropperBounds.top = this.startBounds.top + y | |
break | |
case "rightBottom": | |
this.cropperBounds.right = this.startBounds.right - x | |
this.cropperBounds.bottom = this.startBounds.bottom - y | |
break | |
} | |
if (x < 0) { | |
if (this.cropperBounds.left < 0) { | |
this.cropperBounds.left = 0 | |
if (isCropper) { | |
this.cropperBounds.right = this.startBounds.left + this.startBounds.right | |
} | |
} | |
} else if (x > 0) { | |
if (this.cropperBounds.right < 0) { | |
this.cropperBounds.right = 0 | |
if (isCropper) { | |
this.cropperBounds.left = this.startBounds.left + this.startBounds.right | |
} | |
} | |
} | |
if (y < 0) { | |
if (this.cropperBounds.top < 0) { | |
this.cropperBounds.top = 0 | |
if (isCropper) { | |
this.cropperBounds.bottom = this.startBounds.top + this.startBounds.bottom | |
} | |
} | |
} | |
if (y > 0) { | |
if (this.cropperBounds.bottom < 0) { | |
this.cropperBounds.bottom = 0 | |
if (isCropper) { | |
this.cropperBounds.top = this.startBounds.top + this.startBounds.bottom | |
} | |
} | |
} | |
this.adjustGrid() | |
} | |
private adjustGrid() { | |
let b = this.cropperBounds | |
this.cropLayer.style.gridTemplateColumns = b.left + "px auto " + b.right + "px" | |
this.cropLayer.style.gridTemplateRows = b.top + "px auto " + b.bottom + "px" | |
} | |
private getCropBounds() { | |
let width = this.element.offsetWidth | |
let height = this.element.offsetHeight | |
let b = this.cropperBounds | |
return { | |
left: b.left, | |
top: b.top, | |
right: width - b.right, | |
bottom: height - b.bottom | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment