diff --git a/src/Carousel/Carousel.svelte b/src/Carousel/Carousel.svelte
index 72954fc..69beef8 100644
--- a/src/Carousel/Carousel.svelte
+++ b/src/Carousel/Carousel.svelte
@@ -12,6 +12,16 @@
import Dots from '../Dots/Dots.svelte'
import Arrow from '../Arrow/Arrow.svelte'
import { NEXT, PREV } from '../direction'
+ import { swipeable } from '../swipeable'
+ import {
+ addResizeEventListener,
+ removeResizeEventListener
+ } from '../utils/event'
+
+ const directionFnDescription = {
+ [NEXT]: showNextPage,
+ [PREV]: showPrevPage
+ }
/**
* Enable Next/Prev arrows
@@ -37,6 +47,7 @@
* Transition speed (ms)
*/
export let speed = 500
+ let _speed = speed
/**
* Enables auto play of slides
@@ -61,8 +72,8 @@
let currentPageIndex = 0
let pagesCount = 0
let pageWidth = 0
- let offset
- let pageWindow
+ let offset = 0
+ let pageWindowElement
let pagesElement
const unsubscribe = store.subscribe(value => {
@@ -71,7 +82,7 @@
function applySlideSizes() {
const children = pagesElement ? pagesElement.children : []
- pageWidth = pageWindow.clientWidth
+ pageWidth = pageWindowElement.clientWidth
const slidesCount = children.length
pagesCount = getPagesCount({ slidesCount, slidesToShow })
@@ -87,14 +98,10 @@
}
function applyAutoplay() {
- const autoplayDirectionFnDescription = {
- [NEXT]: showNextPage,
- [PREV]: showPrevPage
- }
let interval
if (autoplay) {
interval = setInterval(() => {
- autoplayDirectionFnDescription[autoplayDirection]()
+ directionFnDescription[autoplayDirection]()
}, autoplaySpeed)
}
return {
@@ -105,14 +112,15 @@
}
onMount(() => {
- store.init(initialPageIndex)
applySlideSizes()
+ store.init(initialPageIndex)
+ applyOffset()
const { teardownAutoplay } = applyAutoplay()
- window.addEventListener('resize', applySlideSizes)
+ addResizeEventListener(applySlideSizes)
return () => {
- window.removeEventListener('resize', applySlideSizes)
+ removeResizeEventListener(applySlideSizes)
teardownAutoplay()
}
})
@@ -141,6 +149,21 @@
store.next({ infinite, pagesCount })
applyOffset()
}
+
+ function handleSwipeStart() {
+ _speed = 0
+ }
+ function handleThreshold(event) {
+ _speed = speed
+ directionFnDescription[event.detail.direction]()
+ }
+ function handleSwipeMove(event) {
+ offset += event.detail.dx
+ }
+ function handleSwipeEnd() {
+ _speed = speed
+ showPage(currentPageIndex)
+ }
@@ -154,17 +177,22 @@
{/if}
{#if arrows}
diff --git a/src/Carousel/CarouselView.svelte b/src/Carousel/CarouselView.svelte
index fc57a52..bb29ba3 100644
--- a/src/Carousel/CarouselView.svelte
+++ b/src/Carousel/CarouselView.svelte
@@ -94,6 +94,7 @@
display: flex;
align-items: center;
justify-content: center;
+ user-select: none;
}
.color-container > p {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
diff --git a/src/swipeable.js b/src/swipeable.js
new file mode 100644
index 0000000..e32b74e
--- /dev/null
+++ b/src/swipeable.js
@@ -0,0 +1,77 @@
+import { NEXT, PREV } from './direction'
+import {
+ addStartEventListener,
+ removeStartEventListener,
+ addMoveEventListener,
+ removeMoveEventListener,
+ addEndEventListener,
+ removeEndEventListener,
+ createDispatcher
+} from './utils/event'
+
+function getCoords(event) {
+ if (event instanceof TouchEvent) {
+ const touch = event.touches[0]
+ return {
+ x: touch ? touch.clientX : 0,
+ y: touch ? touch.clientY : 0
+ }
+ }
+ return {
+ x: event.clientX,
+ y: event.clientY
+ }
+}
+
+// TODO: rename to slidable
+export function swipeable(node, { thresholdProvider }) {
+ const dispatch = createDispatcher(node)
+ let x
+ let y
+ let moved = 0
+
+ function handleMousedown(event) {
+ moved = 0
+ const coords = getCoords(event)
+ x = coords.x
+ y = coords.y
+ dispatch('start', { x, y })
+ addMoveEventListener(window, handleMousemove)
+ addEndEventListener(window, handleMouseup)
+ }
+
+ function handleMousemove(event) {
+ const coords = getCoords(event)
+ const dx = coords.x - x
+ const dy = coords.y - y
+ x = coords.x
+ y = coords.y
+ dispatch('move', { x, y, dx, dy })
+
+ if (dx !== 0 && Math.sign(dx) !== Math.sign(moved)) {
+ moved = 0
+ }
+ moved += dx
+ if (Math.abs(moved) > thresholdProvider()) {
+ dispatch('threshold', { direction: moved > 0 ? PREV : NEXT })
+ removeEndEventListener(window, handleMouseup)
+ removeMoveEventListener(window, handleMousemove)
+ }
+ }
+
+ function handleMouseup(event) {
+ const coords = getCoords(event)
+ x = coords.x
+ y = coords.y
+ dispatch('end', { x, y })
+ removeEndEventListener(window, handleMouseup)
+ removeMoveEventListener(window, handleMousemove)
+ }
+
+ addStartEventListener(node, handleMousedown)
+ return {
+ destroy() {
+ removeStartEventListener(node, handleMousedown)
+ }
+ }
+}
diff --git a/src/utils/event.js b/src/utils/event.js
new file mode 100644
index 0000000..4b488c6
--- /dev/null
+++ b/src/utils/event.js
@@ -0,0 +1,46 @@
+// start event
+export function addStartEventListener(source, cb) {
+ source.addEventListener('mousedown', cb)
+ source.addEventListener('touchstart', cb)
+}
+export function removeStartEventListener(source, cb) {
+ source.removeEventListener('mousedown', cb)
+ source.removeEventListener('touchstart', cb)
+}
+
+// end event
+export function addEndEventListener(source, cb) {
+ source.addEventListener('mouseup', cb)
+ source.addEventListener('touchend', cb)
+}
+export function removeEndEventListener(source, cb) {
+ source.removeEventListener('mouseup', cb)
+ source.removeEventListener('touchend', cb)
+}
+
+// move event
+export function addMoveEventListener(source, cb) {
+ source.addEventListener('mousemove', cb)
+ source.addEventListener('touchmove', cb)
+}
+export function removeMoveEventListener(source, cb) {
+ source.removeEventListener('mousemove', cb)
+ source.removeEventListener('touchmove', cb)
+}
+
+// resize event
+export function addResizeEventListener(cb) {
+ window.addEventListener('resize', cb)
+}
+export function removeResizeEventListener(cb) {
+ window.removeEventListener('resize', cb)
+}
+
+export function createDispatcher(source) {
+ function dispatch(event, data) {
+ source.dispatchEvent(new CustomEvent(event, {
+ detail: data
+ }))
+ }
+ return dispatch
+}
\ No newline at end of file