UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

207 lines (150 loc) 5.4 kB
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;