|
186 | 186 |
|
187 | 187 | [iframe src="slider-html" height=40 edit] |
188 | 188 |
|
| 189 | +<p></p> |
| 190 | + |
| 191 | + |
| 192 | + |
189 | 193 | Затем он работает так: |
190 | 194 |
|
191 | | -1. Пользователь сначала нажимает на ползунок - срабатывает `pointerdown`. |
192 | | -2. Затем двигает указателем его - срабатывает `pointermove`, и мы передвигаем ползунок вместе с ним. |
| 195 | +1. Пользователь сначала нажимает на ползунок `thumb` - срабатывает `pointerdown`. |
| 196 | +2. Затем двигает его указателем - срабатывает `pointermove`, и наш код перемещает элемент `thumb`. |
193 | 197 | - ...Причём, по мере движения, указатель может покидать ползунок - перемещаться выше или ниже. При этом ползунок должен передвигаться строго по горизонтали, на одной линии с указателем. |
194 | 198 |
|
195 | | -Так что для полного отслеживания перемещения указателя, включая ниже и выше ползунка, нам пришлось поставить обработчик `pointermove` на весь документ `document`. |
| 199 | +В решении, основанном на событиях мыши, для отслеживания всех движений указателя, включая те, которые происходят выше/ниже элемента `thumb`, мы должны были назначить обработчик события `mousemove` на весь документ `document`. |
196 | 200 |
|
197 | | -Такое решение выглядит слегка "грязным". Одна из проблем - это то, что движения указателя по документу могут вызвать сторонние эффекты, заставить сработать другие обработчики, не имеющие отношения к слайдеру. |
| 201 | +Однако это не самое правильное решение. Одна из проблем - это то, что движения указателя по документу могут вызвать сторонние эффекты, заставить работать другие обработчики (например, `mouseover`), не имеющие отношения к слайдеру. |
198 | 202 |
|
199 | | -Захват указателя позволяет привязать `pointermove` к `thumb` и избежать любых подобных проблем: |
| 203 | +Именно здесь вступает в игру `setPointerCapture`: |
200 | 204 |
|
201 | 205 | - Мы можем вызывать `thumb.setPointerCapture(event.pointerId)` в обработчике `pointerdown`, |
202 | 206 | - Тогда дальнейшие события указателя до `pointerup/cancel` будут привязаны к `thumb`. |
|
208 | 212 |
|
209 | 213 | ```js |
210 | 214 | thumb.onpointerdown = function(event) { |
211 | | - // все события указателя перенаправить на thumb (пока не произойдёт 'pointerup') |
| 215 | + // перенацелить все события указателя (до pointerup) на thumb |
212 | 216 | thumb.setPointerCapture(event.pointerId); |
| 217 | + // начать отслеживание перемещения указателя |
| 218 | + thumb.onpointermove = function(event) { |
| 219 | + // перемещение слайдера: отслеживание thumb, т.к все события указателя перенацелены на него |
| 220 | + let newLeft = event.clientX - slider.getBoundingClientRect().left; |
| 221 | + thumb.style.left = newLeft + 'px'; |
| 222 | + }; |
| 223 | + // если сработало событие pointerup, завершить отслеживание перемещения указателя |
| 224 | + thumb.onpointerup = function(event) { |
| 225 | + thumb.onpointermove = null; |
| 226 | + thumb.onpointerup = null; |
| 227 | + // ...при необходимости также обработайте "конец перемещения" |
| 228 | + }; |
213 | 229 | }; |
214 | | - |
215 | | -thumb.onpointermove = function(event) { |
216 | | - // перемещение ползунка: все события перенаправлены на этот обработчик |
217 | | - let newLeft = event.clientX - slider.getBoundingClientRect().left; |
218 | | - thumb.style.left = newLeft + 'px'; |
219 | | -}; |
220 | | - |
221 | | -// примечание: нет необходимости вызывать thumb.releasePointerCapture, |
222 | | -// при срабатывании события 'pointerup' это происходит автоматически |
| 230 | +// примечание: нет необходимости вызывать thumb.releasePointerCapture, |
| 231 | +// это происходит автоматически при pointerup |
223 | 232 | ``` |
224 | 233 |
|
225 | 234 | ```online |
226 | 235 | Полное демо: |
227 | 236 |
|
228 | 237 | [iframe src="slider" height=100 edit] |
| 238 | +
|
| 239 | +<p></p> |
| 240 | +
|
| 241 | +В демонстрационном примере также имеется дополнительный элемент с обработчиком `onmouseover`, показывающий текущую дату. |
| 242 | +
|
| 243 | +Обратите внимание: пока вы перетаскиваете ползунок, вы можете навести курсор на этот элемент, и его обработчик *не сработает*. |
| 244 | +
|
| 245 | +Таким образом, благодаря `setPointerCapture` перетаскивание теперь не имеет побочных эффектов. |
229 | 246 | ``` |
230 | 247 |
|
231 | 248 | Таким образом, мы имеем два бонуса: |
|
0 commit comments