/** * API 文档 * props default 说明 * step 1 步进值 ✅ * min 0 最小值 ✅ * max 100 最大值 ✅ * width 200 组件的宽度 ✅ * value 0 组件的值 ✅ * grooveWidth 3 slider 滑动槽的宽度 ✅ * grooveRadius 0 slider 滑动槽的 border-radius ✅ * barRadius 15 按钮半径 ✅ * barColor #FFF 按钮颜色 ✅ * barBorderColor #EEE 按钮 border 颜色 ✅ * barType circle 按钮类型, circle[圆] | block[方块] | dount[同心圆环] | custom[自定义slot传入] ✅ * direction row slider 方向, row[横向] | column [纵向] * activeColor #0082ff 选择部分的值的槽颜色 ✅ * inactiveColor #807F7F 未选择部分的槽颜色 ✅ * activeGrooveRadius 0 选择部分的槽的 radius * * * 事件文档 * 事件名 说明 * change (value: number) => {} 值改变之后的回调 * dragStart (dataset: JSONObject) => {} 拖拽开始的回调 * dragEnd (dataset: JSONObject) => {} 拖拽结束的回调 */ import { BaseEvent, ComponentProps, console, Component, Target, setTimeout, TouchEvent, Event } from "waft"; import { JSON, JSONObject } from "waft-json"; import { lodash } from "waft-ui-common"; class StateData { deltaX: i64 = 0; // 移动的偏移量 deltaY: i64 = 0; // 移动的偏移量 startX: i64 = 0; // 初始的位置 startY: i64 = 0; // 初始的位置 min: i64 = 0; // 最小值 max: i64 = 100; // 最大值 barRadius: i64 = 15; // 按钮的半径 step: i64 = 1; // 步进值 stepLength: f64 = 2; // 每步 step 的宽度 width: i64 = 200; // step 的宽度 value: i64 = 0; // 当前的值 baseValue: i64 = 0; // 每次移动的基础值 timer: i64 = 0; // 定时器 canMove: boolean = true; // 节流用, 是否可滑动 direction: string = 'row'; // 滚动方向 } export class Slider extends Component { data: StateData = new StateData(); MIN_DISTANCE: i64 = 10; constructor(props: ComponentProps) { super(props); } /** * 触摸开始事件, 记录当前的点击位置, 方便之后计算点的位置 * @param event */ onTouchStart(e: Event): void { console.log('==== ### 开始点击'); this.resetTouchStatus(); const touch = (e as TouchEvent).changedTouches[0]; this.data.startX = touch.screenX; this.data.startY = touch.screenY; this.data.baseValue = this.format(this.data.value); // ??? this.props.dispatch("onTouchStart", e.target.dataset); } onTouchEnd(e: Event): void { console.log("结束点击"); this.props.dispatch("onTouchEnd", e.target.dataset); } /** * 触摸移动事件, 与初始位置比较, 计算出来对应的 step 值 * @param event */ onTouchMove(e: Event): void { // 节流处理, 每秒 40 帧的速度处理 if (this.data.canMove) { this.data.canMove = false; setTimeout((event, target) => { if (target) { const _this = target as Slider; _this.data.canMove = true; } }, 25, this); // 正式的逻辑处理 // 记录相关数据 const touch = (e as TouchEvent).changedTouches[0]; console.log('====### ' + (touch.screenX - this.data.startX).toString()); this.data.deltaX = touch.screenX - this.data.startX; this.data.deltaY = this.data.startY - touch.screenY; // 计算 step if (this.data.direction == 'row') { const diff = parseInt((this.data.deltaX as f64 / this.data.stepLength).toString()) as i64; console.log('====#### diff 是: ' + diff.toString()); this.data.value = this.data.baseValue + diff; } else if (this.data.direction == 'column') { const diff = parseInt((this.data.deltaY as f64 / this.data.stepLength).toString()) as i64; console.log('====#### diff 是: ' + diff.toString()); this.data.value = this.data.baseValue + diff; } // 边界值判断 if (this.data.value < this.data.min) { this.data.value = this.data.min; } else if (this.data.value > this.data.max) { this.data.value = this.data.max; } let carryData: JSONObject = new JSONObject(); carryData.set("value", this.data.value); this.props.dispatch("onChange", carryData); this.updateValue(this.data.value); } } /** * 将 value 格式化为 step 的倍数 * @param value */ format(value: i64): i64 { let step: i64 = this.data.step; return ((Math.round((value / step) as f64) as i64) * step) as i64; } /** * 更新值 * @param value */ updateValue(value: i64): void { const width = parseInt((value as f64 * this.data.stepLength).toString()) as i64; let changeData: JSONObject = new JSONObject(); changeData.set("activeValue", width); changeData.set("buttonLeft", this.getButtonPosition(width)); this.setState(changeData); } /** * 初始化 (重置) 数据 */ resetTouchStatus(): void { this.data.deltaX = 0; this.data.deltaY = 0; } /** * 获取 button 的位置 (不能超出 slider 本身) * @param value */ getButtonPosition(value: i64): i64 { let res = value - this.data.barRadius; if (res < 0) { res = 0; } else if (res > (this.data.width - this.data.barRadius * 2)) { res = this.data.width - this.data.barRadius * 2; } return res; } willMount(props: JSONObject): void { this.data.min = lodash.get(props, 'min', 0 as i64); this.data.max = lodash.get(props, 'max', 100 as i64); this.data.step = lodash.get(props, 'step', 1 as i64); this.data.width = lodash.get(props, "width", 200 as i64); this.data.barRadius = lodash.get(props, 'barRadius', 15 as i64); this.data.stepLength = (this.data.width as f64 / ((this.data.max as f64) - (this.data.min as f64))); this.data.value = lodash.get(props, 'value', 0 as i64); this.data.direction = lodash.get(props, 'direction', 'row'); console.log('====### value is ' + this.data.stepLength.toString()); let activeValue = (this.data.width * this.data.value) / 100; console.log('====### activeValue is ' + activeValue.toString()); let buttonLeft = this.getButtonPosition(activeValue); let stateData: JSONObject = new JSONObject(); stateData.set("barWidth", this.data.width); stateData.set("activeValue", activeValue.toString()); stateData.set("buttonLeft", buttonLeft.toString()); stateData.set('activeUseLinear', lodash.get(props, 'activeColor', '').includes('linear-gradient')); stateData.set('inactiveUseLinear', lodash.get(props, 'inactiveColor', '').includes('linear-gradient')); this.setState(stateData); console.log("switch willMount" + props.toString()); } }