UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

119 lines 4.01 kB
import { Glyph, GlyphView } from "./glyph"; import { generic_line_vector_legend } from "./utils"; import { Selection } from "../selections/selection"; import { LineVector } from "../../core/property_mixins"; import * as uniforms from "../../core/uniforms"; import { map } from "../../core/util/arrayable"; import { range } from "../../core/util/array"; import * as p from "../../core/properties"; const { abs, max } = Math; const UNUSED = 0; export class VSpanView extends GlyphView { static __name__ = "VSpanView"; after_visuals() { super.after_visuals(); this.max_line_width = uniforms.max(this.line_width); } _index_data(index) { for (const x_i of this.x) { index.add_point(x_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_sx) { const sx = map(this.sx, (xi) => round(xi)); this._define_attr("sx", sx); } } scenterxy(i) { const { vcenter } = this.renderer.plot_view.frame.bbox; return [this.sx[i], vcenter]; } _paint(ctx, indices, data) { const { sx } = { ...this, ...data }; const { top, bottom } = this.renderer.plot_view.frame.bbox; for (const i of indices) { const sx_i = sx[i]; if (!isFinite(sx_i)) { continue; } ctx.beginPath(); ctx.moveTo(sx_i, top); ctx.lineTo(sx_i, bottom); this.visuals.line.apply(ctx, i); } } _get_candidates(sx0, sx1) { const { max_line_width } = this; const [x0, x1] = this.renderer.xscale.r_invert(sx0 - max_line_width, (sx1 ?? sx0) + max_line_width); return this.index.indices({ x0, x1, y0: 0, y1: 0 }); } _find_spans(candidates, fn) { const { sx, line_width } = this; const indices = []; for (const i of candidates) { const sx_i = sx[i]; const line_width_i = line_width.get(i); if (fn(sx_i, line_width_i)) { indices.push(i); } } return indices; } _hit_point(geometry) { const { sx: gsx } = geometry; const candidates = this._get_candidates(gsx); const indices = this._find_spans(candidates, (sx, line_width) => { return abs(sx - gsx) <= max(line_width, 2 /*px*/); }); return new Selection({ indices }); } _hit_span(geometry) { const indices = (() => { if (geometry.direction == "h") { return range(0, this.data_size); } else { const { sx: gsx } = geometry; const candidates = this._get_candidates(gsx); return this._find_spans(candidates, (sx, line_width) => { return abs(sx - gsx) <= max(line_width / 2, 2 /*px*/); }); } })(); 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_spans(candidates, (sx, line_width) => { return gsx0 - line_width / 2 <= sx && sx <= gsx1 + line_width / 2; }); })(); return new Selection({ indices }); } draw_legend_for_index(ctx, bbox, index) { generic_line_vector_legend(this.visuals, ctx, bbox, index); } } export class VSpan extends Glyph { static __name__ = "VSpan"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = VSpanView; this.mixins([LineVector]); this.define(() => ({ x: [p.XCoordinateSpec, { field: "x" }], })); } } //# sourceMappingURL=vspan.js.map