directives.js 10.7 KB
Newer Older
JingChao's avatar
JingChao committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
import Autosize from 'autosize'

function vueTouch (el, binding, type) {
  var _this = this
  this.obj = el
  this.binding = binding
  this.touchType = type
  this.vueTouches = {x: 0, y: 0}
  this.vueMoves = true
  this.vueLeave = true
  this.longTouch = true
  this.vueCallBack = typeof (binding.value) === 'object' ? binding.value.fn : binding.value
  this.obj.addEventListener('touchstart', function (e) {
    _this.start(e)
  }, false)
  this.obj.addEventListener('touchend', function (e) {
    _this.end(e)
  }, false)
  this.obj.addEventListener('touchmove', function (e) {
    _this.move(e)
  }, false)
李晓兵's avatar
李晓兵 committed
22 23 24 25
};

vueTouch.prototype = {
  start: function (e) {
JingChao's avatar
JingChao committed
26 27 28 29
    this.vueMoves = true
    this.vueLeave = true
    this.longTouch = true
    this.vueTouches = {x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY}
李晓兵's avatar
李晓兵 committed
30 31
    this.time = setTimeout(function () {
      if (this.vueLeave && this.vueMoves) {
JingChao's avatar
JingChao committed
32 33
        this.touchType === 'longtap' && this.vueCallBack(this.binding.value, e)
        this.longTouch = false
李晓兵's avatar
李晓兵 committed
34
      }
JingChao's avatar
JingChao committed
35
    }.bind(this), 1000)
李晓兵's avatar
李晓兵 committed
36 37
  },
  end: function (e) {
JingChao's avatar
JingChao committed
38 39 40 41 42
    var disX = e.changedTouches[0].pageX - this.vueTouches.x
    var disY = e.changedTouches[0].pageY - this.vueTouches.y
    clearTimeout(this.time)
    if (Math.abs(disX) > 100 || Math.abs(disY) > 100) {
      this.touchType === 'swipe' && this.vueCallBack(this.binding.value, e)
李晓兵's avatar
李晓兵 committed
43
      if (Math.abs(disX) > Math.abs(disY)) {
JingChao's avatar
JingChao committed
44 45
        if (disX > 100) {
          this.touchType === 'swiperight' && this.vueCallBack(this.binding.value, e)
李晓兵's avatar
李晓兵 committed
46 47
        }

JingChao's avatar
JingChao committed
48 49
        if (disX < -100) {
          this.touchType === 'swipeleft' && this.vueCallBack(this.binding.value, e)
李晓兵's avatar
李晓兵 committed
50 51
        }
      } else {
JingChao's avatar
JingChao committed
52 53
        if (disY > 100) {
          this.touchType === 'swipedown' && this.vueCallBack(this.binding.value, e)
李晓兵's avatar
李晓兵 committed
54 55
        }

JingChao's avatar
JingChao committed
56 57
        if (disY < -100) {
          this.touchType === 'swipeup' && this.vueCallBack(this.binding.value, e)
李晓兵's avatar
李晓兵 committed
58 59 60 61
        }
      }
    } else {
      if (this.longTouch && this.vueMoves) {
JingChao's avatar
JingChao committed
62
        this.touchType === 'tap' && this.vueCallBack(this.binding.value, e)
李晓兵's avatar
李晓兵 committed
63 64 65 66 67
        this.vueLeave = false
      }
    }
  },
  move: function (e) {
JingChao's avatar
JingChao committed
68 69 70
    this.vueMoves = false
  },
} // prop.autosize
李晓兵's avatar
李晓兵 committed
71
export default (Vue) => {
JingChao's avatar
JingChao committed
72 73
  Vue.directive('focus', {
    // 自动获取鼠标焦点
李晓兵's avatar
李晓兵 committed
74
    inserted: function (el) {
JingChao's avatar
JingChao committed
75 76 77 78
      el.focus()
    },
  })
  Vue.directive('tap', {// 点击事件
李晓兵's avatar
李晓兵 committed
79
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
80 81 82 83
      new vueTouch(el, binding, 'tap') // eslint-disable-line
    },
  })
  Vue.directive('swipe', {// 滑动事件
李晓兵's avatar
李晓兵 committed
84
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
85 86 87 88
      new vueTouch(el, binding, 'swipe') // eslint-disable-line
    },
  })
  Vue.directive('swipeleft', {// 左滑事件
李晓兵's avatar
李晓兵 committed
89
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
90 91 92 93
      new vueTouch(el, binding, 'swipeleft') // eslint-disable-line
    },
  })
  Vue.directive('swiperight', {// 右滑事件
李晓兵's avatar
李晓兵 committed
94
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
95 96 97 98
      new vueTouch(el, binding, 'swiperight') // eslint-disable-line
    },
  })
  Vue.directive('swipedown', {// 下滑事件
李晓兵's avatar
李晓兵 committed
99
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
100 101 102 103
      new vueTouch(el, binding, 'swipedown') // eslint-disable-line
    },
  })
  Vue.directive('swipeup', {// 上滑事件
李晓兵's avatar
李晓兵 committed
104
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
105 106 107 108
      new vueTouch(el, binding, 'swipeup') // eslint-disable-line
    },
  })
  Vue.directive('longtap', {// 长按事件
李晓兵's avatar
李晓兵 committed
109
    bind: function (el, binding) {
JingChao's avatar
JingChao committed
110 111 112
      new vueTouch(el, binding, 'longtap') // eslint-disable-line
    },
  })
