Skip to content

Commit bd47d5b

Browse files
authored
Merge pull request #14 from github/keyboard-support
Add keyboard support (arrow keys -/+ esc)
2 parents 7ef4197 + 4b2e423 commit bd47d5b

File tree

2 files changed

+52
-17
lines changed

2 files changed

+52
-17
lines changed

examples/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<title>image-crop-element demo</title>
1919
</head>
2020
<body>
21-
<image-crop src="../ams.jpg" class="wrapper">
21+
<image-crop src="../ams.jpg" class="wrapper" tabindex="0">
2222
<div data-loading-slot class="loading">loading</div>
2323
<input type="text" data-image-crop-input="x" name="x" size="4" aria-label="x">
2424
<input type="text" data-image-crop-input="y" name="y" size="4" aria-label="y">

index.js

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,26 @@ tmpl.innerHTML = `
1616

1717
function moveCropArea(event) {
1818
const el = event.currentTarget
19-
if (el.dragStartX && el.dragStartY) {
20-
const x = Math.min(
21-
Math.max(0, el.box.offsetLeft + event.pageX - el.dragStartX),
22-
el.image.width - el.box.offsetWidth
23-
)
24-
const y = Math.min(
25-
Math.max(0, el.box.offsetTop + event.pageY - el.dragStartY),
26-
el.image.height - el.box.offsetHeight
27-
)
19+
let deltaX = 0
20+
let deltaY = 0
21+
if (event.type === 'keydown') {
22+
if (event.key === 'ArrowUp') {
23+
deltaY = -1
24+
} else if (event.key === 'ArrowDown') {
25+
deltaY = 1
26+
} else if (event.key === 'ArrowLeft') {
27+
deltaX = -1
28+
} else if (event.key === 'ArrowRight') {
29+
deltaX = 1
30+
}
31+
} else if (el.dragStartX && el.dragStartY) {
32+
deltaX = event.pageX - el.dragStartX
33+
deltaY = event.pageY - el.dragStartY
34+
}
35+
36+
if (deltaX !== 0 || deltaY !== 0) {
37+
const x = Math.min(Math.max(0, el.box.offsetLeft + deltaX), el.image.width - el.box.offsetWidth)
38+
const y = Math.min(Math.max(0, el.box.offsetTop + deltaY), el.image.height - el.box.offsetHeight)
2839
el.box.style.left = `${x}px`
2940
el.box.style.top = `${y}px`
3041

@@ -38,9 +49,22 @@ function moveCropArea(event) {
3849
function updateCropArea(event) {
3950
const el = event.target.closest('image-crop')
4051
const rect = el.getBoundingClientRect()
41-
const deltaX = event.pageX - el.startX - rect.left - window.pageXOffset
42-
const deltaY = event.pageY - el.startY - rect.top - window.pageYOffset
43-
updateDimensions(el, deltaX, deltaY)
52+
let deltaX, deltaY, delta
53+
if (event.key) {
54+
if (event.key === 'Escape') return setInitialPosition(el)
55+
if (event.key === '-') delta = -10
56+
if (event.key === '=') delta = +10
57+
if (!delta) return
58+
deltaX = el.box.offsetWidth + delta
59+
deltaY = el.box.offsetHeight + delta
60+
el.startX = el.box.offsetLeft
61+
el.startY = el.box.offsetTop
62+
} else {
63+
deltaX = event.pageX - el.startX - rect.left - window.pageXOffset
64+
deltaY = event.pageY - el.startY - rect.top - window.pageYOffset
65+
}
66+
67+
if (deltaX && deltaY) updateDimensions(el, deltaX, deltaY, !event.key)
4468
}
4569

4670
function startUpdate(event) {
@@ -60,19 +84,24 @@ function startUpdate(event) {
6084
}
6185
}
6286

63-
function updateDimensions(target, deltaX, deltaY) {
87+
function updateDimensions(target, deltaX, deltaY, reposition = true) {
6488
let newSide = Math.max(Math.abs(deltaX), Math.abs(deltaY), target.minWidth)
6589
newSide = Math.min(
6690
newSide,
6791
deltaY > 0 ? target.image.height - target.startY : target.startY,
6892
deltaX > 0 ? target.image.width - target.startX : target.startX
6993
)
7094

71-
const x = Math.round(Math.max(0, deltaX > 0 ? target.startX : target.startX - newSide))
72-
const y = Math.round(Math.max(0, deltaY > 0 ? target.startY : target.startY - newSide))
95+
const x = reposition
96+
? Math.round(Math.max(0, deltaX > 0 ? target.startX : target.startX - newSide))
97+
: target.box.offsetLeft
98+
const y = reposition
99+
? Math.round(Math.max(0, deltaY > 0 ? target.startY : target.startY - newSide))
100+
: target.box.offsetTop
73101

74102
target.box.style.left = `${x}px`
75103
target.box.style.top = `${y}px`
104+
76105
target.box.style.width = `${newSide}px`
77106
target.box.style.height = `${newSide}px`
78107
fireChangeEvent(target, {x, y, width: newSide, height: newSide})
@@ -81,7 +110,11 @@ function updateDimensions(target, deltaX, deltaY) {
81110
function imageReady(event) {
82111
const el = event.currentTarget.closest('image-crop')
83112
el.loaded = true
84-
const image = event.target
113+
setInitialPosition(el)
114+
}
115+
116+
function setInitialPosition(el) {
117+
const image = el.image
85118
const side = Math.round(image.clientWidth > image.clientHeight ? image.clientHeight : image.clientWidth)
86119
el.startX = (image.clientWidth - side) / 2
87120
el.startY = (image.clientHeight - side) / 2
@@ -128,6 +161,8 @@ export class ImageCropElement extends HTMLElement {
128161
this.addEventListener('mouseleave', stopUpdate)
129162
this.addEventListener('mouseup', stopUpdate)
130163
this.box.addEventListener('mousedown', startUpdate)
164+
this.addEventListener('keydown', moveCropArea)
165+
this.addEventListener('keydown', updateCropArea)
131166

132167
if (this.src) this.image.src = this.src
133168
}

0 commit comments

Comments
 (0)