diff --git a/examples/index.html b/examples/index.html index c6f715f..77b82d0 100644 --- a/examples/index.html +++ b/examples/index.html @@ -3,7 +3,6 @@ + diff --git a/package-lock.json b/package-lock.json index 91fda94..14bcf1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@github/image-crop-element", - "version": "4.0.0", + "version": "4.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d2fac3f..08b3c5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@github/image-crop-element", - "version": "4.0.0", + "version": "4.1.0", "description": "Select area for cropping an image. This does not actually crop.", "main": "dist/index.js", "type": "module", diff --git a/src/index.css b/src/index.css index 87567ae..0700161 100644 --- a/src/index.css +++ b/src/index.css @@ -1,4 +1,7 @@ -image-crop { display: block; } +image-crop { + touch-action: none; + display: block; +} image-crop.nesw { cursor: nesw-resize; } image-crop.nwse { cursor: nwse-resize; } image-crop.nesw .crop-box, diff --git a/src/index.ts b/src/index.ts index 9902720..197d299 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,7 +18,7 @@ const startPositions: WeakMap = new WeakMap() const constructedElements: WeakMap = new WeakMap() -function moveCropArea(event: MouseEvent | KeyboardEvent) { +function moveCropArea(event: TouchEvent | MouseEvent | KeyboardEvent) { const el = event.currentTarget if (!(el instanceof ImageCropElement)) return const {box, image} = constructedElements.get(el) || {} @@ -37,10 +37,16 @@ function moveCropArea(event: MouseEvent | KeyboardEvent) { deltaX = 1 } } else if (dragStartPositions.has(el) && event instanceof MouseEvent) { - const pos = dragStartPositions.get(el) - if (!pos) return + const pos = dragStartPositions.get(el)! deltaX = event.pageX - pos.dragStartX deltaY = event.pageY - pos.dragStartY + } else if (dragStartPositions.has(el) && event instanceof TouchEvent) { + // Only support a single touch at a time + const {pageX, pageY} = event.changedTouches[0] + + const {dragStartX, dragStartY} = dragStartPositions.get(el)! + deltaX = pageX - dragStartX + deltaY = pageY - dragStartY } if (deltaX !== 0 || deltaY !== 0) { @@ -57,10 +63,17 @@ function moveCropArea(event: MouseEvent | KeyboardEvent) { dragStartX: event.pageX, dragStartY: event.pageY }) + } else if (event instanceof TouchEvent) { + // Only support a single touch at a time + const {pageX, pageY} = event.changedTouches[0] + dragStartPositions.set(el, { + dragStartX: pageX, + dragStartY: pageY + }) } } -function updateCropArea(event: MouseEvent | KeyboardEvent) { +function updateCropArea(event: TouchEvent | MouseEvent | KeyboardEvent) { const target = event.target if (!(target instanceof HTMLElement)) return @@ -84,12 +97,17 @@ function updateCropArea(event: MouseEvent | KeyboardEvent) { if (!pos) return deltaX = event.pageX - pos.startX - rect.left - window.pageXOffset deltaY = event.pageY - pos.startY - rect.top - window.pageYOffset + } else if (event instanceof TouchEvent) { + const pos = startPositions.get(el) + if (!pos) return + deltaX = event.changedTouches[0].pageX - pos.startX - rect.left - window.pageXOffset + deltaY = event.changedTouches[0].pageY - pos.startY - rect.top - window.pageYOffset } if (deltaX && deltaY) updateDimensions(el, deltaX, deltaY, !(event instanceof KeyboardEvent)) } -function startUpdate(event: MouseEvent) { +function startUpdate(event: TouchEvent | MouseEvent) { const currentTarget = event.currentTarget if (!(currentTarget instanceof HTMLElement)) return @@ -105,6 +123,7 @@ function startUpdate(event: MouseEvent) { const direction = target.getAttribute('data-direction') || '' // Change crop area el.addEventListener('mousemove', updateCropArea) + el.addEventListener('touchmove', updateCropArea) if (['nw', 'se'].indexOf(direction) >= 0) el.classList.add('nwse') if (['ne', 'sw'].indexOf(direction) >= 0) el.classList.add('nesw') startPositions.set(el, { @@ -115,6 +134,7 @@ function startUpdate(event: MouseEvent) { } else { // Move crop area el.addEventListener('mousemove', moveCropArea) + el.addEventListener('touchmove', moveCropArea) } } @@ -164,7 +184,7 @@ function setInitialPosition(el: ImageCropElement) { updateDimensions(el, side, side) } -function stopUpdate(event: MouseEvent) { +function stopUpdate(event: TouchEvent | MouseEvent) { const el = event.currentTarget if (!(el instanceof ImageCropElement)) return @@ -172,6 +192,8 @@ function stopUpdate(event: MouseEvent) { el.classList.remove('nwse', 'nesw') el.removeEventListener('mousemove', updateCropArea) el.removeEventListener('mousemove', moveCropArea) + el.removeEventListener('touchmove', updateCropArea) + el.removeEventListener('touchmove', moveCropArea) } interface Result { @@ -208,8 +230,10 @@ class ImageCropElement extends HTMLElement { image.addEventListener('load', imageReady) this.addEventListener('mouseleave', stopUpdate) + this.addEventListener('touchend', stopUpdate) this.addEventListener('mouseup', stopUpdate) box.addEventListener('mousedown', startUpdate) + box.addEventListener('touchstart', startUpdate) this.addEventListener('keydown', moveCropArea) this.addEventListener('keydown', updateCropArea)