mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-20 16:49:52 +00:00
Add snapWithin() and add snapping to like sides
This commit is contained in:
parent
59727d78ed
commit
785af97700
2 changed files with 148 additions and 11 deletions
|
|
@ -8,7 +8,9 @@ import {
|
|||
near,
|
||||
snap,
|
||||
overlapY,
|
||||
overlapX
|
||||
overlapX,
|
||||
snapWithin,
|
||||
applySnap
|
||||
} from '../snapUtils';
|
||||
|
||||
describe('side functions', () => {
|
||||
|
|
@ -102,28 +104,28 @@ describe('snap function', () => {
|
|||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the left of A to the right of B', () => {
|
||||
const a = {x: 120, y: 10, width: 100, height: 100};
|
||||
const a = {x: 120, y: 30, width: 100, height: 100};
|
||||
const b = {x: 10, y: 10, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {x: 110};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the right of A to the left of B', () => {
|
||||
const a = {x: 10, y: 10, width: 100, height: 100};
|
||||
const a = {x: 10, y: 30, width: 100, height: 100};
|
||||
const b = {x: 120, y: 10, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {x: 20};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the top of A to the bottom of B', () => {
|
||||
const a = {x: 10, y: 10, width: 100, height: 100};
|
||||
const a = {x: 30, y: 10, width: 100, height: 100};
|
||||
const b = {x: 10, y: 120, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {y: 20};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the bottom of A to the top of B', () => {
|
||||
const a = {x: 10, y: 120, width: 100, height: 100};
|
||||
const a = {x: 30, y: 120, width: 100, height: 100};
|
||||
const b = {x: 10, y: 10, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {y: 110};
|
||||
|
|
@ -143,4 +145,108 @@ describe('snap function', () => {
|
|||
const expected = {x: 20, y: 20};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the left of A to the left of B', () => {
|
||||
const a = {x: 10, y: 10, width: 100, height: 100};
|
||||
const b = {x: 15, y: 110, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {x: 15, y: 10};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the top of A to the bottom of B', () => {
|
||||
const a = {x: 10, y: 10, width: 100, height: 100};
|
||||
const b = {x: 110, y: 15, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {x: 10, y: 15};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the top left corner of A to the bottom right corner of B', () => {
|
||||
const a = {x: 110, y: 110, width: 100, height: 100};
|
||||
const b = {x: 0, y: 0, width: 100, height: 100};
|
||||
const actual = snap(a, b);
|
||||
const expected = {x: 100, y: 100};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('snapWithin function', () => {
|
||||
it('snaps the inner box to the top of the outer box', () => {
|
||||
const inner = {x: 120, y: 10, width: 100, height: 100};
|
||||
const outer = {width: 1000, height: 1000};
|
||||
const actual = snapWithin(inner, outer);
|
||||
const expected = {y: 0};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the inner box to the bottom of the outer box', () => {
|
||||
const inner = {x: 120, y: 910, width: 100, height: 100};
|
||||
const outer = {width: 1000, height: 1000};
|
||||
const actual = snapWithin(inner, outer);
|
||||
const expected = {y: 900};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the inner box to the right of the outer box', () => {
|
||||
const inner = {x: 910, y: 120, width: 100, height: 100};
|
||||
const outer = {width: 1000, height: 1000};
|
||||
const actual = snapWithin(inner, outer);
|
||||
const expected = {x: 900};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the inner box to the left of the outer box', () => {
|
||||
const inner = {x: 10, y: 120, width: 100, height: 100};
|
||||
const outer = {width: 1000, height: 1000};
|
||||
const actual = snapWithin(inner, outer);
|
||||
const expected = {x: 0};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('snaps the inner box to the top-left of the outer box', () => {
|
||||
const inner = {x: 10, y: 10, width: 100, height: 100};
|
||||
const outer = {width: 1000, height: 1000};
|
||||
const actual = snapWithin(inner, outer);
|
||||
const expected = {x: 0, y: 0};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('applySnap function', () => {
|
||||
it('does not apply undefined values', () => {
|
||||
const original = {x: 10, y: 10};
|
||||
const snapped = {x: undefined, y: undefined};
|
||||
const actual = applySnap(original, snapped);
|
||||
const expected = original;
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('preserves other values on original', () => {
|
||||
const original = {x: 10, y: 10, foo: 'bar'};
|
||||
const snapped = {x: 50, y: 50};
|
||||
const actual = applySnap(original, snapped);
|
||||
const expected = {x: 50, y: 50, foo: 'bar'};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('will clobber original with falsy "0" values', () => {
|
||||
const original = {x: 10, y: 10};
|
||||
const snapped = {x: 0, y: 0};
|
||||
const actual = applySnap(original, snapped);
|
||||
expect(actual).toEqual(snapped);
|
||||
});
|
||||
it('will clobber original with falsy "0" values', () => {
|
||||
const original = {x: 10, y: 10};
|
||||
const snapped = {x: 0, y: 0};
|
||||
const actual = applySnap(original, snapped);
|
||||
expect(actual).toEqual(snapped);
|
||||
});
|
||||
it('can apply multiple snaps', () => {
|
||||
const original = {x: 10, y: 10};
|
||||
const snapped1 = {x: 0};
|
||||
const snapped2 = {y: 0};
|
||||
const actual = applySnap(original, snapped1, snapped2);
|
||||
const expected = {x: 0, y: 0};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('the last snap wins', () => {
|
||||
const original = {x: 10, y: 10};
|
||||
const snapped1 = {x: 50, y: 20};
|
||||
const snapped2 = {x: 60, y: 60};
|
||||
const actual = applySnap(original, snapped1, snapped2);
|
||||
const expected = {x: 60, y: 60};
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,23 +22,28 @@ export const overlapY = (a, b) => {
|
|||
export const snap = (boxA, boxB) => {
|
||||
let x, y;
|
||||
|
||||
// TODO: Refactor/simplify this code
|
||||
if (overlapY(boxA, boxB)) {
|
||||
if (near(left(boxA), right(boxB))) {
|
||||
x = right(boxB);
|
||||
}
|
||||
|
||||
if (near(right(boxA), left(boxB))) {
|
||||
} else if (near(right(boxA), left(boxB))) {
|
||||
x = left(boxB) - boxA.width;
|
||||
} else if (near(left(boxA), left(boxB))) {
|
||||
x = left(boxB);
|
||||
} else if (near(right(boxA), right(boxB))) {
|
||||
x = right(boxB) - boxA.width;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlapX(boxA, boxB)) {
|
||||
if (near(top(boxA), bottom(boxB))) {
|
||||
y = bottom(boxB);
|
||||
}
|
||||
|
||||
if (near(bottom(boxA), top(boxB))) {
|
||||
} else if (near(bottom(boxA), top(boxB))) {
|
||||
y = top(boxB) - boxA.height;
|
||||
} else if (near(top(boxA), top(boxB))) {
|
||||
y = top(boxB);
|
||||
} else if (near(bottom(boxA), bottom(boxB))) {
|
||||
y = bottom(boxB) - boxA.height;
|
||||
}
|
||||
}
|
||||
return {x, y};
|
||||
|
|
@ -55,3 +60,29 @@ export const snapToMany = (boxA, otherBoxes) => {
|
|||
|
||||
return {x, y};
|
||||
};
|
||||
|
||||
export const snapWithin = (boxA, boundingBox) => {
|
||||
let x, y;
|
||||
|
||||
if (boxA.x - SNAP_DISTANCE < 0) {
|
||||
x = 0;
|
||||
} else if ((boxA.x + boxA.width + SNAP_DISTANCE) > boundingBox.width) {
|
||||
x = boundingBox.width - boxA.width;
|
||||
}
|
||||
|
||||
if (boxA.y - SNAP_DISTANCE < 0) {
|
||||
y = 0;
|
||||
} else if ((boxA.y + boxA.height + SNAP_DISTANCE) > boundingBox.height) {
|
||||
y = boundingBox.height - boxA.height;
|
||||
}
|
||||
|
||||
return {x, y};
|
||||
};
|
||||
|
||||
export const applySnap = (original, ...snaps) => (
|
||||
snaps.reduce((previous, snapped) => ({
|
||||
...previous,
|
||||
x: typeof snapped.x !== 'undefined' ? snapped.x : previous.x,
|
||||
y: typeof snapped.y !== 'undefined' ? snapped.y : previous.y
|
||||
}), original)
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue