feat: dom text
This commit is contained in:
parent
3769b259ab
commit
9fbaf90a14
96
packages/entity/src/traits/dom-node.js
Normal file
96
packages/entity/src/traits/dom-node.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
import {Vector} from '@avocado/math';
|
||||
import {StateProperty, Trait} from '@avocado/traits';
|
||||
import {compose} from '@latus/core';
|
||||
|
||||
const decorate = compose(
|
||||
StateProperty('parentNode', {
|
||||
track: true,
|
||||
}),
|
||||
);
|
||||
|
||||
// TODO...
|
||||
const FACTOR = 5;
|
||||
|
||||
export default () => class DomNode extends decorate(Trait) {
|
||||
|
||||
#scheduledRuleApplication = true;
|
||||
|
||||
static defaultState() {
|
||||
return {
|
||||
parentNode: null,
|
||||
};
|
||||
}
|
||||
|
||||
static dependencies() {
|
||||
return [
|
||||
'Visible',
|
||||
];
|
||||
}
|
||||
|
||||
destroy() {
|
||||
super.parentNode?.removeChild(this.entity.node);
|
||||
}
|
||||
|
||||
listeners() {
|
||||
return {
|
||||
|
||||
opacityChanged: () => {
|
||||
this.#scheduledRuleApplication = true;
|
||||
},
|
||||
|
||||
positionChanged: () => {
|
||||
this.#scheduledRuleApplication = true;
|
||||
},
|
||||
|
||||
rotationChanged: () => {
|
||||
this.#scheduledRuleApplication = true;
|
||||
},
|
||||
|
||||
textChanged: () => {
|
||||
this.#scheduledRuleApplication = true;
|
||||
},
|
||||
|
||||
visibleScaleChanged: () => {
|
||||
this.#scheduledRuleApplication = true;
|
||||
},
|
||||
|
||||
parentNodeChanged: (oldParentNode, newParentNode) => {
|
||||
oldParentNode?.removeChild(this.entity.node);
|
||||
newParentNode?.appendChild(this.entity.node);
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
applyStyleRules() {
|
||||
const {
|
||||
opacity,
|
||||
position,
|
||||
rotation,
|
||||
visibleScale,
|
||||
} = this.entity;
|
||||
const [x, y] = Vector.scale(position, FACTOR);
|
||||
this.entity.node.style.transform = [
|
||||
`translate(${x}px, ${y}px)`,
|
||||
`rotate(${360 * (rotation / (Math.PI * 2))}deg)`,
|
||||
`scale(${visibleScale[0]}, ${visibleScale[1]})`,
|
||||
].join(' ');
|
||||
this.entity.node.style.opacity = opacity;
|
||||
}
|
||||
|
||||
async load(json) {
|
||||
await super.load(json);
|
||||
if ('client' === process.env.SIDE) {
|
||||
this.entity.node = window.document.createElement('entity');
|
||||
this.entity.node.style.position = 'absolute';
|
||||
}
|
||||
}
|
||||
|
||||
tick() {
|
||||
if ('client' === process.env.SIDE && this.#scheduledRuleApplication) {
|
||||
this.#scheduledRuleApplication = false;
|
||||
this.applyStyleRules();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
40
packages/entity/src/traits/dom-text.js
Normal file
40
packages/entity/src/traits/dom-text.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import {Trait} from '@avocado/traits';
|
||||
|
||||
export default () => class DomText extends Trait {
|
||||
|
||||
#text;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.#text = window.document.createElement('span');
|
||||
}
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
textStyle: {},
|
||||
};
|
||||
}
|
||||
|
||||
static dependencies() {
|
||||
return [
|
||||
'Textual',
|
||||
'DomNode',
|
||||
];
|
||||
}
|
||||
|
||||
async load(json) {
|
||||
await super.load(json);
|
||||
const {text} = this.entity;
|
||||
this.#text.innerText = text;
|
||||
Object.entries(this.params.textStyle).forEach(([key, value]) => {
|
||||
this.#text.style[key] = value;
|
||||
});
|
||||
const {fontSize: fontSizeInPx = '16px'} = this.params.textStyle;
|
||||
const fontSize = parseInt(fontSizeInPx, 10);
|
||||
this.#text.style.position = 'relative';
|
||||
this.#text.style.left = `-${(fontSize / 2) * text.length}px`;
|
||||
this.#text.style.top = `-${(fontSize / 2)}px`;
|
||||
this.entity.node.appendChild(this.#text);
|
||||
}
|
||||
|
||||
};
|
Loading…
Reference in New Issue
Block a user