UNPKG

ng-fancy-gui

Version:

This package contains components, for creating userinterfaces in a Angular app.

1,037 lines (1,024 loc) 89.5 kB
import { __decorate } from 'tslib'; import { ɵɵdefineInjectable, Injectable, ElementRef, Input, ViewChild, HostListener, Component, forwardRef, EventEmitter, ChangeDetectorRef, Output, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { DomSanitizer } from '@angular/platform-browser'; import { HttpClient, HttpClientModule } from '@angular/common/http'; class ImageCropperConfig { constructor(width, height, rasterLevels) { this.width = width; this.height = height; this.rasterLevels = rasterLevels; } } var AutCompleteSource; (function (AutCompleteSource) { AutCompleteSource[AutCompleteSource["Input"] = 0] = "Input"; AutCompleteSource[AutCompleteSource["ApiEndpoint"] = 1] = "ApiEndpoint"; })(AutCompleteSource || (AutCompleteSource = {})); var KeywordType; (function (KeywordType) { KeywordType[KeywordType["String"] = 0] = "String"; KeywordType[KeywordType["KeyValue"] = 1] = "KeyValue"; })(KeywordType || (KeywordType = {})); class KeywordPickerConfig { constructor(keywordType = KeywordType.String, autocompleteMode = false, autoCompleteSource = AutCompleteSource.Input, dataMapperFunction = null, autocompleteSourceUrl = null) { this.keywordType = keywordType; this.autocompleteMode = autocompleteMode; this.autoCompleteSource = autoCompleteSource; this.dataMapperFunction = dataMapperFunction; this.autocompleteSourceUrl = autocompleteSourceUrl; } } var AutoCompleteSourceType; (function (AutoCompleteSourceType) { AutoCompleteSourceType[AutoCompleteSourceType["IdValueArray"] = 0] = "IdValueArray"; AutoCompleteSourceType[AutoCompleteSourceType["StringArray"] = 1] = "StringArray"; AutoCompleteSourceType[AutoCompleteSourceType["Object"] = 2] = "Object"; })(AutoCompleteSourceType || (AutoCompleteSourceType = {})); let FileService = class FileService { constructor() { } getBase64(file) { return new Promise(resolve => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { resolve(reader.result); }; reader.onerror = (error) => { console.log('Error: ', error); }; }); } dataURLtoFile(dataurl, filename) { const arr = dataurl.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, { type: mime }); } getBinary(file) { return new Promise(resolve => { const reader = new FileReader(); reader.onloadend = () => { const data = reader.result.split(',')[1]; const binaryBlob = atob(data); resolve(binaryBlob); }; reader.readAsDataURL(file); }); } }; FileService.ɵprov = ɵɵdefineInjectable({ factory: function FileService_Factory() { return new FileService(); }, token: FileService, providedIn: "root" }); FileService = __decorate([ Injectable({ providedIn: 'root' }) ], FileService); var InputBetweenComponent_1; let InputBetweenComponent = InputBetweenComponent_1 = class InputBetweenComponent { constructor(elRef, sanitizer) { this.elRef = elRef; this.sanitizer = sanitizer; this.placeholder = ""; this.max = 100; this.min = 0; this.lockScroll = true; this.mouseDown = false; this.minValue = 0; this.maxValue = 0; this.value = null; this.maxTearMouseDown = false; this.minTearMouseDown = false; this.propagateChange = (_) => { }; } registerOnChange(fn) { this.propagateChange = fn; } registerOnTouched(fn) { } setDisabledState(isDisabled) { } writeValue(value) { if (value !== null) { this.minValue = Math.round(value[0]); this.maxValue = Math.round(value[1]); this.tearMinStyle = this.calcStyle(this.minValue); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); } } ngOnInit() { if (this.value === null) { this.minValue = Math.round(this.min + ((this.max - this.min) / 2)); this.maxValue = Math.round(this.min + ((this.max - this.min) / 2)); } this.tearMinStyle = this.calcStyle(this.minValue); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); this.elRef.nativeElement.ontouchstart = () => { this.disableScroll(); }; this.elRef.nativeElement.ontouchend = () => { this.enableScroll(); }; } resize() { this.tearMinStyle = this.calcStyle(this.minValue); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); } handleMouseLeave(event) { const rect = this.elRef.nativeElement.getBoundingClientRect(); if (event.clientX >= rect.width + rect.x && this.maxTearMouseDown) { this.maxValue = this.max; } if (event.clientX <= rect.x && this.minTearMouseDown) { this.minValue = this.min; } this.maxTearMouseDown = false; this.minTearMouseDown = false; this.calcStyle(this.value); this.tearMinStyle = this.calcStyle(this.minValue); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); } handleTouchEnd(event) { this.minTearMouseDown = false; this.maxTearMouseDown = false; this.calcStyle(this.value); this.tearMinStyle = this.calcStyle(this.minValue); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); } calcStyle(value) { const unit = (this.elRef.nativeElement.clientWidth / (this.max - this.min)); return this.sanitizer.bypassSecurityTrustStyle('translate(' + ((Math.abs(this.min) * unit) + (unit * value)) + 'px, ' + -150 + '%) rotate(-135deg) translate(35%, -35%)'); } calcSliderLineStyle() { const unit = (this.elRef.nativeElement.clientWidth / (this.max - this.min)); this.sliderLineWidthStyle = this.sanitizer.bypassSecurityTrustStyle(unit * (this.maxValue - this.minValue) + 'px'); this.sliderLineLeftStyle = this.sanitizer.bypassSecurityTrustStyle((Math.abs(this.min) * unit) + (unit * this.minValue) + 'px'); } disableScroll() { document.body.style.overflowY = 'hidden'; } enableScroll() { document.body.style.overflowY = 'scroll'; } tearMinDown() { this.tearMin.nativeElement.classList.add('active'); this.minTearMouseDown = true; } tearMaxDown() { this.tearMax.nativeElement.classList.add('active'); this.maxTearMouseDown = true; } processMouseEventTearMin(event) { this.calcMinValue(event.clientX); this.tearMinStyle = this.calcStyle(this.minValue); this.calcSliderLineStyle(); } processMouseEventTearMax(event) { this.calcMaxValue(event.clientX); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); } processMouseEvent(event) { if (this.minTearMouseDown) { this.processMouseEventTearMin(event); } if (this.maxTearMouseDown) { this.processMouseEventTearMax(event); } } processTouchEventTearMin(event) { this.calcMinValue(event.touches[0].clientX); this.tearMinStyle = this.calcStyle(this.minValue); this.calcSliderLineStyle(); } processTouchEventTearMax(event) { this.calcMaxValue(event.touches[0].clientX); this.tearMaxStyle = this.calcStyle(this.maxValue); this.calcSliderLineStyle(); } processTouchEvent(event) { const rect = this.elRef.nativeElement.getBoundingClientRect(); if (this.minTearMouseDown) { this.processTouchEventTearMin(event); } if (this.maxTearMouseDown) { this.processTouchEventTearMax(event); } if (event.changedTouches[0].clientX >= rect.width + rect.x && this.maxTearMouseDown) { this.maxValue = this.max; // console.log("right leave"); this.tearMaxStyle = this.calcStyle(this.maxValue); } if (event.changedTouches[0].clientX <= rect.x && this.minTearMouseDown) { //console.log("left leave"); this.minValue = this.min; this.tearMinStyle = this.calcStyle(this.minValue); } } calcMinValue(mouseX) { const rect = this.elRef.nativeElement.getBoundingClientRect(); const x = mouseX - rect.left; if (this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) > this.min && this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) < this.maxValue) { this.minValue = this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x); } if (this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) < this.min) { this.minValue = this.min; } /*if (Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) > this.maxValue) { this.minValue = this.maxValue; }*/ this.propagateChange([this.minValue, this.maxValue]); } calcMaxValue(mouseX) { const rect = this.elRef.nativeElement.getBoundingClientRect(); const x = mouseX - rect.left; if (this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) > this.minValue && this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) < this.max) { this.maxValue = this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x); } /*if (Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) < this.minValue) { this.maxValue = this.minValue; }*/ if (this.min + Math.round(((this.max - this.min) / (this.elRef.nativeElement.clientWidth)) * x) > this.max) { this.maxValue = this.max; } this.propagateChange([this.minValue, this.maxValue]); } }; InputBetweenComponent.ctorParameters = () => [ { type: ElementRef }, { type: DomSanitizer } ]; __decorate([ Input() ], InputBetweenComponent.prototype, "placeholder", void 0); __decorate([ Input() ], InputBetweenComponent.prototype, "max", void 0); __decorate([ Input() ], InputBetweenComponent.prototype, "min", void 0); __decorate([ ViewChild('tearMax') ], InputBetweenComponent.prototype, "tearMax", void 0); __decorate([ ViewChild('tearMin') ], InputBetweenComponent.prototype, "tearMin", void 0); __decorate([ HostListener('window:resize') ], InputBetweenComponent.prototype, "resize", null); InputBetweenComponent = InputBetweenComponent_1 = __decorate([ Component({ selector: 'fg-input-between', template: "<div class=\"inputWrap noselect\"\n (touchmove)=\"processTouchEvent($event)\"\n (mousemove)=\"processMouseEvent($event)\"\n (mouseleave)=\"tearMin.classList.remove('active');tearMax.classList.remove('active');handleMouseLeave($event)\"\n (mouseup)=\"tearMax.classList.remove('active');maxTearMouseDown=false;tearMin.classList.remove('active');minTearMouseDown=false;\"\n (touchend)=\"tearMin.classList.remove('active');tearMax.classList.remove('active');handleTouchEnd($event)\"\n>\n <div class=\"fakeInputRange\">\n <div #tearMin class=\"tear\" [style.transform]=\"tearMinStyle\"\n [class.up]=\"minValue> 0 && maxValue===max\"\n (mousedown)=\"tearMinDown()\"\n (touchstart)=\"tearMinDown()\"\n >\n <span>{{minValue}}</span>\n </div>\n\n <div #tearMax class=\"tear\" [style.transform]=\"tearMaxStyle\"\n (mousedown)=\"tearMaxDown()\"\n (touchstart)=\"tearMaxDown()\"\n >\n <span>{{maxValue}}</span>\n </div>\n\n <div class=\"sliderLine\">\n <div class=\"sliderBackground\"></div>\n <div [style.width]=\"sliderLineWidthStyle\" [style.left]=\"sliderLineLeftStyle\" class=\"sliderActive\"></div>\n </div>\n </div>\n</div>\n\n\n\n", providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputBetweenComponent_1), multi: true } ], styles: [":host{display:block;position:relative}:host *{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.up{z-index:10}span{display:block;font-size:22px}.inputWrap{padding-top:32px}.inputWrap .fakeInputRange{position:relative}.inputWrap .fakeInputRange .tear{position:absolute;transition:width .5s,height .5s;width:30px;height:30px;border-radius:0 50% 50%;border:3px solid;transform:rotate(-135deg)}.inputWrap .fakeInputRange .tear span{color:#fff;transition:left .5s,top .5s,font-size .5s;font-size:9px;position:absolute;left:11px;top:11px;transform:translate(-50%,-50%) rotate(-225deg)}.inputWrap .fakeInputRange .tear.active{z-index:7;width:50px;height:50px}.inputWrap .fakeInputRange .tear.active span{font-size:19px;left:20px;top:20px}.sliderLine{margin-top:20px;position:relative}.sliderLine .sliderBackground{width:100%;height:2px;background-color:gray}.sliderLine .sliderActive{position:absolute;height:2px;top:0;left:0}input{opacity:0;top:0;left:0;z-index:1;position:absolute;margin-top:7px;height:100%;font-size:21px;border:1px solid}input.invalid{border:1px solid}"] }) ], InputBetweenComponent); class CropImage { constructor(imageCroper, x, y, src) { this.imageCroper = imageCroper; this.x = x; this.y = y; this.src = src; this.loaded = false; this.rotation = 0; this.userInputRotation = 0; this.locked = false; this.minWidth = 0; this.minHeight = 0; this.repositioningSpeed = 1; this.moveing = false; this.orignalImage = new Image(); this.orignalImage.src = src; this.orignalImage.onload = () => { const fc = document.createElement('canvas'); const fctx = fc.getContext("2d"); const oc = document.createElement('canvas'); const octx = oc.getContext('2d'); //document.body.append(oc); //document.body.append(fc); if (this.orignalImage.width > this.orignalImage.height) { fc.width = (this.orignalImage.width / this.orignalImage.height) * this.imageCroper.config.height; fc.height = this.imageCroper.config.height; } else { fc.width = this.imageCroper.config.width; fc.height = (this.orignalImage.height / this.orignalImage.width) * this.imageCroper.config.width; } const steps = Math.ceil(Math.log(this.orignalImage.width / this.imageCroper.config.width) / Math.log(2)); //console.log(fc); // console.log(this.orignalImage.width, this.orignalImage.height); oc.width = this.orignalImage.width * 0.5; oc.height = this.orignalImage.height * 0.5; octx.drawImage(this.orignalImage, 0, 0, oc.width, oc.height); let factor = 1; for (let i = 0; i < steps - 3; i++) { octx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5); factor *= 0.5; } fctx.drawImage(oc, 0, 0, oc.width * factor, oc.height * factor, 0, 0, fctx.canvas.width, fctx.canvas.height); this.image = new Image(); this.image.src = fc.toDataURL(); this.image.onload = () => { console.log(this.image.width); this.originalWidth = this.image.width; this.originalHeight = this.image.height; this.width = this.originalWidth; this.height = this.originalHeight; this.coverCanvas(); this.loaded = true; }; }; } setMinSize() { if (this.userInputRotation === 0) { switch (this.rotation) { case 0: { if (this.originalWidth >= this.originalHeight) { this.setMinSizeByWidth(this.imageCroper.canvas.width); } if (this.originalHeight >= this.originalWidth) { this.setMinSizeByHeight(this.imageCroper.canvas.height); } break; } case -90: { if (this.originalWidth >= this.originalHeight) { this.setMinSizeByHeight(this.imageCroper.canvas.width); } if (this.originalHeight >= this.originalWidth) { this.setMinSizeByWidth(this.imageCroper.canvas.height); } break; } case -180: { if (this.originalWidth >= this.originalHeight) { this.setMinSizeByWidth(this.imageCroper.canvas.width); } if (this.originalHeight >= this.originalWidth) { this.setMinSizeByHeight(this.imageCroper.canvas.height); } break; } case -270: { if (this.originalWidth >= this.originalHeight) { this.setMinSizeByHeight(this.imageCroper.canvas.width); } if (this.originalHeight >= this.originalWidth) { this.setMinSizeByWidth(this.imageCroper.canvas.height); } break; } } if (this.minWidth < this.imageCroper.canvas.width || this.minHeight < this.imageCroper.canvas.height) { if (this.rotation === 0 || this.rotation === -180) { if (this.imageCroper.canvas.width > this.imageCroper.canvas.height) { this.setMinSizeByWidth(this.imageCroper.canvas.width); } else { this.setMinSizeByHeight(this.imageCroper.canvas.height); } } else { if (this.imageCroper.canvas.width > this.imageCroper.canvas.height) { this.setMinSizeByHeight(this.imageCroper.canvas.width); } else { this.setMinSizeByWidth(this.imageCroper.canvas.height); } } } } } drawImageToCanvas(ctx = this.imageCroper.ctx) { const x = (this.x / this.imageCroper.canvas.width) * ctx.canvas.width; const y = (this.y / this.imageCroper.canvas.height) * ctx.canvas.height; const width = (this.width / this.imageCroper.canvas.width) * ctx.canvas.width; const height = (this.height / this.imageCroper.canvas.height) * ctx.canvas.height; ctx.beginPath(); ctx.translate(x, y); ctx.rotate((Math.PI / 180) * (this.rotation + this.userInputRotation)); ctx.imageSmoothingEnabled = false; ctx.drawImage(this.orignalImage, -width * 0.5, -height * 0.5, width, height); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.closePath(); } render() { if (this.loaded) { this.drawImageToCanvas(); } } resize(factor) { const verhaeltinis = this.originalHeight / this.originalWidth; this.width = this.width * factor; this.height = verhaeltinis * this.width; this.coverCanvas(); } coverCanvas() { let overLeftBorder = false; let overRightBorder = false; let overTopBorder = false; let overBottomBorder = false; this.setMinSize(); if (this.minHeight > this.height || this.minWidth > this.width) { this.width = this.minWidth; this.height = this.minHeight; // console.log(`set min size ${this.width} ${this.height}`); } if (this.rotation === 0 || this.rotation === -180) { if (this.x - (this.width / 2) > 0) { // over left border this.x = (this.width / 2); overLeftBorder = true; } if (this.x + (this.width / 2) < this.imageCroper.canvas.width) { // over right border this.x = this.imageCroper.canvas.width - (this.width / 2); overRightBorder = true; } if (this.y - (this.height / 2) > 0) { // over top this.y = (this.height / 2); overTopBorder = true; } if (this.y + (this.height / 2) < this.imageCroper.canvas.height) { // bottom border this.y = this.imageCroper.canvas.height - (this.height / 2); overBottomBorder = true; } if (this.originalWidth < this.originalHeight) { if (overLeftBorder && overRightBorder) { this.x = (this.imageCroper.canvas.width / 2); this.resizeByWidth(this.imageCroper.canvas.width); if (overTopBorder) { this.y = (this.height / 2); } if (overBottomBorder) { this.y = this.imageCroper.canvas.height - (this.height / 2); } } } else { if (overTopBorder && overBottomBorder) { this.y = (this.imageCroper.canvas.height / 2); this.resizeByHeight(this.imageCroper.canvas.height); if (overLeftBorder) { this.x = (this.width / 2); } if (overRightBorder) { this.x = this.imageCroper.canvas.width - (this.width / 2); } } } } else if (this.rotation === -90 || this.rotation === -270) { if (this.x - (this.height / 2) > 0) { // over left border this.x = (this.height / 2); overLeftBorder = true; } if (this.x + (this.height / 2) < this.imageCroper.canvas.width) { // over right border this.x = this.imageCroper.canvas.width - (this.height / 2); overRightBorder = true; } if (this.y - (this.width / 2) > 0) { // over top this.y = (this.width / 2); overTopBorder = true; } if (this.y + (this.width / 2) < this.imageCroper.canvas.height) { // bottom border this.y = this.imageCroper.canvas.height - (this.width / 2); overBottomBorder = true; } if (this.originalWidth > this.originalHeight) { if (overTopBorder && overBottomBorder) { this.y = (this.imageCroper.canvas.height / 2); this.resizeByWidth(this.imageCroper.canvas.height); if (overLeftBorder) { this.x = (this.height / 2); } if (overRightBorder) { this.x = this.imageCroper.canvas.width - (this.height / 2); } } } else { if (overLeftBorder && overRightBorder) { this.x = (this.imageCroper.canvas.width / 2); this.resizeByHeight(this.imageCroper.canvas.width); if (overTopBorder) { this.y = (this.width / 2); } if (overBottomBorder) { this.y = this.imageCroper.canvas.height - (this.width / 2); } } } } // console.log("cover"); } resizeOriginalImage(factor) { const verhaeltinis = this.originalHeight / this.originalWidth; this.width = this.originalWidth * factor; this.height = verhaeltinis * this.width; } resetOriginalImage() { this.originalWidth = this.width; this.originalHeight = this.height; } resizeByDeltaHeight(delataHeight) { const verhaeltinis = this.originalWidth / this.originalHeight; this.height += delataHeight; this.width = this.height * verhaeltinis; } resizeByDeltaWidth(delataWidth) { const verhaeltinis = this.originalHeight / this.originalWidth; this.width += delataWidth; this.height = verhaeltinis * this.width; } resizeByWidth(width) { const verhaeltinis = this.originalHeight / this.originalWidth; this.width = width; this.height = verhaeltinis * width; } resizeByHeight(height) { const verhaeltinis = this.originalWidth / this.originalHeight; this.height = height; this.width = verhaeltinis * this.height; } setUserInputRotation(deg) { this.userInputRotation = deg; this.setMinSize(); } setMinSizeByWidth(newWidth) { //console.log("set new witdh: ", newWidth); const heightWidthRatio = this.originalHeight / this.originalWidth; this.minWidth = newWidth; this.minHeight = heightWidthRatio * this.minWidth; } setMinSizeByHeight(newHeight) { //console.log("set new height : ", newHeight); const widthHeightRatio = this.originalWidth / this.originalHeight; this.minHeight = newHeight; this.minWidth = widthHeightRatio * this.minHeight; } } class GestureHandler { constructor(imageCroper) { this.imageCroper = imageCroper; this.imageCroper.canvas.onmousemove = (evt) => { this.handleMove(evt); }; this.imageCroper.canvas.ontouchmove = (evt) => { evt.preventDefault(); this.handleTouch(evt); }; this.imageCroper.canvas.onwheel = (evt) => { event.preventDefault(); if (evt.deltaY < 0) { this.imageCroper.cropImage.resize(1.1); } else { if (!this.imageCroper.cropImage.locked) { this.imageCroper.cropImage.resize(0.9); } } }; } handleMove(evt) { //console.log("move"); const halfImageWidth = this.imageCroper.cropImage.width * 0.5; const halfImageHeight = this.imageCroper.cropImage.height * 0.5; const newImageX = this.imageCroper.cropImage.x + this.imageCroper.mouse.x - this.imageCroper.mouse.lastX; const newImageY = this.imageCroper.cropImage.y + this.imageCroper.mouse.y - this.imageCroper.mouse.lastY; const mouseXdiff = this.imageCroper.mouse.x - this.imageCroper.mouse.lastX; const mouseYdiff = this.imageCroper.mouse.y - this.imageCroper.mouse.lastY; if (this.imageCroper.mouse.isDown && !this.imageCroper.cropImage.locked) { if ((this.imageCroper.cropImage.rotation === 0 || this.imageCroper.cropImage.rotation === -180) && this.imageCroper.cropImage.userInputRotation === 0) { // with, height is default if ((newImageX - halfImageWidth <= 0 && newImageX + halfImageWidth >= this.imageCroper.canvas.width) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.x += mouseXdiff; } if ((newImageY + halfImageHeight >= this.imageCroper.canvas.height && newImageY - halfImageHeight <= 0) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.y += mouseYdiff; } } else { // with, height is switched if ((newImageX - halfImageHeight <= 0 && newImageX + halfImageHeight >= this.imageCroper.canvas.width) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.x += mouseXdiff; } if ((newImageY + halfImageWidth >= this.imageCroper.canvas.height && (newImageY - halfImageWidth) <= 0) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.y += mouseYdiff; } } } this.imageCroper.mouse.syncPosition(evt); } handleTouch(evt) { const halfImageWidth = this.imageCroper.cropImage.width * 0.5; const halfImageHeight = this.imageCroper.cropImage.height * 0.5; const newImageX = this.imageCroper.cropImage.x + this.imageCroper.mouse.x - this.imageCroper.mouse.lastX; const newImageY = this.imageCroper.cropImage.y + this.imageCroper.mouse.y - this.imageCroper.mouse.lastY; const mouseXdiff = this.imageCroper.mouse.x - this.imageCroper.mouse.lastX; const mouseYdiff = this.imageCroper.mouse.y - this.imageCroper.mouse.lastY; if (this.imageCroper.mouse.isDown && !this.imageCroper.cropImage.locked) { if ((this.imageCroper.cropImage.rotation === 0 || this.imageCroper.cropImage.rotation === -180) && this.imageCroper.cropImage.userInputRotation === 0) { // with, height is default if ((newImageX - halfImageWidth <= 0 && newImageX + halfImageWidth >= this.imageCroper.canvas.width) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.x += mouseXdiff; } if ((newImageY + halfImageHeight >= this.imageCroper.canvas.height && newImageY - halfImageHeight <= 0) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.y += mouseYdiff; } } else { // with, height is switched if ((newImageX - halfImageHeight <= 0 && newImageX + halfImageHeight >= this.imageCroper.canvas.width) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.x += mouseXdiff; } if ((newImageY + halfImageWidth >= this.imageCroper.canvas.height && (newImageY - halfImageWidth) <= 0) || this.imageCroper.cropImage.userInputRotation !== 0) { this.imageCroper.cropImage.y += mouseYdiff; } } } this.imageCroper.mouse.syncTouchPosition(evt); } } class Mouse { constructor(imageCroper) { this.imageCroper = imageCroper; this.pinching = false; this.lastX = 0; this.lastY = 0; this.isDown = false; this.imageCroper.canvas.style.cursor = 'grab'; this.imageCroper.canvas.onmousedown = (evt) => { this.imageCroper.canvas.style.cursor = 'grabbing'; this.syncPosition(evt); this.lastY = this.y; this.lastX = this.x; this.isDown = true; this.imageCroper.cropImage.moveing = true; }; this.imageCroper.canvas.onmouseup = () => { this.imageCroper.canvas.style.cursor = 'grab'; this.isDown = false; }; this.imageCroper.canvas.ontouchstart = (evt) => { this.imageCroper.canvas.style.cursor = 'grabbing'; this.syncTouchPosition(evt); this.lastY = this.y; this.lastX = this.x; this.isDown = true; this.imageCroper.cropImage.moveing = true; }; this.imageCroper.canvas.ontouchend = () => { this.imageCroper.canvas.style.cursor = 'grab'; this.isDown = false; }; } syncPosition(evt) { const rect = this.imageCroper.canvas.getBoundingClientRect(); this.lastX = this.x; this.lastY = this.y; this.x = evt.clientX - rect.left; this.y = ((evt.clientY - rect.top)); } syncTouchPosition(evt) { const rect = this.imageCroper.canvas.getBoundingClientRect(); this.lastX = this.x; this.lastY = this.y; this.x = evt.touches[0].clientX - rect.left; this.y = ((evt.touches[0].clientY - rect.top)); } } class ImageCroper { constructor(canvas, offscreenCanvas, width, height, imageSrc, config) { this.canvas = canvas; this.offscreenCanvas = offscreenCanvas; this.width = width; this.height = height; this.config = config; this.raster = false; this.rasterLevelIndex = 0; this.ctx = this.setupCanvas(this.canvas); this.offscreenCtx = this.setupCanvas(this.offscreenCanvas); this.canvas.width = config.width; this.canvas.height = config.height; this.offscreenCanvas.width = config.width; this.offscreenCanvas.height = config.height; this.imageHeightWidthRatio = this.config.height / this.config.width; this.imageWidthHeightRatio = this.config.width / this.config.height; this.setCanvasSize(); this.cropImage = new CropImage(this, this.canvas.width / 2, this.canvas.height / 2, imageSrc); this.gestureHandler = new GestureHandler(this); this.mouse = new Mouse(this); this.cropImage.coverCanvas(); } resize() { //console.log("resize imagecropper"); const toSmall = this.setCanvasSize(); this.cropImage.coverCanvas(); return toSmall; } clear() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); } render() { this.clear(); this.cropImage.render(); if (this.raster) { let strecke = this.canvas.height / this.config.rasterLevels[this.rasterLevelIndex]; let streckeT = 0; for (let i = 0; i <= this.config.rasterLevels[this.rasterLevelIndex]; i++) { this.ctx.beginPath(); this.ctx.moveTo(0, streckeT); this.ctx.lineTo(this.canvas.width, streckeT); this.ctx.strokeStyle = 'white'; this.ctx.stroke(); this.ctx.closePath(); streckeT += strecke; } strecke = this.canvas.width / this.config.rasterLevels[this.rasterLevelIndex]; streckeT = 0; for (let i = 0; i <= this.config.rasterLevels[this.rasterLevelIndex]; i++) { this.ctx.beginPath(); this.ctx.moveTo(streckeT, 0); this.ctx.lineTo(streckeT, this.canvas.height); this.ctx.strokeStyle = 'white'; this.ctx.stroke(); this.ctx.closePath(); streckeT += strecke; } } } rotateImage(deg) { this.cropImage.rotation = deg; } switchRasterLevelIndex() { if (this.raster) { if (this.rasterLevelIndex + 1 < this.config.rasterLevels.length) { this.rasterLevelIndex++; } else { this.raster = false; } } else { this.rasterLevelIndex = 0; this.raster = true; } } setupCanvas(canvas) { // Get the device pixel ratio, falling back to 1. const dpr = window.devicePixelRatio || 1; // Get the size of the canvas in CSS pixels. const rect = canvas.getBoundingClientRect(); // Give the canvas pixel dimensions of their CSS // size * the device pixel ratio. canvas.width = rect.width * dpr; canvas.height = rect.height * dpr; const ctx = canvas.getContext('2d'); // Scale all drawing operations by the dpr, so you // don't have to worry about the difference. ctx.scale(dpr, dpr); return ctx; } setCanvasSize() { this.canvas.width = this.canvas.parentElement.clientWidth; this.canvas.height = this.canvas.width * this.imageHeightWidthRatio; this.offscreenCanvas.width = this.width; this.offscreenCanvas.height = this.height; const reducedCanvasHeight = (this.canvas.parentElement.parentElement.clientHeight - 350); if (reducedCanvasHeight < 0) { return true; } if (this.canvas.height > reducedCanvasHeight && this.canvas.width < this.config.width && this.canvas.height < this.config.height) { this.canvas.height = reducedCanvasHeight; this.canvas.width = this.canvas.height * this.imageWidthHeightRatio; } else { this.canvas.width = this.config.width; this.canvas.height = this.config.height; } return false; } } let ImageCropperComponent = class ImageCropperComponent { constructor(cdRef) { this.cdRef = cdRef; this.imageSrc = null; this.config = null; this.continue = new EventEmitter(); this.cancle = new EventEmitter(); this.toSmall = false; this.animationFrameHandler = null; } ngAfterViewInit() { if (this.imageSrc === null) { throw new Error("Ng Fancy GUI: No imagesrc was passed in to the imagecropper component"); } if (this.config === null) { this.config = new ImageCropperConfig(500, 500, [4, 8, 16]); } if (this.config instanceof ImageCropperConfig) { this.imageCroper = new ImageCroper(this.cropperCanvas.nativeElement, this.offscreenCanvas.nativeElement, this.config.width, this.config.height, this.imageSrc, this.config); console.log("immageCropper:", this.imageCroper); this.startLoop(); this.resize(); this.cdRef.detectChanges(); } else { throw new Error("Ng Fancy GUI: Config passed in to imagecropper was not of type ImageCropperConfig"); } } zoom(x) { if (x > 0) { this.imageCroper.cropImage.resize(1.01); } else if (x < 0) { this.imageCroper.cropImage.resize(0.99); } } startLoop() { const step = () => { this.imageCroper.render(); this.animationFrameHandler = window.requestAnimationFrame(step); //console.log("render"); }; this.animationFrameHandler = window.requestAnimationFrame(step); } resize() { this.toSmall = this.imageCroper.resize(); } ngOnDestroy() { window.cancelAnimationFrame(this.animationFrameHandler); //console.log("destroy"); } pinch(event) { this.pinchEvent = event; this.imageCroper.cropImage.resizeOriginalImage(event.scale); } pinchEnd() { this.imageCroper.cropImage.resetOriginalImage(); } toggleRaster() { this.imageCroper.switchRasterLevelIndex(); } rotate90Deg() { this.imageCroper.cropImage.rotation -= 90; if (this.imageCroper.cropImage.rotation === -360) { this.imageCroper.cropImage.rotation = 0; } //console.log(this.imageCroper.cropImage.rotation); this.imageCroper.cropImage.coverCanvas(); } cancleE() { this.cancle.emit(); } continueE() { this.imageCroper.cropImage.drawImageToCanvas(this.imageCroper.offscreenCtx); this.continue.emit(this.imageCroper.offscreenCtx.canvas.toDataURL()); } }; ImageCropperComponent.ctorParameters = () => [ { type: ChangeDetectorRef } ]; __decorate([ ViewChild('cropperCanvas') ], ImageCropperComponent.prototype, "cropperCanvas", void 0); __decorate([ ViewChild('offscreenCanvas') ], ImageCropperComponent.prototype, "offscreenCanvas", void 0); __decorate([ Input() ], ImageCropperComponent.prototype, "imageSrc", void 0); __decorate([ Input() ], ImageCropperComponent.prototype, "config", void 0); __decorate([ Output() ], ImageCropperComponent.prototype, "continue", void 0); __decorate([ Output() ], ImageCropperComponent.prototype, "cancle", void 0); __decorate([ HostListener('window:resize') ], ImageCropperComponent.prototype, "resize", null); ImageCropperComponent = __decorate([ Component({ selector: 'fg-image-cropper', template: "<ng-container [class.hidden]=\"imageCroper && imageCroper.cropImage.loaded\">\n <div [class.hidden]=\"!toSmall\" class=\"tosmallOverlay\">\n <div>\n <div>\n <h2>Screen is to small</h2>\n </div>\n <div (click)=\"cancleE()\">\n cancle\n </div>\n </div>\n </div>\n <div class=\"topSection\">\n <div class=\"inner\">\n <h2>Crop Your Image</h2>\n <button (click)=\"rotate90Deg()\" class=\"right\" type=\"button\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path d=\"M0 0h24v24H0z\" fill=\"none\" />\n <path\n d=\"M7.11 8.53L5.7 7.11C4.8 8.27 4.24 9.61 4.07 11h2.02c.14-.87.49-1.72 1.02-2.47zM6.09 13H4.07c.17 1.39.72 2.73 1.62 3.89l1.41-1.42c-.52-.75-.87-1.59-1.01-2.47zm1.01 5.32c1.16.9 2.51 1.44 3.9 1.61V17.9c-.87-.15-1.71-.49-2.46-1.03L7.1 18.32zM13 4.07V1L8.45 5.55 13 10V6.09c2.84.48 5 2.94 5 5.91s-2.16 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93s-3.05-7.44-7-7.93z\" />\n </svg>\n </button>\n\n <button type=\"button\" (click)=\"toggleRaster()\" class=\"left\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"300\" height=\"300\" viewBox=\"0 0 300 300\">\n <g id=\"Gruppe_48\" data-name=\"Gruppe 48\" transform=\"translate(-467.5 -968.5)\">\n <g id=\"Gruppe_47\" data-name=\"Gruppe 47\" transform=\"translate(3 443)\">\n <line id=\"Linie_3\" data-name=\"Linie 3\" y2=\"300\" transform=\"translate(559.5 525.5)\" fill=\"none\"\n stroke=\"#000\" stroke-width=\"20\" />\n <line id=\"Linie_4\" data-name=\"Linie 4\" y2=\"300\" transform=\"translate(669.5 525.5)\" fill=\"none\"\n stroke=\"#000\" stroke-width=\"20\" />\n </g>\n <g id=\"Gruppe_46\" data-name=\"Gruppe 46\" transform=\"translate(135 416)\">\n <line id=\"Linie_5\" data-name=\"Linie 5\" x2=\"300\" transform=\"translate(332.5 647.5)\" fill=\"none\"\n stroke=\"#000\" stroke-width=\"20\" />\n <line id=\"Linie_6\" data-name=\"Linie 6\" x2=\"300\" transform=\"translate(332.5 757.5)\" fill=\"none\"\n stroke=\"#000\" stroke-width=\"20\" />\n </g>\n </g>\n </svg>\n </button>\n </div>\n </div>\n <div class=\"canvasWrap\">\n <canvas #cropperCanvas></canvas>\n <canvas #offscreenCanvas style=\"display: none\"></canvas>\n </div>\n <div class=\"container\">\n <fg-slider-infinite (change)=\"zoom($event)\"></fg-slider-infinite>\n <div class=\"buttonWrapp\">\n <button (click)=\"continueE()\" class=\"btn\" type=\"button\">Continue</button>\n <button (click)=\"cancleE()\" class=\"btn\" type=\"button\">Cancle</button>\n </div>\n </div>\n</ng-container>", styles: [".buttonWrapp{display:flex;justify-content:space-between}:host{overflow:hidden;display:block}:host *{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.hidden{display:none!important}.tosmallOverlay{text-align:center;width:100%;height:100%;background-color:rgba(0,0,0,.767);color:#fff;display:flex;justify-content:center;align-items:center}canvas{border:1px solid #000}fg-slider-infinite{margin-top:10px;display:block}button{touch-action:none;margin-top:10px}.btn{color:#fff;flex-basis:48%;font-size:20px;border:none;height:50px;padding:9px auto}.canvasWrap{text-align:center;max-width:1000px;margin:0 auto}.topSection{border-bottom:1px solid gray;position:relative;text-align:center}.topSection .inner{margin:0 auto;width:100%;max-width:500px;height:100%;position:relative}.topSection .inner h2{display:inline-block;padding-top:10px;padding-bottom:10px}.topSection .inner button{background-color:transparent;border:none;outline:0;margin-top:0;height:100%;width:52px;position:absolute}.topSection .inner button.left{left:0}.topSection .inner button.right{right:0}.topSection .inner button svg{margin-top:5px;width:30px;height:auto}.topSection .inner button:hover{opacity:.75}.container{max-width:1000px;padding:0 20px;margin:0 auto}"] }) ], ImageCropperComponent); var InputImageComponent_1; let InputImageComponent = InputImageComponent_1 = class InputImageComponent { constructor(host, fileService, sanitizer) { this.host = host; this.fileService = fileService; this.sanitizer = sanitizer; this.invalid = false; this.width = 500; this.height = 500; this.value = null; this.crop = false; //cropImageSrc: string ="https://helpx.adobe.com/content/dam/help/en/stock/how-to/visual-reverse-image-search/jcr_content/main-pars/image/visual-reverse-image-search-v2_intro.jpg"; this.cropperConfig = null; this.pending = false; this.previewHeightStyle = null; this.propagateChange = (_) => { }; this.markAsTouched = (_) => { }; } registerOnChange(fn) { this.propagateChange = fn; } registerOnTouched(fn) { this.markAsTouched = fn; } setDisabledState(isDisabled) { } change($event) { this.propagateChange($event.target.value); } writeValue(value) { if (value !== null) { this.value = value; this.cropImageSrc = value; this.previewImageUrl = value; } } ngOnInit() { this.widthHeightRatio = this.height / this.width; this.cropperConfig = new ImageCropperConfig(this.width, this.height, [4, 8, 16]); this.resize(); } resize() { this.previewHeightStyle = this.sanitizer.bypassSecurityTrustStyle(this.host.nativeElement.clientWidth * this.widthHeightRatio + 'px'); } openCropImageDialog($event) { this.fileService.getBase64($event.target.files[0]).then(x => { this.cropImageSrc = x; this.crop = true; document.body.style.overflowY = "hidden"; }); } showImage($event) { this.hideImageCroper(); this.previewImageUrl = $event; this.value = $event; this.propagateChange(this.value); } hideImageCroper() { this.cropImageSrc = null; this.crop = false; this.imageInput.nativeElement.value = ''; document.body.style.overflowY = "auto"; } }; InputImageComponent.ctorParameters = () => [ { type: ElementRef }, { type: FileService }, { type: DomSanitizer } ]; __decorate([ Input() ], InputImageComponent.prototype, "invalid", void 0); __decorate([ Input() ], InputImageComponent.prototype, "width", void 0); __decorate([ Input() ], InputImageComponent.prototype, "height", void 0); __decorate([ ViewChild('imageInput') ], InputImageComponent.prototype, "imageInput", void 0); __decorate([ HostListener('window:resize') ], InputImageComponent.prototype, "resize", null); InputImageComponent = InputImageComponent_1 = __decorate([ Component({ selector: 'fg-input-image', template: "\n\n<div [class.invalid]=\"invalid\" [style.height]=\"previewHeightStyle\" *ngIf=\"value===null&&pending===false\"\n class=\"imageInputWrapper noselect\" (click)=\"imageInput.click()\">\n <div class=\"placeholderWrapper\">\n <div class=\"icon\">\n <svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"27.949\" height=\"27.949\" viewBox=\"0 0 27.949 27.949\">\n <path id=\"ic_add_24px\" d=\"M32.949,20.971H20.971V32.949H16.978V20.971H5V16.978H16.978V5h3.993V16.978H32.949Z\"\n transform=\"translate(-5 -5)\"/>\n </svg>\n </div>\n <div class=\"text\">Add image</div>\n </div>\n</div>\n\n<div [style.height]=\"previewHeightStyle\"\n [style.background-image]=\"'url('+previewImageUrl+')'\" *ngIf=\"value!==null&&pending===false\"\n class=\"imageInputWrapper withImage noselect\" (click)=\"imageInput.click()\">\n <div class=\"placeholderWrapper\">\n <div class=\"icon\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n <path\n d=\"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z\"/>\n <path d=\"M0 0h24v24H0z\" fill=\"none\"/>\n </svg>\n </div>\n <div class=\"text\">Change image</div>\n </div>\n</div>\n\n<div [style.height]=\"previewHeightStyle\" *ngIf=\"pending===true\"\n class=\"imageInputWrapper withImage noselect\" (click)=\"imageInput.click()\">\n <div class=\"placeholderWrapper\">\n <div class=\"icon\">\n <div class=\"spinner\">\n <div class=\"rect1\"></div>\n <div class=\"rect2\"></div>\n <div class=\"rect3\"></div>\n <div class=\"rect4\"></div>\n <div class=\"rect5\"></div>\n </div>\n </div>\n </div>\n</div>\n\n<input class=\"hidden\" (change)=\"openCropImageDialog($event);\" type=\"file\" accept=\