Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(event): add option for step-before/step-after charts for tooltip to match step behavior #2332

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -760,11 +760,15 @@ var demos = {
StepChart: [
{
options: {
title: {
text: "default",
},
data: {
columns: [
["data1", 300, 350, 300, 20, 240, 100],
["data2", 130, 100, 140, 200, 150, 50]
],
type: "step",
types: {
data1: "step",
data2: 'area-step'
Expand All @@ -774,38 +778,48 @@ var demos = {
},
{
options: {
title: {
text: "step-before",
},
data: {
columns: [
["data1", 300, 350, 300, 20, 240, 100],
["data2", 130, 100, 140, 200, 150, 50]
],
type: "step",
types: {
data1: "step",
data2: 'area-step'
}
},
line: {
step: {
type: "step-before"
type: "step-before",
tooltipMatch: true,
}
}
}
},
{
options: {
title: {
text: "step-after",
},
data: {
columns: [
["data1", 300, 350, 300, 20, 240, 100],
["data2", 130, 100, 140, 200, 150, 50]
],
type: "step",
types: {
data1: "step",
data2: 'area-step'
}
},
line: {
step: {
type: "step-after"
type: "step-after",
tooltipMatch: true
}
}
}
Expand Down
26 changes: 23 additions & 3 deletions src/ChartInternal/interactions/eventrect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,15 +406,35 @@ export default {

state.event = event;

if (!d) {
return;
}

let {index} = d;

if ($$.isStepType(d)) {
const scale = $$.scale.zoom || $$.scale.x;

if (config.line_step_type === "step-after" &&
config.line_step_tooltipMatch &&
scale.invert(getPointer(event, this)[0]) < $$.axis.xs[index]
) {
index -= 1;
} else if (config.line_step_type === "step-before" &&
config.line_step_tooltipMatch &&
scale.invert(getPointer(event, this)[0]) > $$.axis.xs[index]
) {
index += 1;
}
}

// do nothing while dragging/flowing
if (state.dragging || state.flowing || $$.hasArcType() ||
!d || (config.tooltip_grouped && d && d.index === eventReceiver.currentIdx)
(config.tooltip_grouped && d && index === eventReceiver.currentIdx)
) {
return;
}

const {index} = d;

if (index !== eventReceiver.currentIdx) {
$$.setOverOut(false, eventReceiver.currentIdx);
eventReceiver.currentIdx = index;
Expand Down
6 changes: 5 additions & 1 deletion src/config/Options/shape/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export default {
* - step
* - step-before
* - step-after
* @property {boolean} [line.step.tooltipMatch=false] Set to true for step-before and step-after types to have cursor/tooltip match to hovered step's point instead of nearest point.<br>
* Note that [data.type](#.data․type) must be set to `step`.
* @property {boolean|Array} [line.point=true] Set to false to not draw points on linecharts. Or pass an array of line ids to draw points for.
* @property {boolean} [line.zerobased=false] Set if min or max value will be 0 on line chart.
* @example
Expand All @@ -30,7 +32,8 @@ export default {
* "line-class2"
* ],
* step: {
* type: "step-after"
* type: "step-after",
* tooltipMatch: true
* },
*
* // hide all data points ('point.show=false' also has similar effect)
Expand All @@ -46,6 +49,7 @@ export default {
*/
line_connectNull: false,
line_step_type: <"step"|"step-before"|"step-after"> "step",
line_step_tooltipMatch: false,
line_zerobased: false,
line_classes: <string[]|undefined> undefined,
line_point: <string[]|boolean> true
Expand Down
99 changes: 99 additions & 0 deletions test/internals/tooltip-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,105 @@ describe("TOOLTIP", function() {
})
});

describe('tooltip index with step types and tooltipMatch', function () {
// x axis ticks getBoundingClientRect x are at [43.4375, 336.4375, 630.4375]
before(() => {
args = {
data: {
columns: [
['data1', 30, 40, 20],
],
type: 'step',
},
line: {
step: {
type: 'step',
tooltipMatch: true,
}
}
}
});

it("should have tooltip to nearest", () => {
util.hoverChart(chart, "mousemove", {clientX: 150, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(0);

util.hoverChart(chart, "mousemove", {clientX: 200, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);

util.hoverChart(chart, "mousemove", {clientX: 425, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);

util.hoverChart(chart, "mousemove", {clientX: 500, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(2);
})

it("set step type to step before", () => {
args.line.step.type = 'step-before';
});

it("should have tooltip to right", () => {
util.hoverChart(chart, "mousemove", {clientX: 150, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);

util.hoverChart(chart, "mousemove", {clientX: 200, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);

util.hoverChart(chart, "mousemove", {clientX: 450, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(2);

util.hoverChart(chart, "mousemove", {clientX: 500, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(2);
});

it("set step type to default", () => {
args.line.step.type = 'step-after';
});

const checkStepAfter = () => {
util.hoverChart(chart, "mousemove", {clientX: 150, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(0);

util.hoverChart(chart, "mousemove", {clientX: 200, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(0);

util.hoverChart(chart, "mousemove", {clientX: 450, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);

util.hoverChart(chart, "mousemove", {clientX: 500, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);
}

it("should have tooltip to left", () => {
checkStepAfter();
});

it("set timeseries", () => {
args.axis = {
x: {
type: "timeseries",
}
}
args.data.x = "x";
args.data.columns = args.data.columns.concat([
["x", "2021-01-01", "2021-01-02", "2021-01-03"],
]);
});

it("should work with timeseries", () => {
checkStepAfter();
});

it("should change when enter from right", () => {
util.hoverChart(chart, "mousemove", {clientX: 350, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(1);

util.hoverChart(chart, "mousemove", {clientX: 250, clientY: 300});
expect(chart.internal.state.eventReceiver.currentIdx).to.be.equal(0);
});

});

describe("Narrow width container's tooltip position", () => {
const orgArgs = args;

Expand Down