@bokeh/bokehjs
Version:
Interactive, novel data visualization
128 lines • 3.85 kB
JavaScript
import { SVGRenderingContext2D } from "./svg";
import { BBox } from "./bbox";
import { div, canvas } from "../dom";
export class CanvasLayer {
backend;
hidpi;
static __name__ = "CanvasLayer";
_canvas;
get canvas() {
return this._canvas;
}
_ctx;
get ctx() {
return this._ctx;
}
_el;
get el() {
return this._el;
}
_pixel_ratio = 1;
get pixel_ratio() {
return this._pixel_ratio;
}
bbox = new BBox();
constructor(backend, hidpi) {
this.backend = backend;
this.hidpi = hidpi;
switch (backend) {
case "webgl":
case "canvas": {
this._el = this._canvas = canvas({ class: "bk-layer" });
const ctx = this.canvas.getContext("2d");
if (ctx == null) {
throw new Error("unable to obtain 2D rendering context");
}
this._ctx = ctx;
if (hidpi) {
this._pixel_ratio = devicePixelRatio;
}
break;
}
case "svg": {
const ctx = new SVGRenderingContext2D();
this._ctx = ctx;
this._canvas = ctx.get_svg();
this._el = div({ class: "bk-layer" });
const shadow_el = this._el.attachShadow({ mode: "open" });
shadow_el.appendChild(this._canvas);
break;
}
}
Object.assign(this._ctx, {
layer: this,
rect_bbox(bbox) {
const { x, y, width, height } = bbox;
this.rect(x, y, width, height);
},
});
}
get pixel_ratio_changed() {
if (this.hidpi && (this.backend == "canvas" || this.backend == "webgl")) {
return this.pixel_ratio != devicePixelRatio;
}
else {
return false;
}
}
resize(width, height) {
const size_changed = this.bbox.width != width || this.bbox.height != height;
const { pixel_ratio_changed } = this;
if (!size_changed && !pixel_ratio_changed) {
return;
}
if (pixel_ratio_changed) {
this._pixel_ratio = devicePixelRatio;
}
this.bbox = new BBox({ left: 0, top: 0, width, height });
const { target } = this;
target.width = width * this.pixel_ratio;
target.height = height * this.pixel_ratio;
}
get target() {
return this._ctx instanceof SVGRenderingContext2D ? this._ctx : this.canvas;
}
undo_transform(fn) {
const { ctx } = this;
const current_transform = ctx.getTransform();
ctx.resetTransform();
try {
fn(ctx);
}
finally {
ctx.setTransform(current_transform);
}
}
prepare() {
const { ctx, hidpi, pixel_ratio } = this;
ctx.save();
if (hidpi) {
ctx.scale(pixel_ratio, pixel_ratio);
ctx.translate(0.5, 0.5);
}
this.clear();
return ctx;
}
clear() {
const { x, y, width, height } = this.bbox;
this.ctx.clearRect(x, y, width, height);
}
finish() {
this.ctx.restore();
}
to_blob() {
const { _canvas } = this;
if (_canvas instanceof HTMLCanvasElement) {
return new Promise((resolve, reject) => {
_canvas.toBlob((blob) => blob != null ? resolve(blob) : reject(), "image/png");
});
}
else {
const ctx = this._ctx;
const svg = ctx.get_serialized_svg(true);
const blob = new Blob([svg], { type: "image/svg+xml" });
return Promise.resolve(blob);
}
}
}
//# sourceMappingURL=canvas.js.map