UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

172 lines 5.92 kB
import { Glyph, GlyphView } from "./glyph"; import { generic_area_vector_legend } from "./utils"; import { Selection } from "../selections/selection"; import { LineVector, FillVector, HatchVector } from "../../core/property_mixins"; import { ScreenArray } from "../../core/types"; import { map } from "../../core/util/arrayable"; import * as iter from "../../core/util/iterator"; import { range } from "../../core/util/array"; import * as p from "../../core/properties"; const UNUSED = 0; export class VStripView extends GlyphView { static __name__ = "VStripView"; async lazy_initialize() { await super.lazy_initialize(); const { webgl } = this.renderer.plot_view.canvas_view; if (webgl != null && webgl.regl_wrapper.has_webgl) { const { LRTBGL } = await import("./webgl/lrtb"); this.glglyph = new LRTBGL(webgl.regl_wrapper, this); } } get sleft() { return this.sx0; } get sright() { return this.sx1; } get stop() { const { top } = this.renderer.plot_view.frame.bbox; const n = this.data_size; const stop = new ScreenArray(n); stop.fill(top); return stop; } get sbottom() { const { bottom } = this.renderer.plot_view.frame.bbox; const n = this.data_size; const sbottom = new ScreenArray(n); sbottom.fill(bottom); return sbottom; } _set_data(indices) { super._set_data(indices); const { abs } = Math; const { max, map, zip } = iter; const { x0, x1 } = this; if (this.inherited_x0 && this.inherited_x1) { this._inherit_attr("max_width"); } else { const max_width = max(map(zip(x0, x1), ([x0_i, x1_i]) => abs(x0_i - x1_i))); this._define_attr("max_width", max_width); } } _index_data(index) { const { x0, x1, data_size } = this; for (let i = 0; i < data_size; i++) { const x0_i = x0[i]; const x1_i = x1[i]; index.add_rect(x0_i, UNUSED, x1_i, UNUSED); } } _bounds(bounds) { const { x0, x1 } = bounds; return { x0, x1, y0: NaN, y1: NaN }; } _map_data() { super._map_data(); const { round } = Math; if (!this.inherited_sx0) { const sx0 = map(this.sx0, (xi) => round(xi)); this._define_attr("sx0", sx0); } if (!this.inherited_sx1) { const sx1 = map(this.sx1, (xi) => round(xi)); this._define_attr("sx1", sx1); } } scenterxy(i) { const { vcenter } = this.renderer.plot_view.frame.bbox; return [(this.sx0[i] + this.sx1[i]) / 2, vcenter]; } _paint(ctx, indices, data) { const { sx0, sx1 } = { ...this, ...data }; const { top, bottom, height } = this.renderer.plot_view.frame.bbox; for (const i of indices) { const sx0_i = sx0[i]; const sx1_i = sx1[i]; if (!isFinite(sx0_i + sx1_i)) { continue; } ctx.beginPath(); ctx.rect(sx0_i, top, sx1_i - sx0_i, height); this.visuals.fill.apply(ctx, i); this.visuals.hatch.apply(ctx, i); ctx.beginPath(); ctx.moveTo(sx0_i, top); ctx.lineTo(sx0_i, bottom); ctx.moveTo(sx1_i, top); ctx.lineTo(sx1_i, bottom); this.visuals.line.apply(ctx, i); } } _get_candidates(sx0, sx1) { const { max_width } = this; const [dx0, dx1] = this.renderer.xscale.r_invert(sx0, sx1 ?? sx0); const x0 = dx0 - max_width; const x1 = dx1 + max_width; return this.index.indices({ x0, x1, y0: 0, y1: 0 }); } _find_strips(candidates, fn) { function contains(sx0, sx1) { return sx0 <= sx1 ? fn(sx0, sx1) : fn(sx1, sx0); } const { sx0, sx1 } = this; const indices = []; for (const i of candidates) { const sx0_i = sx0[i]; const sx1_i = sx1[i]; if (contains(sx0_i, sx1_i)) { indices.push(i); } } return indices; } _hit_point(geometry) { const { sx } = geometry; const candidates = this._get_candidates(sx); const indices = this._find_strips(candidates, (sx0, sx1) => sx0 <= sx && sx <= sx1); return new Selection({ indices }); } _hit_span(geometry) { const indices = (() => { if (geometry.direction == "h") { return range(0, this.data_size); } else { const { sx } = geometry; const candidates = this._get_candidates(sx); return this._find_strips(candidates, (sx0, sx1) => sx0 <= sx && sx <= sx1); } })(); return new Selection({ indices }); } _hit_rect(geometry) { const indices = (() => { const { sx0: gsx0, sx1: gsx1 } = geometry; const candidates = this._get_candidates(gsx0, gsx1); return this._find_strips(candidates, (sx0, sx1) => { return gsx0 <= sx0 && sx0 <= gsx1 && gsx0 <= sx1 && sx1 <= gsx1; }); })(); return new Selection({ indices }); } draw_legend_for_index(ctx, bbox, index) { generic_area_vector_legend(this.visuals, ctx, bbox, index); } } export class VStrip extends Glyph { static __name__ = "VStrip"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = VStripView; this.mixins([LineVector, FillVector, HatchVector]); this.define(() => ({ x0: [p.XCoordinateSpec, { field: "x0" }], x1: [p.XCoordinateSpec, { field: "x1" }], })); } } //# sourceMappingURL=vstrip.js.map