mh-two-thousand-and-two
2024-04-12 3d2ec2fd0578d3ba0a414b0cc4e4a2ae60878596
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import UniAnimationElement from './animation'
 
export default class UniHoverElement extends UniAnimationElement {
  setAttribute (key, value) {
    if (key === 'hover-class') {
      this._updateHoverClass(value)
    }
    super.setAttribute(key, value)
  }
 
  removeAttribute (key) {
    if (key === 'hover-class') {
      this._updateHoverClass()
    }
    super.removeAttribute(key)
  }
 
  get hovering () {
    return this._hovering
  }
 
  set hovering (hovering) {
    this._hovering = hovering
    const hoverClass = this.getAttribute('hover-class').split(' ').filter(Boolean)
    const ClassList = this.classList
    if (hovering) {
      ClassList.add.apply(ClassList, hoverClass)
    } else {
      ClassList.remove.apply(ClassList, hoverClass)
    }
  }
 
  _updateHoverClass (hoverClass) {
    hoverClass = hoverClass || 'none'
    if (hoverClass === 'none') {
      this._removeEventListener()
    } else {
      this._addEventListener()
    }
  }
 
  _addEventListener () {
    if (!this.__hoverTouchStart) {
      this.addEventListener('touchstart', this.__hoverTouchStart = this._hoverTouchStart.bind(this))
      this.addEventListener('touchend', this.__hoverTouchEnd = this._hoverTouchEnd.bind(this))
      this.addEventListener('touchcancel', this.__hoverTouchCancel = this._hoverTouchCancel.bind(this))
    }
  }
 
  _removeEventListener () {
    if (this.__hoverTouchStart) {
      this.removeEventListener('touchstart', this.__hoverTouchStart)
      delete this.__hoverTouchStart
      this.removeEventListener('touchend', this.__hoverTouchEnd)
      delete this.__hoverTouchEnd
      this.removeEventListener('touchcancel', this.__hoverTouchCancel)
      delete this.__hoverTouchCancel
    }
  }
 
  _hoverTouchStart (evt) {
    if (evt._hoverPropagationStopped) {
      return
    }
    if (this.disabled) {
      return
    }
    if (evt.touches.length > 1) {
      return
    }
    if (this.getAttribute('hover-stop-propagation')) {
      evt._hoverPropagationStopped = true
    }
    this._hoverTouch = true
    const hoverStartTimeDefault = 50
    const hoverStartTime = Number(this.getAttribute('hover-start-time') || hoverStartTimeDefault)
    this._hoverStartTimer = setTimeout(() => {
      this.hovering = true
      if (!this._hoverTouch) {
        // 防止在hoverStartTime时间内触发了 touchend 或 touchcancel
        this._hoverReset()
      }
    }, isNaN(hoverStartTime) ? hoverStartTimeDefault : hoverStartTime)
  }
 
  _hoverTouchEnd () {
    this._hoverTouch = false
    if (this.hovering) {
      this._hoverReset()
    }
  }
 
  _hoverReset () {
    requestAnimationFrame(() => {
      clearTimeout(this._hoverStayTimer)
      const hoverStayTimeDefault = 400
      const hoverStayTime = Number(this.getAttribute('hover-stay-time') || hoverStayTimeDefault)
      this._hoverStayTimer = setTimeout(() => {
        this.hovering = false
      }, isNaN(hoverStayTime) ? hoverStayTimeDefault : hoverStayTime)
    })
  }
 
  _hoverTouchCancel () {
    this._hoverTouch = false
    this.hovering = false
    clearTimeout(this._hoverStartTimer)
  }
}