123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- import {Component, Mixins, Ref} from "vue-property-decorator";
- import {emitNames} from '../enum/emit';
- import ScrollApi from '../api/scroll';
- import ScrollStatus from './status';
- import {
- Config,
- EventTypes,
- ListenerEventTarget,
- ScrollConfig,
- ScrollXConfig,
- ScrollYConfig
- } from "../types/on";
- @Component({
- created(this:ScrollViewConfig){
- this._config = {};
- this._scrollConfig = {
- look:false,
- stipitate:undefined,
- x:{
- x:0,
- width:0,
- actualWidth:0,
- maxScroll:0
- },
- y:{
- y:0,
- height:0,
- actualHeight:0,
- maxScroll:0
- }
- };
- },
- mounted(this:ScrollViewConfig){
- // 执行安装
- return this.installScroll();
- },
- // 释放组件的时候触发
- beforeDestroy(this:ScrollViewConfig){
- this._scrollApi && this._scrollApi.destroy();
- this._scrollConfig.stipitate&&clearTimeout(this._scrollConfig.stipitate);
- this._scrollApi = undefined;
- this.scrollEl && this._config.scrollUnique && this.removeEventListener(this.scrollEl,'scroll',this._config.scrollUnique);
- }
- })
- export default class ScrollViewConfig extends Mixins(ScrollStatus) {
- // 滚动标签实例
- @Ref('scroll') scrollEl:HTMLElement | undefined;
- // 滚动包容标签实例
- @Ref('scrollTake') scrollTakeEl:HTMLElement | undefined;
- // 运行时的 scrollApi
- _scrollApi:ScrollApi | undefined;
- // 运行时参数
- _config:Config={};
- // 滚动系列参数配置
- _scrollConfig:ScrollConfig={
- look:false,
- stipitate:undefined,
- x:{
- x:0,
- width:0,
- actualWidth:0,
- maxScroll:0
- },
- y:{
- y:0,
- height:0,
- actualHeight:0,
- maxScroll:0
- }
- };
- // 配置滚动系列参数
- setScrollConfig(){
- if (this._scrollConfig.look) return;
- // 设置锁
- this._scrollConfig.look = true;
- // 配置 x 轴
- this.scrollX && this.setScrollAxisConfig('x');
- // 配置 y 轴
- this.scrollY && this.setScrollAxisConfig('y');
- // 帧频率不允许重复
- this._scrollConfig.stipitate = setTimeout(()=>{
- this._scrollConfig.stipitate = undefined;
- this._scrollConfig.look = false;
- },16.66);
- };
- // 配置单独轴系列参数
- setScrollAxisConfig(axis:'x' | 'y'){
- if (this.scrollEl === undefined || this.scrollTakeEl === undefined) return;
- let sizeKey: 'width' | 'height' = axis === 'x' ? 'width':'height';
- let actualKey : 'actualWidth' | 'actualHeight' = axis === 'x' ? 'actualWidth' :'actualHeight';
- let scrollAxis: 'scrollLeft' | 'scrollTop' = axis === 'x'? 'scrollLeft' :'scrollTop';
- let elSizeKey:'offsetWidth' | 'offsetHeight' = axis === 'x' ? 'offsetWidth' :'offsetHeight';
- // 设置配置文件
- // @ts-ignore
- this._scrollConfig[axis] = {
- [sizeKey]: this.scrollEl[elSizeKey] || 0,
- [axis]: this.scrollEl[scrollAxis] || 0,
- [actualKey]: this.scrollTakeEl[elSizeKey] || 0,
- maxScroll:0
- };
- //
- // // 设置最大滚动
- // @ts-ignore
- (this._scrollConfig[axis] as ScrollYConfig | ScrollXConfig).maxScroll = Math.max(0,this._scrollConfig[axis][actualKey] - this._scrollConfig[axis][sizeKey]);
- };
- // 安装
- installScroll(){
- // 设置当前的配置文件
- this.setScrollConfig();
- // 创建滚动Api
- if (this.scrollEl !== undefined) {
- this._scrollApi = new ScrollApi(this._scrollConfig,this.scrollEl);
- }
- // 如果存在此三种的任何一种 事件开启监听
- if (
- (this.$listeners[emitNames.onScroll]
- ||
- this.$listeners[emitNames.onScrollLower]
- ||
- this.$listeners[emitNames.onScrollUpper]) && this.scrollEl !== undefined
- ) {
- // 获取存储的唯一标识
- this._config.scrollUnique = this.addEventListener(this.scrollEl,'scroll',()=> this.onScroll());
- }
- }
- // 滚动时触发
- onScroll(){
- if (this.scrollEl) {
- // 设置配置
- this.setScrollConfig();
- if (this.$listeners[emitNames.onScrollUpper] || this.$listeners[emitNames.onScrollLower]) {
- if (this.scrollY) {
- if ( this.$listeners[emitNames.onScrollLower] && this.testScrollDistance('y','lowerThreshold','_lowerThresholdYStatus')) {
- this.emitScrollLower('y');
- } else if (this.$listeners[emitNames.onScrollUpper] && this.testScrollDistance('y','upperThreshold','_upperThresholdYStatus')) {
- this.emitScrollUpper('y');
- }
- }
- if (this.scrollX) {
- if ( this.$listeners[emitNames.onScrollLower] && this.testScrollDistance('x','lowerThreshold','_lowerThresholdXStatus')) {
- this.emitScrollLower('x');
- } else if (this.$listeners[emitNames.onScrollUpper] && this.testScrollDistance('x','upperThreshold','_upperThresholdXStatus')) {
- this.emitScrollUpper('x');
- }
- }
- }
- if(this.$listeners[emitNames.onScroll]) {
- return this.emitScroll(this._scrollConfig);
- }
- }
- }
- // 校验是否满足条件
- testScrollDistance(axis:'x' | 'y',key:'lowerThreshold' | 'upperThreshold',testKey:'_lowerThresholdXStatus'|'_lowerThresholdYStatus'|'_upperThresholdXStatus'|'_upperThresholdYStatus'){
- if (
- this[key] !== undefined
- &&
- // @ts-ignore
- key === 'upperThreshold' ? this._scrollConfig[axis][axis] <= this[key] : this._scrollConfig[axis].maxScroll - this._scrollConfig[axis][axis] <= this[key]
- ) {
- if (!this[testKey]) {
- this[testKey] = true;
- return true;
- }
- } else {
- this[testKey] = false;
- }
- return false;
- }
- // 监听器对象
- _listeners: { [key:string]:ListenerEventTarget } | undefined = undefined;
- // 添加监听
- addEventListener<T extends EventTypes>(el:HTMLElement,event:T,target:ListenerEventTarget){
- // 如果没有监听器对象创建
- if (this._listeners === undefined) {
- this._listeners = {};
- }
- let unique:string = this.getUnique(event);
- this._listeners[unique] = target;
- if (window.addEventListener !== undefined) {
- el.addEventListener(event,target,{
- passive:true
- });
- } else {
- // @ts-ignore 兼容策略
- el.attachEvent('on'+event,target,{
- passive:true
- });
- }
- return unique;
- }
- // 移除兼容
- removeEventListener<K extends EventTypes>(el:HTMLElement,event:K,unique:string){
- if (this._listeners !== undefined && this._listeners[unique] !== undefined) {
- if (window.removeEventListener !== undefined) {
- el.removeEventListener(event, this._listeners[unique]);
- } else {
- // @ts-ignore 兼容策略
- el.detachEvent('on' + event, this._listeners[unique]);
- }
- return true;
- } else {
- return false;
- }
- }
- // 获取唯一值
- getUnique(value:string=''):string{
- return new Date().getTime() + value + Math.floor(Math.random() * 10000) ;
- }
- }
|