UNPKG

ng-cw-v12

Version:

Angular UI Component Library

454 lines (449 loc) 25.1 kB
import * as i0 from '@angular/core'; import { EventEmitter, Component, Input, Output, NgModule } from '@angular/core'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i2 from '@angular/forms'; import { FormsModule } from '@angular/forms'; import { __awaiter } from 'tslib'; class ImgClipComponent { constructor(eleRef) { this.eleRef = eleRef; /** 图片地址 */ this.ncUrl = ''; /** 确认裁剪回调 */ this.ncConfirm = new EventEmitter(); /** 裁剪回调返回图片格式 */ this.ncImgType = 'base64'; /** 容器宽度 */ this.ncWidth = 300; /** 默认裁剪框的尺寸占图片比例 */ this.ncClipSize = 0.7; /** 裁剪框最小宽度 */ this.ncClipMinWidth = 50; /** 裁剪框最小高度 */ this.ncClipMinHeight = 50; /** 确认裁剪时是否下载图片 */ this._download = false; /** 调整工具栏 */ this._tool = false; /** 上传 */ this._upload = false; this.hasImage = false; // 图片当前宽高 this.clipImageWidth = 0; this.clipImageHeight = 0; // 图片原始宽高 this.clipImageOriginWidth = 0; this.clipImageOriginHeight = 0; this.scale = 0; //缩放比例 this.clipWidth = 0; //裁剪框宽度 this.clipHeight = 0; //裁剪框高度 this.clipX = 0; //裁剪框x this.clipY = 0; //裁剪框y } set ncDownload(value) { this._download = value !== null && value !== undefined && value !== false && value !== 'false'; } get ncDownload() { return this._download; } set ncTool(value) { this._tool = value !== null && value !== undefined && value !== false && value !== 'false'; } get ncTool() { return this._tool; } set ncUpload(value) { this._upload = value !== null && value !== undefined && value !== false && value !== 'false'; } get ncUpload() { return this._upload; } ngOnInit() { this.clipImage = this.eleRef.nativeElement.querySelector('#clipImage'); this.clipPathImg = this.eleRef.nativeElement.querySelector('#clipPathImg'); this.clip = this.eleRef.nativeElement.querySelector('#clip'); if (this.ncUpload) { setTimeout(() => { this.file = this.eleRef.nativeElement.querySelector('#file'); // 监听上传状态 浏览图片 this.file.addEventListener('change', (e) => { const file = e.target.files[0]; const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { this.readImage(reader.result); }; }); }); } //裁剪框缩放、拖拽 this.clipBoxZoom(); this.clipBpxDrag(); //读取图片 this.readImage(this.ncUrl); } ngOnChanges(changes) { if (changes['ncUrl'] && !changes['ncUrl'].firstChange) { this.readImage(this.ncUrl); } } //读取图片 readImage(url) { // 读取到的图片数据 this.clipImage.src = url; // 裁剪使用的图片 this.clipPathImg.src = url; //获取当前图片的宽高 this.getClipImageSize(url).then((res) => { // 初始化 this.init(); this.hasImage = true; }); } // 获取上传图片的当前尺寸和原始尺寸 getClipImageSize(dataurl) { return __awaiter(this, void 0, void 0, function* () { const data = yield new Promise((resolve) => { this.clipImage.onload = () => { resolve(this.clipImage); }; }); // 获取图片当前宽高 this.clipImageWidth = data.width; this.clipImageHeight = data.height; const data_1 = yield new Promise((resolve_1) => { // 获取图片原始宽高 let img = document.createElement('img'); img.src = dataurl; img.onload = () => { resolve_1(img); }; }); // 获取图片原始宽高 this.clipImageOriginWidth = data_1.width; this.clipImageOriginHeight = data_1.height; return yield Promise.resolve(); }); } // 初始化 init() { // 显示裁剪框 this.clip.style.display = 'block'; // 缩放比例 this.scale = this.clipImageOriginWidth / this.clipImageWidth; // 设置裁剪框的宽高 let clipWidth = Math.floor(this.clipImageWidth * this.ncClipSize); let clipHeight = Math.floor(this.clipImageHeight * this.ncClipSize); this.setClipSize(clipWidth, clipHeight); // 设置裁剪框的位置 let x = Math.floor((this.clipImageWidth - clipWidth) / 2); let y = Math.floor((this.clipImageHeight - clipHeight) / 2); this.setClipPosition(x, y); } // 设置裁剪框的尺寸 setClipSize(clipWidth, clipHeight) { this.clip.style.setProperty('--clipWidth', clipWidth + 'px'); this.clip.style.setProperty('--clipHeight', clipHeight + 'px'); this.clipWidth = clipWidth; this.clipHeight = clipHeight; } // 设置裁剪框的位置 setClipPosition(x, y) { this.clip.style.setProperty('--clipX', x + 'px'); this.clip.style.setProperty('--clipY', y + 'px'); this.clipX = x; this.clipY = y; // 设置裁剪阴影 this.setClipPath(); } // 设置裁剪阴影 setClipPath() { let lt = this.clip.offsetLeft + 'px' + ' ' + this.clip.offsetTop + 'px'; let rt = (this.clip.offsetLeft + this.clip.offsetWidth) + 'px' + ' ' + this.clip.offsetTop + 'px'; let rb = (this.clip.offsetLeft + this.clip.offsetWidth) + 'px' + ' ' + (this.clip.offsetTop + this.clip.offsetHeight) + 'px'; let lb = this.clip.offsetLeft + 'px' + ' ' + (this.clip.offsetTop + this.clip.offsetHeight) + 'px'; this.clipPathImg.style.setProperty('--clipPath', `polygon(${lt}, ${rt}, ${rb}, ${lb})`); } // 裁剪 clipImg(x, y, cutWidth, cutHeight, width, height) { return __awaiter(this, void 0, void 0, function* () { let canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(this.clipImage, x, y, cutWidth, cutHeight, 0, 0, width, height); //下载 if (this.ncDownload) { const a = document.createElement('a'); a.download = '裁剪图片'; a.href = canvas.toDataURL('image/png'); a.click(); } // 返回裁剪后的图片 return new Promise((resolve) => { if (this.ncImgType == 'base64') { resolve(canvas.toDataURL('image/png')); } else { canvas.toBlob((blob) => { resolve(new File([blob], 'clip.png', { type: 'image/png' })); }); } }); }); } //确认裁剪 confirm() { return __awaiter(this, void 0, void 0, function* () { let res = yield this.clipImg(this.clip.offsetLeft * this.scale, this.clip.offsetTop * this.scale, this.clip.offsetWidth * this.scale, this.clip.offsetHeight * this.scale, this.clip.offsetWidth, this.clip.offsetHeight); this.ncConfirm.emit(res); }); } //裁剪框的拖拽 clipBpxDrag() { // 鼠标按下 this.clip.onmousedown = (e) => { // 偏移量 let py = { x: e.clientX - this.clip.offsetLeft, y: e.clientY - this.clip.offsetTop }; // 鼠标移动 window.onmousemove = (e) => { // 鼠标移动的距离 let moveX = e.clientX - py.x; let moveY = e.clientY - py.y; // 裁剪框的位置 let left = moveX; let top = moveY; // 裁剪框的位置限制 if (left < 0) { left = 0; } if (top < 0) { top = 0; } if (left > this.clipImageWidth - this.clip.offsetWidth) { left = this.clipImageWidth - this.clip.offsetWidth; } if (top > this.clipImageHeight - this.clip.offsetHeight) { top = this.clipImageHeight - this.clip.offsetHeight; } // 设置裁剪框的位置 this.setClipPosition(left, top); }; // 鼠标松开 window.onmouseup = () => { window.onmouseup = null; window.onmousemove = null; }; }; } //裁剪框缩放 clipBoxZoom() { // 获取裁剪框的四个角 let zoomDom = { lt: this.eleRef.nativeElement.querySelector('.lt'), rt: this.eleRef.nativeElement.querySelector('.rt'), rb: this.eleRef.nativeElement.querySelector('.rb'), lb: this.eleRef.nativeElement.querySelector('.lb'), }; // 鼠标按下时的位置 let zoomInfo = { x: 0, y: 0, minWidth: this.ncClipMinWidth, minHeight: this.ncClipMinHeight }; // 鼠标按下时裁剪框的位置 for (let key in zoomDom) { zoomDom[key].onmousedown = (e) => { // 禁止冒泡 e.stopPropagation(); // 鼠标按下时的位置 zoomInfo.x = e.clientX; zoomInfo.y = e.clientY; // 鼠标移动 window.onmousemove = (e) => { // 鼠标移动的距离 let moveX = e.clientX - zoomInfo.x; let moveY = e.clientY - zoomInfo.y; // 裁剪框的位置 let left = 0; let top = 0; // 裁剪框的尺寸 let width = 0; let height = 0; // 左上角 if (key === 'lt') { // 裁剪框的位置 left = this.clip.offsetLeft + moveX; top = this.clip.offsetTop + moveY; // 裁剪框的尺寸 width = this.clip.offsetWidth - moveX; height = this.clip.offsetHeight - moveY; // 裁剪框的位置限制 if (left < 0) { left = 0; // 原来宽度+原来left width = this.clip.offsetWidth + this.clip.offsetLeft; } if (top < 0) { top = 0; // 原来高度+原来top height = this.clip.offsetHeight + this.clip.offsetTop; } } // 右上角 if (key === 'rt') { // 裁剪框的位置 top = this.clip.offsetTop + moveY; left = this.clip.offsetLeft; // 裁剪框的尺寸 width = this.clip.offsetWidth + moveX; height = this.clip.offsetHeight - moveY; // 裁剪框的位置限制 if (top < 0) { top = 0; // 原来高度+原来top height = this.clip.offsetHeight + this.clip.offsetTop; } if (left + width > this.clipImageWidth) { // 图片当前宽-原来left width = this.clipImageWidth - left; } } // 右下角 if (key === 'rb') { // 裁剪框的尺寸 top = this.clip.offsetTop; left = this.clip.offsetLeft; width = this.clip.offsetWidth + moveX; height = this.clip.offsetHeight + moveY; // 裁剪框的位置限制 // 当前的left+当前的width>图片当前宽 if (this.clip.offsetLeft + width > this.clipImageWidth) { width = this.clipImageWidth - left; } // 当前的top+当前的height>图片当前宽 if (this.clip.offsetTop + height > this.clipImageHeight) { height = this.clipImageHeight - top; } } // 左下角 if (key === 'lb') { // 裁剪框的位置 left = this.clip.offsetLeft + moveX; top = this.clip.offsetTop; // 裁剪框的尺寸 width = this.clip.offsetWidth - moveX; height = this.clip.offsetHeight + moveY; // 裁剪框的位置限制 if (left < 0) { left = 0; width = this.clip.offsetWidth + this.clip.offsetLeft; } // 当前的top+当前的height>图片当前宽 if (this.clip.offsetTop + height > this.clipImageHeight) { height = this.clipImageHeight - top; } } // 裁剪框的限制 ({ width, height, left, top } = this.ClipWidthPosition(zoomInfo, width, height, left, top)); // 设置裁剪框的位置 this.setClipPosition(left, top); // 设置裁剪框的尺寸 this.setClipSize(width, height); // 记录上一次的位置 zoomInfo.x = e.clientX; zoomInfo.y = e.clientY; }; // 鼠标松开 window.onmouseup = () => { window.onmouseup = null; window.onmousemove = null; }; }; } } // 裁剪框的宽高限制以及位置限制 ClipWidthPosition(zoomInfo, w, h, l, t) { let width = w; //裁剪框宽度 let height = h; //裁剪框的高度 let left = l; //裁剪框的left let top = t; //裁剪框的top if (w < zoomInfo.minWidth) { width = zoomInfo.minWidth; left = this.clip.offsetLeft; } if (h < zoomInfo.minHeight) { height = zoomInfo.minHeight; top = this.clip.offsetTop; } return { width, height, left, top }; } //尺寸输入框变化 sizeInputChange() { this.setClipSize(this.clipWidth, this.clipHeight); this.setClipPosition(this.clipX, this.clipY); } } ImgClipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ImgClipComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); ImgClipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: ImgClipComponent, selector: "nc-img-clip", inputs: { ncUrl: "ncUrl", ncImgType: "ncImgType", ncWidth: "ncWidth", ncClipSize: "ncClipSize", ncClipMinWidth: "ncClipMinWidth", ncClipMinHeight: "ncClipMinHeight", ncDownload: "ncDownload", ncTool: "ncTool", ncUpload: "ncUpload" }, outputs: { ncConfirm: "ncConfirm" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"clipContainer\" [ngStyle]=\"{'width': ncWidth + 'px'}\">\r\n <div class=\"clipBtnContainer\">\r\n <div *ngIf=\"ncUpload\" class=\"filebutton\">\r\n <div>\u4E0A\u4F20\u56FE\u7247</div>\r\n <input type=\"file\" id=\"file\" class=\"fileInput\" accept=\"image/*\">\r\n </div>\r\n <div *ngIf=\"hasImage\" class=\"confirmBtn\" (click)=\"confirm()\">\u786E\u5B9A</div>\r\n </div>\r\n <div class=\"clipImageCantainer\">\r\n <img id=\"clipImage\" src=\"\" crossorigin=\"anonymous\">\r\n <img id=\"clipPathImg\" src=\"\">\r\n <div id=\"clip\">\r\n <div class=\"corner lt\"></div>\r\n <div class=\"corner rt\"></div>\r\n <div class=\"corner rb\"></div>\r\n <div class=\"corner lb\"></div>\r\n </div>\r\n </div>\r\n <div class=\"bottomInputContainer\" *ngIf=\"hasImage && ncTool\">\r\n <div class=\"inputRow\">\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">\u5BBD\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipWidth\" [min]=\"ncClipMinWidth\"\r\n [max]=\"clipImageWidth\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">\u9AD8\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipHeight\" [min]=\"ncClipMinHeight\"\r\n [max]=\"clipImageHeight\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n </div>\r\n <div class=\"inputRow\">\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">X\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipX\" [min]=\"0\"\r\n [max]=\"clipImageWidth - clipWidth\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n <div class=\"inputCol\">\r\n <div class=\"rowLabel\">Y\uFF1A</div>\r\n <input class=\"nc-input-number sizeInput\" type=\"number\" [(ngModel)]=\"clipY\" [min]=\"0\"\r\n [max]=\"clipImageHeight - clipHeight\" step=\"1\" (ngModelChange)=\"sizeInputChange()\">\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".clipContainer{margin:5px}.clipContainer .clipBtnContainer{display:flex;align-items:center;justify-content:space-between;margin-bottom:5px}.clipContainer .clipBtnContainer .filebutton{position:relative;display:inline-block;overflow:hidden}.clipContainer .clipBtnContainer .filebutton input{position:absolute;top:0;opacity:0;font-size:0;width:100%;height:100%;cursor:pointer}.clipContainer .clipBtnContainer .filebutton div{font-size:13px;background:#00aeff;color:#fff;padding:4px 8px;border-radius:3px}.clipContainer .clipBtnContainer .confirmBtn{font-size:13px;background:#00aeff;color:#fff;padding:4px 8px;border-radius:3px;cursor:pointer}.clipContainer .clipImageCantainer{width:100%;position:relative}.clipContainer .clipImageCantainer:after{content:\"\";position:absolute;width:100%;height:100%;top:0;left:0;background:rgba(0,0,0,.5);z-index:1}.clipContainer .clipImageCantainer img{width:100%;top:0;left:0;display:block}.clipContainer .clipImageCantainer #clipPathImg{position:absolute;top:0;left:0;width:100%;height:100%;z-index:2;clip-path:var(--clipPath)}.clipContainer .clipImageCantainer #clip{position:absolute;top:0;left:0;width:var(--clipWidth);height:var(--clipHeight);left:var(--clipX);top:var(--clipY);z-index:3;cursor:move;border:1px dashed white;display:none}.clipContainer .clipImageCantainer #clip .corner{position:absolute;width:10px;height:10px;background:#fff;border:1px solid #000}.clipContainer .clipImageCantainer #clip .lt{cursor:nw-resize;left:-5px;top:-5px}.clipContainer .clipImageCantainer #clip .rt{cursor:ne-resize;right:-5px;top:-5px}.clipContainer .clipImageCantainer #clip .lb{cursor:sw-resize;left:-5px;bottom:-5px}.clipContainer .clipImageCantainer #clip .rb{cursor:se-resize;right:-5px;bottom:-5px}.clipContainer .bottomInputContainer .inputRow{display:flex;align-items:center;margin-top:5px}.clipContainer .bottomInputContainer .inputRow .inputCol{display:flex;align-items:center;margin-right:10px}.clipContainer .bottomInputContainer .inputRow .inputCol .rowLabel{width:30px;display:flex;justify-content:flex-end;color:#b9b9b9;mix-blend-mode:difference}.clipContainer .bottomInputContainer .inputRow .inputCol .sizeInput{width:70px}\n"], directives: [{ type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i2.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: ImgClipComponent, decorators: [{ type: Component, args: [{ selector: 'nc-img-clip', templateUrl: './img-clip.component.html', styleUrls: ['./img-clip.component.less'] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { ncUrl: [{ type: Input }], ncConfirm: [{ type: Output }], ncImgType: [{ type: Input }], ncWidth: [{ type: Input }], ncClipSize: [{ type: Input }], ncClipMinWidth: [{ type: Input }], ncClipMinHeight: [{ type: Input }], ncDownload: [{ type: Input }], ncTool: [{ type: Input }], ncUpload: [{ type: Input }] } }); class NcImgClipModule { } NcImgClipModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcImgClipModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); NcImgClipModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcImgClipModule, declarations: [ImgClipComponent], imports: [CommonModule, FormsModule], exports: [ImgClipComponent] }); NcImgClipModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcImgClipModule, imports: [[ CommonModule, FormsModule ]] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcImgClipModule, decorators: [{ type: NgModule, args: [{ declarations: [ ImgClipComponent ], imports: [ CommonModule, FormsModule ], exports: [ ImgClipComponent ] }] }] }); /** * Generated bundle index. Do not edit. */ export { ImgClipComponent, NcImgClipModule }; //# sourceMappingURL=ng-cw-v12-img-clip.js.map