UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

88 lines 3.71 kB
import { GestureTool, GestureToolView } from "./gesture_tool"; import { Modifiers, satisfies_modifiers, print_modifiers } from "./common"; import { Dimension } from "../../../core/enums"; import { clamp } from "../../../core/util/math"; import { tool_icon_wheel_pan } from "../../../styles/icons.css"; import { update_ranges } from "./pan_tool"; export class WheelPanToolView extends GestureToolView { static __name__ = "WheelPanToolView"; _scroll(ev) { const { modifiers } = this.model; if (!satisfies_modifiers(modifiers, ev.modifiers)) { this.plot_view.notify_about(`use ${print_modifiers(modifiers)} + scroll to pan`); return false; } // clamp the magnitude of factor, if it is > 1 bad things happen const factor = clamp(this.model.speed * ev.delta, -0.9, 0.9); this._update_ranges(factor); return true; } _update_ranges(factor) { const { frame } = this.plot_view; const hr = frame.bbox.h_range; const vr = frame.bbox.v_range; const [sx_low, sx_high] = [hr.start, hr.end]; const [sy_low, sy_high] = [vr.start, vr.end]; let xrs; let yrs; const { x_scales, y_scales } = frame; // Here we are a bit careful to only update the range info for dimensions that // are "in play". This is to avoid superfluous noise updates to dataranges that // would cause windowed auto-ranging to turn off. switch (this.model.dimension) { case "height": { const sy_range = Math.abs(sy_high - sy_low); const sy0 = sy_low - sy_range * factor; const sy1 = sy_high - sy_range * factor; xrs = new Map(); yrs = update_ranges(y_scales, sy0, sy1); break; } case "width": { const sx_range = Math.abs(sx_high - sx_low); const sx0 = sx_low - sx_range * factor; const sx1 = sx_high - sx_range * factor; xrs = update_ranges(x_scales, sx0, sx1); yrs = new Map(); break; } } // OK this sucks we can't set factor independently in each direction. It is used // for GMap plots, and GMap plots always preserve aspect, so effective the value // of 'dimensions' is ignored. const pan_info = { xrs, yrs, factor }; this.plot_view.state.push("wheel_pan", { range: pan_info }); this.plot_view.update_range(pan_info, { scrolling: true }); this.model.document?.interactive_start(this.plot_view.model, () => this.plot_view.trigger_ranges_update_event()); } } export class WheelPanTool extends GestureTool { static __name__ = "WheelPanTool"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = WheelPanToolView; this.define(() => ({ dimension: [Dimension, "width"], modifiers: [Modifiers, {}], })); this.internal(({ Float }) => ({ speed: [Float, 1 / 1000], })); this.register_alias("xwheel_pan", () => new WheelPanTool({ dimension: "width" })); this.register_alias("ywheel_pan", () => new WheelPanTool({ dimension: "height" })); } tool_name = "Wheel Pan"; tool_icon = tool_icon_wheel_pan; event_type = "scroll"; default_order = 12; get tooltip() { return this._get_dim_tooltip(this.dimension); } supports_auto() { const { alt, ctrl, shift } = this.modifiers; return alt != null || ctrl != null || shift != null; } } //# sourceMappingURL=wheel_pan_tool.js.map