我正在开发一个小型图库组件,它通过 @Input()
将元素作为数组接收。元素本身包含文本或图像:
// [...]
export class SlidesComponent implements OnInit, AfterViewInit {
// currently displayed item index
private _currentItemIndex = 0;
// Width of an item, in this case as wide as the mask (see below)
itemWidth = 0;
// Slides
@Input() slides: SlideInterface[] = [];
// UL which will contain the LIs
@ViewChild( 'ul', { read: ElementRef } ) ul!: ElementRef;
// Mask around the UL
@ViewChild( 'mask', { read: ElementRef } ) mask!: ElementRef;
constructor() {}
ngOnInit(): void {
// [ ... ]
}
ngAfterViewInit(): void {
// Detect Mask size
this.itemWidth = this.mask.nativeElement.getBoundingClientRect().width;
}
// set scrollLeft-Value in template
get listLeft(): number {
return this.itemWidth * this._currentItemIndex;
}
// [ ... ]
}
在模板中,元素在 LI
元素内的 *ngFor
循环中创建为 UL
标签。在此过程中,我会显示文本或图像。
<div class="slides-mask" #mask [scrollLeft]="listLeft">
<ul class="slides" #ul [style.width]="itemWidth * slides.length + 'px'">
<li *ngFor="let item of items"
class="slide"
[style.width]="itemWidth + 'px'">
<ng-container [ngSwitch]="item.type">
<!-- Text -->
<div class="slide-content html-content"
[innerHTML]="item.content"
*ngSwitchCase="'html'"></div>
<!-- Image -->
<my-image *ngSwitchCase="'image'"
[src]="item.content.image.src"></my-image>
<!-- more to come ... -->
</ng-container>
</li>
</ul>
</div>
每个LI
元素与封闭掩码一样宽,其余LI
元素排列在水平轴的UL
中。使用这种方法滚动和滑动手指非常容易,CSS 代码使用 scroll-behavior
、scroll-snap-type
和 scroll-snap-align
处理大部分。
.slides-mask {
width: 100%;
height: 100%;
overflow-x: scroll;
overflow-y: hidden;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
}
.slides {
display: flex;
height: 100%;
flex-flow: row nowrap;
justify-content: space-between;
width: auto;
}
.slide {
scroll-snap-align: start;
}
到目前为止,一切正常。
如果我想从例如开始第三个元素,我可以通过更改属性 [scrollLeft]
在掩码上使用 _currentItemIndex
指定所需的位置。
但这仅在我将 _currentItemIndex
的更改延迟几百毫秒时才有效,这很难看。
为了检查浏览器窗口内的任何大小变化,我添加了一个如下所示的 ResizeObserver。获取大小工作正常,但仍然没有显示所需的幻灯片。
// ...
ngAfterViewInit(): void {
// ...
const r = new ResizeObserver( ( items: any[] ) => {
this.itemWidth = items[ 0 ].contentRect.width;
// Jump to Slide 2
this._currentItemIndex = 1; // <-- this is not working
});
r.observe( this.mask.nativeElement );
}
// ...
当模板中的所有元素渲染完成后,我该如何采取行动?