resize element

This commit is contained in:
“chrisshank” 2024-08-18 16:40:30 -07:00
parent 8503437d4c
commit 9feca14de0
3 changed files with 105 additions and 19 deletions

View File

@ -20,15 +20,13 @@
} }
spatial-geometry { spatial-geometry {
width: 50px;
height: 50px;
border: 2px solid black; border: 2px solid black;
} }
</style> </style>
</head> </head>
<body> <body>
<spatial-geometry x="100" y="100">Shape with some text</spatial-geometry> <spatial-geometry x="100" y="100" width="50" height="50">Shape with some text</spatial-geometry>
<spatial-geometry x="200" y="200">Shape with some text</spatial-geometry> <spatial-geometry x="200" y="200" width="50" height="50">Shape with some text</spatial-geometry>
<script type="module"> <script type="module">
import { SpatialGeometry } from '../src/elements/spatial-geometry.ts'; import { SpatialGeometry } from '../src/elements/spatial-geometry.ts';
@ -45,20 +43,28 @@
); );
} }
document.addEventListener('move', (e) => { function handleCollision(e) {
geometryElements.forEach((el) => { geometryElements.forEach((el) => {
if ( if (
el !== e.target && el !== e.target &&
collisionDetection( collisionDetection(
// TODO: refactor this hack once resizing and the vertices API are figured out // TODO: refactor this hack once resizing and the vertices API are figured out
DOMRectReadOnly.fromRect({ x: el.x, y: el.y, height: 50, width: 50 }), DOMRectReadOnly.fromRect({ x: el.x, y: el.y, height: el.height, width: el.width }),
DOMRectReadOnly.fromRect({ x: e.target.x, y: e.target.y, height: 50, width: 50 }) DOMRectReadOnly.fromRect({
x: e.target.x,
y: e.target.y,
height: e.target.height,
width: e.target.width,
})
) )
) { ) {
e.preventDefault(); e.preventDefault();
} }
}); });
}); }
document.addEventListener('move', handleCollision);
document.addEventListener('resize', handleCollision);
</script> </script>
</body> </body>
</html> </html>

View File

@ -16,14 +16,14 @@
} }
spatial-geometry { spatial-geometry {
width: 50px;
height: 50px;
background: rgb(187, 178, 178); background: rgb(187, 178, 178);
} }
</style> </style>
</head> </head>
<body> <body>
<spatial-geometry x="100" y="100">Shape with some text</spatial-geometry> <input type="text" value="Hello" />
<input type="text" value="World" />
<spatial-geometry x="100" y="100" width="50" height="50">Shape with some text</spatial-geometry>
<script type="module"> <script type="module">
import { SpatialGeometry } from '../src/elements/spatial-geometry.ts'; import { SpatialGeometry } from '../src/elements/spatial-geometry.ts';

View File

