flocc 0.5.21 → 0.5.22
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/dist/environments/Environment.d.ts +38 -0
- package/dist/flocc.es.js +375 -87
- package/dist/flocc.js +375 -87
- package/dist/renderers/CanvasRenderer.d.ts +58 -0
- package/package.json +1 -1
- package/dist/environments/NewEnvironment.d.ts +0 -76
- package/dist/helpers/BS.d.ts +0 -6
- package/dist/types/instanceOfPoint.d.ts +0 -2
- package/dist/types/isAgent.d.ts +0 -2
- package/dist/utils/copyArray.d.ts +0 -10
- package/dist/utils/lcg.d.ts +0 -1
- package/dist/utils/randomizeOrder.d.ts +0 -12
package/dist/flocc.es.js
CHANGED
|
@@ -3212,6 +3212,15 @@ var Environment = /** @class */ (function (_super) {
|
|
|
3212
3212
|
* such as a {@linkcode LineChartRenderer}, {@linkcode Histogram}, etc.
|
|
3213
3213
|
*/
|
|
3214
3214
|
_this.renderers = [];
|
|
3215
|
+
/**
|
|
3216
|
+
* Whether the `Environment` tick cycle is currently playing.
|
|
3217
|
+
* Use {@linkcode pause}, {@linkcode resume}, or {@linkcode toggle}
|
|
3218
|
+
* to control playback.
|
|
3219
|
+
* @since 0.5.22
|
|
3220
|
+
*/
|
|
3221
|
+
_this.playing = true;
|
|
3222
|
+
/** @hidden */
|
|
3223
|
+
_this._tickIntervalId = null;
|
|
3215
3224
|
/**
|
|
3216
3225
|
* This property will always equal the number of tick cycles that
|
|
3217
3226
|
* have passed since the `Environment` was created. If you call
|
|
@@ -3381,6 +3390,9 @@ var Environment = /** @class */ (function (_super) {
|
|
|
3381
3390
|
* @since 0.0.5
|
|
3382
3391
|
*/
|
|
3383
3392
|
Environment.prototype.tick = function (opts) {
|
|
3393
|
+
// If paused, skip the tick cycle (use `step()` to advance manually)
|
|
3394
|
+
if (!this.playing)
|
|
3395
|
+
return;
|
|
3384
3396
|
var _a = this._getTickOptions(opts), activation = _a.activation, activationCount = _a.activationCount, count = _a.count, randomizeOrder = _a.randomizeOrder;
|
|
3385
3397
|
// for uniform activation, every agent is always activated
|
|
3386
3398
|
if (activation === "uniform") {
|
|
@@ -3448,6 +3460,47 @@ var Environment = /** @class */ (function (_super) {
|
|
|
3448
3460
|
}
|
|
3449
3461
|
this.renderers.forEach(function (r) { return r.render(); });
|
|
3450
3462
|
};
|
|
3463
|
+
/**
|
|
3464
|
+
* Pause the tick cycle. While paused, calling {@linkcode tick} will
|
|
3465
|
+
* be a no-op unless you use {@linkcode step} to advance manually.
|
|
3466
|
+
* @since 0.5.22
|
|
3467
|
+
*/
|
|
3468
|
+
Environment.prototype.pause = function () {
|
|
3469
|
+
this.playing = false;
|
|
3470
|
+
};
|
|
3471
|
+
/**
|
|
3472
|
+
* Resume the tick cycle after it has been paused.
|
|
3473
|
+
* @since 0.5.22
|
|
3474
|
+
*/
|
|
3475
|
+
Environment.prototype.resume = function () {
|
|
3476
|
+
this.playing = true;
|
|
3477
|
+
};
|
|
3478
|
+
/**
|
|
3479
|
+
* Toggle the tick cycle between playing and paused.
|
|
3480
|
+
* @since 0.5.22
|
|
3481
|
+
*/
|
|
3482
|
+
Environment.prototype.toggle = function () {
|
|
3483
|
+
this.playing = !this.playing;
|
|
3484
|
+
};
|
|
3485
|
+
/**
|
|
3486
|
+
* Advance the `Environment` by exactly one tick, regardless of whether
|
|
3487
|
+
* it is paused. This is useful for stepping through the simulation
|
|
3488
|
+
* frame-by-frame while paused.
|
|
3489
|
+
*
|
|
3490
|
+
* ```js
|
|
3491
|
+
* environment.pause();
|
|
3492
|
+
* environment.step(); // advances one tick
|
|
3493
|
+
* ```
|
|
3494
|
+
*
|
|
3495
|
+
* @since 0.5.22
|
|
3496
|
+
*/
|
|
3497
|
+
Environment.prototype.step = function (opts) {
|
|
3498
|
+
// Temporarily mark as playing so tick executes, then restore
|
|
3499
|
+
var wasPlaying = this.playing;
|
|
3500
|
+
this.playing = true;
|
|
3501
|
+
this.tick(opts);
|
|
3502
|
+
this.playing = wasPlaying;
|
|
3503
|
+
};
|
|
3451
3504
|
/**
|
|
3452
3505
|
* Use a helper with this environment. A helper can be one of:
|
|
3453
3506
|
* - {@linkcode KDTree}
|
|
@@ -3984,7 +4037,10 @@ var defaultOptions = {
|
|
|
3984
4037
|
width: 500,
|
|
3985
4038
|
height: 500,
|
|
3986
4039
|
scale: 1,
|
|
3987
|
-
trace: false
|
|
4040
|
+
trace: false,
|
|
4041
|
+
interactive: false,
|
|
4042
|
+
zoomMin: 0.1,
|
|
4043
|
+
zoomMax: 10
|
|
3988
4044
|
};
|
|
3989
4045
|
/**
|
|
3990
4046
|
* A `CanvasRenderer` renders an {@linkcode Environment} spatially in two dimensions.
|
|
@@ -4004,6 +4060,12 @@ var defaultOptions = {
|
|
|
4004
4060
|
* - `"triangle"` — Draws a triangle centered at the `Agent`'s `"x"` / `"y"` values.
|
|
4005
4061
|
* - Also uses the `"size"` value.
|
|
4006
4062
|
*
|
|
4063
|
+
* When `interactive` is set to `true` in the options, the renderer supports:
|
|
4064
|
+
* - **Click/hover detection** — Use {@linkcode on} to listen for `"click"`, `"hover"`, and `"unhover"` events on agents.
|
|
4065
|
+
* - **Agent selection** — Clicking an agent selects it (highlighted with a stroke). Access selected agents via {@linkcode selected}.
|
|
4066
|
+
* - **Pan** — Click and drag on empty space to pan.
|
|
4067
|
+
* - **Zoom** — Scroll to zoom in/out (bounded by `zoomMin` / `zoomMax`).
|
|
4068
|
+
*
|
|
4007
4069
|
* @since 0.0.11
|
|
4008
4070
|
*/
|
|
4009
4071
|
var CanvasRenderer = /** @class */ (function (_super) {
|
|
@@ -4019,15 +4081,33 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4019
4081
|
* - `connectionOpacity` (*number* = `1`) — For `Environment`s using a `Network`, the opacity of lines
|
|
4020
4082
|
* - `connectionWidth` (*number* = `1`) — For `Environment`s using a `Network`, the width of lines
|
|
4021
4083
|
* - `height` (*number* = `500`) — The height, in pixels, of the canvas on which to render
|
|
4084
|
+
* - `interactive` (*boolean* = `false`) — Enables interactive features (click/hover detection, selection, pan, zoom)
|
|
4085
|
+
* - `onSelect` (*function*) — Optional callback when an agent is selected or deselected
|
|
4022
4086
|
* - `origin` (*{ x: number; y: number }* = `{ x: 0, y: 0 }`) — The coordinate of the upper-left point of the space to be rendered
|
|
4023
4087
|
* - `scale` (*number* = `1`) — The scale at which to render (the larger the scale, the smaller the size of the space that is actually rendered)
|
|
4024
4088
|
* - `trace` (*boolean* = `false`) — If `true`, the renderer will not clear old drawings, causing the `Agent`s to appear to *trace* their paths across space
|
|
4025
4089
|
* - `width` (*number* = `500`) — The width, in pixels, of the canvas on which to render
|
|
4090
|
+
* - `zoomMin` (*number* = `0.1`) — Minimum scale when zooming
|
|
4091
|
+
* - `zoomMax` (*number* = `10`) — Maximum scale when zooming
|
|
4026
4092
|
*/
|
|
4027
4093
|
function CanvasRenderer(environment, opts) {
|
|
4028
4094
|
var _this = _super.call(this) || this;
|
|
4029
4095
|
/** @hidden */
|
|
4030
4096
|
_this.terrainBuffer = document.createElement("canvas");
|
|
4097
|
+
/** The currently selected agents (only used when `interactive` is `true`). */
|
|
4098
|
+
_this.selected = [];
|
|
4099
|
+
/** @hidden */
|
|
4100
|
+
_this._listeners = new Map();
|
|
4101
|
+
/** @hidden */
|
|
4102
|
+
_this._hoveredAgent = null;
|
|
4103
|
+
/** @hidden */
|
|
4104
|
+
_this._isPanning = false;
|
|
4105
|
+
/** @hidden */
|
|
4106
|
+
_this._panStart = null;
|
|
4107
|
+
/** @hidden */
|
|
4108
|
+
_this._panOriginStart = null;
|
|
4109
|
+
/** @hidden */
|
|
4110
|
+
_this._boundHandlers = {};
|
|
4031
4111
|
_this.environment = environment;
|
|
4032
4112
|
environment.renderers.push(_this);
|
|
4033
4113
|
_this.opts = Object.assign({}, defaultOptions);
|
|
@@ -4044,9 +4124,158 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4044
4124
|
_this.terrainBuffer.width = width;
|
|
4045
4125
|
_this.terrainBuffer.height = height;
|
|
4046
4126
|
_this.context.fillStyle = opts.background;
|
|
4047
|
-
_this.context.fillRect(0, 0, width, height);
|
|
4127
|
+
_this.context.fillRect(0, 0, _this.width, _this.height);
|
|
4128
|
+
if (_this.opts.interactive) {
|
|
4129
|
+
_this._setupInteractiveListeners();
|
|
4130
|
+
}
|
|
4048
4131
|
return _this;
|
|
4049
4132
|
}
|
|
4133
|
+
/**
|
|
4134
|
+
* Register a callback for an interactive event.
|
|
4135
|
+
* Supported event names: `"click"`, `"hover"`, `"unhover"`.
|
|
4136
|
+
*
|
|
4137
|
+
* ```js
|
|
4138
|
+
* renderer.on("click", (agent, event) => {
|
|
4139
|
+
* console.log("Clicked agent:", agent.id);
|
|
4140
|
+
* });
|
|
4141
|
+
* ```
|
|
4142
|
+
*
|
|
4143
|
+
* @param eventName - The event to listen for.
|
|
4144
|
+
* @param callback - The callback, invoked with the `Agent` and the `MouseEvent`.
|
|
4145
|
+
*/
|
|
4146
|
+
CanvasRenderer.prototype.on = function (eventName, callback) {
|
|
4147
|
+
if (!this._listeners.has(eventName)) {
|
|
4148
|
+
this._listeners.set(eventName, []);
|
|
4149
|
+
}
|
|
4150
|
+
this._listeners.get(eventName).push(callback);
|
|
4151
|
+
};
|
|
4152
|
+
/** @hidden */
|
|
4153
|
+
CanvasRenderer.prototype._emit = function (eventName, agent, event) {
|
|
4154
|
+
var callbacks = this._listeners.get(eventName);
|
|
4155
|
+
if (callbacks) {
|
|
4156
|
+
callbacks.forEach(function (cb) { return cb(agent, event); });
|
|
4157
|
+
}
|
|
4158
|
+
};
|
|
4159
|
+
/**
|
|
4160
|
+
* Given a mouse event, return the agent at that position (if any).
|
|
4161
|
+
* Hit-testing accounts for the agent's shape and size.
|
|
4162
|
+
* @hidden
|
|
4163
|
+
*/
|
|
4164
|
+
CanvasRenderer.prototype._agentAtPoint = function (clientX, clientY) {
|
|
4165
|
+
var rect = this.canvas.getBoundingClientRect();
|
|
4166
|
+
var dpr = window.devicePixelRatio;
|
|
4167
|
+
var canvasX = (clientX - rect.left) * dpr;
|
|
4168
|
+
var canvasY = (clientY - rect.top) * dpr;
|
|
4169
|
+
var agents = this.environment.getAgents();
|
|
4170
|
+
// Iterate in reverse so topmost-drawn agent is found first
|
|
4171
|
+
for (var i = agents.length - 1; i >= 0; i--) {
|
|
4172
|
+
var agent = agents[i];
|
|
4173
|
+
var data = agent.getData();
|
|
4174
|
+
var ax = this.x(data.x);
|
|
4175
|
+
var ay = this.y(data.y);
|
|
4176
|
+
var shape = data.shape;
|
|
4177
|
+
var size = (data.size || 1) * dpr;
|
|
4178
|
+
if (shape === "rect") {
|
|
4179
|
+
var w = (data.width || 1) * dpr;
|
|
4180
|
+
var h = (data.height || 1) * dpr;
|
|
4181
|
+
var rx = ax - w / 2;
|
|
4182
|
+
var ry = ay - h / 2;
|
|
4183
|
+
if (canvasX >= rx && canvasX <= rx + w && canvasY >= ry && canvasY <= ry + h) {
|
|
4184
|
+
return agent;
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
else if (shape === "triangle") {
|
|
4188
|
+
// Simple bounding-box hit test for triangles
|
|
4189
|
+
var halfSize = size / 2;
|
|
4190
|
+
if (canvasX >= ax - halfSize &&
|
|
4191
|
+
canvasX <= ax + halfSize &&
|
|
4192
|
+
canvasY >= ay - halfSize &&
|
|
4193
|
+
canvasY <= ay + halfSize) {
|
|
4194
|
+
return agent;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
else {
|
|
4198
|
+
// Default: circle (and arrow) — distance-based hit test
|
|
4199
|
+
var dx = canvasX - ax;
|
|
4200
|
+
var dy = canvasY - ay;
|
|
4201
|
+
var hitRadius = Math.max(size, 4 * dpr); // minimum hit area for tiny agents
|
|
4202
|
+
if (dx * dx + dy * dy <= hitRadius * hitRadius) {
|
|
4203
|
+
return agent;
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
return null;
|
|
4208
|
+
};
|
|
4209
|
+
/** @hidden */
|
|
4210
|
+
CanvasRenderer.prototype._setupInteractiveListeners = function () {
|
|
4211
|
+
var _this = this;
|
|
4212
|
+
var onMouseDown = function (e) {
|
|
4213
|
+
var agent = _this._agentAtPoint(e.clientX, e.clientY);
|
|
4214
|
+
if (agent) {
|
|
4215
|
+
// Agent click — select it
|
|
4216
|
+
_this.selected = [agent];
|
|
4217
|
+
if (_this.opts.onSelect)
|
|
4218
|
+
_this.opts.onSelect(agent);
|
|
4219
|
+
_this._emit("click", agent, e);
|
|
4220
|
+
_this.render();
|
|
4221
|
+
}
|
|
4222
|
+
else {
|
|
4223
|
+
// Empty space — deselect and start panning
|
|
4224
|
+
if (_this.selected.length > 0) {
|
|
4225
|
+
_this.selected = [];
|
|
4226
|
+
if (_this.opts.onSelect)
|
|
4227
|
+
_this.opts.onSelect(null);
|
|
4228
|
+
_this.render();
|
|
4229
|
+
}
|
|
4230
|
+
_this._isPanning = true;
|
|
4231
|
+
_this._panStart = { x: e.clientX, y: e.clientY };
|
|
4232
|
+
_this._panOriginStart = { x: _this.opts.origin.x, y: _this.opts.origin.y };
|
|
4233
|
+
}
|
|
4234
|
+
};
|
|
4235
|
+
var onMouseMove = function (e) {
|
|
4236
|
+
if (_this._isPanning && _this._panStart && _this._panOriginStart) {
|
|
4237
|
+
var dpr = window.devicePixelRatio;
|
|
4238
|
+
var dx = e.clientX - _this._panStart.x;
|
|
4239
|
+
var dy = e.clientY - _this._panStart.y;
|
|
4240
|
+
_this.opts.origin = {
|
|
4241
|
+
x: _this._panOriginStart.x - dx / (_this.opts.scale * dpr),
|
|
4242
|
+
y: _this._panOriginStart.y - dy / (_this.opts.scale * dpr)
|
|
4243
|
+
};
|
|
4244
|
+
_this.render();
|
|
4245
|
+
return;
|
|
4246
|
+
}
|
|
4247
|
+
// Hover detection
|
|
4248
|
+
var agent = _this._agentAtPoint(e.clientX, e.clientY);
|
|
4249
|
+
if (agent !== _this._hoveredAgent) {
|
|
4250
|
+
if (_this._hoveredAgent) {
|
|
4251
|
+
_this._emit("unhover", _this._hoveredAgent, e);
|
|
4252
|
+
}
|
|
4253
|
+
if (agent) {
|
|
4254
|
+
_this._emit("hover", agent, e);
|
|
4255
|
+
}
|
|
4256
|
+
_this._hoveredAgent = agent;
|
|
4257
|
+
}
|
|
4258
|
+
};
|
|
4259
|
+
var onMouseUp = function (e) {
|
|
4260
|
+
_this._isPanning = false;
|
|
4261
|
+
_this._panStart = null;
|
|
4262
|
+
_this._panOriginStart = null;
|
|
4263
|
+
};
|
|
4264
|
+
var onWheel = function (e) {
|
|
4265
|
+
e.preventDefault();
|
|
4266
|
+
var _a = _this.opts, zoomMin = _a.zoomMin, zoomMax = _a.zoomMax;
|
|
4267
|
+
var delta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
4268
|
+
var newScale = _this.opts.scale * delta;
|
|
4269
|
+
newScale = Math.max(zoomMin, Math.min(zoomMax, newScale));
|
|
4270
|
+
_this.opts.scale = newScale;
|
|
4271
|
+
_this.render();
|
|
4272
|
+
};
|
|
4273
|
+
this._boundHandlers = { mousedown: onMouseDown, mousemove: onMouseMove, mouseup: onMouseUp, wheel: onWheel };
|
|
4274
|
+
this.canvas.addEventListener("mousedown", onMouseDown);
|
|
4275
|
+
this.canvas.addEventListener("mousemove", onMouseMove);
|
|
4276
|
+
this.canvas.addEventListener("mouseup", onMouseUp);
|
|
4277
|
+
this.canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
4278
|
+
};
|
|
4050
4279
|
/** @hidden */
|
|
4051
4280
|
CanvasRenderer.prototype.x = function (v) {
|
|
4052
4281
|
var _a = this.opts, origin = _a.origin, scale = _a.scale;
|
|
@@ -4083,21 +4312,21 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4083
4312
|
};
|
|
4084
4313
|
/** @hidden */
|
|
4085
4314
|
CanvasRenderer.prototype.drawPathWrap = function (points) {
|
|
4086
|
-
var _this = this;
|
|
4087
4315
|
var _a = this, width = _a.width, height = _a.height;
|
|
4088
4316
|
var right = false;
|
|
4089
4317
|
var left = false;
|
|
4090
4318
|
var lower = false;
|
|
4091
4319
|
var upper = false;
|
|
4320
|
+
// points are already in DPR-scaled pixel space, so compare directly
|
|
4092
4321
|
points.forEach(function (_a) {
|
|
4093
4322
|
var px = _a[0], py = _a[1];
|
|
4094
|
-
if (
|
|
4323
|
+
if (px >= width)
|
|
4095
4324
|
right = true;
|
|
4096
|
-
if (
|
|
4325
|
+
if (px < 0)
|
|
4097
4326
|
left = true;
|
|
4098
|
-
if (
|
|
4327
|
+
if (py >= height)
|
|
4099
4328
|
lower = true;
|
|
4100
|
-
if (
|
|
4329
|
+
if (py < 0)
|
|
4101
4330
|
upper = true;
|
|
4102
4331
|
});
|
|
4103
4332
|
if (right)
|
|
@@ -4126,24 +4355,26 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4126
4355
|
/** @hidden */
|
|
4127
4356
|
CanvasRenderer.prototype.drawCircleWrap = function (x, y, size) {
|
|
4128
4357
|
var _a = this, width = _a.width, height = _a.height;
|
|
4358
|
+
var worldWidth = this.opts.width;
|
|
4359
|
+
var worldHeight = this.opts.height;
|
|
4129
4360
|
if (this.x(x + size) >= width) {
|
|
4130
|
-
this.drawCircle(x -
|
|
4361
|
+
this.drawCircle(x - worldWidth, y, size);
|
|
4131
4362
|
if (this.y(y + size) >= height)
|
|
4132
|
-
this.drawCircle(x -
|
|
4363
|
+
this.drawCircle(x - worldWidth, y - worldHeight, size);
|
|
4133
4364
|
if (this.y(y - size) < 0)
|
|
4134
|
-
this.drawCircle(x -
|
|
4365
|
+
this.drawCircle(x - worldWidth, y + worldHeight, size);
|
|
4135
4366
|
}
|
|
4136
4367
|
if (this.x(x - size) < 0) {
|
|
4137
|
-
this.drawCircle(x +
|
|
4368
|
+
this.drawCircle(x + worldWidth, y, size);
|
|
4138
4369
|
if (this.y(y + size) >= height)
|
|
4139
|
-
this.drawCircle(x +
|
|
4370
|
+
this.drawCircle(x + worldWidth, y - worldHeight, size);
|
|
4140
4371
|
if (this.y(y - size) < 0)
|
|
4141
|
-
this.drawCircle(x +
|
|
4372
|
+
this.drawCircle(x + worldWidth, y + worldHeight, size);
|
|
4142
4373
|
}
|
|
4143
4374
|
if (this.y(y + size) > height)
|
|
4144
|
-
this.drawCircle(x, y -
|
|
4375
|
+
this.drawCircle(x, y - worldHeight, size);
|
|
4145
4376
|
if (this.y(y - size) < 0)
|
|
4146
|
-
this.drawCircle(x, y +
|
|
4377
|
+
this.drawCircle(x, y + worldHeight, size);
|
|
4147
4378
|
};
|
|
4148
4379
|
/**
|
|
4149
4380
|
* Draw a rectangle centered at (x, y). Automatically calculates the offset
|
|
@@ -4157,25 +4388,55 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4157
4388
|
};
|
|
4158
4389
|
/** @hidden */
|
|
4159
4390
|
CanvasRenderer.prototype.drawRectWrap = function (x, y, w, h) {
|
|
4160
|
-
var _a = this
|
|
4391
|
+
var _a = this, width = _a.width, height = _a.height;
|
|
4392
|
+
var worldWidth = this.opts.width;
|
|
4393
|
+
var worldHeight = this.opts.height;
|
|
4161
4394
|
if (this.x(x + w / 2) >= width) {
|
|
4162
|
-
this.drawRect(x -
|
|
4395
|
+
this.drawRect(x - worldWidth, y, w, h);
|
|
4163
4396
|
if (this.y(y + h / 2) >= height)
|
|
4164
|
-
this.drawRect(x -
|
|
4165
|
-
if (this.y(y -
|
|
4166
|
-
this.drawRect(x -
|
|
4397
|
+
this.drawRect(x - worldWidth, y - worldHeight, w, h);
|
|
4398
|
+
if (this.y(y - h / 2) < 0)
|
|
4399
|
+
this.drawRect(x - worldWidth, y + worldHeight, w, h);
|
|
4167
4400
|
}
|
|
4168
4401
|
if (this.x(x - w / 2) < 0) {
|
|
4169
|
-
this.drawRect(x +
|
|
4402
|
+
this.drawRect(x + worldWidth, y, w, h);
|
|
4170
4403
|
if (this.y(y + h / 2) >= height)
|
|
4171
|
-
this.drawRect(x +
|
|
4172
|
-
if (this.y(y -
|
|
4173
|
-
this.drawRect(x +
|
|
4404
|
+
this.drawRect(x + worldWidth, y - worldHeight, w, h);
|
|
4405
|
+
if (this.y(y - h / 2) < 0)
|
|
4406
|
+
this.drawRect(x + worldWidth, y + worldHeight, w, h);
|
|
4174
4407
|
}
|
|
4175
4408
|
if (this.y(y + h / 2) > height)
|
|
4176
|
-
this.drawRect(x, y -
|
|
4177
|
-
if (this.y(y -
|
|
4178
|
-
this.drawRect(x, y +
|
|
4409
|
+
this.drawRect(x, y - worldHeight, w, h);
|
|
4410
|
+
if (this.y(y - h / 2) < 0)
|
|
4411
|
+
this.drawRect(x, y + worldHeight, w, h);
|
|
4412
|
+
};
|
|
4413
|
+
/**
|
|
4414
|
+
* Draw a selection highlight around the given agent.
|
|
4415
|
+
* @hidden
|
|
4416
|
+
*/
|
|
4417
|
+
CanvasRenderer.prototype._drawSelectionHighlight = function (agent) {
|
|
4418
|
+
var bufferContext = this.buffer.getContext("2d");
|
|
4419
|
+
var dpr = window.devicePixelRatio;
|
|
4420
|
+
var data = agent.getData();
|
|
4421
|
+
var ax = this.x(data.x);
|
|
4422
|
+
var ay = this.y(data.y);
|
|
4423
|
+
var shape = data.shape;
|
|
4424
|
+
var size = (data.size || 1) * dpr;
|
|
4425
|
+
bufferContext.save();
|
|
4426
|
+
bufferContext.strokeStyle = "#0af";
|
|
4427
|
+
bufferContext.lineWidth = 2 * dpr;
|
|
4428
|
+
if (shape === "rect") {
|
|
4429
|
+
var w = (data.width || 1) * dpr;
|
|
4430
|
+
var h = (data.height || 1) * dpr;
|
|
4431
|
+
bufferContext.strokeRect(ax - w / 2 - 2 * dpr, ay - h / 2 - 2 * dpr, w + 4 * dpr, h + 4 * dpr);
|
|
4432
|
+
}
|
|
4433
|
+
else {
|
|
4434
|
+
bufferContext.beginPath();
|
|
4435
|
+
var highlightRadius = Math.max(size, 4 * dpr) + 3 * dpr;
|
|
4436
|
+
bufferContext.arc(ax, ay, highlightRadius, 0, 2 * Math.PI);
|
|
4437
|
+
bufferContext.stroke();
|
|
4438
|
+
}
|
|
4439
|
+
bufferContext.restore();
|
|
4179
4440
|
};
|
|
4180
4441
|
CanvasRenderer.prototype.render = function () {
|
|
4181
4442
|
var _this = this;
|
|
@@ -4188,22 +4449,24 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4188
4449
|
// if "trace" is truthy, don't clear the canvas with every frame
|
|
4189
4450
|
// to trace the paths of agents
|
|
4190
4451
|
if (!trace) {
|
|
4191
|
-
context.clearRect(0, 0, width
|
|
4452
|
+
context.clearRect(0, 0, width, height);
|
|
4192
4453
|
context.fillStyle = opts.background;
|
|
4193
|
-
context.fillRect(0, 0, width
|
|
4454
|
+
context.fillRect(0, 0, width, height);
|
|
4194
4455
|
}
|
|
4195
4456
|
// automatically position agents in an environment that uses a network helper
|
|
4196
4457
|
if (opts.autoPosition && environment.helpers.network) {
|
|
4197
4458
|
environment.getAgents().forEach(function (agent) {
|
|
4198
4459
|
var network = _this.environment.helpers.network;
|
|
4199
|
-
|
|
4460
|
+
// Use CSS pixel dimensions (opts), not the DPI-scaled canvas dimensions,
|
|
4461
|
+
// since x() and y() already apply the devicePixelRatio transform.
|
|
4462
|
+
var _a = _this.opts, w = _a.width, h = _a.height;
|
|
4200
4463
|
// only set once
|
|
4201
4464
|
if ((agent.get("x") === null || agent.get("y") === null) &&
|
|
4202
4465
|
network.isInNetwork(agent)) {
|
|
4203
4466
|
var idx = network.indexOf(agent);
|
|
4204
4467
|
var angle = idx / network.agents.length;
|
|
4205
|
-
var x =
|
|
4206
|
-
var y =
|
|
4468
|
+
var x = w / 2 + 0.4 * w * Math.cos(2 * Math.PI * angle);
|
|
4469
|
+
var y = h / 2 + 0.4 * h * Math.sin(2 * Math.PI * angle);
|
|
4207
4470
|
agent.set({ x: x, y: y });
|
|
4208
4471
|
}
|
|
4209
4472
|
});
|
|
@@ -4248,8 +4511,8 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4248
4511
|
context.globalAlpha = _this.opts.connectionOpacity;
|
|
4249
4512
|
context.strokeStyle = _this.opts.connectionColor;
|
|
4250
4513
|
context.lineWidth = _this.opts.connectionWidth;
|
|
4251
|
-
context.moveTo(_this.x(x), _this.
|
|
4252
|
-
context.lineTo(_this.x(nx), _this.
|
|
4514
|
+
context.moveTo(_this.x(x), _this.y(y));
|
|
4515
|
+
context.lineTo(_this.x(nx), _this.y(ny));
|
|
4253
4516
|
context.stroke();
|
|
4254
4517
|
context.closePath();
|
|
4255
4518
|
context.restore();
|
|
@@ -4281,10 +4544,11 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4281
4544
|
}
|
|
4282
4545
|
else if (shape === "triangle") {
|
|
4283
4546
|
bufferContext.beginPath();
|
|
4547
|
+
var scaledSize = size * dpr;
|
|
4284
4548
|
var points = [
|
|
4285
|
-
[_this.x(x), _this.y(y) -
|
|
4286
|
-
[_this.x(x) +
|
|
4287
|
-
[_this.x(x) -
|
|
4549
|
+
[_this.x(x), _this.y(y) - scaledSize / 2],
|
|
4550
|
+
[_this.x(x) + scaledSize / 2, _this.y(y) + scaledSize / 2],
|
|
4551
|
+
[_this.x(x) - scaledSize / 2, _this.y(y) + scaledSize / 2]
|
|
4288
4552
|
];
|
|
4289
4553
|
_this.drawPath(points);
|
|
4290
4554
|
if (environment.opts.torus)
|
|
@@ -4310,6 +4574,12 @@ var CanvasRenderer = /** @class */ (function (_super) {
|
|
|
4310
4574
|
bufferContext.restore();
|
|
4311
4575
|
}
|
|
4312
4576
|
});
|
|
4577
|
+
// Draw selection highlights for selected agents
|
|
4578
|
+
if (opts.interactive && this.selected.length > 0) {
|
|
4579
|
+
this.selected.forEach(function (agent) {
|
|
4580
|
+
_this._drawSelectionHighlight(agent);
|
|
4581
|
+
});
|
|
4582
|
+
}
|
|
4313
4583
|
context.drawImage(buffer, 0, 0);
|
|
4314
4584
|
};
|
|
4315
4585
|
return CanvasRenderer;
|
|
@@ -4400,11 +4670,13 @@ var Histogram = /** @class */ (function (_super) {
|
|
|
4400
4670
|
};
|
|
4401
4671
|
Histogram.prototype.x = function (value) {
|
|
4402
4672
|
var _a = this, width = _a.width, markerWidth = _a.markerWidth;
|
|
4403
|
-
|
|
4673
|
+
var dpr = window.devicePixelRatio;
|
|
4674
|
+
return remap(value, 0, width, markerWidth + PADDING_AT_LEFT * dpr, width - PADDING_AT_RIGHT * dpr);
|
|
4404
4675
|
};
|
|
4405
4676
|
Histogram.prototype.y = function (value) {
|
|
4406
4677
|
var _a = this, height = _a.height, maxValue = _a.maxValue;
|
|
4407
|
-
|
|
4678
|
+
var dpr = window.devicePixelRatio;
|
|
4679
|
+
return remap(value, 0, maxValue, height - PADDING_AT_BOTTOM * dpr, 0);
|
|
4408
4680
|
};
|
|
4409
4681
|
Histogram.prototype.setMaxValue = function () {
|
|
4410
4682
|
var _this = this;
|
|
@@ -4433,11 +4705,12 @@ var Histogram = /** @class */ (function (_super) {
|
|
|
4433
4705
|
var context = this.canvas.getContext("2d");
|
|
4434
4706
|
var _a = this, height = _a.height, width = _a.width;
|
|
4435
4707
|
var _b = this.opts, aboveMax = _b.aboveMax, belowMin = _b.belowMin, buckets = _b.buckets, min = _b.min, max$1 = _b.max;
|
|
4708
|
+
var dpr = window.devicePixelRatio;
|
|
4436
4709
|
var yMin = 0;
|
|
4437
4710
|
var yMax = this.maxValue;
|
|
4438
4711
|
var markers = extractRoundNumbers({ min: yMin, max: yMax });
|
|
4439
4712
|
context.fillStyle = "black";
|
|
4440
|
-
context.font = 14 *
|
|
4713
|
+
context.font = 14 * dpr + "px Helvetica";
|
|
4441
4714
|
// determine the width of the longest marker
|
|
4442
4715
|
this.markerWidth = max(markers.map(function (marker) { return context.measureText(marker.toLocaleString()).width; }));
|
|
4443
4716
|
// draw horizontal lines
|
|
@@ -4446,9 +4719,9 @@ var Histogram = /** @class */ (function (_super) {
|
|
|
4446
4719
|
context.textBaseline = "middle";
|
|
4447
4720
|
context.fillText(marker.toLocaleString(), _this.markerWidth, _this.y(marker));
|
|
4448
4721
|
context.beginPath();
|
|
4449
|
-
context.moveTo(_this.markerWidth + 10, _this.y(marker));
|
|
4722
|
+
context.moveTo(_this.markerWidth + 10 * dpr, _this.y(marker));
|
|
4450
4723
|
context.lineTo(_this.width, _this.y(marker));
|
|
4451
|
-
context.setLineDash(LINE_DASH);
|
|
4724
|
+
context.setLineDash(LINE_DASH.map(function (v) { return v * dpr; }));
|
|
4452
4725
|
context.stroke();
|
|
4453
4726
|
});
|
|
4454
4727
|
var numBuckets = bucketValues.length - (aboveMax ? 1 : 0) - (belowMin ? 1 : 0);
|
|
@@ -4471,9 +4744,9 @@ var Histogram = /** @class */ (function (_super) {
|
|
|
4471
4744
|
.forEach(function (label, i) {
|
|
4472
4745
|
context.save();
|
|
4473
4746
|
context.translate(_this.x((i * width) / bucketValues.length +
|
|
4474
|
-
(0.5 * width) / bucketValues.length), height - 50);
|
|
4747
|
+
(0.5 * width) / bucketValues.length), height - 50 * dpr);
|
|
4475
4748
|
context.rotate(Math.PI / 4);
|
|
4476
|
-
context.font = 12 *
|
|
4749
|
+
context.font = 12 * dpr + "px Helvetica";
|
|
4477
4750
|
context.textAlign = "left";
|
|
4478
4751
|
context.textBaseline = "middle";
|
|
4479
4752
|
context.fillText(label, 0, 0);
|
|
@@ -4483,22 +4756,23 @@ var Histogram = /** @class */ (function (_super) {
|
|
|
4483
4756
|
Histogram.prototype.drawBuckets = function (bucketValues, offset) {
|
|
4484
4757
|
var _this = this;
|
|
4485
4758
|
if (offset === void 0) { offset = 0; }
|
|
4486
|
-
var canvas =
|
|
4759
|
+
var _a = this, canvas = _a.canvas, width = _a.width, height = _a.height;
|
|
4487
4760
|
var metric = this._metric;
|
|
4488
4761
|
var numMetrics = Array.isArray(metric) ? metric.length : 1;
|
|
4489
|
-
var
|
|
4762
|
+
var _b = this.opts, aboveMax = _b.aboveMax, belowMin = _b.belowMin, color = _b.color;
|
|
4763
|
+
var dpr = window.devicePixelRatio;
|
|
4490
4764
|
var context = canvas.getContext("2d");
|
|
4491
4765
|
context.fillStyle = Array.isArray(color)
|
|
4492
4766
|
? color[offset % color.length]
|
|
4493
4767
|
: color;
|
|
4494
4768
|
var numBuckets = bucketValues.length;
|
|
4495
|
-
var barWidth = (width - PADDING_AT_LEFT - PADDING_AT_RIGHT - this.markerWidth) /
|
|
4769
|
+
var barWidth = (width - PADDING_AT_LEFT * dpr - PADDING_AT_RIGHT * dpr - this.markerWidth) /
|
|
4496
4770
|
numBuckets;
|
|
4497
4771
|
barWidth *= 0.8;
|
|
4498
4772
|
bucketValues.forEach(function (value, i) {
|
|
4499
4773
|
var mappedValue = remap(value, 0, _this.maxValue, 0, 1);
|
|
4500
4774
|
var x = _this.x(((0.1 + i) * width) / numBuckets);
|
|
4501
|
-
context.fillRect(x + (offset * barWidth - (numMetrics - 1)) / numMetrics + offset, remap(mappedValue, 0, 1, height - PADDING_AT_BOTTOM, 0), barWidth / numMetrics, remap(mappedValue, 0, 1, 0, height - PADDING_AT_BOTTOM));
|
|
4775
|
+
context.fillRect(x + (offset * barWidth - (numMetrics - 1)) / numMetrics + offset, remap(mappedValue, 0, 1, height - PADDING_AT_BOTTOM * dpr, 0), barWidth / numMetrics, remap(mappedValue, 0, 1, 0, height - PADDING_AT_BOTTOM * dpr));
|
|
4502
4776
|
});
|
|
4503
4777
|
};
|
|
4504
4778
|
Histogram.prototype.getBucketValues = function (metric) {
|
|
@@ -4635,12 +4909,16 @@ var LineChartRenderer = /** @class */ (function (_super) {
|
|
|
4635
4909
|
var height = this.height;
|
|
4636
4910
|
var range = this.opts.range;
|
|
4637
4911
|
var min = range.min, max = range.max;
|
|
4638
|
-
var
|
|
4639
|
-
|
|
4912
|
+
var dpr = window.devicePixelRatio;
|
|
4913
|
+
var paddingBottom = PADDING_BOTTOM * dpr;
|
|
4914
|
+
var pxPerUnit = (height - 2 * paddingBottom) / (max - min);
|
|
4915
|
+
return Math.round(height - (value - min) * pxPerUnit) - 2 * paddingBottom;
|
|
4640
4916
|
};
|
|
4641
4917
|
LineChartRenderer.prototype.drawBackground = function () {
|
|
4642
4918
|
var _this = this;
|
|
4643
4919
|
var _a = this, context = _a.context, width = _a.width, height = _a.height, opts = _a.opts, t = _a.t;
|
|
4920
|
+
var dpr = window.devicePixelRatio;
|
|
4921
|
+
var paddingBottom = PADDING_BOTTOM * dpr;
|
|
4644
4922
|
// draw background and lines
|
|
4645
4923
|
context.fillStyle = this.opts.background;
|
|
4646
4924
|
context.fillRect(0, 0, width, height);
|
|
@@ -4648,27 +4926,27 @@ var LineChartRenderer = /** @class */ (function (_super) {
|
|
|
4648
4926
|
var markers = extractRoundNumbers(range);
|
|
4649
4927
|
var textMaxWidth = 0;
|
|
4650
4928
|
// write values on vertical axis
|
|
4651
|
-
context.font = 14 *
|
|
4929
|
+
context.font = 14 * dpr + "px Helvetica";
|
|
4652
4930
|
context.fillStyle = "#000";
|
|
4653
4931
|
context.textBaseline = "middle";
|
|
4654
4932
|
markers.forEach(function (marker) {
|
|
4655
|
-
if (_this.y(marker) < 10 || _this.y(marker) + 10 > height)
|
|
4933
|
+
if (_this.y(marker) < 10 * dpr || _this.y(marker) + 10 * dpr > height)
|
|
4656
4934
|
return;
|
|
4657
4935
|
var width = context.measureText(marker.toLocaleString()).width;
|
|
4658
4936
|
if (width > textMaxWidth)
|
|
4659
4937
|
textMaxWidth = width;
|
|
4660
|
-
context.fillText(marker.toLocaleString(), 5, _this.y(marker));
|
|
4938
|
+
context.fillText(marker.toLocaleString(), 5 * dpr, _this.y(marker));
|
|
4661
4939
|
});
|
|
4662
4940
|
// draw horizontal lines for vertical axis
|
|
4663
4941
|
context.save();
|
|
4664
4942
|
context.strokeStyle = "#999";
|
|
4665
4943
|
markers.forEach(function (marker) {
|
|
4666
|
-
if (_this.y(marker) >= height -
|
|
4944
|
+
if (_this.y(marker) >= height - paddingBottom)
|
|
4667
4945
|
return;
|
|
4668
4946
|
context.beginPath();
|
|
4669
|
-
context.moveTo(textMaxWidth + 10, _this.y(marker));
|
|
4947
|
+
context.moveTo(textMaxWidth + 10 * dpr, _this.y(marker));
|
|
4670
4948
|
context.lineTo(_this.x(Math.max(width, _this.environment.time)), _this.y(marker));
|
|
4671
|
-
context.setLineDash(lineDash);
|
|
4949
|
+
context.setLineDash(lineDash.map(function (v) { return v * dpr; }));
|
|
4672
4950
|
context.stroke();
|
|
4673
4951
|
});
|
|
4674
4952
|
context.restore();
|
|
@@ -4685,12 +4963,12 @@ var LineChartRenderer = /** @class */ (function (_super) {
|
|
|
4685
4963
|
_this.x(marker) - width / 2 < textMaxWidth) {
|
|
4686
4964
|
return;
|
|
4687
4965
|
}
|
|
4688
|
-
context.font = 11 *
|
|
4689
|
-
context.fillText(marker.toLocaleString(), _this.x(marker), height -
|
|
4966
|
+
context.font = 11 * dpr + "px Helvetica";
|
|
4967
|
+
context.fillText(marker.toLocaleString(), _this.x(marker), height - paddingBottom);
|
|
4690
4968
|
context.strokeStyle = "black";
|
|
4691
4969
|
context.lineWidth = 1;
|
|
4692
4970
|
context.beginPath();
|
|
4693
|
-
context.moveTo(_this.x(marker), height - 4);
|
|
4971
|
+
context.moveTo(_this.x(marker), height - 4 * dpr);
|
|
4694
4972
|
context.lineTo(_this.x(marker), height);
|
|
4695
4973
|
context.stroke();
|
|
4696
4974
|
});
|
|
@@ -5038,7 +5316,8 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5038
5316
|
*/
|
|
5039
5317
|
Heatmap.prototype.x = function (value) {
|
|
5040
5318
|
var width = this.width;
|
|
5041
|
-
|
|
5319
|
+
var dpr = window.devicePixelRatio;
|
|
5320
|
+
return remap(value, this.getMin("x"), this.getMax("x"), PADDING_AT_LEFT$1 * dpr, width);
|
|
5042
5321
|
};
|
|
5043
5322
|
/**
|
|
5044
5323
|
* Map a value (on the range y-min to y-max) onto canvas space to draw it along the y-axis.
|
|
@@ -5046,7 +5325,8 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5046
5325
|
*/
|
|
5047
5326
|
Heatmap.prototype.y = function (value) {
|
|
5048
5327
|
var height = this.height;
|
|
5049
|
-
|
|
5328
|
+
var dpr = window.devicePixelRatio;
|
|
5329
|
+
return remap(value, this.getMin("y"), this.getMax("y"), height - PADDING_AT_BOTTOM$1 * dpr, 0);
|
|
5050
5330
|
};
|
|
5051
5331
|
/** @hidden */
|
|
5052
5332
|
Heatmap.prototype.getKey = function (axis) {
|
|
@@ -5089,52 +5369,55 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5089
5369
|
Heatmap.prototype.drawMarkers = function () {
|
|
5090
5370
|
var _a = this, context = _a.context, width = _a.width, height = _a.height;
|
|
5091
5371
|
var _b = this.opts, from = _b.from, to = _b.to;
|
|
5372
|
+
var dpr = window.devicePixelRatio;
|
|
5373
|
+
var padLeft = PADDING_AT_LEFT$1 * dpr;
|
|
5374
|
+
var padBottom = PADDING_AT_BOTTOM$1 * dpr;
|
|
5092
5375
|
context.strokeStyle = "black";
|
|
5093
5376
|
context.lineWidth = 1;
|
|
5094
|
-
context.moveTo(
|
|
5095
|
-
context.lineTo(
|
|
5096
|
-
context.lineTo(width, height -
|
|
5377
|
+
context.moveTo(padLeft - 1, 0);
|
|
5378
|
+
context.lineTo(padLeft - 1, height - padBottom + 1);
|
|
5379
|
+
context.lineTo(width, height - padBottom + 1);
|
|
5097
5380
|
context.stroke();
|
|
5098
5381
|
context.lineWidth = 0;
|
|
5099
|
-
var gradient = context.createLinearGradient(10, 0,
|
|
5382
|
+
var gradient = context.createLinearGradient(10 * dpr, 0, padLeft - 10 * dpr, 0);
|
|
5100
5383
|
gradient.addColorStop(0, from);
|
|
5101
5384
|
gradient.addColorStop(1, to);
|
|
5102
5385
|
context.fillStyle = gradient;
|
|
5103
|
-
context.fillRect(10, height -
|
|
5386
|
+
context.fillRect(10 * dpr, height - padBottom + 20 * dpr, padLeft - 24 * dpr, 20 * dpr);
|
|
5104
5387
|
context.fillStyle = "black";
|
|
5105
5388
|
var step = (this.getMax("x") - this.getMin("x")) / this.getBuckets("x");
|
|
5106
5389
|
var originalStep = step;
|
|
5107
|
-
while (Math.abs(this.x(step) - this.x(0)) < 35)
|
|
5390
|
+
while (Math.abs(this.x(step) - this.x(0)) < 35 * dpr)
|
|
5108
5391
|
step *= 2;
|
|
5109
5392
|
for (var marker = this.getMin("x"); marker <= this.getMax("x"); marker += originalStep) {
|
|
5110
|
-
if (this.x(marker) + 10 > width)
|
|
5393
|
+
if (this.x(marker) + 10 * dpr > width)
|
|
5111
5394
|
continue;
|
|
5112
|
-
context.moveTo(this.x(marker), height -
|
|
5113
|
-
context.lineTo(this.x(marker), height -
|
|
5395
|
+
context.moveTo(this.x(marker), height - padBottom);
|
|
5396
|
+
context.lineTo(this.x(marker), height - padBottom + 10 * dpr);
|
|
5114
5397
|
context.stroke();
|
|
5115
5398
|
if (Math.abs(((marker - this.getMin("x")) / step) % 1) < 0.001 ||
|
|
5116
5399
|
Math.abs((((marker - this.getMin("x")) / step) % 1) - 1) < 0.001) {
|
|
5117
|
-
context.font = 12 *
|
|
5400
|
+
context.font = 12 * dpr + "px Helvetica";
|
|
5118
5401
|
context.textAlign = "center";
|
|
5119
|
-
context.fillText(marker.toLocaleString(), this.x(marker), height -
|
|
5402
|
+
context.fillText(marker.toLocaleString(), this.x(marker), height - padBottom + 24 * dpr);
|
|
5120
5403
|
}
|
|
5121
5404
|
}
|
|
5122
5405
|
step = (this.getMax("y") - this.getMin("y")) / this.getBuckets("y");
|
|
5123
5406
|
originalStep = step;
|
|
5124
|
-
while (Math.abs(this.y(step) - this.y(0)) < 20)
|
|
5407
|
+
while (Math.abs(this.y(step) - this.y(0)) < 20 * dpr)
|
|
5125
5408
|
step *= 2;
|
|
5126
5409
|
for (var marker = this.getMin("y"); marker <= this.getMax("y"); marker += originalStep) {
|
|
5127
|
-
if (this.y(marker) - 10 < 0)
|
|
5410
|
+
if (this.y(marker) - 10 * dpr < 0)
|
|
5128
5411
|
continue;
|
|
5129
|
-
context.moveTo(
|
|
5130
|
-
context.lineTo(
|
|
5412
|
+
context.moveTo(padLeft, this.y(marker));
|
|
5413
|
+
context.lineTo(padLeft - 10 * dpr, this.y(marker));
|
|
5131
5414
|
context.stroke();
|
|
5132
5415
|
if (Math.abs(((marker - this.getMin("y")) / step) % 1) < 0.001 ||
|
|
5133
5416
|
Math.abs((((marker - this.getMin("y")) / step) % 1) - 1) < 0.001) {
|
|
5134
|
-
context.font = 12 *
|
|
5417
|
+
context.font = 12 * dpr + "px Helvetica";
|
|
5135
5418
|
context.textAlign = "right";
|
|
5136
5419
|
context.textBaseline = "middle";
|
|
5137
|
-
context.fillText(marker.toLocaleString(),
|
|
5420
|
+
context.fillText(marker.toLocaleString(), padLeft - 14 * dpr, this.y(marker));
|
|
5138
5421
|
}
|
|
5139
5422
|
}
|
|
5140
5423
|
};
|
|
@@ -5142,6 +5425,8 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5142
5425
|
Heatmap.prototype.updateScale = function () {
|
|
5143
5426
|
var _a = this, context = _a.context, environment = _a.environment, height = _a.height;
|
|
5144
5427
|
var scale = this.opts.scale;
|
|
5428
|
+
var dpr = window.devicePixelRatio;
|
|
5429
|
+
var padLeft = PADDING_AT_LEFT$1 * dpr;
|
|
5145
5430
|
var max = scale === "relative" ? this.localMax : this.opts.max;
|
|
5146
5431
|
if (max === undefined) {
|
|
5147
5432
|
if (!this.lastUpdatedScale) {
|
|
@@ -5150,13 +5435,13 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5150
5435
|
max = environment.getAgents().length;
|
|
5151
5436
|
}
|
|
5152
5437
|
if (!this.lastUpdatedScale || +new Date() - +this.lastUpdatedScale > 250) {
|
|
5153
|
-
context.clearRect(0, height - 20,
|
|
5438
|
+
context.clearRect(0, height - 20 * dpr, padLeft, 20 * dpr);
|
|
5154
5439
|
context.fillStyle = "black";
|
|
5155
|
-
context.font = 12 *
|
|
5440
|
+
context.font = 12 * dpr + "px Helvetica";
|
|
5156
5441
|
context.textAlign = "center";
|
|
5157
5442
|
context.textBaseline = "bottom";
|
|
5158
|
-
context.fillText("0", 10, height - 5);
|
|
5159
|
-
context.fillText(max.toString(),
|
|
5443
|
+
context.fillText("0", 10 * dpr, height - 5 * dpr);
|
|
5444
|
+
context.fillText(max.toString(), padLeft - 16 * dpr, height - 5 * dpr);
|
|
5160
5445
|
this.lastUpdatedScale = new Date();
|
|
5161
5446
|
}
|
|
5162
5447
|
};
|
|
@@ -5164,6 +5449,9 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5164
5449
|
Heatmap.prototype.drawRectangles = function () {
|
|
5165
5450
|
var _a = this, canvas = _a.canvas, environment = _a.environment, width = _a.width, height = _a.height;
|
|
5166
5451
|
var _b = this.opts, scale = _b.scale, from = _b.from, to = _b.to;
|
|
5452
|
+
var dpr = window.devicePixelRatio;
|
|
5453
|
+
var padLeft = PADDING_AT_LEFT$1 * dpr;
|
|
5454
|
+
var padBottom = PADDING_AT_BOTTOM$1 * dpr;
|
|
5167
5455
|
var context = canvas.getContext("2d");
|
|
5168
5456
|
var xBuckets = this.getBuckets("x");
|
|
5169
5457
|
var yBuckets = this.getBuckets("y");
|
|
@@ -5172,9 +5460,9 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5172
5460
|
max = environment.getAgents().length;
|
|
5173
5461
|
// clear background by drawing background rectangle
|
|
5174
5462
|
context.fillStyle = from;
|
|
5175
|
-
context.fillRect(
|
|
5176
|
-
var w = width / xBuckets;
|
|
5177
|
-
var h = height / yBuckets;
|
|
5463
|
+
context.fillRect(padLeft, 0, width - padLeft, height - padBottom);
|
|
5464
|
+
var w = (width - padLeft) / xBuckets;
|
|
5465
|
+
var h = (height - padBottom) / yBuckets;
|
|
5178
5466
|
for (var row = 0; row < yBuckets; row++) {
|
|
5179
5467
|
for (var column = 0; column < xBuckets; column++) {
|
|
5180
5468
|
var index = row * xBuckets + column;
|
|
@@ -5182,7 +5470,7 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5182
5470
|
var a = clamp(remap(this.buckets[index], 0, max, 0, 1), 0, 1);
|
|
5183
5471
|
context.fillStyle = to;
|
|
5184
5472
|
context.globalAlpha = a;
|
|
5185
|
-
context.fillRect(this.x(remap(column, 0, xBuckets, this.getMin("x"), this.getMax("x"))), this.y(remap(row, -1, yBuckets - 1, this.getMin("y"), this.getMax("y"))),
|
|
5473
|
+
context.fillRect(this.x(remap(column, 0, xBuckets, this.getMin("x"), this.getMax("x"))), this.y(remap(row, -1, yBuckets - 1, this.getMin("y"), this.getMax("y"))), w, h);
|
|
5186
5474
|
}
|
|
5187
5475
|
}
|
|
5188
5476
|
context.globalAlpha = 1;
|
|
@@ -5238,6 +5526,6 @@ var Heatmap = /** @class */ (function (_super) {
|
|
|
5238
5526
|
/**
|
|
5239
5527
|
* The current version of the Flocc library.
|
|
5240
5528
|
*/
|
|
5241
|
-
var version = "0.5.
|
|
5529
|
+
var version = "0.5.22";
|
|
5242
5530
|
|
|
5243
5531
|
export { ASCIIRenderer, Agent, CanvasRenderer, Colors, Environment, GridEnvironment, Heatmap, Histogram, KDTree, LineChartRenderer, Network, NumArray, Rule, TableRenderer, Terrain, version as VERSION, Vector, utils };
|