cu-progress.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. <template>
  2. <view>
  3. <view class="cu-progress-main" :style="{'border-radius':bgBR,'width': progressMainW,'height':progressMainH,'background-color': backgroundColor}">
  4. <view class="cu-progress" :style="{'left':areaLeft, 'flex-direction':flexDirection,'width':areaW,height:areaH}">
  5. <view class="cu-progress-bar" :style="{'bottom':pgBarBottom,'background':pgBarBg,'margin-left':pgBarML, 'margin-bottom':pgBarMB,'width': pgBarW,'height':pgBarH,'border-radius':pgBarBR,'background-color':noActiveColor}"></view>
  6. <movable-area class="cu-area" :style="{'flex-direction':flexDirection,'width':areaW,height:areaH}" @touchcancel="touchCancel" @touchstart="areaTouchStart"
  7. @touchmove="areaTouchMove" @touchend="touchEnd">
  8. <movable-view class="cu-handle" disabled="disabled" :animation="false" :style="{ 'top':handleT, 'width':handleS,'height':handleS,'border-radius': handleBR,'background-color':handleColor}"
  9. @change="change" :damping="damping" :x="handleX" :y="handleY" :direction="direction == 'vertical' ? 'vertical' : 'horizontal'">
  10. <text :class="handleIcon" :style="{'backgroundColor':iconColor,'font-size':iconS,'border-radius':iconBR}"></text>
  11. </movable-view>
  12. </movable-area>
  13. </view>
  14. <text v-if="getShowInfoStatus2view" class="cu-showInfo" :style="{'right':infoRt, 'left':infoLt, 'color':infoColor,'font-size':infoS,width:infoW}">{{showValue}}{{infoEndText}}</text>
  15. </view>
  16. </view>
  17. </template>
  18. <script>
  19. export default {
  20. data() {
  21. return {
  22. scale: 1,
  23. percent: 0, // progress进度
  24. // pgbw: '10px', // progress-bar width
  25. showValue: 0, //显示进度
  26. showVL: 0, // showValue 最大长度
  27. handleMoveStatus: false,
  28. handleX: 0, // 拖柄位置
  29. handleY: 0,
  30. progressBarInfo: {
  31. left: 0,
  32. bottom: 0,
  33. width: 0,
  34. height: 0
  35. },
  36. area: {
  37. left: 0,
  38. bottom: 0,
  39. width: 0,
  40. height: 0,
  41. top: 0
  42. },
  43. handle: {
  44. height: 0
  45. }
  46. };
  47. },
  48. beforeMount: function() {
  49. const res = uni.getSystemInfoSync()
  50. this.scale = 750 / res.windowWidth;
  51. // 0 为 false
  52. if (this.maxValue - this.minValue == 0) {
  53. console.error("min不能等于max:" + this.minValue + "->" + this.maxValue)
  54. return
  55. }
  56. else{
  57. this.showValue = this.valueFormat(this.value)
  58. }
  59. this.percent = Math.abs(this.showValue - this.minValue) / Math.abs(this.maxValue - this.minValue) * 100
  60. let minl = this.textLength(this.minValue + this.infoEndText)
  61. let maxl = this.textLength(this.maxValue + this.infoEndText)
  62. this.showVL = maxl > minl ? maxl : minl
  63. },
  64. mounted: function() {
  65. this.$nextTick(function() {
  66. const query = uni.createSelectorQuery().in(this)
  67. query.select(".cu-progress-bar").boundingClientRect(data => {
  68. this.progressBarInfo.width = data.width
  69. this.progressBarInfo.left = data.left
  70. this.progressBarInfo.bottom = data.bottom
  71. this.progressBarInfo.height = data.height
  72. if (this.direction == 'vertical'){
  73. this.handleY = this.progressBarInfo.height * (100 - this.percent) / 100
  74. }
  75. else{
  76. this.handleX = this.progressBarInfo.width * this.percent / 100
  77. }
  78. }).exec()
  79. query.select(".cu-area").boundingClientRect(data => {
  80. this.area.width = data.width
  81. this.area.left = data.left
  82. this.area.height = data.height
  83. this.area.bottom = data.bottom
  84. this.area.top = data.top
  85. }).exec()
  86. query.select(".cu-handle").boundingClientRect(data => {
  87. this.handle.height = data.height
  88. }).exec()
  89. })
  90. },
  91. props: {
  92. infoAlign: {
  93. default: 'right',
  94. type: String
  95. },
  96. step: {
  97. default: 1,
  98. type: [String, Number]
  99. },
  100. direction: {
  101. default: 'horizontal', //vertical 方向
  102. type: String
  103. },
  104. disabled: {
  105. default: false,
  106. type: [String, Boolean]
  107. },
  108. bgBorderRadius: {
  109. default: 0,
  110. type: [Number, String]
  111. },
  112. iconBorderRadius: {
  113. default: '8px',
  114. type: [Number, String]
  115. },
  116. iconColor: {
  117. default: 'inherit',
  118. type: String
  119. },
  120. iconSize: {
  121. default: '8px',
  122. type: [Number, String]
  123. },
  124. handleIcon: {
  125. default: '',
  126. type: String
  127. },
  128. backgroundColor: {
  129. default: 'inherit',
  130. type: String
  131. },
  132. max: {
  133. default: 100,
  134. type: [String, Number]
  135. },
  136. min: {
  137. default: 0,
  138. type: [String, Number]
  139. },
  140. value: {
  141. default: null, // 设置进度条进度
  142. type: [String, Number]
  143. },
  144. activeColor: {
  145. default: '#444444', // 已经过区域颜色
  146. type: String
  147. },
  148. noActiveColor: {
  149. default: '#888888', // 为经过区域颜色
  150. type: String
  151. },
  152. strokeWidth: {
  153. default: '3', // 行程宽度
  154. type: [String, Number]
  155. },
  156. damping: {
  157. default: 100, // 阻尼系数,越大移动越快
  158. type: [String, Number]
  159. },
  160. handleColor: {
  161. default: '#000000', // 拖柄颜色
  162. type: String
  163. },
  164. handleSize: {
  165. default: '8px', // 拖柄尺寸
  166. type: [String, Number]
  167. },
  168. handleBorderRadius: {
  169. default: '8px', // 拖柄圆角半径
  170. type: [String, Number]
  171. },
  172. showInfo: {
  173. default: false, // 是否在进度条右侧显示百分比
  174. type: [Boolean, String]
  175. },
  176. infoSize: {
  177. default: '16px', // 百分比显示字体尺寸
  178. type: [String, Number]
  179. },
  180. infoColor: {
  181. default: '#000000', // 百分比显示字体颜色
  182. type: String
  183. },
  184. infoEndText: {
  185. default: '',
  186. type: String
  187. },
  188. borderRadius: {
  189. default: 0, // 进度条圆角半径
  190. type: [String, Number]
  191. },
  192. width: {
  193. default: '200px', // 进度条总宽,如果显示百分比,则包括百分比在内的宽度
  194. type: [String, Number]
  195. },
  196. },
  197. computed: {
  198. getShowInfoStatus2view(){
  199. if ((this.showInfo == true || this.showInfo == 'true') && this.direction != "vertical"){
  200. return true
  201. }
  202. else{
  203. return false
  204. }
  205. },
  206. showVLC (){
  207. let minl = this.textLength(this.minValue.toFixed(0) + this.infoEndText)
  208. let maxl = this.textLength(this.maxValue.toFixed(0) + this.infoEndText)
  209. let L = maxl > minl ? maxl : minl
  210. return L
  211. },
  212. flexDirection (){
  213. if (this.direction == 'vertical'){
  214. return 'column'
  215. }
  216. else{
  217. return 'row'
  218. }
  219. },
  220. pgBarBottom (){
  221. // progress-
  222. if (this.direction == 'vertical'){
  223. return '0px'
  224. }
  225. else{
  226. return 'unset'
  227. }
  228. },
  229. showInfoStatus (){
  230. if (this.getShowInfoStatus() && this.direction != "vertical"){
  231. return true
  232. }
  233. else{
  234. return false
  235. }
  236. },
  237. pgBarBg(){
  238. let bg1
  239. if (this.direction == 'vertical'){
  240. bg1 = "linear-gradient(to top," + this.activeColor + ' ' + this.percent + "%," + this.noActiveColor + ' ' + this.percent + "%)"
  241. }
  242. else{
  243. bg1 = "linear-gradient(to right," + this.activeColor + ' ' + this.percent + "%," + this.noActiveColor + ' ' + this.percent + "%)"
  244. // qq
  245. let bg2 = "-webkit-linear-gradient(left," + this.activeColor + ' ' + this.percent + "%," + this.noActiveColor + ' ' + this.percent + "%)"
  246. let bg3 = "-o-linear-gradient(right," + this.activeColor + ' ' + this.percent + "%," + this.noActiveColor + ' ' + this.percent + "%)"
  247. let bg4 = "-moz-linear-gradient(right," + this.activeColor + ' ' + this.percent + "%," + this.noActiveColor + ' ' + this.percent + "%)"
  248. }
  249. return bg1
  250. },
  251. pgBarBR(){
  252. return this.sizeDeal(this.borderRadius)[2]
  253. },
  254. bgBR() {
  255. return this.sizeDeal(this.bgBorderRadius)[2]
  256. },
  257. iconBR() {
  258. return this.sizeDeal(this.iconBorderRadius)[2]
  259. },
  260. iconS() {
  261. return this.sizeDeal(this.iconSize)[2]
  262. },
  263. infoW() {
  264. const s = this.sizeDeal(this.infoSize)
  265. const size = s[0] * this.showVL + s[1]
  266. return size
  267. },
  268. infoS() {
  269. return this.sizeDeal(this.infoSize)[2]
  270. },
  271. infoRt(){
  272. // showinfo right
  273. if (this.infoAlign == 'left' && this.direction != 'vertical'){
  274. return 'unset'
  275. }
  276. else{ return 0 }
  277. },
  278. infoLt(){
  279. if (this.infoAlign == 'left' && this.direction != 'vertical'){
  280. return 0
  281. }
  282. else if (this.infoAlign == 'center' && this.direction != 'vertical'){
  283. let aw = this.area.width / 2
  284. const s = this.sizeDeal(this.infoSize)
  285. const size = aw - (s[0] * this.showVL) / 2 + 'px'
  286. return size
  287. }
  288. else{ return 'unset' }
  289. },
  290. areaW: {
  291. get (){
  292. if (this.direction == 'vertical'){
  293. return this.maxHeight(true)[2]
  294. }
  295. else{
  296. const s = this.sizeDeal(this.infoSize)
  297. const h = this.maxHeight()
  298. let w
  299. if (this.getShowInfoStatus()) {
  300. w = 'calc(' + this.width + ' - ' + s[0] * this.showVL + s[1] + ')'
  301. } else { w = this.width }
  302. return w
  303. }
  304. },
  305. set (w){ return w }
  306. },
  307. areaH: {
  308. get(){
  309. if (this.direction == 'vertical'){ return this.width }
  310. else{ return this.maxHeight()[2] }
  311. },
  312. set (v){ return v }
  313. },
  314. areaLeft() {
  315. if (this.infoAlign == 'left' && this.direction != 'vertical'){
  316. const s = this.sizeDeal(this.infoSize)
  317. const size = s[0] * this.showVL + s[1]
  318. return size
  319. }
  320. else{ return 0 }
  321. },
  322. pgBarW() {
  323. // width
  324. if (this.direction == 'vertical'){
  325. return this.sizeDeal(this.strokeWidth)[2]
  326. }
  327. else{
  328. const s = this.sizeDeal(this.infoSize)
  329. const w = this.sizeDeal(this.width)
  330. const s2 = this.sizeDeal(this.handleSize)
  331. let w2
  332. if (this.getShowInfoStatus()) {
  333. w2 = 'calc(' + w[2] + ' - ' + s[0] * this.showVL + s[1] + ' - ' + s2[2] + ')'
  334. } else {
  335. w2 = 'calc(' + w[2] + ' - ' + s2[2] + ')'
  336. }
  337. return w2
  338. }
  339. },
  340. pgBarH() {
  341. // height
  342. if (this.direction == 'vertical'){
  343. const w = this.sizeDeal(this.width)
  344. const s2 = this.sizeDeal(this.handleSize)
  345. let w2 = 'calc(' + w[2] + ' - ' + s2[2] + ')'
  346. return w2
  347. }
  348. else{ return this.sizeDeal(this.strokeWidth)[2] }
  349. },
  350. pgBarML() {
  351. // margin-left
  352. if (this.direction == 'vertical'){
  353. const s = this.sizeDeal(this.progressBarInfo.width)
  354. const ah = Number(this.area.width) / 2
  355. const t = ah - s[0] / 2 + 'px'
  356. return t
  357. }
  358. else{
  359. const s2 = this.sizeDeal(this.handleSize)
  360. return s2[0] / 2 + s2[1]
  361. }
  362. },
  363. pgBarMB() {
  364. // margin-bottom
  365. if (this.direction == 'vertical'){
  366. const s2 = this.sizeDeal(this.handleSize)
  367. return s2[0] / 2 + s2[1]
  368. }
  369. else{ return 0 }
  370. },
  371. handleS() {
  372. const s = this.sizeDeal(this.handleSize)
  373. return s[2]
  374. },
  375. handleL (){
  376. if (this.direction == 'vertical') {
  377. const s = this.sizeDeal(this.handleSize)
  378. const ah = Number(this.area.width) / 2
  379. const t = ah - s[0] / 2 + 'px'
  380. return t
  381. }
  382. else{
  383. return 'unset'
  384. }
  385. },
  386. handleT() {
  387. if (this.area.height && this.direction != 'vertical') {
  388. const s = this.sizeDeal(this.handleSize)
  389. const ah = Number(this.area.height) / 2
  390. const t = ah - s[0] / 2 + 'px'
  391. return t
  392. }
  393. else{
  394. return 'unset'
  395. }
  396. },
  397. handleBR() {
  398. const r = this.sizeDeal(this.handleBorderRadius)
  399. return r[2]
  400. },
  401. progressMainW() {
  402. let w
  403. if (this.direction == 'vertical'){
  404. w = this.maxHeight(true)[2]
  405. }
  406. else{
  407. w = this.width
  408. }
  409. return w
  410. },
  411. progressMainH() {
  412. let h
  413. if (this.direction == 'vertical'){
  414. h = this.width
  415. }
  416. else{
  417. h = this.maxHeight()[2]
  418. }
  419. return h
  420. },
  421. maxValue() {
  422. let max = Number.isNaN(parseFloat(this.max)) ? 100 : parseFloat(this.max)
  423. return this.valueFormat(max)
  424. },
  425. minValue() {
  426. let min = Number.isNaN(parseFloat(this.min)) ? 0 : parseFloat(this.min)
  427. let si = this.getStepInfo()
  428. return Number(min.toFixed(si[1]))
  429. // return this.valueFormat(min)
  430. },
  431. },
  432. watch: {
  433. showVLC (v){
  434. this.showVL = v
  435. if (this.direction != 'vertical'){
  436. const s = this.sizeDeal(this.infoSize)
  437. const h = this.maxHeight()
  438. let w
  439. if (this.getShowInfoStatus()) {
  440. w = 'calc(' + this.width + ' - ' + s[0] * this.showVL + s[1] + ')'
  441. } else {
  442. w = this.width
  443. }
  444. this.areaW = w
  445. this.areaH = h[2]
  446. }
  447. this.clientInit()
  448. },
  449. value(v) {
  450. // 当处于拖动状态时,禁止进度条外部触发变化
  451. if (!this.handleMoveStatus) {
  452. this.showValue = this.valueFormat(v)
  453. this.percent = (this.showValue - this.minValue) / Math.abs(this.maxValue - this.minValue) * 100
  454. if (this.direction == 'vertical'){
  455. this.handleY = this.progressBarInfo.height * this.percent / 100
  456. }
  457. else{
  458. this.handleX = this.progressBarInfo.width * this.percent / 100
  459. }
  460. }
  461. },
  462. },
  463. methods: {
  464. valueFormat (v){
  465. // set step
  466. v = Number(v - this.minValue).toFixed(7)
  467. let stepInfo = this.getStepInfo()
  468. let valueE = v * 10 ** stepInfo[1]
  469. let remainder = valueE % (stepInfo[0] * 10 ** stepInfo[1])
  470. let remainderInt = Math.floor(remainder)
  471. let value = (Math.floor(valueE) - remainderInt) / (10 ** stepInfo[1])
  472. return Number((value + this.minValue).toFixed(6))
  473. },
  474. getStepInfo() {
  475. // return step, decimal位数
  476. let step = Number(this.step)
  477. if (step <= 0 || !step){
  478. return [1, 0]
  479. }
  480. else{
  481. let steps = step.toString().split('.')
  482. if (steps.length == 1){
  483. return [step,0]
  484. }
  485. else {
  486. return [step,steps[1].length]
  487. }
  488. }
  489. },
  490. clientInit() {
  491. this.$nextTick(function() {
  492. const query = uni.createSelectorQuery().in(this)
  493. query.select(".cu-progress-bar").boundingClientRect(data => {
  494. this.progressBarInfo.width = data.width
  495. this.progressBarInfo.left = data.left
  496. this.progressBarInfo.bottom = data.bottom
  497. this.progressBarInfo.height = data.height
  498. if (this.direction == 'vertical'){
  499. this.handleY = this.progressBarInfo.height * this.percent / 100
  500. }
  501. else{
  502. this.handleX = this.progressBarInfo.width * this.percent / 100
  503. }
  504. }).exec()
  505. query.select(".cu-area").boundingClientRect(data => {
  506. this.area.width = data.width
  507. this.area.left = data.left
  508. this.area.height = data.height
  509. this.area.bottom = data.bottom
  510. this.area.top = data.top
  511. }).exec()
  512. if (this.maxValue - this.minValue == 0) {
  513. console.error("min不能等于max:" + this.minValue + "->" + this.maxValue)
  514. }
  515. else{
  516. let stepInfo = this.getStepInfo()
  517. let v = this.percent * (this.maxValue - this.minValue) / 100
  518. let valueE = v * 10 ** stepInfo[1]
  519. let remainder = valueE % (stepInfo[0] * 10 ** stepInfo[1])
  520. let remainderInt = Math.floor(remainder)
  521. let sv = (Math.floor(valueE) - remainderInt) / (10 ** stepInfo[1])
  522. this.showValue = sv
  523. }
  524. })
  525. },
  526. getShowInfoStatus(){
  527. if ((this.showInfo == true || this.showInfo == 'true') && this.direction != "vertical" && this.infoAlign !== 'center'){
  528. return true
  529. }
  530. else{
  531. return false
  532. }
  533. },
  534. textLength(t) {
  535. t = t.toString()
  536. let int = t.split('.')[0]
  537. let subt = t.match(/[^\x00-\xff]/g)
  538. let subl = 0
  539. if (subt) {
  540. subl = subt.length
  541. }
  542. let l = (int.length - subl + this.getStepInfo()[1]) / 3 * 2 + subl + 0.2
  543. return Number(l.toFixed(2))
  544. },
  545. maxHeight(vertical) {
  546. let h = []
  547. if (!vertical){ // direction 为 vertical 时不显示info
  548. let subt = this.infoEndText.match(/[^\x00-\xff]/g)
  549. if (subt){
  550. h.push(this.sizeDeal(this.infoSize)[0] * 1.1)
  551. }
  552. else{
  553. h.push(this.sizeDeal(this.infoSize)[0])
  554. }
  555. }
  556. h.push(this.sizeDeal(this.strokeWidth)[0])
  557. h.push(this.sizeDeal(this.handleSize)[0])
  558. h.sort(function(a, b) {
  559. return b - a
  560. }) // 降序
  561. return [h[0], 'px', h[0] + 'px']
  562. },
  563. sizeDeal(size) {
  564. // 分离字体大小和单位,rpx 转 px
  565. let s = Number.isNaN(parseFloat(size)) ? 0 : parseFloat(size)
  566. let u = size.toString().replace(/[0-9]/g, '')
  567. if (u == 'rpx') {
  568. s /= this.scale
  569. u = 'px'
  570. } else if (u == '') {
  571. u = 'px'
  572. }else if (u == 'vw') {
  573. u = 'px'
  574. s = s / 100 * 750 / this.scale
  575. }
  576. return [s, u, s + u]
  577. },
  578. change (){
  579. this.$emit('change', {
  580. type: 'change',
  581. value: this.showValue,
  582. })
  583. },
  584. handleMove(x_) {
  585. let x = x_
  586. x = x >= 0 ? x : 0
  587. let s = this.sizeDeal(this.handleSize)
  588. let cp
  589. let sv
  590. if (this.direction == 'vertical'){
  591. // #ifdef H5
  592. x = x - s[0] / 2 - this.area.bottom // ?
  593. cp = x / (this.area.height - s[0] - 1)
  594. // #endif
  595. // #ifndef H5
  596. x = x - this.area.top - s[0] / 2
  597. cp = x / (this.area.height - s[0] - 1)
  598. // #endif
  599. cp = cp <= 1 ? cp : 1
  600. cp = cp > 0 ? cp : 0
  601. let value = Number(((1 - cp) * (this.maxValue - this.minValue))) + this.minValue
  602. this.percent = (1 - cp) * 100
  603. this.showValue = this.valueFormat(value)
  604. this.handleY = x
  605. }
  606. else{
  607. cp = x / (this.area.width - s[0] - 1) // 多减 1 避免达不到maxValue
  608. cp = cp <= 1 ? cp : 1
  609. cp = cp > 0 ? cp : 0
  610. let value = Number((cp * (this.maxValue - this.minValue))) + this.minValue
  611. this.percent = cp * 100
  612. this.showValue = this.valueFormat(value)
  613. this.handleX = x
  614. }
  615. this.$emit('dragging', {
  616. type: 'dragging',
  617. value: this.showValue
  618. })
  619. },
  620. touchEnd() {
  621. if (!this.disabled){
  622. this.handleMoveStatus = false
  623. this.$emit('dragged', {
  624. type: 'dragged',
  625. value: this.showValue
  626. })
  627. }
  628. },
  629. areaTouchStart(e) {
  630. if (!this.disabled){
  631. this.handleMoveStatus = true
  632. let s = this.sizeDeal(this.handleSize)
  633. let tapX
  634. if (this.direction == 'vertical'){
  635. // #ifdef H5
  636. tapX = this.area.height + e.changedTouches[0].pageY
  637. // #endif
  638. // #ifndef H5
  639. tapX = e.changedTouches[0].pageY
  640. // #endif
  641. }
  642. else{
  643. tapX = e.changedTouches[0].pageX - this.area.left - s[0] / 2 // 拖柄中心与鼠标箭头一致
  644. }
  645. tapX = tapX >= 0 ? tapX : 0
  646. this.handleMove(tapX)
  647. this.$emit('dragstart', {
  648. type: 'dragstart',
  649. value: this.showValue
  650. })
  651. }
  652. },
  653. areaTouchMove(e) {
  654. if (!this.disabled){
  655. let s = this.sizeDeal(this.handleSize)
  656. let tapX
  657. if (this.direction == 'vertical'){
  658. // #ifdef H5
  659. tapX = this.area.height + e.changedTouches[0].pageY
  660. // #endif
  661. // #ifndef H5
  662. tapX = e.changedTouches[0].pageY
  663. // #endif
  664. }
  665. else{
  666. tapX = e.changedTouches[0].pageX - this.area.left - s[0] / 2
  667. }
  668. tapX = tapX >= 0 ? tapX : 0
  669. this.handleMove(tapX)
  670. }
  671. },
  672. touchCancel() {
  673. if (!this.disabled){
  674. this.touchEnd()
  675. this.$emit('dragcancel', {
  676. type: 'dragcancel',
  677. value: this.showValue
  678. })
  679. }
  680. },
  681. }
  682. }
  683. </script>
  684. <style scoped>
  685. @import 'cu-progress.css'
  686. </style>