UNPKG

tsp-component

Version:

提供多端和react版本的UI组件

225 lines (202 loc) 5.91 kB
/// <reference path="./definition.d.ts" /> import * as React from 'react'; import { setTranslate } from '../util/animation'; const prefix = 'tsp-component-slider'; class Silder { constructor(params?: TspComponentSliderConstructorParams) { this.sliderElem = params.sliderElem; this.containerElem = params.containerElem; this.count = params.count; this.direction = params.direction; // this.swipeable = params.swipeable || true; this.width = params.width; this.height = params.height; this.selectedIndex = params.selectedIndex; this.afterChangeIndexs = { beforeSelectIndex: this.selectedIndex, afterSelectedIndex: this.selectedIndex }; this.panStart = this.panStart.bind(this); this.panMove = this.panMove.bind(this); this.panEnd = this.panEnd.bind(this); this.sliderMove = this.sliderMove.bind(this); this.getMoveBeforePosition = this.getMoveBeforePosition.bind(this); this.setMoveAfterSelectedIndex = this.setMoveAfterSelectedIndex.bind(this); this.getPanEndDistance = this.getPanEndDistance.bind(this); this.addPanEndClass = this.addPanEndClass.bind(this); this.removePanEndClass = this.removePanEndClass.bind(this); } /** * 滑动方向 */ private direction: TspComponentSliderModel; /** * 宽度 */ private width: number; /** * 高度 */ private height: number; /** * 当前索引 */ public selectedIndex: number; /** * 滑块个数 */ public count: number; /** * 滑动完成后的回调返回的索引值 */ public afterChangeIndexs: TspComponentSliderAfterChangeReturn; /** * 滑动是否结束 */ public isPanEnd: boolean = true; /** * 滑动容器 */ public sliderElem: HTMLElement; /** * 组件顶层容器 */ public containerElem: HTMLElement; /** * 滑动时移动的距离 */ public panDistance: number; /** * 是否超过临界值 */ private get isCritical(): boolean { const model = this.direction === 'horizontal' ? 'width' : 'height'; return this[model] * 0.25 <= this.panDistance; } /** * 标量,用于计算位移 */ private get scalar(): [number, string] { return this.direction === 'horizontal' ? [this.width, 'deltaX'] : [this.height, 'deltaY']; } /** * 开始滑动 */ public panStart(): void { this.isPanEnd = false; this.removePanEndClass(); } /** * 滑动中 */ public panMove(evt: TspComponentSliderEvt): void { // 禁止滑动就不执行下面 if (this.isPanEnd) { return; } if (evt.distance < this.width * 0.9) { const position = this.getMoveBeforePosition(); const moveDistance = { x: position.x ? position.x + evt.deltaX : 0, y: position.y ? position.y + evt.deltaY : 0 }; this.panDistance = evt.distance; this.sliderMove(moveDistance.x , moveDistance.y); } else { this.panEnd(evt); } } /** * 滑动结束 */ public panEnd(evt: TspComponentSliderEvt): void { // 禁止滑动就不执行下面, onPanEnd方法是否已触发 if (this.isPanEnd) { return; } const beforeSelectIndex = this.selectedIndex; const isChangeSlectedIndex = this.setMoveAfterSelectedIndex(evt); const position = this.getPanEndDistance(evt, isChangeSlectedIndex); this.isPanEnd = true; this.afterChangeIndexs = { beforeSelectIndex, afterSelectedIndex: this.selectedIndex }; this.addPanEndClass(); this.sliderMove(position.x, position.y); } /** * 改变索引 */ public onChangeSelectedIndex(evt: TspComponentSliderEvt, selectedIndex: number): void { const position = this.getPanEndDistance(evt, true); const children = this.sliderElem.children; this.afterChangeIndexs = { beforeSelectIndex: this.selectedIndex, afterSelectedIndex: selectedIndex }; this.selectedIndex = selectedIndex; this.addPanEndClass(); this.sliderMove(position.x, position.y); } /** * 移动滑块容器 */ public sliderMove(x: number, y: number): void { setTranslate(this.sliderElem, x, y); } /** * 获取移动前的初始化位置 */ public getMoveBeforePosition(): { x: number, y: number } { return { x: this.direction === 'horizontal' ? -this.width : 0, y: this.direction === 'vertical' ? -this.height : 0 }; } /** * 设置移动后的索引值,如果索引改变为ture */ public setMoveAfterSelectedIndex(evt: TspComponentSliderEvt): boolean { if (!this.isCritical) { return false; } const count = this.count - 1; if (evt[this.scalar[1]] < 0) { this.selectedIndex = this.selectedIndex === count ? 0 : this.selectedIndex + 1; } else { this.selectedIndex = this.selectedIndex === 0 ? count : this.selectedIndex - 1; } return true; } /** * 获取滑动完成后需要移动的距离 */ public getPanEndDistance(evt: TspComponentSliderEvt, isChangeSlectedIndex: boolean): { x: number, y: number } { let value = -this.scalar[0]; if (isChangeSlectedIndex) { if (evt[this.scalar[1]] < 0) { value = 2 * -this.scalar[0]; } else { value = 0; } } return { x: this.direction === 'horizontal' ? value : 0, y: this.direction === 'vertical' ? value : 0 }; } /** * 添加panend样式 */ public addPanEndClass(): void { this.sliderElem.classList.add(`${prefix}-panend`); } /** * 移除panend样式 */ public removePanEndClass(): void { this.sliderElem.classList.remove(`${prefix}-panend`); } } export default Silder;