Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,16 @@ Generated from `dist/` after the package build.
| tooltip plugin entry | `dist/plugins/tooltip.js` | 0.1 KiB |
| crosshair plugin entry | `dist/plugins/crosshair.js` | 0.1 KiB |
| flamegraph plugin | `dist/plugins/flamegraph.js` | 20.7 KiB |
| shared Chart chunk | `dist/Chart-DstwTTQs.js` | 57.2 KiB |
| shared Chart chunk | `dist/Chart-DniudEGP.js` | 57.2 KiB |
| shared streaming data chunk | `dist/UniformRingBuffer-DVJiaja6.js` | 44.0 KiB |
| shared OhlcDataset chunk | `dist/OhlcDataset-BzaK030U.js` | 8.6 KiB |
| shared AxisController chunk | `dist/AxisController-B5zX7JBz.js` | 13.8 KiB |
| shared WebGL2Backend chunk | `dist/WebGL2Backend-DDGRc0UJ.js` | 22.0 KiB |
| shared LinkedChartsCore chunk | `dist/LinkedChartsCore-zxImWpgT.js` | 2.1 KiB |
| shared LinkedChartsCore chunk | `dist/LinkedChartsCore-BLcR3ldB.js` | 2.1 KiB |
| lazy screenshot chunk | `dist/screenshot-CljRIqNW.js` | 3.5 KiB |
| shared OverlayUtils chunk | `dist/OverlayUtils-YP9KSKL4.js` | 3.1 KiB |
| shared Tooltip chunk | `dist/Tooltip-a9NkZoPg.js` | 5.8 KiB |
| shared Crosshair chunk | `dist/Crosshair-C426MhNr.js` | 9.9 KiB |
| shared Crosshair chunk | `dist/Crosshair-Dk4xAusn.js` | 10.3 KiB |

### All public exports

