UNPKG

billboard.js

Version:

Re-usable easy interface JavaScript chart library, based on D3 v4+

192 lines (173 loc) 5.56 kB
/** * Copyright (c) 2017 ~ present NAVER Corp. * billboard.js project is licensed under the MIT license */ import {$SHAPE} from "../../config/classes"; import {isDefined} from "../../module/util"; /** * Define tooltip * @ignore */ const tooltip = { /** * Show tooltip * @function tooltip․show * @instance * @memberof Chart * @param {object} args The object can consist with following members:<br> * * | Key | Type | Description | * | --- | --- | --- | * | index | Number | Determine focus by index | * | x | Number &vert; Date | Determine focus by x Axis index | * | mouse | Array | Determine x and y coordinate value relative the targeted '.bb-event-rect' x Axis.<br>It should be used along with `data`, `index` or `x` value. The default value is set as `[0,0]` | * | data | Object | When [data.xs](Options.html#.data%25E2%2580%25A4xs) option is used or [tooltip.grouped](Options.html#.tooltip) set to 'false', `should be used giving this param`.<br><br>**Key:**<br>- x {number &verbar; Date}: x Axis value<br>- index {number}: x Axis index (useless for data.xs)<br>- id {string}: data id<br>- value {number}: The corresponding value for tooltip. | * * @example * // show the 2nd x Axis coordinate tooltip * // for Arc(gauge, donut & pie) and radar type, approach showing tooltip by using "index" number. * chart.tooltip.show({ * index: 1 * }); * * // show tooltip for the 3rd x Axis in x:50 and y:100 coordinate of '.bb-event-rect' of the x Axis. * chart.tooltip.show({ * x: 2, * mouse: [50, 100] * }); * * // show tooltip for timeseries x axis * chart.tooltip.show({ * x: new Date("2018-01-02 00:00") * }); * * // treemap type can be shown by using "id" only. * chart.tooltip.show({ * data: { * id: "data1" // data id * } * }); * * // for Arc types, specify 'id' or 'index' * chart.tooltip.show({ data: { id: "data2" }}); * chart.tooltip.show({ data: { index: 2 }}); * * // when data.xs is used * chart.tooltip.show({ * data: { * x: 3, // x Axis value * id: "data1", // data id * value: 500 // data value * } * }); * * // when data.xs isn't used, but tooltip.grouped=false is set * chart.tooltip.show({ * data: { * index: 3, // or 'x' key value * id: "data1", // data id * value: 500 // data value * } * }); */ show: function(args): void { const $$ = this.internal; const {$el, config, state: {eventReceiver, hasFunnel, hasTreemap, inputType}} = $$; let index; let mouse; // determine mouse position on the chart if (args.mouse) { mouse = args.mouse; } // determine focus data if (args.data) { const {data} = args; const y = $$.getYScaleById(data.id)?.(data.value); if ((hasFunnel || hasTreemap) && data.id) { const selector = $$.selectorTarget(data.id, undefined, `.${$SHAPE.shape}`); eventReceiver.rect = $el.main.select(selector); } else if ($$.isMultipleX()) { // if multiple xs, target point will be determined by mouse mouse = [$$.xx(data), y]; } else { if (!config.tooltip_grouped) { mouse = [0, y]; } index = data.index ?? ( $$.hasArcType() && data.id ? $$.getArcElementByIdOrIndex(data.id)?.datum().index : $$.getIndexByX(data.x) ); } } else if (isDefined(args.x)) { index = $$.getIndexByX(args.x); } else if (isDefined(args.index)) { index = args.index; } if ($$.state.isCanvasMode) { const targets = $$.filterTargetsToShow?.() || $$.data.targets; const selectedData = args.data?.id && !config.tooltip_grouped ? targets .filter(target => target.id === args.data.id) .map(target => target.values[index ?? args.data.index]) .filter(Boolean) : targets .map(target => target.values[index]) .filter(Boolean); const canvas = $el.canvas?.node?.(); const shape = $$.state.canvasShape || $$.getDrawShape?.(); const first = selectedData[0]; const point = mouse || ( first && shape?.pos?.cx && shape?.pos?.cy ? [ $$.state.margin.left + shape.pos.cx(first), $$.state.margin.top + shape.pos.cy(first) ] : undefined ); if (!selectedData.length || !canvas) { return; } $$.state.canvasFocusKey = selectedData .map(v => `${v.id}:${v.index}`) .join("|"); $$.renderCanvasFocus?.(selectedData, point); $$.showTooltip?.(selectedData, canvas); return; } (inputType === "mouse" ? ["mouseover", "mousemove"] : ["touchstart"]).forEach(eventName => { $$.dispatchEvent(eventName, index, mouse); }); }, /** * Hide tooltip * @function tooltip․hide * @instance * @memberof Chart */ hide: function(): void { const $$ = this.internal; const {state: {inputType, isCanvasMode}, $el: {tooltip}} = $$; const data = tooltip?.datum(); if (isCanvasMode) { $$.state.canvasFocusKey = null; $$.hideTooltip(true); $$.clearCanvasFocus?.(); return; } if (data?.data?.[0]) { const {index} = data.data[0]; // make to finalize, possible pending event flow set from '.tooltip.show()' call (inputType === "mouse" ? ["mouseout"] : ["touchend"]).forEach(eventName => { $$.dispatchEvent(eventName, index); }); } // reset last touch point index inputType === "touch" && $$.callOverOutForTouch(); $$.hideTooltip(true); $$.hideGridFocus?.(); $$.unexpandCircles?.(); $$.expandBarTypeShapes?.(false); } }; export default {tooltip};