|
7 | 7 | @mousedown.passive.stop="startRipple">
|
8 | 8 | <slot />
|
9 | 9 |
|
10 |
| - <transition name="md-ripple" @after-enter="clearWave" v-if="!isDisabled"> |
11 |
| - <span class="md-ripple-wave" :class="waveClasses" :style="waveStyles" v-if="animating" ref="rippleWave" /> |
12 |
| - </transition> |
| 10 | + <template v-if="!isDisabled"> |
| 11 | + <span v-for="(ripple, index) in ripples" :key="'ripple'+index" class="md-ripple-wave" :class="waveClasses" :style="ripple.waveStyles" /> |
| 12 | + </template> |
13 | 13 | </div>
|
14 | 14 | </template>
|
15 | 15 |
|
|
25 | 25 | mdCentered: Boolean
|
26 | 26 | },
|
27 | 27 | data: () => ({
|
28 |
| - eventType: null, |
29 |
| - waveStyles: null, |
30 |
| - animating: false, |
31 |
| - touchTimeout: null |
| 28 | + ripples: [], |
| 29 | + touchTimeout: null, |
| 30 | + eventType: null |
32 | 31 | }),
|
33 | 32 | computed: {
|
34 | 33 | isDisabled () {
|
|
84 | 83 | position = this.getHitPosition($event, size)
|
85 | 84 | }
|
86 | 85 |
|
87 |
| - await this.clearWave() |
88 |
| -
|
89 | 86 | this.eventType = $event.type
|
90 |
| - this.animating = true |
91 |
| - this.applyStyles(position, size) |
| 87 | + this.ripples.push({ |
| 88 | + animating: true, |
| 89 | + waveStyles: this.applyStyles(position, size) |
| 90 | + }) |
92 | 91 | }
|
93 | 92 | })
|
| 93 | + this.clearWaves() |
94 | 94 | },
|
95 | 95 | applyStyles (position, size) {
|
96 | 96 | size += 'px'
|
97 | 97 |
|
98 |
| - this.waveStyles = { |
| 98 | + return { |
99 | 99 | ...position,
|
100 | 100 | width: size,
|
101 | 101 | height: size
|
102 | 102 | }
|
103 | 103 | },
|
104 |
| - clearWave () { |
105 |
| - this.waveStyles = null |
106 |
| - this.animating = false |
107 |
| -
|
108 |
| - return this.$nextTick() |
| 104 | + clearWaves () { |
| 105 | + let timeout |
| 106 | + window.clearTimeout(timeout) |
| 107 | + timeout = window.setTimeout(() => { |
| 108 | + this.ripples = [] |
| 109 | + }, 1000) |
109 | 110 | },
|
110 | 111 | getSize () {
|
111 | 112 | const { offsetWidth, offsetHeight } = this.$el
|
|
158 | 159 | background: currentColor;
|
159 | 160 | border-radius: 50%;
|
160 | 161 | opacity: 0;
|
161 |
| - transform: scale(2) translateZ(0); |
| 162 | + animation: ripple .8s $md-transition-stand-timing; |
| 163 | + transition-property: opacity, transform; |
| 164 | + will-change: opacity, transform; |
162 | 165 |
|
163 | 166 | &.md-centered {
|
| 167 | + animation-duration: 1.2s; |
164 | 168 | top: 50%;
|
165 | 169 | left: 50%;
|
166 | 170 | }
|
167 |
| -
|
168 |
| - ~ * { |
| 171 | + ~ *:not(.md-ripple-wave) { |
169 | 172 | position: relative;
|
170 | 173 | z-index: 2;
|
171 | 174 | }
|
172 | 175 | }
|
173 | 176 |
|
174 |
| - .md-ripple-enter-active { |
175 |
| - transition: .8s $md-transition-stand-timing; |
176 |
| - transition-property: opacity, transform; |
177 |
| - will-change: opacity, transform; |
178 |
| -
|
179 |
| - &.md-centered { |
180 |
| - transition-duration: 1.2s; |
| 177 | + @keyframes ripple { |
| 178 | + 0% { |
| 179 | + opacity: 0; |
| 180 | + transform: scale(0) translateZ(0); |
| 181 | + } |
| 182 | + 20% { |
| 183 | + opacity: .26; |
| 184 | + transform: scale(.26) translateZ(0); |
| 185 | + } |
| 186 | + 100% { |
| 187 | + opacity: 0; |
| 188 | + transform: scale(2) translateZ(0); |
181 | 189 | }
|
182 |
| - } |
183 |
| -
|
184 |
| - .md-ripple-enter { |
185 |
| - opacity: .26; |
186 |
| - transform: scale(.26) translateZ(0); |
187 | 190 | }
|
188 | 191 | </style>
|
0 commit comments