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