ng-cw-v12
Version:
Angular UI Component Library
673 lines • 127 kB
JavaScript
import { Component, Input, ViewChild, HostListener } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class GalleriaComponent {
constructor() {
/** 图片数组 */
this._images = [];
/** 组件宽度 */
this.ncWidth = '100%';
/** 组件高度 */
this.ncHeight = '100%';
/** 缩略图宽度 */
this.ncThumbnailWidth = 80;
/** 缩略图高度 */
this.ncThumbnailHeight = 60;
/** 图片适应方式 */
this.ncObjectFit = 'contain';
/** 自动播放 */
this._autoPlay = false;
/** 自动播放间隔 */
this.ncAutoPlayInterval = 3000;
/** 显示缩略图 */
this._showThumbnails = true;
/** 显示指示器 */
this._showIndicators = false;
/** 指示器显示位置 */
this.ncIndicatorsPosition = 'outside';
/** 显示导航按钮 */
this._showNavButtons = false;
/** 导航按钮显示方式 */
this.ncNavButtonsDisplay = 'always';
/** 启用全屏预览 */
this._enableFullscreen = false;
/** 全屏按钮显示方式 */
this.ncFullscreenButtonDisplay = 'always';
/** 显示图片数目 */
this._showIndex = false;
/** 显示图片标题 */
this._showTitle = false;
/** 滚轮缩放 */
this._wheelScale = false;
this.currentIndex = 0;
this.thumbnailStartIndex = 0;
this.thumbnailTransform = 0; // 缩略图滚动偏移量
this.isFullscreen = false; // 全屏状态
this.isFullscreenAutoPlaying = false; // 全屏模式下的自动播放状态
// 全屏缩放相关属性
this.fullscreenScale = 1; // 当前缩放比例
this.fullscreenTranslateX = 0; // X轴偏移
this.fullscreenTranslateY = 0; // Y轴偏移
this.minScale = 0.5; // 最小缩放比例
this.maxScale = 3; // 最大缩放比例
this.isDragging = false; // 是否正在拖拽
this.lastMouseX = 0; // 上次鼠标X位置
this.lastMouseY = 0; // 上次鼠标Y位置
this.actualContainerWidth = 0;
}
set ncImages(value) {
// 如果传入的是string[],转换为NcGalleriaImage[]
if (value && value.length > 0 && typeof value[0] === 'string') {
this._images = value.map(src => ({
src: src,
title: ''
}));
}
else {
this._images = value;
}
}
get ncImages() {
return this._images;
}
set ncAutoPlay(val) {
this._autoPlay = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncAutoPlay() {
return this._autoPlay;
}
set ncShowThumbnails(val) {
this._showThumbnails = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncShowThumbnails() {
return this._showThumbnails;
}
set ncShowIndicators(val) {
this._showIndicators = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncShowIndicators() {
return this._showIndicators;
}
set ncShowNavButtons(val) {
this._showNavButtons = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncShowNavButtons() {
return this._showNavButtons;
}
set ncEnableFullscreen(val) {
this._enableFullscreen = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncEnableFullscreen() {
return this._enableFullscreen;
}
set ncShowIndex(val) {
this._showIndex = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncShowIndex() {
return this._showIndex;
}
set ncShowTitle(val) {
this._showTitle = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncShowTitle() {
return this._showTitle;
}
set ncWheelScale(val) {
this._wheelScale = val !== null && val !== undefined && val !== false && val !== 'false';
}
get ncWheelScale() {
return this._wheelScale;
}
// 计算缩略图实际宽度(包含gap)
get thumbnailActualWidth() {
return this.ncThumbnailWidth + 8; // 8px gap
}
// 计算实际可显示的缩略图数量
get actualVisibleThumbnailCount() {
// 边界保护:如果没有图片,返回0
if (!this.ncImages || this.ncImages.length === 0) {
return 0;
}
let containerWidth = 0;
if (this.ncWidth && this.ncWidth.includes('px')) {
// 如果设置了具体像素宽度
containerWidth = parseInt(this.ncWidth.replace('px', ''));
}
else if (this.actualContainerWidth > 0) {
// 如果是百分比宽度,使用实际测量的宽度
containerWidth = this.actualContainerWidth;
}
else {
// 如果还没有测量到实际宽度,先返回图片数量(避免初始化时的问题)
return this.ncImages.length;
}
// 边界保护:确保容器宽度和缩略图宽度都是正数
if (containerWidth <= 0 || this.thumbnailActualWidth <= 0) {
return 1;
}
// 减去左右滚动按钮的宽度(32px + 8px gap)× 2 = 80px,再减去容器padding
const availableWidth = containerWidth - 80 - 32; // 额外减去32px的padding
// 边界保护:确保可用宽度为正数
if (availableWidth <= 0) {
return 1;
}
const visibleCount = Math.floor(availableWidth / this.thumbnailActualWidth);
// 确保至少显示1个,最多不超过图片总数
return Math.max(1, Math.min(visibleCount, this.ncImages.length));
}
// 判断缩略图是否应该居中显示
get shouldCenterThumbnails() {
return this.ncImages.length <= this.actualVisibleThumbnailCount;
}
// 计算缩略图最大滚动距离
getMaxThumbnailScroll() {
const actualVisibleCount = this.actualVisibleThumbnailCount;
if (this.ncImages.length <= actualVisibleCount) {
return 0;
}
// 计算总宽度减去实际可见区域宽度
const totalWidth = this.ncImages.length * this.thumbnailActualWidth;
const visibleWidth = actualVisibleCount * this.thumbnailActualWidth;
return -(totalWidth - visibleWidth);
}
ngAfterViewInit() {
this.startInit();
}
ngOnChanges(changes) {
if (changes['ncImages'] && !changes['ncImages'].firstChange) {
this.startInit();
}
}
startInit() {
setTimeout(() => {
this.updateActualContainerWidth();
this.init();
});
}
updateActualContainerWidth() {
if (this.galleriaContainer && this.galleriaContainer.nativeElement) {
const newWidth = this.galleriaContainer.nativeElement.offsetWidth;
// 只有当宽度真正发生变化时才更新
if (newWidth !== this.actualContainerWidth) {
const oldVisibleCount = this.actualVisibleThumbnailCount;
this.actualContainerWidth = newWidth;
const newVisibleCount = this.actualVisibleThumbnailCount;
// 如果可显示数量发生变化,重新调整缩略图视图
if (oldVisibleCount !== newVisibleCount) {
this.updateThumbnailView();
}
}
}
}
init() {
//先删除autoPlayTimer定时器,防止ncImages更换时重复autoPlayTimer
if (this.autoPlayTimer) {
clearInterval(this.autoPlayTimer);
this.autoPlayTimer = null;
}
if (this.ncAutoPlay && this.ncImages.length > 1) {
this.startAutoPlay();
}
}
ngOnDestroy() {
this.stopAutoPlay();
// 清理resize定时器
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
// 如果组件销毁时还在全屏状态,恢复页面滚动
if (this.isFullscreen) {
document.body.style.overflow = '';
}
}
// 选择图片
selectImage(index) {
if (index >= 0 && index < this.ncImages.length) {
this.currentIndex = index;
this.updateThumbnailView();
// 切换图片时重置缩放状态
this.resetFullscreenZoom();
}
}
// 重置全屏缩放状态
resetFullscreenZoom() {
this.fullscreenScale = 1;
this.fullscreenTranslateX = 0;
this.fullscreenTranslateY = 0;
}
// 上一张图片
previousImage() {
this.currentIndex = this.currentIndex > 0 ? this.currentIndex - 1 : this.ncImages.length - 1;
this.updateThumbnailView();
// 切换图片时重置缩放状态
this.resetFullscreenZoom();
}
// 下一张图片
nextImage() {
this.currentIndex = this.currentIndex < this.ncImages.length - 1 ? this.currentIndex + 1 : 0;
this.updateThumbnailView();
// 切换图片时重置缩放状态
this.resetFullscreenZoom();
}
// 更新缩略图视图
updateThumbnailView() {
const actualVisibleCount = this.actualVisibleThumbnailCount;
if (this.ncImages.length <= actualVisibleCount) {
this.thumbnailStartIndex = 0;
this.thumbnailTransform = 0;
return;
}
// 根据缩略图数量决定滚动策略
const triggerIndex = Math.max(2, actualVisibleCount - 2);
if (this.currentIndex < triggerIndex) {
// 前面几张图片时,缩略图位置不变
this.thumbnailStartIndex = 0;
}
else if (this.currentIndex >= this.ncImages.length - Math.floor(actualVisibleCount / 2)) {
// 最后几张图片时,显示最后几张缩略图
this.thumbnailStartIndex = this.ncImages.length - actualVisibleCount;
}
else {
// 中间部分,让当前图片居中或接近居中显示
const centerOffset = Math.floor(actualVisibleCount / 2);
this.thumbnailStartIndex = this.currentIndex - centerOffset;
}
// 确保不超出边界
this.thumbnailStartIndex = Math.max(0, Math.min(this.thumbnailStartIndex, this.ncImages.length - actualVisibleCount));
// 计算transform偏移量
this.thumbnailTransform = -this.thumbnailStartIndex * this.thumbnailActualWidth;
// 确保不超出最大滚动范围
const maxScroll = this.getMaxThumbnailScroll();
this.thumbnailTransform = Math.max(maxScroll, this.thumbnailTransform);
}
// 缩略图向左滚动
scrollThumbnailsLeft() {
if (this.canScrollLeft()) {
// 每次滚动一个缩略图的宽度
this.thumbnailTransform += this.thumbnailActualWidth;
// 确保不超出左边界
this.thumbnailTransform = Math.min(0, this.thumbnailTransform);
// 更新thumbnailStartIndex以保持一致性
this.thumbnailStartIndex = Math.max(0, Math.round(-this.thumbnailTransform / this.thumbnailActualWidth));
}
}
// 缩略图向右滚动
scrollThumbnailsRight() {
if (this.canScrollRight()) {
// 每次滚动一个缩略图的宽度
this.thumbnailTransform -= this.thumbnailActualWidth;
// 确保不超出右边界
const maxScroll = this.getMaxThumbnailScroll();
this.thumbnailTransform = Math.max(maxScroll, this.thumbnailTransform);
// 更新thumbnailStartIndex以保持一致性
this.thumbnailStartIndex = Math.max(0, Math.round(-this.thumbnailTransform / this.thumbnailActualWidth));
}
}
// 是否可以向左滚动缩略图
canScrollLeft() {
return this.thumbnailTransform < 0;
}
// 是否可以向右滚动缩略图
canScrollRight() {
if (this.ncImages.length <= this.actualVisibleThumbnailCount) {
return false;
}
const maxScroll = this.getMaxThumbnailScroll();
return this.thumbnailTransform > maxScroll;
}
// 开始自动播放
startAutoPlay() {
this.autoPlayTimer = setInterval(() => {
this.nextImage();
}, this.ncAutoPlayInterval);
}
// 停止自动播放
stopAutoPlay() {
if (this.autoPlayTimer) {
clearInterval(this.autoPlayTimer);
this.autoPlayTimer = null;
}
}
// 鼠标进入时暂停自动播放
onMouseEnter() {
// 如果在全屏模式下,不要自动暂停播放,让用户手动控制
if (this.isFullscreen) {
return;
}
if (this.ncAutoPlay) {
this.stopAutoPlay();
}
}
// 鼠标离开时恢复自动播放
onMouseLeave() {
// 如果在全屏模式下,不要自动恢复播放,让用户手动控制
if (this.isFullscreen) {
return;
}
if (this.ncAutoPlay && this.ncImages.length > 1) {
this.startAutoPlay();
}
}
// 监听窗口大小变化
onWindowResize(event) {
// 使用防抖处理,避免频繁计算
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
this.resizeTimeout = setTimeout(() => {
this.updateActualContainerWidth();
}, 150); // 150ms防抖延迟
}
// 键盘导航支持
onKeyDown(event) {
if (!this.ncImages || this.ncImages.length <= 1) {
return;
}
switch (event.key) {
case 'ArrowLeft':
event.preventDefault();
this.previousImage();
break;
case 'ArrowRight':
event.preventDefault();
this.nextImage();
break;
case 'Home':
event.preventDefault();
this.selectImage(0);
break;
case 'End':
event.preventDefault();
this.selectImage(this.ncImages.length - 1);
break;
}
}
// 图片加载错误处理
onImageError(event) {
// 防止错误图片再次触发错误事件
if (event.target.src.startsWith('data:image/svg+xml')) {
return;
}
console.warn('图片加载失败:', event.target.src);
// 使用SVG占位图
const errorSvg = this.createErrorImageSvg(400, 300);
event.target.src = errorSvg;
event.target.style.objectFit = 'contain';
}
// 缩略图加载错误处理
onThumbnailError(event) {
// 防止错误图片再次触发错误事件
if (event.target.src.startsWith('data:image/svg+xml')) {
return;
}
console.warn('缩略图加载失败:', event.target.src);
// 使用SVG占位图
const errorSvg = this.createErrorImageSvg(this.ncThumbnailWidth, this.ncThumbnailHeight);
event.target.src = errorSvg;
event.target.style.objectFit = 'contain';
}
// 创建错误图片的SVG占位图
createErrorImageSvg(width, height) {
const svg = `
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="#f8f9fa" stroke="#dee2e6" stroke-width="2"/>
<g transform="translate(${width / 2}, ${height / 2})">
<!-- 破损图片图标 -->
<g transform="translate(-24, -24)">
<rect x="4" y="4" width="40" height="32" rx="2" fill="none" stroke="#6c757d" stroke-width="2"/>
<circle cx="14" cy="14" r="2" fill="#6c757d"/>
<path d="M44 28L36 20L24 32L16 24L4 36" stroke="#6c757d" stroke-width="2" fill="none"/>
<!-- X 标记 -->
<line x1="32" y1="8" x2="40" y2="16" stroke="#dc3545" stroke-width="2"/>
<line x1="40" y1="8" x2="32" y2="16" stroke="#dc3545" stroke-width="2"/>
</g>
<!-- 错误文字 -->
<text x="0" y="32" text-anchor="middle" fill="#6c757d" font-family="Arial, sans-serif" font-size="12">
图片加载失败
</text>
</g>
</svg>
`;
// 使用现代方法:直接URL编码,无需base64
return 'data:image/svg+xml,' + encodeURIComponent(svg);
}
// 打开全屏预览
openFullscreen() {
if (this.ncEnableFullscreen) {
this.isFullscreen = true;
// 阻止页面滚动
document.body.style.overflow = 'hidden';
// 重置缩放状态
this.resetFullscreenZoom();
// 检查当前是否有自动播放在运行
const wasAutoPlaying = !!this.autoPlayTimer;
// console.log('打开全屏,当前自动播放状态:', wasAutoPlaying);
// 如果原本有自动播放,在全屏模式下继续播放
if (this.ncAutoPlay && this.ncImages.length > 1) {
this.isFullscreenAutoPlaying = wasAutoPlaying;
// 如果之前没有在播放,需要启动
if (!wasAutoPlaying) {
this.startAutoPlay();
this.isFullscreenAutoPlaying = true;
}
}
}
}
// 关闭全屏预览
closeFullscreen() {
this.isFullscreen = false;
this.isFullscreenAutoPlaying = false;
// 恢复页面滚动
document.body.style.overflow = '';
// 重置缩放状态
this.resetFullscreenZoom();
//先删除autoPlayTimer定时器,防止恢复自动播放时重复autoPlayTimer
if (this.autoPlayTimer) {
clearInterval(this.autoPlayTimer);
this.autoPlayTimer = null;
}
// 退出全屏时恢复自动播放
if (this.ncAutoPlay && this.ncImages.length > 1) {
this.startAutoPlay();
}
}
// 全屏模式下切换自动播放
toggleFullscreenAutoPlay() {
if (!this.isFullscreen || this.ncImages.length <= 1) {
return;
}
// console.log('切换前状态:', this.isFullscreenAutoPlaying, '定时器:', !!this.autoPlayTimer);
if (this.isFullscreenAutoPlaying) {
this.stopAutoPlay();
this.isFullscreenAutoPlaying = false;
// console.log('已暂停自动播放');
}
else {
this.startAutoPlay();
this.isFullscreenAutoPlaying = true;
// console.log('已开始自动播放');
}
}
// 全屏模式下的键盘事件处理
onFullscreenKeyDown(event) {
if (!this.isFullscreen)
return;
switch (event.key) {
case 'Escape':
event.preventDefault();
this.closeFullscreen();
break;
case 'ArrowLeft':
event.preventDefault();
this.previousImage();
break;
case 'ArrowRight':
event.preventDefault();
this.nextImage();
break;
case ' ': // 空格键
event.preventDefault();
if (this.ncAutoPlay) {
this.toggleFullscreenAutoPlay();
}
break;
}
}
// 全屏模式下的滚轮缩放事件
onFullscreenWheel(event) {
if (!this.isFullscreen || !this.ncWheelScale) {
return;
}
event.preventDefault();
event.stopPropagation();
const delta = event.deltaY;
const scaleStep = 0.1;
const rect = event.target.getBoundingClientRect();
// 计算鼠标相对于图片的位置
const mouseX = event.clientX - rect.left - rect.width / 2;
const mouseY = event.clientY - rect.top - rect.height / 2;
const oldScale = this.fullscreenScale;
// 计算新的缩放比例
if (delta < 0) {
// 向上滚动,放大
this.fullscreenScale = Math.min(this.maxScale, this.fullscreenScale + scaleStep);
}
else {
// 向下滚动,缩小
this.fullscreenScale = Math.max(this.minScale, this.fullscreenScale - scaleStep);
}
// 如果缩放比例发生了变化,调整偏移量以保持鼠标位置不变
if (this.fullscreenScale !== oldScale) {
const scaleRatio = this.fullscreenScale / oldScale;
// 调整偏移量,使缩放以鼠标位置为中心
this.fullscreenTranslateX = mouseX + (this.fullscreenTranslateX - mouseX) * scaleRatio;
this.fullscreenTranslateY = mouseY + (this.fullscreenTranslateY - mouseY) * scaleRatio;
// 限制偏移量范围
this.constrainTranslation();
}
}
// 全屏模式下的鼠标按下事件(开始拖拽)
onFullscreenMouseDown(event) {
if (!this.isFullscreen || !this.ncWheelScale || this.fullscreenScale <= 1) {
return;
}
event.preventDefault();
this.isDragging = true;
this.lastMouseX = event.clientX;
this.lastMouseY = event.clientY;
// 改变鼠标样式
document.body.style.cursor = 'grabbing';
}
// 全屏模式下的鼠标移动事件(拖拽中)
onFullscreenMouseMove(event) {
if (!this.isFullscreen || !this.ncWheelScale || !this.isDragging) {
return;
}
event.preventDefault();
const deltaX = event.clientX - this.lastMouseX;
const deltaY = event.clientY - this.lastMouseY;
this.fullscreenTranslateX += deltaX;
this.fullscreenTranslateY += deltaY;
// 限制偏移量范围
this.constrainTranslation();
this.lastMouseX = event.clientX;
this.lastMouseY = event.clientY;
}
// 全屏模式下的鼠标松开事件(结束拖拽)
onFullscreenMouseUp(event) {
if (!this.isFullscreen || !this.ncWheelScale) {
return;
}
this.isDragging = false;
document.body.style.cursor = '';
}
// 限制图片偏移量范围
constrainTranslation() {
if (this.fullscreenScale <= 1) {
this.fullscreenTranslateX = 0;
this.fullscreenTranslateY = 0;
return;
}
// 获取全屏图片的实际显示尺寸(考虑object-fit: contain)
const viewportWidth = window.innerWidth * 0.9; // 90vw
const viewportHeight = window.innerHeight * 0.9; // 90vh
// 计算图片在当前缩放下超出视口的部分
const scaledWidth = viewportWidth * this.fullscreenScale;
const scaledHeight = viewportHeight * this.fullscreenScale;
const maxTranslateX = Math.max(0, (scaledWidth - window.innerWidth) / 2);
const maxTranslateY = Math.max(0, (scaledHeight - window.innerHeight) / 2);
// 限制X轴偏移
this.fullscreenTranslateX = Math.max(-maxTranslateX, Math.min(maxTranslateX, this.fullscreenTranslateX));
// 限制Y轴偏移
this.fullscreenTranslateY = Math.max(-maxTranslateY, Math.min(maxTranslateY, this.fullscreenTranslateY));
}
// 获取全屏图片的transform样式
getFullscreenImageTransform() {
// 先平移再缩放,这样平移的像素值不会被缩放影响
return `translate(${this.fullscreenTranslateX}px, ${this.fullscreenTranslateY}px) scale(${this.fullscreenScale})`;
}
// 双击重置缩放
onFullscreenDoubleClick(event) {
if (!this.isFullscreen || !this.ncWheelScale) {
return;
}
event.preventDefault();
this.resetFullscreenZoom();
}
}
GalleriaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: GalleriaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
GalleriaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.1.5", type: GalleriaComponent, selector: "nc-galleria", inputs: { ncImages: "ncImages", ncWidth: "ncWidth", ncHeight: "ncHeight", ncThumbnailWidth: "ncThumbnailWidth", ncThumbnailHeight: "ncThumbnailHeight", ncObjectFit: "ncObjectFit", ncAutoPlay: "ncAutoPlay", ncAutoPlayInterval: "ncAutoPlayInterval", ncShowThumbnails: "ncShowThumbnails", ncShowIndicators: "ncShowIndicators", ncIndicatorsPosition: "ncIndicatorsPosition", ncShowNavButtons: "ncShowNavButtons", ncNavButtonsDisplay: "ncNavButtonsDisplay", ncEnableFullscreen: "ncEnableFullscreen", ncFullscreenButtonDisplay: "ncFullscreenButtonDisplay", ncShowIndex: "ncShowIndex", ncShowTitle: "ncShowTitle", ncWheelScale: "ncWheelScale" }, host: { listeners: { "window:resize": "onWindowResize($event)", "keydown": "onKeyDown($event)" } }, viewQueries: [{ propertyName: "galleriaContainer", first: true, predicate: ["galleriaContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"nc-galleria\" #galleriaContainer [style.width]=\"ncWidth\" [style.height]=\"ncHeight\"\r\n (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\" tabindex=\"0\" role=\"img\"\r\n [attr.aria-label]=\"'\u56FE\u7247\u753B\u5ECA\uFF0C\u5F53\u524D\u7B2C' + (currentIndex + 1) + '\u5F20\uFF0C\u5171' + ncImages.length + '\u5F20'\"\r\n *ngIf=\"ncImages && ncImages.length > 0\">\r\n\r\n <!-- \u4E3B\u56FE\u663E\u793A\u533A\u57DF -->\r\n <div class=\"galleria-main\">\r\n <div class=\"main-image-container\" [class.nav-hover-mode]=\"ncNavButtonsDisplay === 'hover'\"\r\n [class.full-hover-mode]=\"ncFullscreenButtonDisplay === 'hover'\">\r\n <img [src]=\"ncImages[currentIndex].src\" [style.object-fit]=\"ncObjectFit\" [alt]=\"'\u56FE\u7247 ' + (currentIndex + 1)\"\r\n [class.clickable]=\"ncEnableFullscreen\" (error)=\"onImageError($event)\"\r\n (click)=\"ncEnableFullscreen && openFullscreen()\" class=\"main-image\">\r\n\r\n <!-- \u6570\u76EE\u4FE1\u606F -->\r\n <div class=\"index-container\" *ngIf=\"ncShowIndex && ncImages.length > 1\">\r\n {{currentIndex + 1}} / {{ncImages.length}}\r\n </div>\r\n\r\n <!-- \u6807\u9898\u4FE1\u606F -->\r\n <div class=\"title-container\" *ngIf=\"ncShowTitle && ncImages[currentIndex].title\">\r\n {{ncImages[currentIndex].title}}\r\n </div>\r\n\r\n <!-- \u5168\u5C4F\u6309\u94AE -->\r\n <button class=\"fullscreen-button\" *ngIf=\"ncEnableFullscreen && ncFullscreenButtonDisplay !== 'hidden'\"\r\n (click)=\"openFullscreen()\" [attr.aria-label]=\"'\u5168\u5C4F\u9884\u89C8'\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path\r\n d=\"M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3\"\r\n stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n <!-- \u5BFC\u822A\u6309\u94AE -->\r\n <button class=\"nav-button nav-prev\" (click)=\"previousImage()\"\r\n *ngIf=\"ncShowNavButtons && ncImages.length > 1\" [attr.aria-label]=\"'\u4E0A\u4E00\u5F20\u56FE\u7247'\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M15 18L9 12L15 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n <button class=\"nav-button nav-next\" (click)=\"nextImage()\" *ngIf=\"ncShowNavButtons && ncImages.length > 1\"\r\n [attr.aria-label]=\"'\u4E0B\u4E00\u5F20\u56FE\u7247'\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M9 18L15 12L9 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n <!-- \u5185\u90E8\u6307\u793A\u5668 -->\r\n <div class=\"indicators indicators-inside\"\r\n *ngIf=\"ncShowIndicators && ncIndicatorsPosition === 'inside' && ncImages.length > 1\">\r\n <span class=\"indicator\" *ngFor=\"let image of ncImages; let i = index\"\r\n [class.active]=\"i === currentIndex\" [attr.aria-label]=\"'\u8DF3\u8F6C\u5230\u7B2C' + (i + 1) + '\u5F20\u56FE\u7247'\" role=\"button\"\r\n tabindex=\"0\" (click)=\"selectImage(i)\" (keydown.enter)=\"selectImage(i)\"\r\n (keydown.space)=\"selectImage(i)\">\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u7F29\u7565\u56FE\u5BFC\u822A -->\r\n <div class=\"galleria-thumbnails\" *ngIf=\"ncShowThumbnails && ncImages.length > 1\">\r\n <div class=\"thumbnails-container\">\r\n <!-- \u5DE6\u6EDA\u52A8\u6309\u94AE -->\r\n <button class=\"scroll-button scroll-left\" (click)=\"scrollThumbnailsLeft()\"\r\n *ngIf=\"!shouldCenterThumbnails && canScrollLeft()\" [attr.aria-label]=\"'\u5411\u5DE6\u6EDA\u52A8\u7F29\u7565\u56FE'\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M15 18L9 12L15 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n <!-- \u7F29\u7565\u56FE\u5217\u8868 -->\r\n <div class=\"thumbnails-list-container\">\r\n <div class=\"thumbnails-list\" [class.center-thumbnails]=\"shouldCenterThumbnails\"\r\n [style.transform]=\"shouldCenterThumbnails ? 'none' : 'translateX(' + thumbnailTransform + 'px)'\">\r\n <div class=\"thumbnail-item\" *ngFor=\"let image of ncImages; let i = index\"\r\n [class.active]=\"i === currentIndex\" [style.width.px]=\"ncThumbnailWidth\"\r\n [style.height.px]=\"ncThumbnailHeight\" [attr.aria-label]=\"'\u7F29\u7565\u56FE ' + (i + 1)\" role=\"button\"\r\n tabindex=\"0\" (click)=\"selectImage(i)\" (keydown.enter)=\"selectImage(i)\"\r\n (keydown.space)=\"selectImage(i)\">\r\n <img [src]=\"image.src\" [alt]=\"'\u7F29\u7565\u56FE ' + (i + 1)\" (error)=\"onThumbnailError($event)\"\r\n class=\"thumbnail-image\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- \u53F3\u6EDA\u52A8\u6309\u94AE -->\r\n <button class=\"scroll-button scroll-right\" (click)=\"scrollThumbnailsRight()\"\r\n *ngIf=\"!shouldCenterThumbnails && canScrollRight()\" [attr.aria-label]=\"'\u5411\u53F3\u6EDA\u52A8\u7F29\u7565\u56FE'\">\r\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M9 18L15 12L9 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- \u5916\u90E8\u6307\u793A\u5668 -->\r\n <div class=\"indicators indicators-outside\"\r\n *ngIf=\"ncShowIndicators && ncIndicatorsPosition === 'outside' && ncImages.length > 1\"\r\n [ngStyle]=\"{'margin-top': ncShowThumbnails ? '0' : '12px'}\">\r\n <span class=\"indicator\" *ngFor=\"let image of ncImages; let i = index\" [class.active]=\"i === currentIndex\"\r\n [attr.aria-label]=\"'\u8DF3\u8F6C\u5230\u7B2C' + (i + 1) + '\u5F20\u56FE\u7247'\" role=\"button\" tabindex=\"0\" (click)=\"selectImage(i)\"\r\n (keydown.enter)=\"selectImage(i)\" (keydown.space)=\"selectImage(i)\">\r\n </span>\r\n </div>\r\n</div>\r\n\r\n<!-- \u7A7A\u72B6\u6001 -->\r\n<div class=\"galleria-empty\" [style.width]=\"ncWidth\" [style.height]=\"ncHeight\"\r\n *ngIf=\"!ncImages || ncImages.length === 0\">\r\n <div class=\"empty-content\">\r\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 24 24\" fill=\"none\" class=\"empty-icon\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n <polyline points=\"21,15 16,10 5,21\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n </svg>\r\n <p>\u6682\u65E0\u56FE\u7247</p>\r\n </div>\r\n</div>\r\n\r\n<!-- \u5168\u5C4F\u9884\u89C8\u6A21\u6001\u6846 -->\r\n<div class=\"fullscreen-modal\" *ngIf=\"isFullscreen\" (click)=\"closeFullscreen()\" (keydown)=\"onFullscreenKeyDown($event)\"\r\n tabindex=\"0\">\r\n <div class=\"fullscreen-content\" (click)=\"$event.stopPropagation()\">\r\n <!-- \u5173\u95ED\u6309\u94AE -->\r\n <button class=\"fullscreen-close\" (click)=\"closeFullscreen()\" [attr.aria-label]=\"'\u5173\u95ED\u5168\u5C4F'\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n </svg>\r\n </button>\r\n\r\n <!-- \u64AD\u653E/\u6682\u505C\u6309\u94AE -->\r\n <button class=\"fullscreen-play-pause\" *ngIf=\"ncAutoPlay && ncImages.length > 1\"\r\n (click)=\"toggleFullscreenAutoPlay()\" [attr.aria-label]=\"isFullscreenAutoPlaying ? '\u6682\u505C\u81EA\u52A8\u64AD\u653E' : '\u5F00\u59CB\u81EA\u52A8\u64AD\u653E'\">\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n *ngIf=\"!isFullscreenAutoPlaying\">\r\n <!-- \u64AD\u653E\u56FE\u6807 -->\r\n <polygon points=\"5,3 19,12 5,21\" fill=\"currentColor\" />\r\n </svg>\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"\r\n *ngIf=\"isFullscreenAutoPlaying\">\r\n <!-- \u6682\u505C\u56FE\u6807 -->\r\n <rect x=\"6\" y=\"4\" width=\"4\" height=\"16\" fill=\"currentColor\" />\r\n <rect x=\"14\" y=\"4\" width=\"4\" height=\"16\" fill=\"currentColor\" />\r\n </svg>\r\n </button>\r\n\r\n <!-- \u7F29\u653E\u63D0\u793A -->\r\n <div class=\"fullscreen-zoom-hint\" *ngIf=\"ncWheelScale\">\r\n <div class=\"zoom-hint-content\">\r\n <span>\u6EDA\u8F6E\u7F29\u653E \u2022 \u62D6\u62FD\u5E73\u79FB \u2022 \u53CC\u51FB\u91CD\u7F6E</span>\r\n </div>\r\n </div>\r\n\r\n <!-- \u5168\u5C4F\u56FE\u7247 -->\r\n <img [src]=\"ncImages[currentIndex].src\" [alt]=\"'\u5168\u5C4F\u9884\u89C8 - \u56FE\u7247 ' + (currentIndex + 1)\" (error)=\"onImageError($event)\"\r\n class=\"fullscreen-image\" [class.scalable]=\"ncWheelScale\"\r\n [style.transform]=\"ncWheelScale ? getFullscreenImageTransform() : ''\"\r\n [style.cursor]=\"ncWheelScale && fullscreenScale > 1 ? 'grab' : (ncWheelScale ? 'zoom-in' : '')\"\r\n (wheel)=\"onFullscreenWheel($event)\" (mousedown)=\"onFullscreenMouseDown($event)\"\r\n (mousemove)=\"onFullscreenMouseMove($event)\" (mouseup)=\"onFullscreenMouseUp($event)\"\r\n (mouseleave)=\"onFullscreenMouseUp($event)\" (dblclick)=\"onFullscreenDoubleClick($event)\">\r\n\r\n <!-- \u5168\u5C4F\u5BFC\u822A\u6309\u94AE -->\r\n <button class=\"fullscreen-nav fullscreen-nav-prev\" (click)=\"previousImage()\" *ngIf=\"ncImages.length > 1\"\r\n [attr.aria-label]=\"'\u4E0A\u4E00\u5F20\u56FE\u7247'\">\r\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M15 18L9 12L15 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n <button class=\"fullscreen-nav fullscreen-nav-next\" (click)=\"nextImage()\" *ngIf=\"ncImages.length > 1\"\r\n [attr.aria-label]=\"'\u4E0B\u4E00\u5F20\u56FE\u7247'\">\r\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\r\n <path d=\"M9 18L15 12L9 6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n\r\n <!-- \u5168\u5C4F\u6307\u793A\u5668 -->\r\n <div class=\"fullscreen-indicators\" *ngIf=\"ncImages.length > 1\">\r\n <span class=\"fullscreen-indicator\" *ngFor=\"let image of ncImages; let i = index\"\r\n [class.active]=\"i === currentIndex\" [attr.aria-label]=\"'\u8DF3\u8F6C\u5230\u7B2C' + (i + 1) + '\u5F20\u56FE\u7247'\" role=\"button\"\r\n tabindex=\"0\" (click)=\"selectImage(i)\" (keydown.enter)=\"selectImage(i)\" (keydown.space)=\"selectImage(i)\">\r\n </span>\r\n </div>\r\n\r\n <!-- \u56FE\u7247\u4FE1\u606F -->\r\n <div class=\"fullscreen-info\">\r\n <span>{{currentIndex + 1}} / {{ncImages.length}}</span>\r\n <span *ngIf=\"ncWheelScale\" class=\"zoom-status\">\r\n {{ (fullscreenScale * 100).toFixed(0) }}%\r\n </span>\r\n <span *ngIf=\"ncAutoPlay && ncImages.length > 1\" class=\"autoplay-status\">\r\n {{ isFullscreenAutoPlaying ? '\u81EA\u52A8\u64AD\u653E\u4E2D' : '\u5DF2\u6682\u505C' }}\r\n </span>\r\n </div>\r\n </div>\r\n</div>", styles: [".nc-galleria{display:flex;flex-direction:column;background:#fff;box-shadow:0 4px 12px #0000001a;overflow:hidden;user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.nc-galleria .galleria-main{position:relative;background:#f8f9fa;flex:1;min-height:0}.nc-galleria .galleria-main .main-image-container{position:relative;width:100%;height:100%;overflow:hidden;display:flex;align-items:center;justify-content:center;background-color:#e5e5e5}.nc-galleria .galleria-main .main-image-container .main-image{width:100%;height:100%;transition:opacity .3s ease;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}.nc-galleria .galleria-main .main-image-container .main-image.clickable{cursor:pointer}.nc-galleria .galleria-main .main-image-container .nav-button{position:absolute;top:50%;transform:translateY(-50%);width:40px;height:40px;border:none;border-radius:50%;background:rgba(0,0,0,.4);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s ease;z-index:2;outline:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.nc-galleria .galleria-main .main-image-container .nav-button:hover{background:rgba(0,0,0,.6);transform:translateY(-50%) scale(1.1)}.nc-galleria .galleria-main .main-image-container .nav-button:focus{outline:none}.nc-galleria .galleria-main .main-image-container .nav-button:active{outline:none;background:rgba(0,0,0,.9)}.nc-galleria .galleria-main .main-image-container .nav-button.nav-prev{left:16px}.nc-galleria .galleria-main .main-image-container .nav-button.nav-next{right:16px}.nc-galleria .galleria-main .main-image-container .nav-button svg{width:24px;height:24px}.nc-galleria .galleria-main .main-image-container.nav-hover-mode .nav-button{opacity:0;visibility:hidden;transition:all .3s ease}.nc-galleria .galleria-main .main-image-container.nav-hover-mode:hover .nav-button{opacity:1;visibility:visible}.nc-galleria .galleria-main .main-image-container .indicators-inside{position:absolute;bottom:16px;left:50%;transform:translate(-50%);display:flex;justify-content:center;grid-gap:6px;gap:6px;z-index:3}.nc-galleria .galleria-main .main-image-container .indicators-inside .indicator{width:10px;height:10px;border-radius:50%;background:rgba(255,255,255,.6);cursor:pointer;transition:all .2s ease;border:1px solid rgba(0,0,0,.2)}.nc-galleria .galleria-main .main-image-container .indicators-inside .indicator:hover{background:rgba(255,255,255,.8)}.nc-galleria .galleria-main .main-image-container .indicators-inside .indicator.active{background:#007bff;box-shadow:0 0 4px #0000004d}.nc-galleria .galleria-main .main-image-container .fullscreen-button{position:absolute;top:16px;right:16px;width:36px;height:36px;border:none;border-radius:6px;background:rgba(0,0,0,.6);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s ease;z-index:3;opacity:.8}.nc-galleria .galleria-main .main-image-container .fullscreen-button:hover{background:rgba(0,0,0,.8);opacity:1;transform:scale(1.05)}.nc-galleria .galleria-main .main-image-container.full-hover-mode .fullscreen-button{opacity:0;visibility:hidden;transition:all .3s ease}.nc-galleria .galleria-main .main-image-container.full-hover-mode:hover .fullscreen-button{opacity:1;visibility:visible}.nc-galleria .galleria-main .main-image-container .index-container{position:absolute;top:14px;left:50%;transform:translate(-50%);color:#fff;font-size:16px;background:rgba(0,0,0,.3);padding:2px 16px;border-radius:20px}.nc-galleria .galleria-main .main-image-container .title-container{position:absolute;bottom:10px;right:10px;color:#fff;font-size:16px;background:rgba(0,0,0,.5);padding:2px 16px;border-radius:20px}.nc-galleria .galleria-thumbnails{background:#fff;padding:16px;border-top:1px solid #e9ecef;flex-shrink:0}.nc-galleria .galleria-thumbnails .thumbnails-container{display:flex;align-items:center;grid-gap:8px;gap:8px;position:relative;width:100%}.nc-galleria .galleria-thumbnails .thumbnails-container .scroll-button{flex-shrink:0;width:32px;height:32px;border:1px solid #dee2e6;border-radius:4px;background:#fff;color:#6c757d;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s ease;outline:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.nc-galleria .galleria-thumbnails .thumbnails-container .scroll-button:hover{background:#f8f9fa;border-color:#adb5bd;color:#495057}.nc-galleria .galleria-thumbnails .thumbnails-container .scroll-button:focus{outline:none}.nc-galleria .galleria-thumbnails .thumbnails-container .scroll-button:active{outline:none;background:#e9ecef}.nc-galleria .galleria-thumbnails .thumbnails-container .scroll-button svg{width:16px;height:16px}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list-container{overflow:hidden;position:relative;flex:1;min-width:0}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list{display:flex;align-items:center;grid-gap:8px;gap:8px;justify-content:flex-start;transition:transform .4s cubic-bezier(.25,.46,.45,.94);will-change:transform}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list.center-thumbnails{justify-content:center}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list .thumbnail-item{flex-shrink:0;border:2px solid transparent;border-radius:4px;overflow:hidden;cursor:pointer;transition:all .2s ease;position:relative;opacity:.6}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list .thumbnail-item:hover{opacity:1}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list .thumbnail-item.active{border-color:#007bff91;box-shadow:0 0 0 2px #fffc;opacity:1}.nc-galleria .galleria-thumbnails .thumbnails-container .thumbnails-list .thumbnail-item .thumbnail-image{width:100%;height:100%;object-fit:cover;display:block;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}.nc-galleria .indicators-outside{display:flex;justify-content:center;grid-gap:6px;gap:6px;margin-bottom:12px}.nc-galleria .indicators-outside .indicator{width:10px;height:10px;border-radius:50%;background:#dee2e6;cursor:pointer;transition:all .2s ease}.nc-galleria .indicators-outside .indicator:hover{background:#adb5bd}.nc-galleria .indicators-outside .indicator.active{background:#007bff}.galleria-empty{display:flex;align-items:center;justify-content:center;background:#f8f9fa;border-radius:8px;border:2px dashed #dee2e6;box-sizing:border-box}.galleria-empty .empty-content{text-align:center;color:#6c757d}.galleria-empty .empty-content .empty-icon{margin-bottom:16px;opacity:.5}.galleria-empty .empty-content p{margin:0;font-size:16px}.fullscreen-modal{position:fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,.95);z-index:9999;display:flex;align-items:center;justify-content:center;animation:fadeIn .3s ease}.fullscreen-modal .fullscreen-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.fullscreen-modal .fullscreen-close{position:absolute;top:20px;right:20px;width:44px;height:44px;border:none;border-radius:50%;background:rgba(255,255,255,.2);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s ease;z-index:10}.fullscreen-modal .fullscreen-close:hover{background:rgba(255,255,255,.3);transform:scale(1.1)}.fullscreen-modal .fullscreen-play-pause{position:absolute;top:20px;right:80px;width:44px;height:44px;border:none;border-radius:50%;background:rgba(255,255,255,.2);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s ease;z-index:10}.fullscreen-modal .fullscreen-play-pause:hover{background:rgba(255,255,255,.3);transform:scale(1.1)}.fullscreen-modal .fullscreen-zoom-hint{position:absolute;top:20px;left:20px;z-index:10;opacity:.7;animation:fadeInOut 4s ease-in-out}.fullscreen-modal .fullscreen-zoom-hint .zoom-hint-content{background:rgba(0,0,0,.6);color:#fff;padding:8px 16px;border-radius:20px;font-size:14px;white-space:nowrap}.fullscreen-modal .fullscreen-image{max-width:90vw;max-height:90vh;object-fit:contain;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;transition:transform .1s ease-out;transform-origin:center center}.fullscreen-modal .fullscreen-nav{position:absolute;top:50%;transform:translateY(-50%);width:60px;height:60px;border:none;border-radius:50%;background:rgba(255,255,255,.2);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .3s ease;z-index:10}.fullscreen-modal .fullscreen-nav:hover{background:rgba(255,255,255,.3);transform:translateY(-50%) scale(1.1)}.fullscreen-modal .fullscreen-nav.fullscreen-nav-prev{left:30px}.fullscreen-modal .fullscreen-nav.fullscreen-nav-next{right:30px}.fullscreen-modal .fullscreen-indicators{position:absolute;bottom:30px;left:50%;transform:translate(-50%);display:flex;grid-gap:8px;gap:8px;z-index:10}.fullscreen-modal .fullscreen-indicators .fullscreen-indicator{width:12px;height:12px;border-radius:50%;background:rgba(255,255,255,.5);cursor:pointer;transition:all .3s ease}.fullscreen-modal .fullscreen-indicators .fullscreen-indicator:hover{background:rgba(255,255,255,.8);transform:scale(1.2)}.fullscreen-modal .fullscreen-indicators .fullscreen-indicator.active{background:white;transform:scale(1.3)}.fullscreen-modal .fullscreen-info{position:absolute;bottom:20px;right:20px;color:#fff;font-size:16px;background:rgba(0,0,0,.5);padding:8px 16px;border-radius:20px;z-index:10}.fullscreen-modal .fullscreen-info .zoom-status{margin-left:12px;font-size:14px;opacity:.8}.fullscreen-modal .fullscreen-info .zoom-status:before{content:\"\\2022\";margin-right:6px}.fullscreen-modal .fullscreen-info .autoplay-status{margin-left:12px;font-size:14px;opacity:.8}.fullscreen-modal .fullscreen-info .autoplay-status:before{content:\"\\2022\";margin-right:6px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeInOut{0%{opacity:0}10%{opacity:.7}90%{opacity:.7}to{opacity:0}}\n"], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: GalleriaComponent, decorators: [{
type: Component,
args: [{
selector: 'nc-galleria',
templateUrl: './galleria.component.html',
styleUrls: ['./galleria.component.less']
}]
}], ctorParameters: function () { return []; }, propDecorators: { ncImages: [{
type: Input
}], ncWidth: [{
type: Input
}], ncHeight: [{
type: Input
}], ncThumbnailWidth: [{
type: Input
}], ncThumbnailHeight: [{
type: Input
}], ncObjectFit: [{
type: Input
}], ncAutoPlay: [{
type: Input
}], ncAutoPlayInterval: [{
type: Input
}], ncShowThumbnails: [{
type: Input
}], ncShowIndicators: [{
type: Input
}], ncIndicatorsPosition: [{
type: Input
}], ncShowNavButtons: [{
type: Input
}], ncNavButtonsDisplay: [{
type: Input
}], ncEnableFullscreen: [{
type: Input
}], ncFullscreenButtonDisplay: [{
type: Input
}], ncShowIndex: [{
type: Input
}], ncShowTitle: [{
type: Input
}], ncWheelScale: [{
type: Input
}], galleriaContainer: [{
type: ViewChild,
args: ['galleriaContainer', { static: false }]
}], onWindowResize: [{
type: HostListener,
args: ['window:resize', ['$event']]
}], onKeyDown: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FsbGVyaWEuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvY29tcG9uZW50cy9nYWxsZXJpYS9nYWxsZXJpYS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2dhbGxlcmlhL2dhbGxlcmlhLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQWEsS0FBSyxFQUFFLFNBQVMsRUFBNkIsWUFBWSxFQUE0QixNQUFNLGVBQWUsQ0FBQzs7O0FBaUIxSSxNQUFNLE9BQU8saUJBQWlCO0lBZ001QjtRQS9MQSxXQUFXO1FBQ0gsWUFBTyxHQUFzQixFQUFFLENBQUM7UUFnQnhDLFdBQVc7UUFDRixZQUFPLEdBQVcsTUFBTSxDQUFDO1FBQ2xDLFdBQVc7UUFDRixhQUFRLEdBQVcsTUFBTSxDQUFDO1FBQ25DLFlBQVk7UUFDSCxxQkFBZ0IsR0FBVyxFQUFFLENBQUM7UUFDdkMsWUFBWTtRQUNILHNCQUFpQixHQUFXLEVBQUUsQ0FBQztRQUN4QyxhQUFhO1FBQ0osZ0JBQVcsR0FBb0IsU0FBUyxDQUFDO1FBQ2xELFdBQVc7UUFDSCxjQUFTLEdBQVksS0FBSyxDQUFDO1FBUW5DLGFBQWE7UUFDSix1QkFBa0IsR0FBVyxJQUFJLENBQUM7UUFDM0MsWUFBWTtRQUNKLG9CQUFlLEdBQVksSUFBSSxDQUFDO1FBUXhDLFlBQVk7UUFDSixvQkFBZSxHQUFZLEtBQUssQ0FBQztRQVF6QyxjQUFjO1FBQ0wseUJBQW9CLEdBQTZCLFNBQVMsQ0FBQztRQUNwRSxhQUFhO1FBQ0wsb0JBQWUsR0FBWSxLQUFLLENBQUM7UUFRekMsZUFBZTtRQUNOLHdCQUFtQixHQUE0QixRQUFRLENBQUM7UUFDakUsYUFBYTtRQUNMLHNCQUFpQixHQUFZLEtBQUssQ