@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
207 lines (150 loc) • 5.4 kB
JavaScript
import { computeIsoscelesTriangleApexAngle } from "../../../core/math/computeIsoscelesTriangleApexAngle.js";
import dom from "../../DOM.js";
import SVG from "../../SVG.js";
import View from "../../View.js";
import { RadialText } from "./RadialText.js";
const PI2 = Math.PI * 2;
const elementPrototype = (function () {
const svgElement = SVG.createElement("path");
svgElement.setAttribute("fill", "rgba(255,0,0,0.5)");
return svgElement;
})();
class RadialMenuElement extends View {
/**
*
* @param {RadialMenuElementDefinition} description
*/
constructor(description) {
super();
/**
*
* @type {RadialMenuElementDefinition}
*/
this.description = description;
const self = this;
let dRoot = dom().addClass("ui-radial-menu-element");
this.el = dRoot.el;
if (description.cssClass !== null) {
this.addClass(description.cssClass);
}
const elSvg = SVG.createElement("svg");
const elArc = SVG.createElement("g");
const elPath = elementPrototype.cloneNode(true);
this.elPath = elPath;
elSvg.appendChild(elArc);
elArc.appendChild(elPath);
elPath.classList.add("backdrop");
elPath.setAttribute("fill", this.description.fill);
const iconSize = description.iconSize;
const outerRadius = description.outerRadius;
dRoot.append(elSvg);
if (description.autoSizeIcon === false) {
description.iconView.size.set(iconSize, iconSize);
}
this.radialText = new RadialText({
share: description.share,
offset: description.offset,
fill: description.nameFill,
radius: outerRadius + description.nameRadiusOffset
});
this.radialText.setText(description.name);
this.addChild(this.radialText);
this.addChild(description.iconView);
}
/**
*
* @returns {number}
*/
get iconSize() {
return this.description.iconSize;
}
/**
*
* @param {number} v
*/
set iconSize(v) {
this.description.iconSize = v;
this.updateIcon();
}
/**
*
* @returns {number}
*/
get innerRadius() {
return this.description.innerRadius;
}
/**
*
* @param {number} v
*/
set innerRadius(v) {
this.description.innerRadius = v;
this.render();
}
/**
*
* @returns {number}
*/
get outerRadius() {
return this.description.outerRadius;
}
/**
*
* @param {number} v
*/
set outerRadius(v) {
this.description.outerRadius = v;
this.render();
}
updateIcon() {
const description = this.description;
const vIcon = description.iconView;
const outerRadius = this.outerRadius;
const innerRadius = this.innerRadius;
let iconSize;
if (description.autoSizeIcon) {
iconSize = (outerRadius - innerRadius) / Math.SQRT2;
vIcon.size.set(iconSize, iconSize);
} else {
iconSize = Math.max(vIcon.size.x, vIcon.size.y);
}
const a0 = description.offset * PI2;
const a1 = a0 + description.share * PI2;
const aMid = (a1 + a0) / 2;
const cm = Math.cos(aMid);
const sm = Math.sin(aMid);
const r = (innerRadius + outerRadius) / 2;
const iconMidX = cm * r;
const iconMidY = sm * r;
const x = iconMidX - iconSize / 2;
const y = iconMidY - iconSize / 2;
vIcon.position.set(x, y);
}
render() {
const description = this.description;
const padding = description.padding;
const padding_2 = padding / 2;
//compute padding angle for inner and outer arcs
const outerRadius = this.outerRadius;
const innerRadius = this.innerRadius;
const outerArcPadding = computeIsoscelesTriangleApexAngle(outerRadius, padding_2);
const innerArcPadding = computeIsoscelesTriangleApexAngle(innerRadius, padding_2);
//compute wedge bounds of the element
const a0 = description.offset * PI2;
const a1 = a0 + description.share * PI2;
//compute inner and outer arcs for rendered element
const innerStart = a0 + innerArcPadding;
const innerEnd = a1 - innerArcPadding;
const outerStart = a0 + outerArcPadding;
const outerEnd = a1 - outerArcPadding;
//draw arc
this.elPath.setAttribute("d", SVG.svgArc2(innerRadius, outerRadius, innerStart, innerEnd, outerStart, outerEnd));
this.radialText.radius = outerRadius + description.nameRadiusOffset;
this.radialText.share = description.share;
this.radialText.offset = description.offset;
this.radialText.render();
//update icon position
this.updateIcon();
}
}
export default RadialMenuElement;