Merge pull request #52 from vadimkorr/feature/#49-Update-focus-event-for-touch
feature/#49 Update focus handlers for touch events
This commit is contained in:
@@ -43,7 +43,7 @@ Import component
|
|||||||
| `autoplay` | `boolean` | `false` | Enables auto play of pages |
|
| `autoplay` | `boolean` | `false` | Enables auto play of pages |
|
||||||
| `autoplayDuration` | `number` | `3000` | Autoplay change interval (ms) |
|
| `autoplayDuration` | `number` | `3000` | Autoplay change interval (ms) |
|
||||||
| `autoplayDirection` | `string` | `'next'` | Autoplay change direction (`next` or `prev`) |
|
| `autoplayDirection` | `string` | `'next'` | Autoplay change direction (`next` or `prev`) |
|
||||||
| `pauseOnFocus` | `boolean` | `false` | Pause autoplay on focus |
|
| `pauseOnFocus` | `boolean` | `false` | Pauses autoplay on focus (for desktop - hover on the carousel to toggle the autoplay, for touchable devices - tap the carousel to toggle the autoplay) |
|
||||||
| `autoplayProgressVisible` | `boolean` | `false` | Show autoplay duration progress indicator |
|
| `autoplayProgressVisible` | `boolean` | `false` | Show autoplay duration progress indicator |
|
||||||
| `dots` | `boolean` | `true` | Current page indicator dots |
|
| `dots` | `boolean` | `true` | Current page indicator dots |
|
||||||
| `timingFunction` | `string` | `'ease-in-out'` | CSS animation timing function |
|
| `timingFunction` | `string` | `'ease-in-out'` | CSS animation timing function |
|
||||||
|
|||||||
@@ -1,21 +1,15 @@
|
|||||||
// focusin event
|
// focusin event
|
||||||
export function addFocusinEventListener(source, cb) {
|
export function addFocusinEventListener(source, cb) {
|
||||||
source.addEventListener('mouseenter', cb)
|
source.addEventListener('mouseenter', cb)
|
||||||
source.addEventListener('touchstart', cb)
|
|
||||||
}
|
}
|
||||||
export function removeFocusinEventListener(source, cb) {
|
export function removeFocusinEventListener(source, cb) {
|
||||||
source.removeEventListener('mouseenter', cb)
|
source.removeEventListener('mouseenter', cb)
|
||||||
source.removeEventListener('touchstart', cb)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// focusout event
|
// focusout event
|
||||||
export function addFocusoutEventListener(source, cb) {
|
export function addFocusoutEventListener(source, cb) {
|
||||||
source.addEventListener('mouseleave', cb)
|
source.addEventListener('mouseleave', cb)
|
||||||
source.addEventListener('touchend', cb)
|
|
||||||
source.addEventListener('touchcancel', cb)
|
|
||||||
}
|
}
|
||||||
export function removeFocusoutEventListener(source, cb) {
|
export function removeFocusoutEventListener(source, cb) {
|
||||||
source.removeEventListener('mouseleave', cb)
|
source.removeEventListener('mouseleave', cb)
|
||||||
source.removeEventListener('touchend', cb)
|
|
||||||
source.removeEventListener('touchcancel', cb)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,31 @@
|
|||||||
import { createDispatcher } from '../../utils/event'
|
import { createDispatcher } from '../../utils/event'
|
||||||
|
import { get } from '../../utils/object'
|
||||||
import {
|
import {
|
||||||
addFocusinEventListener,
|
addFocusinEventListener,
|
||||||
removeFocusinEventListener,
|
removeFocusinEventListener,
|
||||||
addFocusoutEventListener,
|
addFocusoutEventListener,
|
||||||
removeFocusoutEventListener,
|
removeFocusoutEventListener
|
||||||
} from './event'
|
} from './event'
|
||||||
|
|
||||||
export function focusable(node) {
|
/**
|
||||||
const dispatch = createDispatcher(node)
|
* focusable events are for mouse events only
|
||||||
|
*/
|
||||||
|
export function focusable(node, options) {
|
||||||
|
// pass custom dispatch fn in order to re-translate dispatched event
|
||||||
|
const dispatch = get(options, 'dispatch', createDispatcher(node))
|
||||||
|
|
||||||
function handleFocusin() {
|
function handleFocusin() {
|
||||||
|
addFocusoutEventListener(node, handleFocusout)
|
||||||
dispatch('focused', { value: true })
|
dispatch('focused', { value: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFocusout() {
|
function handleFocusout() {
|
||||||
dispatch('focused', { value: false })
|
dispatch('focused', { value: false })
|
||||||
|
removeFocusoutEventListener(node, handleFocusout)
|
||||||
}
|
}
|
||||||
|
|
||||||
addFocusinEventListener(node, handleFocusin)
|
addFocusinEventListener(node, handleFocusin)
|
||||||
addFocusoutEventListener(node, handleFocusout)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
destroy() {
|
destroy() {
|
||||||
removeFocusinEventListener(node, handleFocusin)
|
removeFocusinEventListener(node, handleFocusin)
|
||||||
|
|||||||
1
src/actions/pausable/index.js
Normal file
1
src/actions/pausable/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './pausable'
|
||||||
30
src/actions/pausable/pausable.js
Normal file
30
src/actions/pausable/pausable.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
createDispatcher,
|
||||||
|
getIsTouchable,
|
||||||
|
} from '../../utils/event'
|
||||||
|
|
||||||
|
import { focusable } from '../focusable'
|
||||||
|
import { tappable } from '../tappable'
|
||||||
|
|
||||||
|
export function pausable(node) {
|
||||||
|
const dispatch = createDispatcher(node)
|
||||||
|
|
||||||
|
if (getIsTouchable()) {
|
||||||
|
return tappable(node, {
|
||||||
|
dispatch: (_, payload) => {
|
||||||
|
dispatch('pausedToggle', {
|
||||||
|
isTouchable: true,
|
||||||
|
...payload
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return focusable(node, {
|
||||||
|
dispatch: (_, payload) => {
|
||||||
|
dispatch('pausedToggle', {
|
||||||
|
isTouchable: false,
|
||||||
|
...payload
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
removeEndEventListener,
|
removeEndEventListener,
|
||||||
} from './event'
|
} from './event'
|
||||||
import { createDispatcher } from '../../utils/event'
|
import { createDispatcher } from '../../utils/event'
|
||||||
|
import { SWIPE_MIN_DURATION_MS, SWIPE_MIN_DISTANCE_PX } from '../../units'
|
||||||
|
|
||||||
function getCoords(event) {
|
function getCoords(event) {
|
||||||
if ('TouchEvent' in window && event instanceof TouchEvent) {
|
if ('TouchEvent' in window && event instanceof TouchEvent) {
|
||||||
@@ -28,49 +29,64 @@ export function swipeable(node, { thresholdProvider }) {
|
|||||||
let x
|
let x
|
||||||
let y
|
let y
|
||||||
let moved = 0
|
let moved = 0
|
||||||
|
let swipeStartedAt
|
||||||
|
let isTouching = false
|
||||||
|
|
||||||
function handleMousedown(event) {
|
function isValidSwipe() {
|
||||||
|
const swipeDurationMs = Date.now() - swipeStartedAt
|
||||||
|
return swipeDurationMs >= SWIPE_MIN_DURATION_MS && Math.abs(moved) >= SWIPE_MIN_DISTANCE_PX
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDown(event) {
|
||||||
|
swipeStartedAt = Date.now()
|
||||||
moved = 0
|
moved = 0
|
||||||
|
isTouching = true
|
||||||
const coords = getCoords(event)
|
const coords = getCoords(event)
|
||||||
x = coords.x
|
x = coords.x
|
||||||
y = coords.y
|
y = coords.y
|
||||||
dispatch('start', { x, y })
|
dispatch('swipeStart', { x, y })
|
||||||
addMoveEventListener(window, handleMousemove)
|
addMoveEventListener(window, handleMove)
|
||||||
addEndEventListener(window, handleMouseup)
|
addEndEventListener(window, handleUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMousemove(event) {
|
function handleMove(event) {
|
||||||
|
if (!isTouching) return
|
||||||
const coords = getCoords(event)
|
const coords = getCoords(event)
|
||||||
const dx = coords.x - x
|
const dx = coords.x - x
|
||||||
const dy = coords.y - y
|
const dy = coords.y - y
|
||||||
x = coords.x
|
x = coords.x
|
||||||
y = coords.y
|
y = coords.y
|
||||||
dispatch('move', { x, y, dx, dy })
|
dispatch('swipeMove', { x, y, dx, dy })
|
||||||
|
|
||||||
if (dx !== 0 && Math.sign(dx) !== Math.sign(moved)) {
|
if (dx !== 0 && Math.sign(dx) !== Math.sign(moved)) {
|
||||||
moved = 0
|
moved = 0
|
||||||
}
|
}
|
||||||
moved += dx
|
moved += dx
|
||||||
if (Math.abs(moved) > thresholdProvider()) {
|
if (Math.abs(moved) > thresholdProvider()) {
|
||||||
dispatch('threshold', { direction: moved > 0 ? PREV : NEXT })
|
dispatch('swipeThresholdReached', { direction: moved > 0 ? PREV : NEXT })
|
||||||
removeEndEventListener(window, handleMouseup)
|
removeEndEventListener(window, handleUp)
|
||||||
removeMoveEventListener(window, handleMousemove)
|
removeMoveEventListener(window, handleMove)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseup(event) {
|
function handleUp(event) {
|
||||||
|
removeEndEventListener(window, handleUp)
|
||||||
|
removeMoveEventListener(window, handleMove)
|
||||||
|
|
||||||
|
isTouching = false
|
||||||
|
|
||||||
|
if (!isValidSwipe()) {
|
||||||
|
dispatch('swipeFailed')
|
||||||
|
return
|
||||||
|
}
|
||||||
const coords = getCoords(event)
|
const coords = getCoords(event)
|
||||||
x = coords.x
|
dispatch('swipeEnd', { x: coords.x, y: coords.y })
|
||||||
y = coords.y
|
|
||||||
dispatch('end', { x, y })
|
|
||||||
removeEndEventListener(window, handleMouseup)
|
|
||||||
removeMoveEventListener(window, handleMousemove)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addStartEventListener(node, handleMousedown)
|
addStartEventListener(node, handleDown)
|
||||||
return {
|
return {
|
||||||
destroy() {
|
destroy() {
|
||||||
removeStartEventListener(node, handleMousedown)
|
removeStartEventListener(node, handleDown)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/actions/tappable/event.js
Normal file
15
src/actions/tappable/event.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// tap start event
|
||||||
|
export function addFocusinEventListener(source, cb) {
|
||||||
|
source.addEventListener('touchstart', cb)
|
||||||
|
}
|
||||||
|
export function removeFocusinEventListener(source, cb) {
|
||||||
|
source.removeEventListener('touchstart', cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tap end event
|
||||||
|
export function addFocusoutEventListener(source, cb) {
|
||||||
|
source.addEventListener('touchend', cb)
|
||||||
|
}
|
||||||
|
export function removeFocusoutEventListener(source, cb) {
|
||||||
|
source.removeEventListener('touchend', cb)
|
||||||
|
}
|
||||||
1
src/actions/tappable/index.js
Normal file
1
src/actions/tappable/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './tappable'
|
||||||
66
src/actions/tappable/tappable.js
Normal file
66
src/actions/tappable/tappable.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { createDispatcher } from '../../utils/event'
|
||||||
|
import { get } from '../../utils/object'
|
||||||
|
import { getDistance } from '../../utils/math'
|
||||||
|
import {
|
||||||
|
addFocusinEventListener,
|
||||||
|
removeFocusinEventListener,
|
||||||
|
addFocusoutEventListener,
|
||||||
|
removeFocusoutEventListener,
|
||||||
|
} from './event'
|
||||||
|
import {
|
||||||
|
TAP_DURATION_MS,
|
||||||
|
TAP_MOVEMENT_PX,
|
||||||
|
} from '../../units'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tappable events are for touchable devices only
|
||||||
|
*/
|
||||||
|
export function tappable(node, options) {
|
||||||
|
// pass custom dispatch fn in order to re-translate dispatched event
|
||||||
|
const dispatch = get(options, 'dispatch', createDispatcher(node))
|
||||||
|
|
||||||
|
let tapStartedAt = 0
|
||||||
|
let tapStartPos = { x: 0, y: 0 }
|
||||||
|
|
||||||
|
function getIsValidTap({
|
||||||
|
tapEndedAt,
|
||||||
|
tapEndedPos
|
||||||
|
}) {
|
||||||
|
const tapTime = tapEndedAt - tapStartedAt
|
||||||
|
const tapDist = getDistance(tapStartPos, tapEndedPos)
|
||||||
|
return (
|
||||||
|
tapTime <= TAP_DURATION_MS &&
|
||||||
|
tapDist <= TAP_MOVEMENT_PX
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTapstart(event) {
|
||||||
|
tapStartedAt = Date.now()
|
||||||
|
|
||||||
|
const touch = event.touches[0]
|
||||||
|
tapStartPos = { x: touch.clientX, y: touch.clientY }
|
||||||
|
|
||||||
|
addFocusoutEventListener(node, handleTapend)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTapend(event) {
|
||||||
|
removeFocusoutEventListener(node, handleTapend)
|
||||||
|
|
||||||
|
const touch = event.changedTouches[0]
|
||||||
|
if (getIsValidTap({
|
||||||
|
tapEndedAt: Date.now(),
|
||||||
|
tapEndedPos: { x: touch.clientX, y: touch.clientY }
|
||||||
|
})) {
|
||||||
|
dispatch('tapped')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addFocusinEventListener(node, handleTapstart)
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
removeFocusinEventListener(node, handleTapstart)
|
||||||
|
removeFocusoutEventListener(node, handleTapend)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
import Progress from '../Progress/Progress.svelte'
|
import Progress from '../Progress/Progress.svelte'
|
||||||
import { NEXT, PREV } from '../../direction'
|
import { NEXT, PREV } from '../../direction'
|
||||||
import { swipeable } from '../../actions/swipeable'
|
import { swipeable } from '../../actions/swipeable'
|
||||||
import { focusable } from '../../actions/focusable'
|
import { pausable } from '../../actions/pausable'
|
||||||
import {
|
import {
|
||||||
addResizeEventListener,
|
addResizeEventListener,
|
||||||
removeResizeEventListener
|
removeResizeEventListener
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
children[pageIndex].style.maxWidth = `${pageWidth}px`
|
children[pageIndex].style.maxWidth = `${pageWidth}px`
|
||||||
}
|
}
|
||||||
|
|
||||||
offsetPage(false)
|
offsetPage({ animated: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
function addClones() {
|
function addClones() {
|
||||||
@@ -190,7 +190,9 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
autoplay && await autoplayDirectionFnDescription[autoplayDirection]()
|
if (autoplay) {
|
||||||
|
await autoplayDirectionFnDescription[autoplayDirection]()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cleanupFns = []
|
let cleanupFns = []
|
||||||
@@ -225,7 +227,8 @@
|
|||||||
await showPage(pageIndex + Number(infinite))
|
await showPage(pageIndex + Number(infinite))
|
||||||
}
|
}
|
||||||
|
|
||||||
function offsetPage(animated) {
|
function offsetPage(options) {
|
||||||
|
const animated = get(options, 'animated', true)
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// _duration is an offset animation time
|
// _duration is an offset animation time
|
||||||
_duration = animated ? duration : 0
|
_duration = animated ? duration : 0
|
||||||
@@ -254,11 +257,12 @@
|
|||||||
// Disable page change while animation is in progress
|
// Disable page change while animation is in progress
|
||||||
let disabled = false
|
let disabled = false
|
||||||
async function changePage(updateStoreFn, options) {
|
async function changePage(updateStoreFn, options) {
|
||||||
|
progressManager.reset()
|
||||||
if (disabled) return
|
if (disabled) return
|
||||||
disabled = true
|
disabled = true
|
||||||
|
|
||||||
updateStoreFn()
|
updateStoreFn()
|
||||||
await offsetPage(get(options, 'animated', true))
|
await offsetPage({ animated: get(options, 'animated', true) })
|
||||||
disabled = false
|
disabled = false
|
||||||
|
|
||||||
const jumped = await jumpIfNeeded()
|
const jumped = await jumpIfNeeded()
|
||||||
@@ -289,7 +293,7 @@
|
|||||||
if (!swiping) return
|
if (!swiping) return
|
||||||
_duration = 0
|
_duration = 0
|
||||||
}
|
}
|
||||||
async function handleThreshold(event) {
|
async function handleSwipeThresholdReached(event) {
|
||||||
if (!swiping) return
|
if (!swiping) return
|
||||||
await directionFnDescription[event.detail.direction]()
|
await directionFnDescription[event.detail.direction]()
|
||||||
}
|
}
|
||||||
@@ -301,7 +305,16 @@
|
|||||||
if (!swiping) return
|
if (!swiping) return
|
||||||
showPage(currentPageIndex)
|
showPage(currentPageIndex)
|
||||||
}
|
}
|
||||||
function handleFocused(event) {
|
async function handleSwipeFailed() {
|
||||||
|
if (!swiping) return
|
||||||
|
await offsetPage({ animated: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePausedToggle(event) {
|
||||||
|
if (event.detail.isTouchable) {
|
||||||
|
focused = !focused
|
||||||
|
return
|
||||||
|
}
|
||||||
focused = event.detail.value
|
focused = event.detail.value
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -322,16 +335,18 @@
|
|||||||
<div
|
<div
|
||||||
class="sc-carousel__pages-window"
|
class="sc-carousel__pages-window"
|
||||||
bind:this={pageWindowElement}
|
bind:this={pageWindowElement}
|
||||||
use:focusable
|
|
||||||
on:focused={handleFocused}
|
use:pausable
|
||||||
|
on:pausedToggle={handlePausedToggle}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-carousel__pages-container"
|
class="sc-carousel__pages-container"
|
||||||
use:swipeable="{{ thresholdProvider: () => pageWidth/3 }}"
|
use:swipeable="{{ thresholdProvider: () => pageWidth/3 }}"
|
||||||
on:start={handleSwipeStart}
|
on:swipeStart={handleSwipeStart}
|
||||||
on:move={handleSwipeMove}
|
on:swipeMove={handleSwipeMove}
|
||||||
on:end={handleSwipeEnd}
|
on:swipeEnd={handleSwipeEnd}
|
||||||
on:threshold={handleThreshold}
|
on:swipeFailed={handleSwipeFailed}
|
||||||
|
on:swipeThresholdReached={handleSwipeThresholdReached}
|
||||||
style="
|
style="
|
||||||
transform: translateX({offset}px);
|
transform: translateX({offset}px);
|
||||||
transition-duration: {_duration}ms;
|
transition-duration: {_duration}ms;
|
||||||
|
|||||||
@@ -269,7 +269,7 @@ Import component
|
|||||||
| `autoplay` | `boolean` | `false` | Enables auto play of pages |
|
| `autoplay` | `boolean` | `false` | Enables auto play of pages |
|
||||||
| `autoplayDuration` | `number` | `3000` | Autoplay change interval (ms) |
|
| `autoplayDuration` | `number` | `3000` | Autoplay change interval (ms) |
|
||||||
| `autoplayDirection` | `string` | `'next'` | Autoplay change direction (`next` or `prev`) |
|
| `autoplayDirection` | `string` | `'next'` | Autoplay change direction (`next` or `prev`) |
|
||||||
| `pauseOnFocus` | `boolean` | `false` | Pause autoplay on focus |
|
| `pauseOnFocus` | `boolean` | `false` | Pauses autoplay on focus (for desktop - hover on the carousel to toggle the autoplay, for touchable devices - tap the carousel to toggle the autoplay) |
|
||||||
| `autoplayProgressVisible` | `boolean` | `false` | Show autoplay duration progress indicator |
|
| `autoplayProgressVisible` | `boolean` | `false` | Show autoplay duration progress indicator |
|
||||||
| `dots` | `boolean` | `true` | Current page indicator dots |
|
| `dots` | `boolean` | `true` | Current page indicator dots |
|
||||||
| `timingFunction` | `string` | `'ease-in-out'` | CSS animation timing function |
|
| `timingFunction` | `string` | `'ease-in-out'` | CSS animation timing function |
|
||||||
|
|||||||
5
src/units.js
Normal file
5
src/units.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const TAP_DURATION_MS = 110
|
||||||
|
export const TAP_MOVEMENT_PX = 9 // max movement during the tap, keep it small
|
||||||
|
|
||||||
|
export const SWIPE_MIN_DURATION_MS = 111
|
||||||
|
export const SWIPE_MIN_DISTANCE_PX = 20
|
||||||
@@ -7,12 +7,19 @@ export function removeResizeEventListener(cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createDispatcher(source) {
|
export function createDispatcher(source) {
|
||||||
function dispatch(event, data) {
|
return function (event, data) {
|
||||||
source.dispatchEvent(
|
source.dispatchEvent(
|
||||||
new CustomEvent(event, {
|
new CustomEvent(event, {
|
||||||
detail: data,
|
detail: data,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return dispatch
|
}
|
||||||
|
|
||||||
|
export function getIsTouchable() {
|
||||||
|
return (
|
||||||
|
('ontouchstart' in window) ||
|
||||||
|
(navigator.maxTouchPoints > 0) ||
|
||||||
|
(navigator.msMaxTouchPoints > 0)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/utils/math.js
Normal file
6
src/utils/math.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export const getDistance = (p1, p2) => {
|
||||||
|
const xDist = p2.x - p1.x;
|
||||||
|
const yDist = p2.y - p1.y;
|
||||||
|
|
||||||
|
return Math.sqrt((xDist * xDist) + (yDist * yDist));
|
||||||
|
}
|
||||||
19
src/utils/math.test.js
Normal file
19
src/utils/math.test.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import {
|
||||||
|
getDistance,
|
||||||
|
} from './math.js'
|
||||||
|
|
||||||
|
describe('getDistance', () => {
|
||||||
|
it('returns correct distance between 2 points laying in one horizontal line', () => {
|
||||||
|
const p1 = { x: 0, y: 0 }
|
||||||
|
const p2 = { x: 5, y: 0 }
|
||||||
|
|
||||||
|
expect(getDistance(p1, p2)).toBe(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns correct distance between 2 points', () => {
|
||||||
|
const p1 = { x: 1, y: 1 }
|
||||||
|
const p2 = { x: 5, y: 4 }
|
||||||
|
|
||||||
|
expect(getDistance(p1, p2)).toBe(5)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user