李晓兵's avatar
李晓兵 committed
113

JingChao's avatar
JingChao committed
114
  Vue.directive('hlsImgZoom', {
李晓兵's avatar
李晓兵 committed
115
    componentUpdated: function (element) {
JingChao's avatar
JingChao committed
116
      var elWidth, elHeight
李晓兵's avatar
李晓兵 committed
117 118

      // mode : 'pinch' or 'swipe'
JingChao's avatar
JingChao committed
119
      var mode = ''
李晓兵's avatar
李晓兵 committed
120 121

      // distance between two touche points (mode : 'pinch')
JingChao's avatar
JingChao committed
122 123
      var distance = 0
      var initialDistance = 0
李晓兵's avatar
李晓兵 committed
124 125

      // image scaling
JingChao's avatar
JingChao committed
126 127 128 129
      var scale = 1
      var relativeScale = 1
      var initialScale = 1
      var maxScale = 5
李晓兵's avatar
李晓兵 committed
130
      if (isNaN(maxScale) || maxScale <= 1) {
JingChao's avatar
JingChao committed
131
        maxScale = 3
李晓兵's avatar
李晓兵 committed
132 133 134
      }

      // position of the upper left corner of the element
JingChao's avatar
JingChao committed
135 136
      var positionX = 0
      var positionY = 0
李晓兵's avatar
李晓兵 committed
137

JingChao's avatar
JingChao committed
138 139
      var initialPositionX = 0
      var initialPositionY = 0
李晓兵's avatar
李晓兵 committed
140 141

      // central origin (mode : 'pinch')
JingChao's avatar
JingChao committed
142 143
      var originX = 0
      var originY = 0
李晓兵's avatar
李晓兵 committed
144 145

      // start coordinate and amount of movement (mode : 'swipe')
JingChao's avatar
JingChao committed
146 147 148 149
      var startX = 0
      var startY = 0
      var moveX = 0
      var moveY = 0
李晓兵's avatar
李晓兵 committed
150

JingChao's avatar
JingChao committed
151
      var image = new Image()
李晓兵's avatar
李晓兵 committed
152
      image.onload = function () {
JingChao's avatar
JingChao committed
153 154 155 156 157 158 159 160 161 162
        elWidth = element.clientWidth
        elHeight = element.clientHeight
        element.style.webkitTransformOrigin = '0px 0px 0px'
        element.style.transformOrigin = '0px 0px 0px'

        element.addEventListener('touchstart', touchstartHandler)
        element.addEventListener('touchmove', touchmoveHandler)
        element.addEventListener('touchend', touchendHandler)
      }
      image.src = element.src
李晓兵's avatar
李晓兵 committed
163 164 165 166

      /**
       * @param {object} evt
       */
JingChao's avatar
JingChao committed
167 168 169 170 171 172 173 174 175
      function touchstartHandler (evt) {
        var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches

        startX = touches[0].clientX
        startY = touches[0].clientY
        initialPositionX = positionX
        initialPositionY = positionY
        moveX = 0
        moveY = 0
李晓兵's avatar
李晓兵 committed
176 177 178 179 180
      }

      /**
       * @param {object} evt
       */
JingChao's avatar
JingChao committed
181 182
      function touchmoveHandler (evt) {
        var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches
李晓兵's avatar
李晓兵 committed
183 184 185

        if (mode === '') {
          if (touches.length === 1 && scale > 1) {
JingChao's avatar
JingChao committed
186
            mode = 'swipe'
李晓兵's avatar
李晓兵 committed
187
          } else if (touches.length === 2) {
JingChao's avatar
JingChao committed
188
            mode = 'pinch'
李晓兵's avatar
李晓兵 committed
189

JingChao's avatar
JingChao committed
190 191
            initialScale = scale
            initialDistance = getDistance(touches)
李晓兵's avatar
李晓兵 committed
192 193
            originX = touches[0].clientX -
              parseInt((touches[0].clientX - touches[1].clientX) / 2, 10) -
JingChao's avatar
JingChao committed
194
              element.offsetLeft - initialPositionX
李晓兵's avatar
李晓兵 committed
195 196
            originY = touches[0].clientY -
              parseInt((touches[0].clientY - touches[1].clientY) / 2, 10) -
JingChao's avatar
JingChao committed
197
              element.offsetTop - initialPositionY
李晓兵's avatar
李晓兵 committed
198 199 200 201
          }
        }

        if (mode === 'swipe') {
JingChao's avatar
JingChao committed
202
          evt.preventDefault()
李晓兵's avatar
李晓兵 committed
203

JingChao's avatar
JingChao committed
204 205
          moveX = touches[0].clientX - startX
          moveY = touches[0].clientY - startY
李晓兵's avatar
李晓兵 committed
206

JingChao's avatar
JingChao committed
207 208
          positionX = initialPositionX + moveX
          positionY = initialPositionY + moveY
李晓兵's avatar
李晓兵 committed
209

JingChao's avatar
JingChao committed
210
          transformElement()
李晓兵's avatar
李晓兵 committed
211
        } else if (mode === 'pinch') {
JingChao's avatar
JingChao committed
212
          evt.preventDefault()
李晓兵's avatar
李晓兵 committed
213

JingChao's avatar
JingChao committed
214 215 216
          distance = getDistance(touches)
          relativeScale = distance / initialDistance
          scale = relativeScale * initialScale
李晓兵's avatar
李晓兵 committed
217

JingChao's avatar
JingChao committed
218 219
          positionX = originX * (1 - relativeScale) + initialPositionX + moveX
          positionY = originY * (1 - relativeScale) + initialPositionY + moveY
李晓兵's avatar
李晓兵 committed
220

JingChao's avatar
JingChao committed
221
          transformElement()
李晓兵's avatar
李晓兵 committed
222 223 224 225 226 227
        }
      }

      /**
       * @param {object} evt
       */
JingChao's avatar
JingChao committed
228 229
      function touchendHandler (evt) {
        var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches
李晓兵's avatar
李晓兵 committed
230 231

        if (mode === '' || touches.length > 0) {
JingChao's avatar
JingChao committed
232
          return
李晓兵's avatar
李晓兵 committed
233 234 235
        }

        if (scale < 1) {
JingChao's avatar
JingChao committed
236 237 238
          scale = 1
          positionX = 0
          positionY = 0
李晓兵's avatar
李晓兵 committed
239
        } else if (scale > maxScale) {
JingChao's avatar
JingChao committed
240 241 242 243
          scale = maxScale
          relativeScale = scale / initialScale
          positionX = originX * (1 - relativeScale) + initialPositionX + moveX
          positionY = originY * (1 - relativeScale) + initialPositionY + moveY
李晓兵's avatar
李晓兵 committed
244 245
        } else {
          if (positionX > 0) {
JingChao's avatar
JingChao committed
246
            positionX = 0
李晓兵's avatar
李晓兵 committed
247
          } else if (positionX < elWidth * (1 - scale)) {
JingChao's avatar
JingChao committed
248
            positionX = elWidth * (1 - scale)
李晓兵's avatar
李晓兵 committed
249 250
          }
          if (positionY > 0) {
JingChao's avatar
JingChao committed
251
            positionY = 0
李晓兵's avatar
李晓兵 committed
252
          } else if (positionY < elHeight * (1 - scale)) {
JingChao's avatar
JingChao committed
253
            positionY = elHeight * (1 - scale)
李晓兵's avatar
李晓兵 committed
254 255 256
          }
        }

JingChao's avatar
JingChao committed
257 258
        transformElement(0.1)
        mode = ''
李晓兵's avatar
李晓兵 committed
259 260 261 262 263 264
      }

      /**
       * @param {Array} touches
       * @return {number}
       */
JingChao's avatar
JingChao committed
265
      function getDistance (touches) {
李晓兵's avatar
李晓兵 committed
266
        var d = Math.sqrt(Math.pow(touches[0].clientX - touches[1].clientX, 2) +
JingChao's avatar
JingChao committed
267 268
          Math.pow(touches[0].clientY - touches[1].clientY, 2))
        return parseInt(d, 10)
李晓兵's avatar
李晓兵 committed
269 270 271 272 273
      }

      /**
       * @param {number} [duration]
       */
JingChao's avatar
JingChao committed
274 275 276 277 278 279 280 281 282
      function transformElement (duration) {
        var transition = duration ? 'all cubic-bezier(0,0,.5,1) ' + duration + 's' : ''
        var matrixArray = [scale, 0, 0, scale, positionX, positionY]
        var matrix = 'matrix(' + matrixArray.join(',') + ')'

        element.style.webkitTransition = transition
        element.style.transition = transition
        element.style.webkitTransform = matrix + ' translate3d(0,0,0)'
        element.style.transform = matrix + ' translate3d(0,0,0)'
李晓兵's avatar
李晓兵 committed
283
      }
JingChao's avatar
JingChao committed
284
    },
李晓兵's avatar
李晓兵 committed
285

JingChao's avatar
JingChao committed
286
  })
