better text area for propagators
This commit is contained in:
parent
b8aae90d1b
commit
328442627f
|
|
@ -33,7 +33,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<fc-geometry id="box1" x="100" y="100" width="30" height="30"></fc-geometry>
|
<fc-geometry id="box1" x="100" y="100" width="30" height="30"></fc-geometry>
|
||||||
<fc-geometry id="box2" x="200" y="300">Hello World</fc-geometry>
|
<fc-geometry id="box2" x="200" y="350">Hello World</fc-geometry>
|
||||||
<event-propagator
|
<event-propagator
|
||||||
source="#box1"
|
source="#box1"
|
||||||
target="#box2"
|
target="#box2"
|
||||||
|
|
@ -41,8 +41,8 @@
|
||||||
expression="$target.textContent += '!'"
|
expression="$target.textContent += '!'"
|
||||||
></event-propagator>
|
></event-propagator>
|
||||||
|
|
||||||
<fc-geometry id="box3" x="150" y="200" width="30" height="30"></fc-geometry>
|
<fc-geometry id="box3" x="350" y="200" width="30" height="30"></fc-geometry>
|
||||||
<fc-geometry id="box4" x="300" y="350" width="30" height="30"></fc-geometry>
|
<fc-geometry id="box4" x="500" y="250" width="30" height="30"></fc-geometry>
|
||||||
<event-propagator
|
<event-propagator
|
||||||
source="#box3"
|
source="#box3"
|
||||||
target="#box4"
|
target="#box4"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,23 @@
|
||||||
import { FolkRope } from './fc-rope.ts';
|
import { FolkRope } from './fc-rope.ts';
|
||||||
|
|
||||||
|
const styles = new CSSStyleSheet();
|
||||||
|
styles.replaceSync(`
|
||||||
|
textarea {
|
||||||
|
position: absolute;
|
||||||
|
width: auto;
|
||||||
|
min-width: 60px;
|
||||||
|
height: auto;
|
||||||
|
resize: none;
|
||||||
|
background: rgba(256, 256, 256, 0.8);
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 4px;
|
||||||
|
pointer-events: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
field-sizing: content;
|
||||||
|
translate: -50% -50%;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
export class EventPropagator extends FolkRope {
|
export class EventPropagator extends FolkRope {
|
||||||
static override tagName = 'event-propagator';
|
static override tagName = 'event-propagator';
|
||||||
|
|
||||||
|
|
@ -24,7 +42,7 @@ export class EventPropagator extends FolkRope {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn('Failed to parse expression:', error);
|
console.warn('Failed to parse expression:', error);
|
||||||
// Use no-op function when parsing fails
|
// Use no-op function when parsing fails
|
||||||
this.break();
|
this.cut();
|
||||||
this.#function = () => {};
|
this.#function = () => {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,27 +52,15 @@ export class EventPropagator extends FolkRope {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.#textarea.style.cssText = `
|
this.shadowRoot?.adoptedStyleSheets.push(styles);
|
||||||
position: absolute;
|
|
||||||
width: auto;
|
|
||||||
min-width: 60px;
|
|
||||||
height: auto;
|
|
||||||
resize: none;
|
|
||||||
background: white;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
padding: 4px;
|
|
||||||
pointer-events: auto;
|
|
||||||
overflow: hidden;
|
|
||||||
field-sizing: content;
|
|
||||||
`;
|
|
||||||
|
|
||||||
this.#textarea.value = this.getAttribute('expression') || '';
|
|
||||||
this.#textarea.addEventListener('input', () => {
|
this.#textarea.addEventListener('input', () => {
|
||||||
this.expression = this.#textarea.value;
|
this.expression = this.#textarea.value;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.shadowRoot?.appendChild(this.#textarea);
|
this.shadowRoot?.appendChild(this.#textarea);
|
||||||
this.expression = this.#textarea.value;
|
|
||||||
|
this.expression = this.#textarea.value = this.getAttribute('expression') || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
override render(sourceRect: DOMRectReadOnly, targetRect: DOMRectReadOnly) {
|
override render(sourceRect: DOMRectReadOnly, targetRect: DOMRectReadOnly) {
|
||||||
|
|
@ -63,10 +69,15 @@ export class EventPropagator extends FolkRope {
|
||||||
// Position textarea between source and target
|
// Position textarea between source and target
|
||||||
const midX = (sourceRect.x + targetRect.x) / 2;
|
const midX = (sourceRect.x + targetRect.x) / 2;
|
||||||
const midY = (sourceRect.y + targetRect.y) / 2;
|
const midY = (sourceRect.y + targetRect.y) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
override draw() {
|
||||||
|
super.draw();
|
||||||
|
|
||||||
|
const point = this.points[Math.floor(this.points.length / 2)];
|
||||||
// Center the textarea by subtracting half its width and height
|
// Center the textarea by subtracting half its width and height
|
||||||
this.#textarea.style.left = `${midX - this.#textarea.offsetWidth / 2}px`;
|
this.#textarea.style.left = `${point.pos.x}px`;
|
||||||
this.#textarea.style.top = `${midY - this.#textarea.offsetHeight / 2}px`;
|
this.#textarea.style.top = `${point.pos.y}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
override observeSource() {
|
override observeSource() {
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,10 @@ export class FolkRope extends AbstractArrow {
|
||||||
#gravity = { x: 0, y: 3000 };
|
#gravity = { x: 0, y: 3000 };
|
||||||
#points: RopePoint[] = [];
|
#points: RopePoint[] = [];
|
||||||
|
|
||||||
|
get points() {
|
||||||
|
return this.#points;
|
||||||
|
}
|
||||||
|
|
||||||
#stroke = this.getAttribute('stroke') || 'black';
|
#stroke = this.getAttribute('stroke') || 'black';
|
||||||
get stroke() {
|
get stroke() {
|
||||||
return this.#stroke;
|
return this.#stroke;
|
||||||
|
|
@ -92,7 +96,7 @@ export class FolkRope extends AbstractArrow {
|
||||||
#onResize = (entry: ResizeObserverEntry) => {
|
#onResize = (entry: ResizeObserverEntry) => {
|
||||||
this.#canvas.width = entry.contentRect.width;
|
this.#canvas.width = entry.contentRect.width;
|
||||||
this.#canvas.height = entry.contentRect.height;
|
this.#canvas.height = entry.contentRect.height;
|
||||||
this.#drawRopePoints();
|
this.draw();
|
||||||
};
|
};
|
||||||
|
|
||||||
#tick = (timestamp: number = performance.now()) => {
|
#tick = (timestamp: number = performance.now()) => {
|
||||||
|
|
@ -117,7 +121,7 @@ export class FolkRope extends AbstractArrow {
|
||||||
|
|
||||||
this.#previousDelta = dts;
|
this.#previousDelta = dts;
|
||||||
|
|
||||||
this.#drawRopePoints();
|
this.draw();
|
||||||
|
|
||||||
this.#lastTime = this.#currentTime - (this.#deltaTime % this.#interval);
|
this.#lastTime = this.#currentTime - (this.#deltaTime % this.#interval);
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +153,7 @@ export class FolkRope extends AbstractArrow {
|
||||||
endingPoint.pos.y = targetRect.bottom;
|
endingPoint.pos.y = targetRect.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
#drawRopePoints() {
|
draw() {
|
||||||
this.#context.clearRect(0, 0, this.#canvas.width, this.#canvas.height);
|
this.#context.clearRect(0, 0, this.#canvas.width, this.#canvas.height);
|
||||||
|
|
||||||
for (let i = 0; i < this.#points.length; i++) {
|
for (let i = 0; i < this.#points.length; i++) {
|
||||||
|
|
@ -264,7 +268,7 @@ export class FolkRope extends AbstractArrow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break(index = Math.floor(this.#points.length / 2)) {
|
cut(index = Math.floor(this.#points.length / 2)) {
|
||||||
if (this.#points.length === 0) return;
|
if (this.#points.length === 0) return;
|
||||||
|
|
||||||
this.#points[index].next = null;
|
this.#points[index].next = null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue