Fixed dragging not positioning properly

This commit is contained in:
Jan Zípek 2022-08-24 19:32:50 +02:00
parent dddcfa7154
commit 1a75e7bad0
Signed by: kamen
GPG Key ID: A17882625B33AC31
2 changed files with 49 additions and 20 deletions

View File

@ -2,6 +2,7 @@ import { useWindowEvent } from '@/utils/hooks/useWindowEvent'
import { useState } from 'preact/hooks' import { useState } from 'preact/hooks'
import { BoxDefinition } from '../types' import { BoxDefinition } from '../types'
import { GRID_H_SNAP, GRID_WIDTH } from '../constants' import { GRID_H_SNAP, GRID_WIDTH } from '../constants'
import { range } from '@/utils/range'
type Props = { type Props = {
cellWidth: number cellWidth: number
@ -26,22 +27,42 @@ export const useDragging = ({ cellWidth, boxes, box }: Props) => {
const dragY = Math.max(0, Math.round(state.y / GRID_H_SNAP) * GRID_H_SNAP) const dragY = Math.max(0, Math.round(state.y / GRID_H_SNAP) * GRID_H_SNAP)
const gridHeights = Array(GRID_WIDTH) const maxHeight = Math.max(
.fill(null) ...range(actualX, actualX + box.w).map((x) => {
.map((_, index) => { // All boxes that are in this column
return boxes const boxesAtColumn = boxes.filter(
.filter( (b) => b.id !== box.id && b.x <= x && b.x + b.w > x
(b) => )
b.id !== box.id &&
b.x <= index && // Find boxes that would be colliding at this position
b.x + b.w > index && const collisions = boxesAtColumn.filter(
((b.y < dragY + box.h && dragY < b.y + b.h) || b.y < dragY) (b) => b.y < dragY + box.h && dragY < b.y + b.h
) )
.reduce(
(acc, item) => (item.y + item.h > acc ? item.y + item.h : acc), if (collisions.length > 0) {
0 const upperBoxes = boxesAtColumn.filter((b) => b.y + b.h > dragY)
)
// Try to find a space to fit somewhere up
for (let i = 1; i < upperBoxes.length; i++) {
const prevBox = upperBoxes[i - 1]
const thisBox = upperBoxes[i]
if (thisBox.y - (prevBox.y + prevBox.h) >= box.h) {
return prevBox.y + prevBox.h
}
}
// Nothing found, we'll have to stack to the upper box
const lastBox = boxesAtColumn[boxesAtColumn.length - 1]
return lastBox ? lastBox.y + lastBox.h : 0
} else {
const bottomBox = boxesAtColumn.reverse().find((b) => b.y < dragY)
return bottomBox ? bottomBox.y + bottomBox.h : 0
}
}) })
)
useWindowEvent('mousemove', (e) => { useWindowEvent('mousemove', (e) => {
if (state.active) { if (state.active) {
@ -58,11 +79,7 @@ export const useDragging = ({ cellWidth, boxes, box }: Props) => {
setDragging: setState, setDragging: setState,
draggingPosition: { draggingPosition: {
x: actualX, x: actualX,
y: Math.max( y: maxHeight,
...Array(box.w)
.fill(null)
.map((_, x) => gridHeights[actualX + x])
),
}, },
} }
} }

12
client/src/utils/range.ts Normal file
View File

@ -0,0 +1,12 @@
export function range(length: number): number[]
export function range(start: number, end: number, step?: number): number[]
export function range(a1: number, a2?: number, a3?: number): number[] {
const start = typeof a2 === 'undefined' ? 0 : a1
const end = typeof a2 === 'undefined' ? a1 : a2
const step = a3 ?? 1
return Array(end - start)
.fill(null)
.map((_, i) => start + i * step)
}