李晓兵's avatar
李晓兵 committed
287

JingChao's avatar
JingChao committed
288
  Vue.directive('keyboardAttach', {// 监听键盘
李晓兵's avatar
李晓兵 committed
289
    inserted: function (el, binding) {
JingChao's avatar
JingChao committed
290
      let KEYBOARD_OPEN_CSS = 'foot-keyboard-open'
李晓兵's avatar
李晓兵 committed
291

JingChao's avatar
JingChao committed
292 293 294
      function keyboardHeight () {
        let innerHeight = window.innerHeight
        let innerWidth = window.innerWidth
李晓兵's avatar
李晓兵 committed
295 296
        if (vum.Platform.isIOS()) {
          if (!vum.Platform.isWebView()) {
JingChao's avatar
JingChao committed
297
            return 266
李晓兵's avatar
李晓兵 committed
298
          }
JingChao's avatar
JingChao committed
299 300
          if (innerWidth >= 375 && innerHeight >= 812) {
            return 330
李晓兵's avatar
李晓兵 committed
301
          }
JingChao's avatar
JingChao committed
302
          return 300
李晓兵's avatar
李晓兵 committed
303
        } else {
JingChao's avatar
JingChao committed
304
          return 275
李晓兵's avatar
李晓兵 committed
305 306 307
        }
      }

JingChao's avatar
JingChao committed
308
      let height = keyboardHeight()
李晓兵's avatar
李晓兵 committed
309

JingChao's avatar
JingChao committed
310 311
      function hasClass (element, csName) {
        return element.className.match(RegExp('(\\s|^)' + csName + '(\\s|$)'))
李晓兵's avatar
李晓兵 committed
312 313
      }

JingChao's avatar
JingChao committed
314
      function addClass (element, csName) {
李晓兵's avatar
李晓兵 committed
315
        if (!hasClass(element, csName)) {
JingChao's avatar
JingChao committed
316
          element.className += ' ' + csName
李晓兵's avatar
李晓兵 committed
317
        }
JingChao's avatar
JingChao committed
318
        element.style.marginBottom = height + 'px'
李晓兵's avatar
李晓兵 committed
319 320
      }

JingChao's avatar
JingChao committed
321
      function removeClass (element, csName) {
李晓兵's avatar
李晓兵 committed
322 323 324
        if (hasClass(element, csName)) {
          element.classList.remove(csName)
        }
JingChao's avatar
JingChao committed
325
        element.style.marginBottom = 0 + 'px'
李晓兵's avatar
李晓兵 committed
326 327 328
      }

      window.addEventListener('native.keyboardshow', function (e) {
JingChao's avatar
JingChao committed
329 330
        addClass(el, KEYBOARD_OPEN_CSS)
      })
李晓兵's avatar
李晓兵 committed
331 332 333

      window.addEventListener('native.keyboardhide', function (e) {
        removeClass(el, KEYBOARD_OPEN_CSS)
JingChao's avatar
JingChao committed
334
      })
李晓兵's avatar
李晓兵 committed
335 336
    },
    unbind: function (el, binding) {
JingChao's avatar
JingChao committed
337
      let KEYBOARD_OPEN_CSS = 'foot-keyboard-open'
李晓兵's avatar
李晓兵 committed
338

JingChao's avatar
JingChao committed
339 340
      function hasClass (element, csName) {
        return element.className.match(RegExp('(\\s|^)' + csName + '(\\s|$)'))
李晓兵's avatar
李晓兵 committed
341 342
      }

JingChao's avatar
JingChao committed
343
      function removeClass (element, csName) {
李晓兵's avatar
李晓兵 committed
344 345 346
        if (hasClass(element, csName)) {
          element.classList.remove(csName)
        }
JingChao's avatar
JingChao committed
347
        element.style.marginBottom = 0 + 'px'
李晓兵's avatar
李晓兵 committed
348 349
      }

JingChao's avatar
JingChao committed
350
      removeClass(el, KEYBOARD_OPEN_CSS)
李晓兵's avatar
李晓兵 committed
351 352 353 354 355 356
      window.removeEventListener('native.keyboardshow', function (e) {

      })
      window.removeEventListener('native.keyboardhide', function (e) {

      })
JingChao's avatar
JingChao committed
357 358
    },
  })
李晓兵's avatar
李晓兵 committed
359

JingChao's avatar
JingChao committed
360
  Vue.directive('autoSize', {
李晓兵's avatar
李晓兵 committed
361 362 363 364 365 366 367 368 369 370 371 372 373
    bind: function (el, binding) {
      if (el.nodeName === 'TEXTAREA') {
        Autosize(el)
      }
      el.addEventListener('oninput', function (e) {
        Autosize.update(el)
      })
    },
    unbind: function (el, binding) {
      Autosize.update(el)
      Autosize.destroy(el)
      el.removeEventListener('oninput', function (e) {
      })
JingChao's avatar
JingChao committed
374 375
    },
  })
李晓兵's avatar
李晓兵 committed
376
}