export class MuralProp { public computedOrigin: number[] public computedPosition: number[] public computedRatio: number public computedSize: number[] public element: HTMLElement public maxSize: Array public minSize: Array public origin: number[] public position: number[] public size: number[] constructor(element: HTMLElement, properties?: object) { this.initializeStates() this.setElement(element) if (typeof properties !== 'undefined') { this.setProperties(properties) } this.reset() return this } public setElement(element: HTMLElement): MuralProp { this.element = element return this } public setProperties(properties: object): MuralProp { for (let key in properties) { this[key] = properties[key] } return this } public initializeStates(): MuralProp { this.computedOrigin = [0, 0] this.computedPosition = [0, 0] this.computedSize = [0, 0] this.maxSize = [null, null] this.minSize = [null, null] this.origin = [0, 0] this.position = [0, 0] this.size = [0, 0] return this } public reset(): MuralProp { this.resize(this.size) this.moveTo(this.position) this.constrainSize() this.computeRatio() return this } public createNullElement(): MuralProp { this.element = document.createElement('DIV') this.element.style.position = 'fixed' this.element.style.zIndex = (-9999).toString() this.element.style.visibility = 'hidden' document.body.appendChild(this.element) return this } public computeOrigin(): MuralProp { let scale = this.getScaleFromOriginal() this.computedOrigin[0] = this.origin[0] * scale[0] this.computedOrigin[1] = this.origin[1] * scale[1] return this } public computeRatio(): MuralProp { let w: number = this.computedSize[0] === 0 ? 1 : this.computedSize[0] let h: number = this.computedSize[1] === 0 ? 1 : this.computedSize[1] this.computedRatio = w / h return this } public setOrigin(origin: number[]): MuralProp { this.origin[0] = origin[0] this.origin[1] = origin[1] return this } public setOriginPercentage(origin: number[]): MuralProp { this.origin[0] = origin[0] * this.size[0] this.origin[1] = origin[1] * this.size[1] return this } // Resize public resize(size: number[]): MuralProp { this.resizeWidth(size[0]) this.resizeHeight(size[1]) return this } public resizeHeight(height: number, constrainProportions: boolean = false): MuralProp { this.computedSize[1] = height if (constrainProportions === true) { this.computedSize[0] = this.computedRatio * this.computedSize[1] } return this } public resizeWidth(width, constrainProportions = false): MuralProp { this.computedSize[0] = width if (constrainProportions === true) { this.computedSize[1] = this.computedRatio * this.computedSize[0] } return this } // Constrain public constrainSize(): MuralProp { this.constrainWidth() this.constrainHeight() return this } public constrainHeight(): MuralProp { if ( typeof this.maxSize[1] === 'number' && this.computedSize[1] > this.maxSize[1] ) { this.computedSize[1] = this.maxSize[1] } if ( typeof this.minSize[1] === 'number' && this.computedSize[1] < this.minSize[1] ) { this.computedSize[1] = this.minSize[1] } return this } public constrainWidth(): MuralProp { if ( typeof this.maxSize[0] === 'number' && this.computedSize[0] > this.maxSize[0] ) { this.computedSize[0] = this.maxSize[0] } if ( typeof this.minSize[0] === 'number' && this.computedSize[0] < this.minSize[0] ) { this.computedSize[0] = this.minSize[0] } return this } public constrainProportionsByHeight() { this.computeRatio() this.computedSize[0] = this.computedSize[1] * this.computedRatio return this } public constrainProportionsByWidth() { this.computeRatio() this.computedSize[1] = this.computedSize[0] / this.computedRatio return this } // Scale public scale(scale) { this.scaleWidth(scale[0]) this.scaleHeight(scale[1]) return this } public scaleHeight(scale: number): MuralProp { this.computedSize[1] = this.computedSize[1] * scale return this } public scaleWidth(scale: number): MuralProp { this.computedSize[0] = this.computedSize[0] * scale return this } public scalePosition(scale: number[]): MuralProp { this.scalePositionX(scale[0]) this.scalePositionY(scale[1]) return this } public scalePositionX(scale: number): MuralProp { this.computedPosition[0] *= scale return this } public scalePositionY(scale: number): MuralProp { this.computedPosition[1] *= scale return this } // Translate public move(offset: number[]): MuralProp { this.moveX(offset[0]) this.moveY(offset[1]) return this } public moveX(x) { this.computedPosition[0] += x return this } public moveY(y) { this.computedPosition[1] += y return this } public moveTo(to: number[]) { this.moveXTo(to[0]) this.moveYTo(to[1]) return this } public moveXTo(x: number) { this.computedPosition[0] = x return this } public moveYTo(y: number) { this.computedPosition[1] = y return this } // Cover public cover(input) { let size = this.inputToSize(input) let newSize = [] if (this.computedSize[0] < size[0]) { newSize[0] = size[0] newSize[1] = newSize[0] / this.computedRatio } else if (this.computedSize[1] < size[1]) { newSize[1] = size[1] newSize[0] = this.computedRatio * newSize[1] } if (newSize[1] < size[1]) { newSize[1] = size[1] newSize[0] = this.computedRatio * newSize[1] } else if (newSize[0] < size[0]) { newSize[0] = size[0] newSize[1] = newSize[0] / this.computedRatio } this.resize(newSize) return this } public stretch(input) { let size = this.inputToSize(input) this.resize(size) return this } // Align public alignBottom(input) { let size = this.inputToSize(input) this.computedPosition[1] = size[1] - this.computedSize[1] return this } public alignCenter(input) { let size = this.inputToSize(input) let a = size[0] === 0 ? 0 : size[0] / 2 let b = this.computedSize[0] === 0 ? 0 : this.computedSize[0] / 2 this.computedPosition[0] = a - b a = size[1] === 0 ? 0 : size[1] / 2 b = this.computedSize[1] === 0 ? 0 : this.computedSize[1] / 2 this.computedPosition[1] = a - b return this } public alignHorizontalCenter(input) { let size = this.inputToSize(input) let a = size[0] === 0 ? 0 : size[0] / 2 let b = this.computedSize[0] === 0 ? 0 : this.computedSize[0] / 2 this.computedPosition[0] = a - b return this } public alignLeft() { this.computedPosition[0] = 0 return this } public alignRight(input) { let size = this.inputToSize(input) this.computedPosition[0] = size[0] - this.computedSize[0] } public alignTop(input) { this.computedPosition[1] = 0 return this } public alignVerticalCenter(input) { let size = this.inputToSize(input) let a = size[1] === 0 ? 0 : size[1] / 2 let b = this.computedSize[1] === 0 ? 0 : this.computedSize[1] / 2 this.computedPosition[0] = a - b return this } public getScaleFromOriginal() { let a = this.computedSize[0] === 0 ? 1 : this.computedSize[0] let b = this.size[0] === 0 ? 1 : this.size[0] let x = a / b a = this.computedSize[1] === 0 ? 1 : this.computedSize[1] b = this.size[1] === 0 ? 1 : this.size[1] let y = a / b return [x, y] } public inputToSize(input) { let size = typeof input && input.nodeType === 1 ? [input.offsetWidth, input.offsetHeight] : input return size } public draw() { this.computeOrigin() this.element.style.left = `${this.computedPosition[0] - this.computedOrigin[0]}px` this.element.style.top = `${this.computedPosition[1] - this.computedOrigin[0]}px` this.element.style.width = `${this.computedSize[0]}px` this.element.style.height = `${this.computedSize[1]}px` return this } public remove() { let styleProperties = ['left', 'top', 'width', 'height'] for (let styleProperty of styleProperties) { this.element.style[styleProperty] = null } return this } }