tsp-component
Version:
提供多端和react版本的UI组件
225 lines (202 loc) • 5.91 kB
text/typescript
/// <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;