@ -3,12 +3,21 @@ export type Shape = 'rectangle' | 'circle' | 'triangle';
// Can we make adding new shapes extensible via a static property? // Can we make adding new shapes extensible via a static property?
const shapes = new Set(['rectangle', 'circle', 'triangle']); const shapes = new Set(['rectangle', 'circle', 'triangle']);
export type MoveEventDetail = { x: number; y: number; movementX: number; movementY: number }; export type MoveEventDetail = { movementX: number; movementY: number };
// Should the move event bubble? // Should the move event bubble?
export class MoveEvent extends CustomEvent<MoveEventDetail> { export class MoveEvent extends CustomEvent<MoveEventDetail> {
constructor(vector: MoveEventDetail) { constructor(detail: MoveEventDetail) {
super('move', { detail: vector, cancelable: true, bubbles: true }); super('move', { detail, cancelable: true, bubbles: true });
}
}
export type ResizeEventDetail = { movementX: number; movementY: number };
// Should the move event bubble?
export class ResizeEvent extends CustomEvent<MoveEventDetail> {
constructor(detail: MoveEventDetail) {
super('resize', { detail, cancelable: true, bubbles: true });
} }
} }
@ -135,7 +144,7 @@ export class SpatialGeometry extends HTMLElement {
customElements.define(this.tagName, this); customElements.define(this.tagName, this);
} }
static observedAttributes = ['type', 'x', 'y']; static observedAttributes = ['type', 'x', 'y', 'width', 'height'];
#internals: ElementInternals; #internals: ElementInternals;
@ -190,6 +199,26 @@ export class SpatialGeometry extends HTMLElement {
this.setAttribute('y', y.toString()); this.setAttribute('y', y.toString());
} }
#previousWidth = 0;
#width = 0;
get width(): number {
return this.#width;
}
set width(width: number) {
this.setAttribute('width', width.toString());
}
#previousHeight = 0;
#height = 0;
get height(): number {
return this.#height;
}
set height(height: number) {
this.setAttribute('height', height.toString());
}
attributeChangedCallback(name: string, _oldValue: string, newValue: string) { attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
if (name === 'x') { if (name === 'x') {
this.#previousX = this.#x; this.#previousX = this.#x;
@ -199,6 +228,14 @@ export class SpatialGeometry extends HTMLElement {
this.#previousY = this.#y; this.#previousY = this.#y;
this.#y = Number(newValue); this.#y = Number(newValue);
this.#requestUpdate('y'); this.#requestUpdate('y');
} else if (name === 'width') {
this.#previousWidth = this.#width;
this.#width = Number(newValue);
this.#requestUpdate('width');
} else if (name === 'height') {
this.#previousHeight = this.#height;
this.#height = Number(newValue);
this.#requestUpdate('height');
} else if (name === 'type') { } else if (name === 'type') {
if (shapes.has(newValue)) { if (shapes.has(newValue)) {
this.#type = newValue as Shape; this.#type = newValue as Shape;
@ -238,8 +275,29 @@ export class SpatialGeometry extends HTMLElement {
if (event.target === this) { if (event.target === this) {
this.x += event.movementX; this.x += event.movementX;
this.y += event.movementY; this.y += event.movementY;
} else if ((event.target as HTMLElement).matches('[resize-handler]')) { return;
console.log('resizing'); }
const direction = (event.target as HTMLElement).getAttribute('resize-handler');
if (direction === null) return;
if (direction.includes('top')) {
this.y += event.movementY;
this.height -= event.movementY;
}
if (direction.includes('right')) {
this.width += event.movementX;
}
if (direction.includes('bottom')) {
this.height += event.movementY;
}
if (direction.includes('left')) {
this.x += event.movementX;
this.width -= event.movementX;
} }
return; return;
} }
@ -288,8 +346,6 @@ export class SpatialGeometry extends HTMLElement {
// Although the change in movement isn't useful inside this component, the outside world might find it helpful to calculate acceleration and other physics // Although the change in movement isn't useful inside this component, the outside world might find it helpful to calculate acceleration and other physics
const notCancelled = this.dispatchEvent( const notCancelled = this.dispatchEvent(
new MoveEvent({ new MoveEvent({
x: this.#x,
y: this.#y,
movementX: this.#x - this.#previousX, movementX: this.#x - this.#previousX,
movementY: this.#y - this.#previousY, movementY: this.#y - this.#previousY,
}) })
@ -310,5 +366,29 @@ export class SpatialGeometry extends HTMLElement {
this.#y = this.#previousY; this.#y = this.#previousY;
} }
} }
if (updatedProperties.has('width') || updatedProperties.has('height')) {
// Although the change in resize isn't useful inside this component, the outside world might find it helpful to calculate acceleration and other physics
const notCancelled = this.dispatchEvent(
new ResizeEvent({
movementX: this.#width - this.#previousWidth,
movementY: this.#height - this.#previousHeight,
})
);
if (notCancelled) {
if (updatedProperties.has('width')) {
this.style.width = `${this.#width}px`;
}
if (updatedProperties.has('height')) {
this.style.height = `${this.#height}px`;
}
} else {
// Revert changes to movement
this.#height = this.#previousHeight;
this.#width = this.#previousWidth;
}
}
} }
} }