Expand Down
6 changes: 3 additions & 3 deletions docs/api-reference.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions src/ui/Chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1383,9 +1383,8 @@ export class Chart implements ChartPluginContext {
this.applyAutoFitYPolicy();

try {
const [r, g, b, a] = this.resolvedTheme.backgroundColor;
this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);
this.renderer.clear(r, g, b, a);
this.renderer.clear(0, 0, 0, 0);

const viewport = this.camera.viewport;
this.currentXOrigin = viewport.xMin;
Expand Down
1 change: 1 addition & 0 deletions src/ui/ChartLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export class ChartLayout implements ChartLayoutElements {

this.canvas.style.position = "absolute";
this.canvas.style.inset = "0";
this.canvas.style.zIndex = "1";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep inside axis labels above the canvas

When an axis is configured with position: "inside", AxisOverlay appends its tick-label divs directly to chart.plotElement without assigning a z-index, so adding zIndex = "1" to the canvas puts the WebGL canvas above those labels in the plot stacking order. In that configuration the inside tick labels are now painted underneath grid/series pixels instead of overlaying the chart as before; give the inside-axis labels a z-index above the canvas or avoid raising the canvas above existing plot overlays.

Useful? React with 👍 / 👎.

this.canvas.style.display = "block";
this.canvas.style.width = "100%";
this.canvas.style.height = "100%";
Expand Down
39 changes: 28 additions & 11 deletions src/ui/Crosshair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ function createXRangeHighlight(item: ChartPickItem, chart: Chart, strokeColor: s
return marker;
}

function createCrosshairLayer(className: string, zIndex: number): HTMLDivElement {
const layer = document.createElement("div");
layer.className = className;
layer.style.position = "absolute";
layer.style.inset = "0";
layer.style.display = "none";
layer.style.pointerEvents = "none";
layer.style.zIndex = String(zIndex);
return layer;
}

function renderDefaultLabel(
position: CrosshairPosition,
container: HTMLElement,
Expand Down Expand Up @@ -189,6 +200,8 @@ export function crosshairPlugin(options: CrosshairPluginOptions = {}): Crosshair
const rulerModifier = options.rulerModifier ?? "none";
let chartRef: ChartPluginContext | null = null;
let root: HTMLDivElement | null = null;
let lineLayer: HTMLDivElement | null = null;
let overlayLayer: HTMLDivElement | null = null;
let vertical: HTMLDivElement | null = null;
let horizontal: HTMLDivElement | null = null;
let markerLayer: HTMLDivElement | null = null;
Expand All @@ -208,7 +221,8 @@ export function crosshairPlugin(options: CrosshairPluginOptions = {}): Crosshair
const measureEndSubscribers = new Set<(measurement: RulerMeasurement) => void>();

const setVisible = (visible: boolean): void => {
if (root) root.style.display = visible ? "block" : "none";
if (lineLayer) lineLayer.style.display = visible ? "block" : "none";
if (overlayLayer) overlayLayer.style.display = visible ? "block" : "none";
};

const emitMove = (position: CrosshairPosition | null): void => {
Expand Down Expand Up @@ -271,7 +285,7 @@ export function crosshairPlugin(options: CrosshairPluginOptions = {}): Crosshair

const renderPosition = (position: CrosshairPosition | null): void => {
renderMarkers(position);
if (!position || !root || !vertical || !horizontal || !label) {
if (!position || !lineLayer || !overlayLayer || !vertical || !horizontal || !label) {
setVisible(false);
return;
}
Expand Down Expand Up @@ -354,11 +368,11 @@ export function crosshairPlugin(options: CrosshairPluginOptions = {}): Crosshair

root = document.createElement("div");
root.className = "blazeplot-crosshair";
root.style.position = "absolute";
root.style.inset = "0";
root.style.display = "none";
root.style.display = "contents";
root.style.pointerEvents = "none";
root.style.zIndex = String(options.zIndex ?? 22);

lineLayer = createCrosshairLayer("blazeplot-crosshair-lines", options.zIndex ?? 0);
overlayLayer = createCrosshairLayer("blazeplot-crosshair-overlay", options.zIndex ?? 22);

vertical = document.createElement("div");
vertical.style.position = "absolute";
Expand Down Expand Up @@ -407,11 +421,12 @@ export function crosshairPlugin(options: CrosshairPluginOptions = {}): Crosshair
if (dash) rulerLine.setAttribute("stroke-dasharray", dash);
rulerSvg.appendChild(rulerLine);

root.appendChild(vertical);
root.appendChild(horizontal);
root.appendChild(rulerSvg);
root.appendChild(markerLayer);
root.appendChild(label);
lineLayer.appendChild(vertical);
lineLayer.appendChild(horizontal);
lineLayer.appendChild(rulerSvg);
overlayLayer.appendChild(markerLayer);
overlayLayer.appendChild(label);
root.append(lineLayer, overlayLayer);
chart.plotElement.appendChild(root);

if (options.group) {
Expand Down Expand Up @@ -507,6 +522,8 @@ export function crosshairPlugin(options: CrosshairPluginOptions = {}): Crosshair
}
root?.remove();
root = null;
lineLayer = null;
overlayLayer = null;
vertical = null;
horizontal = null;
markerLayer = null;
Expand Down
50 changes: 36 additions & 14 deletions website/src/site/previews-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type ReactiveController, type ReactiveControllerHost } from "lit";
import { Chart, OhlcRingBuffer, ServerSampledDataset, StaticDataset, UniformRingBuffer, type ChartFrameStats, type ChartPickGroup, type ChartPickMode, type ChartTheme, type SeriesStore, type ViewportPolicy } from "../../../src/index.ts";
import { Chart, OhlcRingBuffer, ServerSampledDataset, StaticDataset, UniformRingBuffer, type ChartFrameStats, type ChartPickGroup, type ChartPickMode, type ChartTheme, type HistogramBin, type HistogramResult, type SeriesStore, type ViewportPolicy } from "../../../src/index.ts";
import { createLinkedCharts } from "../../../src/linked.ts";
import { annotationsPlugin } from "../../../src/plugins/annotations.ts";
import { crosshairPlugin } from "../../../src/plugins/crosshair.ts";
Expand Down Expand Up @@ -589,35 +589,57 @@ export class PreviewChartsController implements ReactiveController {
}

private mountHistogramPreview(target: HTMLElement): void {
const values = new Float64Array(18_000);
for (let index = 0; index < values.length; index++) {
const phase = index / values.length;
const cluster = index % 9;
const baseline = cluster < 5 ? 70 : cluster < 8 ? 115 : 165;
const seasonal = Math.sin(phase * Math.PI * 10) * 8 + Math.sin(index * 0.017) * 5;
const jitter = (Math.sin(index * 12.9898) * 43758.5453 % 1) * 10;
values[index] = baseline + seasonal + jitter + (index % 997 === 0 ? 85 : 0);
const binCount = 1_000_000;
const initialBins = 1_000;
const x = new Float64Array(binCount);
const y = new Float32Array(binCount);
const bins = new Array<HistogramBin>(binCount);
let total = 0;
let initialYMax = 0;
for (let index = 0; index < binCount; index++) {
const wave = 80
+ Math.sin(index * 0.00031) * 34
+ Math.sin(index * 0.017) * 18
+ Math.sin(index * 0.071) * 9;
const burst = index % 12_001 < 120 ? 70 * (1 - (index % 12_001) / 120) : 0;
const count = Math.max(1, Math.round(wave + burst + (index % 997 === 0 ? 90 : 0)));
x[index] = index + 0.5;
y[index] = count;
bins[index] = { x: index + 0.5, y: count, xStart: index, xEnd: index + 1, count, index };
total += count;
if (index < initialBins && count > initialYMax) initialYMax = count;
}
const histogram: HistogramResult = {
bins,
x,
y,
binWidth: 1,
total,
underflow: 0,
overflow: 0,
invalid: 0,
min: 0,
max: binCount,
};

const chart = new Chart(target, {
axes: { x: { position: "outside", title: "latency (ms)" }, y: { position: "outside", title: "density" } },
axes: { x: { position: "outside", title: "bin" }, y: { position: "outside", title: "count" } },
grid: true,
hover: { mode: "nearest-x", group: "none" },
plugins: [
interactionsPlugin({ wheelZoom: true, shiftDragPan: true, boxZoom: true, doubleClickReset: true }),
crosshairPlugin({ snap: "nearest-x", label: true, labelPlacement: "top-right", formatX: (value) => `${value.toFixed(0)} ms`, formatY: (value) => value.toFixed(4) }),
crosshairPlugin({ snap: "nearest-x", label: true, labelPlacement: "top-right", formatX: (value) => `bin ${Math.floor(value).toLocaleString()}`, formatY: (value) => value.toFixed(0) }),
legendPlugin({ position: "top-left" }),
],
accessibility: { label: "Histogram preview" },
});
this.previewCharts.push(chart);

chart.addHistogram({ values, binSize: 5, min: 40, max: 260, normalize: "density", name: "Latency density", downsample: "none" }, {
chart.addHistogram({ histogram, name: "1M bins" }, {
color: [0.988, 0.29, 0.02, 0.95],
baseline: 0,
});
chart.fitToData({ includeZero: true, padding: { y: 0.12 } });
chart.setViewport({ ...chart.getViewport(), xMin: 40, xMax: 260, yMin: 0 });
chart.setViewport({ xMin: 0, xMax: initialBins, yMin: 0, yMax: initialYMax * 1.12 });
chart.start();
}

Expand Down
Loading