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 HStripView extends GlyphView { static __name__ = "HStripView"; 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() { const { left } = this.renderer.plot_view.frame.bbox; const n = this.data_size; const sleft = new ScreenArray(n); sleft.fill(left); return sleft; } get sright() { const { right } = this.renderer.plot_view.frame.bbox; const n = this.data_size; const sright = new ScreenArray(n); sright.fill(right); return sright; } get stop() { return this.sy0; } get sbottom() { return this.sy1; } _set_data(indices) { super._set_data(indices); const { abs } = Math; const { max, map, zip } = iter; const { y0, y1 } = this; if (this.inherited_y0 && this.inherited_y1) { this._inherit_attr("max_height"); } else { const max_height = max(map(zip(y0, y1), ([y0_i, y1_i]) => abs(y0_i - y1_i))); this._define_attr("max_height", max_height); } } _index_data(index) { const { y0, y1, data_size } = this; for (let i = 0; i < data_size; i++) { const y0_i = y0[i]; const y1_i = y1[i]; index.add_rect(UNUSED, y0_i, UNUSED, y1_i); } } _bounds(bounds) { const { y0, y1 } = bounds; return { x0: NaN, x1: NaN, y0, y1 }; } _map_data() { super._map_data(); const { round } = Math; if (!this.inherited_sy0) { const sy0 = map(this.sy0, (yi) => round(yi)); this._define_attr("sy0", sy0); } if (!this.inherited_sy1) { const sy1 = map(this.sy1, (yi) => round(yi)); this._define_attr("sy1", sy1); } } scenterxy(i) { const { hcenter } = this.renderer.plot_view.frame.bbox; return [hcenter, (this.sy0[i] + this.sy1[i]) / 2]; } _paint(ctx, indices, data) { const { sy0, sy1 } = { ...this, ...data }; const { left, right, width } = this.renderer.plot_view.frame.bbox; for (const i of indices) { const sy0_i = sy0[i]; const sy1_i = sy1[i]; if (!isFinite(sy0_i + sy1_i)) { continue; } ctx.beginPath(); ctx.rect(left, sy0_i, width, sy1_i - sy0_i); this.visuals.fill.apply(ctx, i); this.visuals.hatch.apply(ctx, i); ctx.beginPath(); ctx.moveTo(left, sy0_i); ctx.lineTo(right, sy0_i); ctx.moveTo(left, sy1_i); ctx.lineTo(right, sy1_i); this.visuals.line.apply(ctx, i); } } _get_candidates(sy0, sy1) { const { max_height } = this; const [dy0, dy1] = this.renderer.yscale.r_invert(sy0, sy1 ?? sy0); const y0 = dy0 - max_height; const y1 = dy1 + max_height; return this.index.indices({ x0: 0, x1: 0, y0, y1 }); } _find_strips(candidates, fn) { function contains(sy0, sy1) { return sy0 <= sy1 ? fn(sy0, sy1) : fn(sy1, sy0); } const { sy0, sy1 } = this; const indices = []; for (const i of candidates) { const sy0_i = sy0[i]; const sy1_i = sy1[i]; if (contains(sy0_i, sy1_i)) { indices.push(i); } } return indices; } _hit_point(geometry) { const { sy } = geometry; const candidates = this._get_candidates(sy); const indices = this._find_strips(candidates, (sy0, sy1) => sy0 <= sy && sy <= sy1); return new Selection({ indices }); } _hit_span(geometry) { const indices = (() => { if (geometry.direction == "v") { return range(0, this.data_size); } else { const { sy } = geometry; const candidates = this._get_candidates(sy); return this._find_strips(candidates, (sy0, sy1) => sy0 <= sy && sy <= sy1); } })(); return new Selection({ indices }); } _hit_rect(geometry) { const indices = (() => { const { sy0: gsy0, sy1: gsy1 } = geometry; const candidates = this._get_candidates(gsy0, gsy1); return this._find_strips(candidates, (sy0, sy1) => { return gsy0 <= sy0 && sy0 <= gsy1 && gsy0 <= sy1 && sy1 <= gsy1; }); })(); return new Selection({ indices }); } draw_legend_for_index(ctx, bbox, index) { generic_area_vector_legend(this.visuals, ctx, bbox, index); } } export class HStrip extends Glyph { static __name__ = "HStrip"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = HStripView; this.mixins([LineVector, FillVector, HatchVector]); this.define(() => ({ y0: [p.YCoordinateSpec, { field: "y0" }], y1: [p.YCoordinateSpec, { field: "y1" }], })); } } //# sourceMappingURL=hstrip.js.map