add trigger textarea

This commit is contained in:
“chrisshank” 2024-11-25 21:06:41 -08:00
parent 328442627f
commit e61ec657d7
2 changed files with 50 additions and 26 deletions

View File

@ -5,7 +5,7 @@ styles.replaceSync(`
textarea { textarea {
position: absolute; position: absolute;
width: auto; width: auto;
min-width: 60px; min-width: 3ch;
height: auto; height: auto;
resize: none; resize: none;
background: rgba(256, 256, 256, 0.8); background: rgba(256, 256, 256, 0.8);
@ -15,18 +15,26 @@ textarea {
overflow: hidden; overflow: hidden;
field-sizing: content; field-sizing: content;
translate: -50% -50%; translate: -50% -50%;
border-radius: 5px;
} }
`); `);
export class EventPropagator extends FolkRope { export class EventPropagator extends FolkRope {
static override tagName = 'event-propagator'; static override tagName = 'event-propagator';
#triggers = (this.getAttribute('triggers') || '').split(','); #triggers: string[] = [];
get triggers() { get triggers() {
return this.#triggers; return this.#triggers;
} }
set triggers(triggers) { set triggers(triggers: string | string[]) {
if (typeof triggers === 'string') {
triggers = triggers.split(',');
}
this.#removeEventListenersToSource();
this.#triggers = triggers; this.#triggers = triggers;
this.#addEventListenersToSource();
} }
#expression = ''; #expression = '';
@ -47,62 +55,78 @@ export class EventPropagator extends FolkRope {
} }
} }
#textarea = document.createElement('textarea'); #triggerTextarea = document.createElement('textarea');
#expressionTextarea = document.createElement('textarea');
constructor() { constructor() {
super(); super();
this.shadowRoot?.adoptedStyleSheets.push(styles); this.shadowRoot?.adoptedStyleSheets.push(styles);
this.#textarea.addEventListener('input', () => { this.#triggerTextarea.addEventListener('change', () => {
this.expression = this.#textarea.value; this.triggers = this.#triggerTextarea.value;
});
this.triggers = this.#triggerTextarea.value = this.getAttribute('triggers') || '';
this.shadowRoot?.appendChild(this.#triggerTextarea);
this.#expressionTextarea.addEventListener('input', () => {
this.expression = this.#expressionTextarea.value;
}); });
this.shadowRoot?.appendChild(this.#textarea); this.shadowRoot?.appendChild(this.#expressionTextarea);
this.expression = this.#textarea.value = this.getAttribute('expression') || ''; this.expression = this.#expressionTextarea.value = this.getAttribute('expression') || '';
} }
override render(sourceRect: DOMRectReadOnly, targetRect: DOMRectReadOnly) { override render(sourceRect: DOMRectReadOnly, targetRect: DOMRectReadOnly) {
super.render(sourceRect, targetRect); super.render(sourceRect, targetRect);
// Position textarea between source and target
const midX = (sourceRect.x + targetRect.x) / 2;
const midY = (sourceRect.y + targetRect.y) / 2;
} }
override draw() { override draw() {
super.draw(); super.draw();
const point = this.points[Math.floor(this.points.length / 2)]; const triggerPoint = this.points[Math.floor(this.points.length / 5)];
// Center the textarea by subtracting half its width and height
this.#textarea.style.left = `${point.pos.x}px`; if (triggerPoint) {
this.#textarea.style.top = `${point.pos.y}px`; this.#triggerTextarea.style.left = `${triggerPoint.pos.x}px`;
this.#triggerTextarea.style.top = `${triggerPoint.pos.y}px`;
}
const expressionPoint = this.points[Math.floor((this.points.length * 3) / 5)];
if (expressionPoint) {
this.#expressionTextarea.style.left = `${expressionPoint.pos.x}px`;
this.#expressionTextarea.style.top = `${expressionPoint.pos.y}px`;
}
} }
override observeSource() { override observeSource() {
super.observeSource(); super.observeSource();
this.#addEventListenersToSource();
}
#addEventListenersToSource() {
for (const trigger of this.#triggers) { for (const trigger of this.#triggers) {
// TODO: add special triggers for intersection, rAF, etc. // TODO: add special triggers for intersection, rAF, etc.
this.sourceElement?.addEventListener(trigger, this.evaluateExpression); this.sourceElement?.addEventListener(trigger, this.evaluateExpression);
} }
//should we evaluate them immediately?
// this.evaluateExpression();
} }
override unobserveSource() { override unobserveSource() {
super.unobserveSource(); super.unobserveSource();
this.#removeEventListenersToSource();
}
#removeEventListenersToSource() {
for (const trigger of this.#triggers) { for (const trigger of this.#triggers) {
// TODO: add special triggers for intersection, rAF, etc.
this.sourceElement?.removeEventListener(trigger, this.evaluateExpression); this.sourceElement?.removeEventListener(trigger, this.evaluateExpression);
} }
} }
override observeTarget() { override observeTarget() {
super.observeTarget(); super.observeTarget();
// this.evaluateExpression();
} }
override unobserveTarget() { override unobserveTarget() {

View File

@ -100,10 +100,10 @@ export class FolkRope extends AbstractArrow {
}; };
#tick = (timestamp: number = performance.now()) => { #tick = (timestamp: number = performance.now()) => {
this.#rAFId = requestAnimationFrame(this.#tick);
this.#currentTime = timestamp; this.#currentTime = timestamp;
this.#rAFId = requestAnimationFrame(this.#tick);
this.#deltaTime = this.#currentTime - this.#lastTime; this.#deltaTime = this.#currentTime - this.#lastTime;
if (this.#deltaTime > this.#interval) { if (this.#deltaTime > this.#interval) {
@ -130,8 +130,8 @@ export class FolkRope extends AbstractArrow {
override render(sourceRect: DOMRectReadOnly, targetRect: DOMRectReadOnly) { override render(sourceRect: DOMRectReadOnly, targetRect: DOMRectReadOnly) {
if (this.#points.length === 0) { if (this.#points.length === 0) {
this.#points = this.#generatePoints( this.#points = this.#generatePoints(
{ x: sourceRect.x, y: sourceRect.y }, { x: sourceRect.x + sourceRect.width / 2, y: sourceRect.bottom },
{ x: targetRect.right, y: targetRect.bottom } { x: targetRect.x + targetRect.width / 2, y: targetRect.bottom }
); );
this.#lastTime = 0; this.#lastTime = 0;
@ -183,7 +183,7 @@ export class FolkRope extends AbstractArrow {
x: lerp(start.x, end.x, percentage), x: lerp(start.x, end.x, percentage),
y: lerp(start.y, end.y, percentage), y: lerp(start.y, end.y, percentage),
}; };
// new RopePoint({ x: lerpX, y: lerpY }, resolution, mass, damping, isFixed)
points.push({ points.push({
pos, pos,
oldPos: { ...pos }, oldPos: { ...pos },
@ -217,7 +217,7 @@ export class FolkRope extends AbstractArrow {
point.oldPos = { ...point.pos }; point.oldPos = { ...point.pos };
// Drastically improves stability // Drastically improves stability
const timeCorrection = previousFrameDt != 0.0 ? dt / previousFrameDt : 0.0; const timeCorrection = previousFrameDt !== 0.0 ? dt / previousFrameDt : 0.0;
const accel = Vector.add(gravity, { x: 0, y: point.mass }); const accel = Vector.add(gravity, { x: 0, y: point.mass });