UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

119 lines 4.44 kB
import { CenterRotatable, CenterRotatableView } from "./center_rotatable"; import { inherit } from "./glyph"; import * as hittest from "../../core/hittest"; import { to_screen } from "../../core/types"; import { Selection } from "../selections/selection"; import * as p from "../../core/properties"; export class EllipseView extends CenterRotatableView { static __name__ = "EllipseView"; _map_data() { this._define_or_inherit_attr("swidth", () => { if (this.model.properties.width.units == "data") { if (this.inherited_x && this.inherited_width) { return inherit; } else { return this.sdist(this.renderer.xscale, this.x, this.width, "center"); } } else { return this.inherited_width ? inherit : to_screen(this.width); } }); this._define_or_inherit_attr("sheight", () => { if (this.model.properties.height.units == "data") { if (this.inherited_y && this.inherited_height) { return inherit; } else { return this.sdist(this.renderer.yscale, this.y, this.height, "center"); } } else { return this.inherited_height ? inherit : to_screen(this.height); } }); } _paint(ctx, indices, data) { const { sx, sy, swidth, sheight, angle } = { ...this, ...data }; for (const i of indices) { const sx_i = sx[i]; const sy_i = sy[i]; const swidth_i = swidth[i]; const sheight_i = sheight[i]; const angle_i = angle.get(i); if (!isFinite(sx_i + sy_i + swidth_i + sheight_i + angle_i)) { continue; } ctx.beginPath(); ctx.ellipse(sx_i, sy_i, swidth_i / 2, sheight_i / 2, angle_i, 0, 2 * Math.PI); this.visuals.fill.apply(ctx, i); this.visuals.hatch.apply(ctx, i); this.visuals.line.apply(ctx, i); } } _hit_point(geometry) { let x0, x1, y0, y1, cond, sx0, sx1, sy0, sy1; const { sx, sy } = geometry; const x = this.renderer.xscale.invert(sx); const y = this.renderer.yscale.invert(sy); if (this.model.properties.width.units == "data") { x0 = x - this.max_width; x1 = x + this.max_width; } else { sx0 = sx - this.max_width; sx1 = sx + this.max_width; [x0, x1] = this.renderer.xscale.r_invert(sx0, sx1); } if (this.model.properties.height.units == "data") { y0 = y - this.max_height; y1 = y + this.max_height; } else { sy0 = sy - this.max_height; sy1 = sy + this.max_height; [y0, y1] = this.renderer.yscale.r_invert(sy0, sy1); } const candidates = this.index.indices({ x0, x1, y0, y1 }); const indices = []; for (const i of candidates) { cond = hittest.point_in_ellipse(sx, sy, this.angle.get(i), this.sheight[i] / 2, this.swidth[i] / 2, this.sx[i], this.sy[i]); if (cond) { indices.push(i); } } return new Selection({ indices }); } draw_legend_for_index(ctx, { x0, y0, x1, y1 }, index) { const n = index + 1; const sx = new Array(n); sx[index] = (x0 + x1) / 2; const sy = new Array(n); sy[index] = (y0 + y1) / 2; const scale = this.swidth[index] / this.sheight[index]; const d = Math.min(Math.abs(x1 - x0), Math.abs(y1 - y0)) * 0.8; const swidth = new Array(n); const sheight = new Array(n); if (scale > 1) { swidth[index] = d; sheight[index] = d / scale; } else { swidth[index] = d * scale; sheight[index] = d; } const angle = new p.UniformScalar(0, n); // don't attempt to match glyph angle this._paint(ctx, [index], { sx, sy, swidth, sheight, angle }); } } export class Ellipse extends CenterRotatable { static __name__ = "Ellipse"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = EllipseView; } } //# sourceMappingURL=ellipse.js.map