@woosh/meep-engine 2.39.16 → 2.39.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/view/View.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  import Vector2 from "../core/geom/Vector2";
2
+ import Signal from "../core/events/signal/Signal";
3
+
4
+ export interface IViewSignals {
5
+ readonly linked: Signal
6
+ readonly unlinked: Signal
7
+ }
2
8
 
3
9
  export default class View<T extends Element = HTMLElement> {
4
10
  size: Vector2
@@ -6,6 +12,8 @@ export default class View<T extends Element = HTMLElement> {
6
12
 
7
13
  el: T
8
14
 
15
+ readonly on: IViewSignals
16
+
9
17
  public link(): void
10
18
 
11
19
  public unlink(): void
@@ -3,32 +3,38 @@
3
3
  */
4
4
 
5
5
  import View from "../View.js";
6
- import dom from "../DOM.js";
7
6
 
8
7
  class EmptyView extends View {
9
8
  /**
10
- *
11
- * @param options
9
+ * @param {string[]} [classList]
10
+ * @param {Element} [el]
11
+ * @param {string} [tag]
12
+ * @param {string} [tagNamespace]
13
+ * @param {Object<string>} [css]
14
+ * @param {Object<string>} [attr]
12
15
  * @extends {View}
13
16
  * @constructor
14
17
  */
15
- constructor({ classList = [], tag = 'div', css } = {}) {
18
+ constructor({ classList = [], el, tag = 'div', tagNamespace = undefined, css, attr } = {}) {
16
19
  super();
17
20
 
18
- this.dRoot = dom(tag);
19
-
20
- const elClassList = this.dRoot.el.classList;
21
-
22
- for (let i = 0, l = classList.length; i < l; i++) {
23
- const className = classList[i];
24
- elClassList.add(className);
21
+ if (el !== undefined) {
22
+ this.el = el;
23
+ } else if (tagNamespace !== undefined) {
24
+ this.el = document.createElementNS(tagNamespace, tag);
25
+ } else {
26
+ this.el = document.createElement(tag);
25
27
  }
26
28
 
27
- this.el = this.dRoot.el;
29
+ this.addClasses(classList);
28
30
 
29
31
  if (css !== undefined) {
30
32
  this.css(css);
31
33
  }
34
+
35
+ if (attr !== undefined) {
36
+ this.attr(attr);
37
+ }
32
38
  }
33
39
 
34
40
  /**
@@ -17,6 +17,15 @@ function makeTextAbsolute(value, max, process) {
17
17
  }
18
18
 
19
19
  class ProgressBarView extends View {
20
+ /**
21
+ *
22
+ * @param {number[]|BoundedValue} model
23
+ * @param classList
24
+ * @param displayLabel
25
+ * @param displayLabelType
26
+ * @param displayTipMarker
27
+ * @param process
28
+ */
20
29
  constructor(model, {
21
30
  classList = [],
22
31
  displayLabel = false,
@@ -1,13 +1,369 @@
1
1
  import View from "../../View.js";
2
+ import { assert } from "../../../core/assert.js";
3
+ import EmptyView from "../EmptyView.js";
4
+ import LabelView from "../../common/LabelView.js";
5
+ import SVG from "../../SVG.js";
6
+ import ImageView from "../image/ImageView.js";
7
+ import { isDefined } from "../../../core/process/matcher/Matchers.js";
2
8
 
3
9
  export class WindRoseDiagram extends View {
4
- constructor() {
10
+
11
+ /**
12
+ *
13
+ * @param {{name:string,icon?:(View|string),value?:number,tooltip?:function, tooltipContext?:*}[]} axes
14
+ * @param {number} value_mark_stride
15
+ * @param {number} angular_offset
16
+ * @param {number} radius
17
+ * @param {number} value_max
18
+ * @param {DomTooltipManager} [tooltips]
19
+ */
20
+ constructor({
21
+ axes,
22
+ angular_offset = 0,
23
+ radius_inner = 200,
24
+ radius_outer = radius_inner,
25
+ value_max = 10,
26
+ value_mark_stride = value_max / 5,
27
+
28
+ icon_size = 32,
29
+
30
+ tooltips,
31
+
32
+ backplate_stroke_width = 2,
33
+ backplate_stroke_color = 'rgba(0,0,0,1)',
34
+ backplate_fill_color = 'rgba(99,99,99,1)',
35
+ display_backplate = true,
36
+
37
+ graph_stroke_width = 1,
38
+ graph_stroke_color = 'rgba(0,0,0,1)',
39
+ graph_fill_color = 'rgba(0,0,0,0.1)',
40
+
41
+ mark_stroke_width = 1,
42
+ mark_stroke_color = 'rgba(0,0,0,0.13)',
43
+ display_marks = true,
44
+
45
+ origin_radius = 8,
46
+ origin_stroke_width = 0,
47
+ origin_stroke_color = 'transparent',
48
+ origin_fill_color = 'red',
49
+ display_origin = true,
50
+ classList = []
51
+ }) {
5
52
  super();
6
53
 
7
- this.el = document.createElement('div');
54
+ this.__axes = axes;
55
+ this.__settings_value_max = value_max;
56
+ this.__settings_value_mark_stride = value_mark_stride;
57
+ this.__settings_angular_offset = angular_offset;
58
+ this.__settings_icon_size = icon_size;
59
+
60
+ this.__settings_graph_stroke_width = graph_stroke_width;
61
+ this.__settings_graph_stroke_color = graph_stroke_color;
62
+ this.__settings_graph_fill_color = graph_fill_color;
63
+
64
+ this.__settings_backplate_stroke_width = backplate_stroke_width;
65
+ this.__settings_backplate_stroke_color = backplate_stroke_color;
66
+ this.__settings_backplate_fill_color = backplate_fill_color;
67
+ this.__settings_display_backplate = display_backplate;
68
+
69
+ this.__settings_mark_stroke_width = mark_stroke_width;
70
+ this.__settings_mark_stroke_color = mark_stroke_color;
71
+ this.__settings_display_marks = display_marks;
72
+
73
+ this.__settings_origin_radius = origin_radius;
74
+ this.__settings_origin_stroke_width = origin_stroke_width;
75
+ this.__settings_origin_stroke_color = origin_stroke_color;
76
+ this.__settings_origin_fill_color = origin_fill_color;
77
+ this.__settings_display_origin = display_origin;
8
78
 
79
+ this.__settings_radius_inner = radius_inner;
80
+ this.__settings_radius_outer = radius_outer;
81
+
82
+ this.__tooltips = tooltips;
83
+
84
+ this.__values = new Float32Array(axes.length);
85
+
86
+ this.el = document.createElement('div');
9
87
  this.addClass('ui-wind-rose-diagram-view');
88
+ this.addClasses(classList);
89
+
90
+ const has_icons = axes.some(isDefined);
91
+
92
+ const size = radius_outer * 2 + (has_icons ? icon_size * (Math.SQRT1_2 + 0.5) * 2 : 0);
93
+
94
+ this.size.set(size, size);
95
+
96
+
97
+ this.__vCanvas = new EmptyView({
98
+ classList: ['canvas']
99
+ });
100
+
101
+ this.addChild(this.__vCanvas);
102
+
103
+ this.__vGraph = new EmptyView({
104
+ classList: ["graph"],
105
+ el: SVG.createElement('svg'),
106
+ attr: {
107
+ width: this.size.x * 2,
108
+ height: this.size.y * 2
109
+ },
110
+ css: {
111
+ position: 'absolute',
112
+ left: 0,
113
+ top: 0,
114
+ overflow: 'visible'
115
+ }
116
+ });
117
+ this.addChild(this.__vGraph);
118
+
119
+ this.__svg_graph_path = SVG.createElement('path');
120
+ this.__svg_graph_path.classList.add('graph-path-main');
121
+ this.__svg_graph_path.setAttribute('stroke-width', this.__settings_graph_stroke_width);
122
+ this.__svg_graph_path.setAttribute('stroke', this.__settings_graph_stroke_color);
123
+ this.__svg_graph_path.setAttribute('fill', this.__settings_graph_fill_color);
124
+
125
+ this.__vGraph.el.appendChild(this.__svg_graph_path);
126
+
127
+ this.on.linked.add(this.draw, this);
128
+
129
+ // process input axes
130
+ for (let i = 0; i < axes.length; i++) {
131
+ const axis = axes[i];
132
+
133
+ assert.defined(axis, 'axis');
134
+ assert.notNull(axis, 'axis');
135
+
136
+ if (axis.value !== undefined) {
137
+ this.set_axis_value(i, axis.value);
138
+ }
139
+ }
140
+ }
141
+
142
+ /**
143
+ *
144
+ * @param {number} index
145
+ * @param {number} value
146
+ */
147
+ set_axis_value(index, value) {
148
+ assert.isNonNegativeInteger(index, 'index');
149
+ assert.isFiniteNumber(value, 'value');
150
+
151
+ assert.lessThan(index, this.__axes.length, 'index overflow');
152
+
153
+ this.__values[index] = value;
154
+ }
155
+
156
+ draw() {
157
+ this.draw_canvas();
158
+ this.draw_values();
159
+ }
160
+
161
+ __get_axis_count() {
162
+ return this.__axes.length;
163
+ }
164
+
165
+ __get_axis_angle(index) {
166
+ const axis_count = this.__get_axis_count();
167
+ return index * Math.PI * (2 / axis_count) + this.__settings_angular_offset - Math.PI * 0.5;
168
+ }
169
+
170
+ __create_loop_path(radius) {
171
+ const axis_count = this.__get_axis_count();
172
+ const offset_x = this.size.x * 0.5;
173
+ const offset_y = this.size.y * 0.5;
174
+
175
+ let path = 'M';
176
+
177
+ for (let i = 0; i < axis_count; i++) {
178
+
179
+ const angle = this.__get_axis_angle(i);
180
+ const cos = Math.cos(angle);
181
+ const sin = Math.sin(angle);
182
+
183
+ path += cos * radius + offset_x;
184
+ path += ','
185
+ path += sin * radius + offset_y;
186
+
187
+ if (i < axis_count - 1) {
188
+ path += 'L'
189
+ } else {
190
+ path += 'Z';
191
+ }
192
+ }
193
+
194
+ return path;
195
+ }
196
+
197
+ draw_canvas() {
198
+ const container = this.__vCanvas;
199
+ container.removeAllChildren();
200
+
201
+ const axis_count = this.__get_axis_count();
202
+ const offset_x = this.size.x * 0.5;
203
+ const offset_y = this.size.y * 0.5;
204
+
205
+
206
+ // draw background and marks
207
+ const svg_main = SVG.createElement('svg');
208
+ svg_main.setAttribute('width', String(this.size.x));
209
+ svg_main.setAttribute('height', String(this.size.y));
210
+
211
+ if (this.__settings_display_backplate) {
212
+ const svg_path = SVG.createElement('path');
213
+
214
+ svg_path.classList.add('backplate');
215
+
216
+ svg_path.setAttribute('d', this.__create_loop_path(this.__settings_radius_outer + this.__settings_backplate_stroke_width / 2));
217
+ svg_path.setAttribute('stroke-width', String(this.__settings_backplate_stroke_width));
218
+ svg_path.setAttribute('stroke', this.__settings_backplate_stroke_color);
219
+ svg_path.setAttribute('fill', this.__settings_backplate_fill_color);
220
+
221
+ svg_main.appendChild(svg_path);
222
+ }
223
+
224
+ if (this.__settings_display_marks) {
225
+ for (let i = this.__settings_value_mark_stride; i < this.__settings_value_max; i += this.__settings_value_mark_stride) {
226
+ const svg_path = SVG.createElement('path');
227
+ svg_path.classList.add('mark');
228
+
229
+ const f = i / this.__settings_value_max;
230
+
231
+ const radius = f * this.__settings_radius_inner;
232
+
233
+ svg_path.setAttribute('d', this.__create_loop_path(radius));
234
+ svg_path.setAttribute('fill', 'none');
235
+ svg_path.setAttribute('stroke-width', this.__settings_mark_stroke_width);
236
+ svg_path.setAttribute('stroke', this.__settings_mark_stroke_color);
237
+
238
+ svg_main.appendChild(svg_path);
239
+ }
240
+ }
241
+
242
+ if (this.__settings_display_origin) {
243
+ const svg_path = SVG.createElement('path');
244
+
245
+ svg_path.classList.add('origin');
246
+
247
+ svg_path.setAttribute('d', this.__create_loop_path(this.__settings_origin_radius));
248
+ svg_path.setAttribute('fill', this.__settings_origin_fill_color);
249
+ svg_path.setAttribute('stroke-width', this.__settings_origin_stroke_width);
250
+ svg_path.setAttribute('stroke', this.__settings_origin_stroke_color);
251
+
252
+ svg_main.appendChild(svg_path);
253
+ }
254
+
255
+ const vSvgMain = new EmptyView({
256
+ el: svg_main,
257
+ css: {
258
+ position: 'absolute',
259
+ top: 0,
260
+ left: 0
261
+ }
262
+ });
263
+
264
+ container.addChild(vSvgMain);
265
+
266
+ for (let i = 0; i < axis_count; i++) {
267
+
268
+ // draw axis name
269
+ const axis = this.__axes[i];
270
+
271
+ if (axis === undefined) {
272
+ continue;
273
+ }
274
+
275
+ const angle = this.__get_axis_angle(i);
276
+ const cos = Math.cos(angle);
277
+ const sin = Math.sin(angle);
278
+
279
+ if (axis.name !== undefined) {
280
+ const vName = new LabelView(axis.name, {
281
+ classList: ['axis-name'],
282
+ css: {
283
+ position: "absolute",
284
+ top: "0",
285
+ left: "0"
286
+ }
287
+ });
288
+
289
+ const label_offset = this.__settings_radius_inner;
290
+ vName.position.set(
291
+ cos * label_offset + offset_x,
292
+ sin * label_offset + offset_y
293
+ );
294
+
295
+ if (this.__tooltips !== undefined && axis.tooltip !== undefined) {
296
+ this.__tooltips.add(vName, axis.tooltip, axis.tooltipContext);
297
+ }
298
+
299
+ container.addChild(vName);
300
+ }
301
+
302
+ // process icon
303
+ if (axis.icon !== undefined) {
304
+ let vIcon;
305
+ if (typeof axis.icon === "string") {
306
+ vIcon = new ImageView(axis.icon);
307
+ } else {
308
+ vIcon = axis.icon;
309
+ }
310
+
311
+ const icon_size = this.__settings_icon_size;
312
+ vIcon.css({
313
+ position: 'absolute',
314
+ left: `-${icon_size * 0.5}px`,
315
+ top: `-${icon_size * 0.5}px`
316
+ });
317
+
318
+ const icon_offset = this.__settings_radius_outer + icon_size * Math.SQRT1_2;
319
+
320
+ vIcon.position.set(
321
+ cos * icon_offset + offset_x,
322
+ sin * icon_offset + offset_y
323
+ );
324
+
325
+ vIcon.size.set(
326
+ icon_size,
327
+ icon_size
328
+ );
329
+
330
+ if (this.__tooltips !== undefined && axis.tooltip !== undefined) {
331
+ this.__tooltips.add(vIcon, axis.tooltip, axis.tooltipContext);
332
+ }
333
+
334
+ container.addChild(vIcon);
335
+ }
336
+ }
337
+ }
338
+
339
+ draw_values() {
340
+
341
+ const axis_count = this.__get_axis_count();
342
+ const offset_x = this.size.x * 0.5;
343
+ const offset_y = this.size.y * 0.5;
344
+
345
+ let path = 'M';
346
+
347
+ for (let i = 0; i < axis_count; i++) {
348
+
349
+ const angle = this.__get_axis_angle(i);
350
+ const cos = Math.cos(angle);
351
+ const sin = Math.sin(angle);
352
+
353
+ const f = this.__values[i] / this.__settings_value_max;
354
+ const radius = this.__settings_radius_inner * f;
355
+
356
+ path += cos * radius + offset_x;
357
+ path += ','
358
+ path += sin * radius + offset_y;
10
359
 
360
+ if (i < axis_count - 1) {
361
+ path += 'L'
362
+ } else {
363
+ path += 'Z';
364
+ }
365
+ }
11
366
 
367
+ this.__svg_graph_path.setAttribute('d', path);
12
368
  }
13
369
  }
@@ -0,0 +1,37 @@
1
+ import { WindRoseDiagram } from "./WindRoseDiagram.js";
2
+
3
+ const diagram = new WindRoseDiagram({
4
+ axes: [
5
+ {
6
+ name: 'Cost',
7
+ value: 7,
8
+ icon:'data/textures/icons/NhanceSpellIconsBundle/x64/T_Icon_Arcane_33.png'
9
+ },
10
+ {
11
+ name: "Quality",
12
+ value: 3,
13
+ icon:'data/textures/icons/NhanceSpellIconsBundle/x64/T_Icon_BloodCombat_21.png'
14
+ },
15
+ {
16
+ name: "Resource",
17
+ value: 9,
18
+ icon:'data/textures/icons/NhanceSpellIconsBundle/x64/T_Icon_Elements_38.png'
19
+ },
20
+ {
21
+ name: "Time",
22
+ value: 5
23
+ },
24
+ // {
25
+ // name: "Risk",
26
+ // value: 10
27
+ // },
28
+ // {
29
+ // name: "v",
30
+ // value: 10
31
+ // }
32
+ ]
33
+ });
34
+
35
+ document.body.append(diagram.el);
36
+
37
+ diagram.link();
@@ -2,7 +2,7 @@ import { DomTooltipObserver } from "./DomTooltipObserver.js";
2
2
 
3
3
 
4
4
  /**
5
- *
5
+ * @class
6
6
  */
7
7
  export class DomTooltipManager {
8
8
  /**