Skip to content

Commit edb8a73

Browse files
authored
Merge pull request #5 from riyaddecoder/fix/touch-drag
fix: touch drag.
2 parents c947dc3 + 0fc45d8 commit edb8a73

3 files changed

Lines changed: 70 additions & 22 deletions

File tree

src/components/AudioPlayer.tsx

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from 'react';
22
import { iconPaths } from '../helpers/icons/icons';
33
import { formatTime } from '../helpers/utils/formatTime';
44
import { getRangeBox } from '../helpers/utils/getRangeBox';
5+
import getDeviceEventNames from '../helpers/utils/getDeviceEventNames';
56
import './audioPlay.css';
67

78
export interface AudioInterface {
@@ -197,37 +198,43 @@ export const AudioPlayer: React.FC<AudioInterface> = ({
197198
}
198199
};
199200

200-
const inRange = (event: MouseEvent | React.MouseEvent<HTMLDivElement>) => {
201+
const inRange = (event: MouseEvent | TouchEvent | React.MouseEvent<HTMLDivElement, MouseEvent>) => {
201202
const rangeBox = getRangeBox(event, currentlyDragged.current);
202203
const rect = rangeBox.getBoundingClientRect();
203204
const direction = rangeBox.dataset.direction;
204205
if (direction === 'horizontal') {
205-
if (event.clientX - rect.left < 0 || event.clientX - rect.right > 0) return false;
206+
const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX;
207+
if (clientX - rect.left < 0 || clientX - rect.right > 0) return false;
206208
} else {
207209
const min = rect.top;
208210
const max = min + rangeBox.offsetHeight;
209-
if (event.clientY < min || event.clientY > max) return false;
211+
const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY;
212+
if (clientY < min || clientY > max) return false;
210213
}
211214
return true;
212215
};
213216

214-
function getCoefficient(event: MouseEvent | React.MouseEvent<HTMLDivElement>) {
217+
function getCoefficient(event: MouseEvent | TouchEvent | React.MouseEvent<HTMLDivElement, MouseEvent>) {
215218
const slider = getRangeBox(event, currentlyDragged.current);
216219
const rect = slider.getBoundingClientRect();
217220
let K = 0;
221+
218222
if (slider.dataset.direction === 'horizontal') {
219-
const offsetX = event.clientX - rect.left;
223+
const clientX = 'touches' in event ? event.touches[0].clientX : event.clientX;
224+
const offsetX = clientX - rect.left;
220225
const width = slider.clientWidth;
221226
K = offsetX / width;
222227
} else if (slider.dataset.direction === 'vertical') {
228+
const clientY = 'touches' in event ? event.touches[0].clientY : event.clientY;
223229
const height = slider.clientHeight;
224-
const offsetY = event.clientY - rect.top;
230+
const offsetY = clientY - rect.top;
225231
K = 1 - offsetY / height;
226232
}
233+
227234
return K;
228235
}
229236

230-
const rewind = (event: MouseEvent | React.MouseEvent<HTMLDivElement>) => {
237+
const rewind = (event: MouseEvent | TouchEvent | React.MouseEvent<HTMLDivElement>) => {
231238
if (inRange(event) && audioRef.current) {
232239
if (preload === 'none' && !audioRef.current.duration) {
233240
setCanPlay(false);
@@ -239,37 +246,38 @@ export const AudioPlayer: React.FC<AudioInterface> = ({
239246
}
240247
};
241248

242-
const changeVolume = (event: MouseEvent | React.MouseEvent<HTMLDivElement>) => {
249+
const changeVolume = (event: MouseEvent | TouchEvent | React.MouseEvent<HTMLDivElement>) => {
243250
if (inRange(event) && audioRef.current) {
244251
audioRef.current.volume = getCoefficient(event);
245252
}
246253
};
247254

248-
const handleRewindMouseDown = () => {
255+
const handleRewindDragging = () => {
249256
currentlyDragged.current = rewindPin.current;
250-
251-
window.addEventListener('mousemove', rewind, false);
257+
const events = getDeviceEventNames();
258+
window.addEventListener(events.move, rewind, false);
252259

253260
window.addEventListener(
254-
'mouseup',
261+
events.up,
255262
() => {
256263
currentlyDragged.current = null;
257-
window.removeEventListener('mousemove', rewind, false);
264+
window.removeEventListener(events.move, rewind, false);
258265
},
259266
{ once: true }
260267
);
261268
};
262269

263-
const handleVolumeMouseDown = () => {
270+
const handleVolumeDragging = () => {
264271
currentlyDragged.current = volumePin.current;
272+
const events = getDeviceEventNames();
265273

266-
window.addEventListener('mousemove', changeVolume, false);
274+
window.addEventListener(events.move, changeVolume, false);
267275

268276
window.addEventListener(
269-
'mouseup',
277+
events.up,
270278
() => {
271279
currentlyDragged.current = null;
272-
window.removeEventListener('mousemove', changeVolume, false);
280+
window.removeEventListener(events.move, changeVolume, false);
273281
},
274282
false
275283
);
@@ -352,15 +360,22 @@ export const AudioPlayer: React.FC<AudioInterface> = ({
352360

353361
<div className="rap-controls">
354362
<span className="rap-current-time">{currentTime}</span>
355-
<div className="rap-slider" data-direction="horizontal" onMouseDown={handleRewindMouseDown} onClick={rewind}>
363+
<div className="rap-slider" data-direction="horizontal" onMouseDown={handleRewindDragging} onTouchStart={handleRewindDragging} onClick={rewind}>
356364
<div
357365
className="rap-progress"
358366
style={{
359367
...{ width: progressBarPercent + '%' },
360368
...(sliderColor ? { backgroundColor: sliderColor } : {})
361369
}}
362370
>
363-
<div ref={rewindPin} className="rap-pin" data-method="rewind" onMouseDown={handleRewindMouseDown} style={sliderColor ? { backgroundColor: sliderColor } : {}}></div>
371+
<div
372+
ref={rewindPin}
373+
className="rap-pin"
374+
data-method="rewind"
375+
onMouseDown={handleRewindDragging}
376+
onTouchStart={handleRewindDragging}
377+
style={sliderColor ? { backgroundColor: sliderColor } : {}}
378+
></div>
364379
</div>
365380
</div>
366381
{totalTime !== '--:--' && <span className="rap-total-time">{totalTime}</span>}
@@ -380,15 +395,22 @@ export const AudioPlayer: React.FC<AudioInterface> = ({
380395
e.stopPropagation();
381396
}}
382397
>
383-
<div className="rap-slider" data-direction="vertical" onClick={changeVolume} onMouseDown={handleVolumeMouseDown}>
398+
<div className="rap-slider" data-direction="vertical" onClick={changeVolume} onMouseDown={handleVolumeDragging} onTouchStart={handleVolumeDragging}>
384399
<div
385400
className="rap-progress"
386401
style={{
387402
...{ height: `${volumeProgress}%` },
388403
...(sliderColor ? { backgroundColor: sliderColor } : {})
389404
}}
390405
>
391-
<div ref={volumePin} className="rap-pin" data-method="changeVolume" style={sliderColor ? { backgroundColor: sliderColor } : {}} onMouseDown={handleVolumeMouseDown}></div>
406+
<div
407+
ref={volumePin}
408+
className="rap-pin"
409+
data-method="changeVolume"
410+
style={sliderColor ? { backgroundColor: sliderColor } : {}}
411+
onMouseDown={handleVolumeDragging}
412+
onTouchStart={handleVolumeDragging}
413+
></div>
392414
</div>
393415
</div>
394416
</div>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
type moveEvents = 'touchmove' | 'mousemove';
2+
type upEvents = 'touchend' | 'mouseup';
3+
4+
interface returnProp {
5+
move: moveEvents;
6+
up: upEvents;
7+
}
8+
9+
const getDeviceEventNames = (): returnProp => {
10+
if (isTouchDevice()) {
11+
return {
12+
move: 'touchmove',
13+
up: 'touchend'
14+
};
15+
}
16+
return {
17+
move: 'mousemove',
18+
up: 'mouseup'
19+
};
20+
};
21+
22+
const isTouchDevice = () => {
23+
return 'ontouchstart' in window || navigator.maxTouchPoints;
24+
};
25+
26+
export default getDeviceEventNames;

src/helpers/utils/getRangeBox.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ function isDraggable(el: HTMLElement) {
22
return Array.from(el.classList).indexOf('rap-pin') !== -1;
33
}
44

5-
export const getRangeBox = (event: MouseEvent | React.MouseEvent<HTMLDivElement>, currentDragElement: HTMLDivElement | null) => {
5+
export const getRangeBox = (event: MouseEvent | TouchEvent | React.MouseEvent<HTMLDivElement>, currentDragElement: HTMLDivElement | null) => {
66
let rangeBox = event.target as HTMLElement;
77
if (event.type === 'click' && isDraggable(rangeBox) && rangeBox?.parentElement?.parentElement) {
88
rangeBox = rangeBox.parentElement.parentElement;

0 commit comments

Comments
 (0)