slider.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  2. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  3. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  4. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  5. return c > 3 && r && Object.defineProperty(target, key, r), r;
  6. };
  7. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  8. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  9. return new (P || (P = Promise))(function (resolve, reject) {
  10. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  11. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  12. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  13. step((generator = generator.apply(thisArg, _arguments || [])).next());
  14. });
  15. };
  16. import { SuperComponent, wxComponent } from '../common/src/index';
  17. import config from '../common/config';
  18. import { trimSingleValue, trimValue } from './tool';
  19. import props from './props';
  20. import { getRect } from '../common/utils';
  21. import Bus from '../common/bus';
  22. const { prefix } = config;
  23. const name = `${prefix}-slider`;
  24. let Slider = class Slider extends SuperComponent {
  25. constructor() {
  26. super(...arguments);
  27. this.externalClasses = [
  28. `${prefix}-class`,
  29. `${prefix}-class-bar`,
  30. `${prefix}-class-bar-active`,
  31. `${prefix}-class-bar-disabled`,
  32. `${prefix}-class-cursor`,
  33. ];
  34. this.properties = props;
  35. this.controlledProps = [
  36. {
  37. key: 'value',
  38. event: 'change',
  39. },
  40. ];
  41. this.data = {
  42. sliderStyles: '',
  43. classPrefix: name,
  44. initialLeft: null,
  45. initialRight: null,
  46. activeLeft: 0,
  47. activeRight: 0,
  48. maxRange: 0,
  49. lineLeft: 0,
  50. lineRight: 0,
  51. dotTopValue: [0, 0],
  52. _value: 0,
  53. blockSize: 20,
  54. isScale: false,
  55. scaleArray: [],
  56. scaleTextArray: [],
  57. prefix,
  58. isVisibleToScreenReader: false,
  59. };
  60. this.observers = {
  61. value(newValue) {
  62. this.handlePropsChange(newValue);
  63. },
  64. _value(newValue) {
  65. const { min, max, range } = this.properties;
  66. const { maxRange } = this.data;
  67. if (range) {
  68. const left = (maxRange * (newValue[0] - Number(min))) / (Number(max) - Number(min));
  69. const right = (maxRange * (Number(max) - newValue[1])) / (Number(max) - Number(min));
  70. this.setLineStyle(left, right);
  71. }
  72. else {
  73. this.setSingleBarWidth(newValue);
  74. }
  75. this.setData({
  76. isVisibleToScreenReader: true,
  77. });
  78. setTimeout(() => {
  79. this.setData({
  80. isVisibleToScreenReader: false,
  81. });
  82. }, 2e3);
  83. },
  84. marks(val) {
  85. if (this.data.initialLeft != null) {
  86. this.handleMask(val);
  87. }
  88. else {
  89. this.bus.on('initial', () => this.handleMask(val));
  90. }
  91. },
  92. };
  93. this.lifetimes = {
  94. created() {
  95. this.bus = new Bus();
  96. },
  97. attached() {
  98. const { value } = this.properties;
  99. if (!value)
  100. this.handlePropsChange(0);
  101. this.getInitialStyle();
  102. },
  103. };
  104. }
  105. triggerValue(value) {
  106. this._trigger('change', {
  107. value: trimValue(value, this.properties),
  108. });
  109. }
  110. handlePropsChange(newValue) {
  111. const value = trimValue(newValue, this.properties);
  112. const setValueAndTrigger = () => {
  113. this.setData({
  114. _value: value,
  115. });
  116. };
  117. if (this.data.maxRange === 0) {
  118. this.getInitialStyle().then(setValueAndTrigger);
  119. return;
  120. }
  121. setValueAndTrigger();
  122. }
  123. handleMask(marks) {
  124. const calcPos = (arr) => {
  125. const { theme } = this.properties;
  126. const { blockSize, maxRange } = this.data;
  127. const margin = theme === 'capsule' ? blockSize / 2 : 0;
  128. return arr.map((item) => ({
  129. val: item,
  130. left: Math.round((item / 100) * maxRange) + margin,
  131. }));
  132. };
  133. if ((marks === null || marks === void 0 ? void 0 : marks.length) && Array.isArray(marks)) {
  134. this.setData({
  135. isScale: true,
  136. scaleArray: calcPos(marks),
  137. scaleTextArray: [],
  138. });
  139. }
  140. if (Object.prototype.toString.call(marks) === '[object Object]') {
  141. const scaleArray = Object.keys(marks).map((item) => Number(item));
  142. const scaleTextArray = scaleArray.map((item) => marks[item]);
  143. this.setData({
  144. isScale: scaleArray.length > 0,
  145. scaleArray: calcPos(scaleArray),
  146. scaleTextArray,
  147. });
  148. }
  149. }
  150. setSingleBarWidth(value) {
  151. const { max, min, theme } = this.properties;
  152. const { maxRange, blockSize } = this.data;
  153. const halfBlock = theme === 'capsule' ? Number(blockSize) / 2 : 0;
  154. const percentage = (Number(value) - Number(min)) / (Number(max) - Number(min));
  155. const width = percentage * maxRange + halfBlock;
  156. this.setData({
  157. lineBarWidth: `${width}px`,
  158. });
  159. }
  160. getInitialStyle() {
  161. return __awaiter(this, void 0, void 0, function* () {
  162. const line = yield getRect(this, '#sliderLine');
  163. const { blockSize } = this.data;
  164. const { theme } = this.properties;
  165. const halfBlock = Number(blockSize) / 2;
  166. let maxRange = line.right - line.left;
  167. let initialLeft = line.left;
  168. let initialRight = line.right;
  169. if (theme === 'capsule') {
  170. maxRange = maxRange - Number(blockSize) - 6;
  171. initialLeft -= halfBlock;
  172. initialRight -= halfBlock;
  173. }
  174. this.setData({
  175. maxRange,
  176. initialLeft,
  177. initialRight,
  178. });
  179. this.bus.emit('initial');
  180. });
  181. }
  182. stepValue(value) {
  183. const { step, min, max } = this.properties;
  184. if (Number(step) < 1 || Number(step) > Number(max) - Number(min))
  185. return value;
  186. const closestStep = trimSingleValue(Math.round(value / Number(step)) * Number(step), Number(min), Number(max));
  187. return closestStep;
  188. }
  189. onSingleLineTap(e) {
  190. const { disabled } = this.properties;
  191. if (disabled)
  192. return;
  193. const value = this.getSingleChangeValue(e);
  194. this.triggerValue(value);
  195. }
  196. getSingleChangeValue(e) {
  197. const { min, max } = this.properties;
  198. const { initialLeft, maxRange } = this.data;
  199. const [touch] = e.changedTouches;
  200. const { pageX } = touch;
  201. const currentLeft = pageX - initialLeft;
  202. let value = 0;
  203. if (currentLeft <= 0) {
  204. value = Number(min);
  205. }
  206. else if (currentLeft >= maxRange) {
  207. value = Number(max);
  208. }
  209. else {
  210. value = Math.round((currentLeft / maxRange) * (Number(max) - Number(min)) + Number(min));
  211. }
  212. return this.stepValue(value);
  213. }
  214. convertPosToValue(posValue, dir) {
  215. const { maxRange } = this.data;
  216. const { max, min } = this.properties;
  217. return dir === 0
  218. ? (posValue / maxRange) * (Number(max) - Number(min)) + Number(min)
  219. : Number(max) - (posValue / maxRange) * (Number(max) - Number(min));
  220. }
  221. onLineTap(e) {
  222. const { disabled, theme } = this.properties;
  223. const { initialLeft, initialRight, maxRange, blockSize } = this.data;
  224. if (disabled)
  225. return;
  226. const [touch] = e.changedTouches;
  227. const { pageX } = touch;
  228. const halfBlock = theme === 'capsule' ? Number(blockSize) / 2 : 0;
  229. const currentLeft = pageX - initialLeft;
  230. if (currentLeft < 0 || currentLeft > maxRange + Number(blockSize))
  231. return;
  232. Promise.all([getRect(this, '#leftDot'), getRect(this, '#rightDot')]).then(([leftDot, rightDot]) => {
  233. const distanceLeft = Math.abs(pageX - leftDot.left - halfBlock);
  234. const distanceRight = Math.abs(rightDot.left - pageX + halfBlock);
  235. const isMoveLeft = distanceLeft < distanceRight;
  236. if (isMoveLeft) {
  237. const left = pageX - initialLeft;
  238. const leftValue = this.convertPosToValue(left, 0);
  239. this.triggerValue([this.stepValue(leftValue), this.data._value[1]]);
  240. }
  241. else {
  242. const right = -(pageX - initialRight);
  243. const rightValue = this.convertPosToValue(right, 1);
  244. this.triggerValue([this.data._value[0], this.stepValue(rightValue)]);
  245. }
  246. });
  247. }
  248. onTouchMoveLeft(e) {
  249. const { disabled } = this.properties;
  250. const { initialLeft, _value } = this.data;
  251. if (disabled)
  252. return;
  253. const [touch] = e.changedTouches;
  254. const { pageX } = touch;
  255. const currentLeft = pageX - initialLeft;
  256. const newData = [..._value];
  257. const leftValue = this.convertPosToValue(currentLeft, 0);
  258. newData[0] = this.stepValue(leftValue);
  259. this.triggerValue(newData);
  260. }
  261. onTouchMoveRight(e) {
  262. const { disabled } = this.properties;
  263. const { initialRight, _value } = this.data;
  264. if (disabled)
  265. return;
  266. const [touch] = e.changedTouches;
  267. const { pageX } = touch;
  268. const currentRight = -(pageX - initialRight);
  269. const newData = [..._value];
  270. const rightValue = this.convertPosToValue(currentRight, 1);
  271. newData[1] = this.stepValue(rightValue);
  272. this.triggerValue(newData);
  273. }
  274. setLineStyle(left, right) {
  275. const { theme } = this.properties;
  276. const { blockSize, maxRange } = this.data;
  277. const halfBlock = theme === 'capsule' ? Number(blockSize) / 2 : 0;
  278. const [a, b] = this.data._value;
  279. const cut = (v) => parseInt(v, 10);
  280. this.setData({
  281. dotTopValue: [a, b],
  282. });
  283. if (left + right <= maxRange) {
  284. this.setData({
  285. lineLeft: cut(left + halfBlock),
  286. lineRight: cut(right + halfBlock),
  287. });
  288. }
  289. else {
  290. this.setData({
  291. lineLeft: cut(maxRange + halfBlock - right),
  292. lineRight: cut(maxRange - left + halfBlock * 1.5),
  293. });
  294. }
  295. }
  296. onTouchEnd() { }
  297. };
  298. Slider = __decorate([
  299. wxComponent()
  300. ], Slider);
  301. export default Slider;