UNPKG

ng-cw-v12

Version:

Angular UI component library

446 lines (437 loc) 24.2 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) : typeof define === 'function' && define.amd ? define('ng-cw-v12/img-preview', ['exports', '@angular/core'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global["ng-cw-v12"] = global["ng-cw-v12"] || {}, global["ng-cw-v12"]["img-preview"] = {}), global.ng.core)); })(this, (function (exports, i0) { 'use strict'; function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var i0__namespace = /*#__PURE__*/_interopNamespace(i0); var ImgPreviewDirective = /** @class */ (function () { function ImgPreviewDirective(el, renderer) { this.el = el; this.renderer = renderer; this.ncImgPreview = ''; // 可选的大图URL,如果不提供则使用原图 this.ncMinScale = 0.5; // 最小缩放比例 this.ncMaxScale = 5; // 最大缩放比例 this.ncScaleStep = 0.25; // 缩放步长 /** 滚轮缩放 */ this._wheelScale = false; this.previewContainer = null; this.previewImg = null; this.toolbar = null; this.isPreviewOpen = false; // 图片变换状态 this.rotation = 0; // 旋转角度 this.scale = 1; // 缩放比例 // 工具按钮引用 this.zoomInBtn = null; this.zoomOutBtn = null; // 事件监听器引用 this.wheelListener = null; this.keyListener = null; } Object.defineProperty(ImgPreviewDirective.prototype, "ncWheelScale", { get: function () { return this._wheelScale; }, set: function (val) { this._wheelScale = val !== null && val !== undefined && val !== false && val !== 'false'; }, enumerable: false, configurable: true }); ImgPreviewDirective.prototype.ngOnInit = function () { // 给图片添加预览样式 this.renderer.setStyle(this.el.nativeElement, 'cursor', 'pointer'); this.renderer.setStyle(this.el.nativeElement, 'transition', 'transform 0.2s ease'); }; ImgPreviewDirective.prototype.onImageClick = function (event) { event.preventDefault(); event.stopPropagation(); this.openPreview(); }; ImgPreviewDirective.prototype.onMouseEnter = function () { this.renderer.setStyle(this.el.nativeElement, 'transform', 'scale(1.05)'); }; ImgPreviewDirective.prototype.onMouseLeave = function () { this.renderer.setStyle(this.el.nativeElement, 'transform', 'scale(1)'); }; ImgPreviewDirective.prototype.openPreview = function () { var _this = this; if (this.isPreviewOpen) return; this.isPreviewOpen = true; // 重置变换状态 this.rotation = 0; this.scale = 1; // 创建预览容器 this.previewContainer = this.renderer.createElement('div'); this.renderer.addClass(this.previewContainer, 'nc-img-preview-overlay'); // 设置遮罩层样式 this.renderer.setStyle(this.previewContainer, 'position', 'fixed'); this.renderer.setStyle(this.previewContainer, 'top', '0'); this.renderer.setStyle(this.previewContainer, 'left', '0'); this.renderer.setStyle(this.previewContainer, 'width', '100vw'); this.renderer.setStyle(this.previewContainer, 'height', '100vh'); this.renderer.setStyle(this.previewContainer, 'background-color', 'rgba(0, 0, 0, 0.45)'); this.renderer.setStyle(this.previewContainer, 'z-index', '9999'); this.renderer.setStyle(this.previewContainer, 'display', 'flex'); this.renderer.setStyle(this.previewContainer, 'justify-content', 'center'); this.renderer.setStyle(this.previewContainer, 'align-items', 'center'); this.renderer.setStyle(this.previewContainer, 'cursor', 'pointer'); this.renderer.setStyle(this.previewContainer, 'opacity', '0'); this.renderer.setStyle(this.previewContainer, 'transition', 'opacity 0.3s ease'); this.renderer.setStyle(this.previewContainer, 'user-select', 'none'); this.renderer.setStyle(this.previewContainer, '-webkit-user-select', 'none'); this.renderer.setStyle(this.previewContainer, '-moz-user-select', 'none'); this.renderer.setStyle(this.previewContainer, '-ms-user-select', 'none'); this.renderer.setStyle(this.previewContainer, 'overflow', 'auto'); // 创建预览图片 this.previewImg = this.renderer.createElement('img'); this.renderer.addClass(this.previewImg, 'nc-img-preview-img'); var imgSrc = this.ncImgPreview || this.el.nativeElement.src; this.renderer.setAttribute(this.previewImg, 'src', imgSrc); this.renderer.setStyle(this.previewImg, 'max-width', '100%'); this.renderer.setStyle(this.previewImg, 'max-height', '100%'); this.renderer.setStyle(this.previewImg, 'object-fit', 'contain'); this.renderer.setStyle(this.previewImg, 'border-radius', '8px'); this.renderer.setStyle(this.previewImg, 'box-shadow', '0 4px 20px rgba(0, 0, 0, 0.3)'); this.renderer.setStyle(this.previewImg, 'transform', 'scale(0.8)'); this.renderer.setStyle(this.previewImg, 'transition', 'transform 0.3s ease'); this.renderer.setStyle(this.previewImg, 'cursor', 'default'); this.renderer.setStyle(this.previewImg, 'user-select', 'none'); this.renderer.setStyle(this.previewImg, '-webkit-user-select', 'none'); this.renderer.setStyle(this.previewImg, '-moz-user-select', 'none'); this.renderer.setStyle(this.previewImg, '-ms-user-select', 'none'); this.renderer.setStyle(this.previewImg, '-webkit-user-drag', 'none'); this.renderer.setStyle(this.previewImg, '-khtml-user-drag', 'none'); this.renderer.setStyle(this.previewImg, '-moz-user-drag', 'none'); this.renderer.setStyle(this.previewImg, '-o-user-drag', 'none'); this.renderer.setStyle(this.previewImg, 'user-drag', 'none'); this.renderer.setAttribute(this.previewImg, 'draggable', 'false'); // 创建工具条容器 this.toolbar = this.renderer.createElement('div'); this.renderer.addClass(this.toolbar, 'nc-img-preview-toolbar'); this.renderer.setStyle(this.toolbar, 'position', 'fixed'); this.renderer.setStyle(this.toolbar, 'top', '20px'); this.renderer.setStyle(this.toolbar, 'right', '20px'); this.renderer.setStyle(this.toolbar, 'display', 'flex'); this.renderer.setStyle(this.toolbar, 'gap', '8px'); this.renderer.setStyle(this.toolbar, 'background-color', 'rgba(0, 0, 0, 0.6)'); this.renderer.setStyle(this.toolbar, 'border-radius', '8px'); this.renderer.setStyle(this.toolbar, 'padding', '8px'); this.renderer.setStyle(this.toolbar, 'backdrop-filter', 'blur(10px)'); this.renderer.setStyle(this.toolbar, 'z-index', '10000'); this.renderer.setStyle(this.toolbar, 'user-select', 'none'); this.renderer.setStyle(this.toolbar, '-webkit-user-select', 'none'); this.renderer.setStyle(this.toolbar, '-moz-user-select', 'none'); this.renderer.setStyle(this.toolbar, '-ms-user-select', 'none'); // 创建工具按钮 var rotateLeftBtn = this.createToolButton('↺', '向左旋转'); var rotateRightBtn = this.createToolButton('↻', '向右旋转'); this.zoomInBtn = this.createToolButton('+', '放大'); this.zoomOutBtn = this.createToolButton('−', '缩小'); var closeBtn = this.createToolButton('×', '关闭'); // 添加按钮事件监听器 this.renderer.listen(rotateLeftBtn, 'click', function (event) { event.preventDefault(); event.stopPropagation(); _this.rotateImage(-90); }); this.renderer.listen(rotateRightBtn, 'click', function (event) { event.preventDefault(); event.stopPropagation(); _this.rotateImage(90); }); this.renderer.listen(this.zoomInBtn, 'click', function (event) { event.preventDefault(); event.stopPropagation(); _this.scaleImage(_this.ncScaleStep); }); this.renderer.listen(this.zoomOutBtn, 'click', function (event) { event.preventDefault(); event.stopPropagation(); _this.scaleImage(-_this.ncScaleStep); }); this.renderer.listen(closeBtn, 'click', function (event) { event.preventDefault(); event.stopPropagation(); _this.closePreview(); }); // 组装工具条 this.renderer.appendChild(this.toolbar, rotateLeftBtn); this.renderer.appendChild(this.toolbar, rotateRightBtn); this.renderer.appendChild(this.toolbar, this.zoomOutBtn); this.renderer.appendChild(this.toolbar, this.zoomInBtn); this.renderer.appendChild(this.toolbar, closeBtn); // 组装预览容器 this.renderer.appendChild(this.previewContainer, this.previewImg); this.renderer.appendChild(document.body, this.previewContainer); this.renderer.appendChild(document.body, this.toolbar); // 添加事件监听器 this.renderer.listen(this.previewContainer, 'click', function (event) { if (event.target === _this.previewContainer) { _this.closePreview(); } }); // 添加鼠标滚轮事件监听器(如果启用了滚轮缩放) if (this.ncWheelScale) { this.wheelListener = this.renderer.listen(this.previewContainer, 'wheel', function (event) { event.preventDefault(); event.stopPropagation(); // 根据滚轮方向决定缩放方向 // deltaY > 0 表示向下滚动(缩小),deltaY < 0 表示向上滚动(放大) var delta = event.deltaY > 0 ? -_this.ncScaleStep : _this.ncScaleStep; _this.scaleImage(delta); }); } // 添加键盘事件监听器 this.keyListener = this.renderer.listen('document', 'keydown', function (event) { if (event.key === 'Escape') { _this.closePreview(); } }); // 禁止页面滚动和文本选择 this.renderer.setStyle(document.body, 'overflow', 'hidden'); this.renderer.setStyle(document.body, 'user-select', 'none'); this.renderer.setStyle(document.body, '-webkit-user-select', 'none'); this.renderer.setStyle(document.body, '-moz-user-select', 'none'); this.renderer.setStyle(document.body, '-ms-user-select', 'none'); // 动画效果 setTimeout(function () { if (_this.previewContainer && _this.previewImg) { _this.renderer.setStyle(_this.previewContainer, 'opacity', '1'); _this.renderer.setStyle(_this.previewImg, 'transform', 'scale(1)'); // 初始化按钮状态 _this.updateZoomButtonsState(); } }, 10); }; ImgPreviewDirective.prototype.createToolButton = function (text, title) { var _this = this; var button = this.renderer.createElement('div'); this.renderer.addClass(button, 'nc-img-preview-toolbar-button'); this.renderer.setStyle(button, 'width', '36px'); this.renderer.setStyle(button, 'height', '36px'); this.renderer.setStyle(button, 'background-color', 'rgba(255, 255, 255, 0.1)'); this.renderer.setStyle(button, 'border-radius', '6px'); this.renderer.setStyle(button, 'display', 'flex'); this.renderer.setStyle(button, 'justify-content', 'center'); this.renderer.setStyle(button, 'align-items', 'center'); this.renderer.setStyle(button, 'cursor', 'pointer'); this.renderer.setStyle(button, 'transition', 'background-color 0.2s ease, transform 0.1s ease'); this.renderer.setStyle(button, 'font-size', '18px'); this.renderer.setStyle(button, 'color', 'white'); this.renderer.setStyle(button, 'font-weight', 'bold'); this.renderer.setStyle(button, 'user-select', 'none'); this.renderer.setAttribute(button, 'title', title); // 设置按钮内容 var buttonText = this.renderer.createText(text); this.renderer.appendChild(button, buttonText); // 添加悬停效果 this.renderer.listen(button, 'mouseenter', function () { _this.renderer.setStyle(button, 'background-color', 'rgba(255, 255, 255, 0.2)'); _this.renderer.setStyle(button, 'transform', 'scale(1.1)'); }); this.renderer.listen(button, 'mouseleave', function () { _this.renderer.setStyle(button, 'background-color', 'rgba(255, 255, 255, 0.1)'); _this.renderer.setStyle(button, 'transform', 'scale(1)'); }); // 添加点击效果 this.renderer.listen(button, 'mousedown', function (event) { event.preventDefault(); _this.renderer.setStyle(button, 'transform', 'scale(0.95)'); }); this.renderer.listen(button, 'mouseup', function (event) { event.preventDefault(); _this.renderer.setStyle(button, 'transform', 'scale(1.1)'); }); // 阻止文本选择开始 this.renderer.listen(button, 'selectstart', function (event) { event.preventDefault(); }); // 阻止拖拽开始 this.renderer.listen(button, 'dragstart', function (event) { event.preventDefault(); }); return button; }; ImgPreviewDirective.prototype.rotateImage = function (angle) { if (!this.previewImg) return; this.rotation += angle; this.updateImageTransform(); }; ImgPreviewDirective.prototype.scaleImage = function (delta) { if (!this.previewImg) return; var newScale = this.mathAdd(this.scale, delta); // 确保缩放比例在合理范围内,超出范围时设置为边界值 if (newScale < this.ncMinScale) { this.scale = this.ncMinScale; } else if (newScale > this.ncMaxScale) { this.scale = this.ncMaxScale; } else { this.scale = newScale; } this.updateImageTransform(); this.updateZoomButtonsState(); }; ImgPreviewDirective.prototype.updateImageTransform = function () { if (!this.previewImg) return; var transform = "scale3d(" + this.scale + ", " + this.scale + ", 1) rotate(" + this.rotation + "deg)"; this.renderer.setStyle(this.previewImg, 'transform', transform); }; ImgPreviewDirective.prototype.updateZoomButtonsState = function () { if (!this.zoomInBtn || !this.zoomOutBtn) return; var isMinScale = this.scale <= this.ncMinScale; var isMaxScale = this.scale >= this.ncMaxScale; // 更新按钮状态 this.setButtonDisabled(this.zoomOutBtn, isMinScale); this.setButtonDisabled(this.zoomInBtn, isMaxScale); }; ImgPreviewDirective.prototype.setButtonDisabled = function (button, disabled) { if (disabled) { this.renderer.setStyle(button, 'opacity', '0.4'); this.renderer.setStyle(button, 'pointer-events', 'none'); } else { this.renderer.setStyle(button, 'opacity', '1'); this.renderer.setStyle(button, 'pointer-events', 'auto'); } }; ImgPreviewDirective.prototype.closePreview = function () { var _this = this; if (!this.isPreviewOpen || !this.previewContainer) return; // 清理事件监听器 if (this.keyListener) { this.keyListener(); this.keyListener = null; } if (this.wheelListener) { this.wheelListener(); this.wheelListener = null; } // 移除工具栏 if (this.toolbar) { this.renderer.removeChild(document.body, this.toolbar); this.toolbar = null; } // 添加关闭动画 this.renderer.setStyle(this.previewContainer, 'opacity', '0'); if (this.previewImg) { this.renderer.setStyle(this.previewImg, 'transform', 'scale(0.8)'); } // 延迟移除元素以完成动画 setTimeout(function () { if (_this.previewContainer) { _this.renderer.removeChild(document.body, _this.previewContainer); _this.previewContainer = null; _this.previewImg = null; _this.zoomInBtn = null; _this.zoomOutBtn = null; } _this.isPreviewOpen = false; // 恢复页面滚动和文本选择 _this.renderer.removeStyle(document.body, 'overflow'); _this.renderer.removeStyle(document.body, 'user-select'); _this.renderer.removeStyle(document.body, '-webkit-user-select'); _this.renderer.removeStyle(document.body, '-moz-user-select'); _this.renderer.removeStyle(document.body, '-ms-user-select'); }, 300); }; ImgPreviewDirective.prototype.mathAdd = function (value1, value2) { // 将浮点数转换为字符串 var aStr = value1.toString(); var bStr = value2.toString(); // 找到小数点后的位置 var aDecimals = (aStr.split('.')[1] || '').length; var bDecimals = (bStr.split('.')[1] || '').length; // 找到最大的小数位数 var maxDecimals = Math.max(aDecimals, bDecimals); // 将浮点数转换为整数 var aInt = Math.round(value1 * Math.pow(10, maxDecimals)); var bInt = Math.round(value2 * Math.pow(10, maxDecimals)); // 进行整数加法 var resultInt = aInt + bInt; // 将结果转换回浮点数 return resultInt / Math.pow(10, maxDecimals); }; return ImgPreviewDirective; }()); ImgPreviewDirective.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: ImgPreviewDirective, deps: [{ token: i0__namespace.ElementRef }, { token: i0__namespace.Renderer2 }], target: i0__namespace.ɵɵFactoryTarget.Directive }); ImgPreviewDirective.ɵdir = i0__namespace.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.1.5", type: ImgPreviewDirective, selector: "[ncImgPreview]", inputs: { ncImgPreview: "ncImgPreview", ncMinScale: "ncMinScale", ncMaxScale: "ncMaxScale", ncScaleStep: "ncScaleStep", ncWheelScale: "ncWheelScale" }, host: { listeners: { "click": "onImageClick($event)", "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, exportAs: ["ncImgPreview"], ngImport: i0__namespace }); i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: ImgPreviewDirective, decorators: [{ type: i0.Directive, args: [{ selector: '[ncImgPreview]', exportAs: 'ncImgPreview' }] }], ctorParameters: function () { return [{ type: i0__namespace.ElementRef }, { type: i0__namespace.Renderer2 }]; }, propDecorators: { ncImgPreview: [{ type: i0.Input }], ncMinScale: [{ type: i0.Input }], ncMaxScale: [{ type: i0.Input }], ncScaleStep: [{ type: i0.Input }], ncWheelScale: [{ type: i0.Input }], onImageClick: [{ type: i0.HostListener, args: ['click', ['$event']] }], onMouseEnter: [{ type: i0.HostListener, args: ['mouseenter'] }], onMouseLeave: [{ type: i0.HostListener, args: ['mouseleave'] }] } }); var NcImgPreviewModule = /** @class */ (function () { function NcImgPreviewModule() { } return NcImgPreviewModule; }()); NcImgPreviewModule.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcImgPreviewModule, deps: [], target: i0__namespace.ɵɵFactoryTarget.NgModule }); NcImgPreviewModule.ɵmod = i0__namespace.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcImgPreviewModule, declarations: [ImgPreviewDirective], exports: [ImgPreviewDirective] }); NcImgPreviewModule.ɵinj = i0__namespace.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcImgPreviewModule, imports: [[]] }); i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0__namespace, type: NcImgPreviewModule, decorators: [{ type: i0.NgModule, args: [{ declarations: [ ImgPreviewDirective ], imports: [], exports: [ ImgPreviewDirective ] }] }] }); /** * Generated bundle index. Do not edit. */ exports.ImgPreviewDirective = ImgPreviewDirective; exports.NcImgPreviewModule = NcImgPreviewModule; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=ng-cw-v12-img-preview.umd.js.map