virtual scroll for scrolling grids
This commit is contained in:
parent
9aea9c3635
commit
40f519afd6
@ -84,6 +84,8 @@ import { CircleButtonComponent } from './components/buttons/circle-button/circle
|
|||||||
import { ChevronButtonComponent } from './components/buttons/chevron-button/chevron-button.component';
|
import { ChevronButtonComponent } from './components/buttons/chevron-button/chevron-button.component';
|
||||||
import { DictionaryListingScreenComponent } from './screens/admin/dictionary-listing-screen/dictionary-listing-screen.component';
|
import { DictionaryListingScreenComponent } from './screens/admin/dictionary-listing-screen/dictionary-listing-screen.component';
|
||||||
import { CustomTooltipModule } from './common/red-tooltip/custom-tooltip.module';
|
import { CustomTooltipModule } from './common/red-tooltip/custom-tooltip.module';
|
||||||
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
||||||
|
import { VirtualScrollComponent } from './utils/virtual-scroll/virtual-scroll.component';
|
||||||
|
|
||||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||||
@ -135,7 +137,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
|
|||||||
UserButtonComponent,
|
UserButtonComponent,
|
||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
ChevronButtonComponent,
|
ChevronButtonComponent,
|
||||||
DictionaryListingScreenComponent
|
DictionaryListingScreenComponent,
|
||||||
|
VirtualScrollComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@ -152,6 +152,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<redaction-virtual-scroll></redaction-virtual-scroll>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
59
apps/red-ui/src/app/utils/sync-scroll.ts
Normal file
59
apps/red-ui/src/app/utils/sync-scroll.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
export function syncScroll(elements: HTMLElement[]) {
|
||||||
|
// clearing existing listeners
|
||||||
|
for (const element of elements) {
|
||||||
|
element.removeEventListener('scroll', (<any>element).scrollSync);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setting-up the new listeners
|
||||||
|
for (let idx = 0; idx < elements.length; ) {
|
||||||
|
const loopElement: any = elements[idx++];
|
||||||
|
|
||||||
|
loopElement.eX = loopElement.eY = 0;
|
||||||
|
|
||||||
|
((el) => {
|
||||||
|
el['addEventListener'](
|
||||||
|
'scroll',
|
||||||
|
(el.scrollSync = () => {
|
||||||
|
let scrollX = el['scrollLeft'];
|
||||||
|
let scrollY = el['scrollTop'];
|
||||||
|
|
||||||
|
const xRate = scrollX / (el['scrollWidth'] - el['clientWidth']);
|
||||||
|
const yRate = scrollY / (el['scrollHeight'] - el['clientHeight']);
|
||||||
|
|
||||||
|
const updateX = scrollX !== el.eX;
|
||||||
|
const updateY = scrollY !== el.eY;
|
||||||
|
|
||||||
|
let otherEl,
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
el.eX = scrollX;
|
||||||
|
el.eY = scrollY;
|
||||||
|
|
||||||
|
for (; i < elements.length; ) {
|
||||||
|
otherEl = elements[i++];
|
||||||
|
if (otherEl !== el) {
|
||||||
|
if (
|
||||||
|
updateX &&
|
||||||
|
Math.round(
|
||||||
|
otherEl['scrollLeft'] - (scrollX = otherEl.eX = Math.round(xRate * (otherEl['scrollWidth'] - otherEl['clientWidth'])))
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
otherEl['scrollLeft'] = scrollX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
updateY &&
|
||||||
|
Math.round(
|
||||||
|
otherEl['scrollTop'] - (scrollY = otherEl.eY = Math.round(yRate * (otherEl['scrollHeight'] - otherEl['clientHeight'])))
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
otherEl['scrollTop'] = scrollY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
})(loopElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
<div class="virtual-scroll" #scrollElement>
|
||||||
|
<div class="virtual" [style.height]="height + 'px'"></div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
.virtual-scroll {
|
||||||
|
// TODO fix this - pass information as input or such
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
width: 10px;
|
||||||
|
right: 480px;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 100;
|
||||||
|
top: 191px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.virtual {
|
||||||
|
height: 2000px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { AfterViewInit, Component, ElementRef, Input, ViewChild } from '@angular/core';
|
||||||
|
import { syncScroll } from '../sync-scroll';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-virtual-scroll',
|
||||||
|
templateUrl: './virtual-scroll.component.html',
|
||||||
|
styleUrls: ['./virtual-scroll.component.scss']
|
||||||
|
})
|
||||||
|
export class VirtualScrollComponent implements AfterViewInit {
|
||||||
|
@Input() targetQuerySelector = '.red-content';
|
||||||
|
@ViewChild('scrollElement')
|
||||||
|
scrollElement: ElementRef;
|
||||||
|
content: HTMLElement;
|
||||||
|
height: number;
|
||||||
|
factor: number;
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this.content = document.querySelector(this.targetQuerySelector);
|
||||||
|
this.factor = this.content.clientHeight / this.scrollElement.nativeElement.clientHeight;
|
||||||
|
this.height = Math.round(this.content.scrollHeight / this.factor);
|
||||||
|
console.log(this.factor, this.height);
|
||||||
|
syncScroll([this.scrollElement.nativeElement, this.content]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user