12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import BaseFoundation, { DefaultAdapter } from '../base/foundation';
- import { Animation } from '@douyinfe/semi-animation';
- export type BackTopClickEvent = any;
- export type Target = any;
- export interface BackTopAdapter extends DefaultAdapter {
- updateVisible: (visible: boolean) => void;
- notifyClick: (e: BackTopClickEvent) => void;
- targetIsWindow: (target: any) => boolean;
- isWindowUndefined: () => boolean;
- targetScrollToTop: (targetNode: any, scrollTop: number) => void;
- }
- export default class BackTopFoundation extends BaseFoundation<BackTopAdapter> {
- animation!: any;
- constructor(adapter: BackTopAdapter) {
- super({ ...adapter });
- }
- init() {
- const { target } = this.getProps();
- const targetNode = target();
- targetNode.addEventListener('scroll', this.handleScroll);
- this.handleScroll();
- }
- destroy() {
- const { target } = this.getProps();
- const targetNode = target();
- targetNode && targetNode.removeEventListener('scroll', this.handleScroll);
- this.animation && this.animation.destroy();
- }
- getScroll(target: Target) {
- if (this._adapter.isWindowUndefined()) {
- return 0;
- }
- const prop = 'pageYOffset';
- const method = 'scrollTop';
- const isWindow = this._adapter.targetIsWindow(target);
- const scroll = isWindow ? target[prop] : target[method];
- return scroll;
- }
- scrollTo = (targetNode: Target, from: number, to: number) => {
- const { duration } = this.getProps();
- this.animation = new Animation(
- {
- from: { scrollTop: from },
- to: { scrollTop: to },
- },
- {
- duration,
- easing: 'easeInOutCubic'
- }
- );
- this.animation.on('frame', ({ scrollTop }: { scrollTop: number }) => {
- this._adapter.targetScrollToTop(targetNode, scrollTop);
- });
- this.animation.start();
- };
- setScrollTop(to: number) {
- const { target } = this.getProps();
- const targetNode = target();
- const from = this.getScroll(targetNode);
- this.scrollTo(targetNode, from, to);
- }
- handleScroll = () => {
- const { target, visibilityHeight } = this.getProps();
- const targetNode = target();
- const update = () => {
- const scrollTop = this.getScroll(targetNode);
- this._adapter.updateVisible(scrollTop > visibilityHeight);
- };
- requestAnimationFrame(update);
- };
- onClick(e: BackTopClickEvent) {
- this.setScrollTop(0);
- this._adapter.notifyClick(e);
- }
- }
|