@bokeh/bokehjs
Version:
Interactive, novel data visualization
119 lines • 4.01 kB
JavaScript
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