Skip to content

Commit

Permalink
feat(point): Intent to ship point.focus.only
Browse files Browse the repository at this point in the history
When point.focus.only is set, only one physical data point node is
generated per dataset to boost peformance.
  • Loading branch information
netil committed May 13, 2020
1 parent f1fa32f commit bb70347
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 43 deletions.
28 changes: 24 additions & 4 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -1493,11 +1493,8 @@ setTimeout(function() {chart.resize();}, 3000)
}
},
point: {
r: 0,
focus: {
expand: {
r: 5
}
only: true
}
}
}
Expand Down Expand Up @@ -2869,6 +2866,29 @@ d3.select(".chart_area")
]
}
}
},
FocusOnly: {
description: "Data point is displayed only when is hovered.",
options: {
data: {
columns: [
["data1", 30, 31.8, 33, 33.8, 34.4, 34.8, 35, 35, 34.6, 34.4, 34.2, 33.8, 33.4, 33.4, 33.6, 33.6, 33.8, 34, 34.2, 34, 34, 34, 34, 34, 34, 33.6, 33, 32.4, 31.8, 31.2, 30.8, 30.8, 31, 31.2, 31.4, 31.8, 32, 32, 32.2, 32.4, 32.4, 32.2, 32, 31.6, 31.2, 31, 31, 31.4, 31.8, 32.2, 32.6, 33, 33, 32.8, 32.6, 32.4, 32.2, 31.8, 31.6, 31.4, 31.2, 31, 31, 31.2, 31.4, 31.6, 31.8, 32, 32, 32, 32.2, 32.2, 32.4, 32.4, 32.4, 32.2, 32.2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32.2, 32.4, 32.4, 32.4, 32.4, 32.2, 32, 32, 32, 32.2, 32.2, 32.2, 32, 31.8, 31.4, 31.2, 31, 31, 31.2, 31.4, 31.2, 31, 31, 30.8, 31, 31.6, 32.2, 32.6, 33, 32.8, 32.4, 32, 32, 31.8, 31.8, 31.8, 31.6, 31, 30.8, 30.8, 31, 31.6, 32.4, 33, 33.4, 33.8, 34, 34, 34, 33.8, 33.6, 33.4, 33.2, 33, 33, 33, 32.8, 32.6, 32.4, 32.2, 32, 32, 31.8, 31.6, 31.4, 31.2, 30.8, 30.6, 30.4, 30.2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29.8, 29.6, 29.6, 29.6, 29.6, 29.8, 30, 30, 30, 30, 30, 30, 29.8, 29.6, 29.4, 29.2, 29.2, 29.4, 29.6, 29.8, 30, 30.2, 30.4, 30.6, 30.8, 31, 31, 31, 31, 30.8, 30.6, 30.4, 30, 29.6, 29.4, 29.2, 29, 28.8, 28.8, 28.8, 28.8, 28.8, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29.2, 29.2, 29.2, 29.4, 29.6, 29.6, 29.8, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30.2, 30.6, 31.2, 32, 33, 34, 34.8, 35.4, 35.8, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36.2, 36.4, 36.6, 37, 37.4, 37.6, 37.8, 37.8, 37.6, 37.4, 37.2, 36.8, 36.8, 36.6, 36.4, 36.2, 36.2, 35.8, 35.6, 35.4, 35.2, 35, 35, 35, 35.2, 35.4, 35.6, 35.8, 36, 36, 36, 36, 36.2, 36.2, 36, 35.6, 35, 34, 33, 32.2, 31.6, 31.2, 31, 31, 31, 31, 31, 31, 31, 31.2, 31.2, 31.2, 31.2, 31.2, 31, 31, 31.2, 31.4, 31.6, 31.6, 31.6, 31.4, 31.2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30.8, 30.6, 30.4, 30.4, 30.4, 30.6, 30.8, 31, 31, 30.8, 30.6, 30.6, 30.6, 30.6, 30.8, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30.8, 30.6, 30.4, 30.2, 30.2, 30.4, 30.6, 30.6, 30.8, 30.6, 30.4, 30.2, 30.2, 30, 30, 30.2, 30.4, 30.4, 30.6, 30.8, 30.6, 30.6, 30.8, 30.8, 30.8, 31, 31, 30.8, 30.8, 30.8, 30.8, 30.8, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30.8, 30.8, 30.6, 30.6, 30.6, 30.8, 30.8, 30.8, 30.6, 30.4, 30.4, 30.2, 30.2, 30.4, 30.6, 30.4, 30.4, 30.4, 30.4, 30.4, 30.6, 30.8, 31, 31, 31, 30.8, 30.8, 30.8, 30.8, 30.8, 31, 31, 30.8, 30.6, 30.4, 30, 29.4, 29, 28.6, 28.2, 28, 28, 28, 28, 28, 28, 28, 28, 28.2, 28.4, 28.6, 28.8, 29, 29, 29, 28.8, 28.6, 28.4, 28.2, 28, 28, 28.2, 28.4, 28.6, 28.8, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28.8, 28.6, 28.4, 28.2, 28, 28, 28.2, 28.4, 28.6, 28.8, 29, 29, 29, 28.8, 28.6, 28.4, 28.2, 28, 28.2, 28.4, 28.6, 28.8, 29, 28.8, 28.8, 28.6, 28.6, 28.8, 29.6, 30.4, 31.6, 33, 34.4, 35.4, 36.2, 36.8, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37.2, 37.4, 37.6, 37.8, 38, 38.2, 38.2, 38, 38, 38, 37.8, 37.8, 38, 38, 38, 38, 38, 38, 38, 38, 38.2, 38.4, 38.6, 38.8, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39.2, 39.4, 39.6, 39.8, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 39.8, 39.6, 39.4, 39, 38.6, 38.2, 37.8, 37.4, 37.2, 37, 36.8, 36.6, 36.4, 36.2, 35.8, 35.6, 35.4, 35.2, 35, 35, 35, 35, 35, 34.8, 34.6, 34.4, 34.2, 34, 34, 34, 34, 34, 33.8, 33.6, 33.4, 33.2, 33, 33, 33, 33, 32.8, 32.6, 32.2, 32, 31.6, 31.4, 31.2, 31.4, 31.4, 31.6, 32, 32.4, 32.6, 32.8, 32.8, 32, 31, 29.6, 28.2, 26.8, 26, 25.8, 26, 26.6, 27.4, 28.2, 28.6, 29, 29, 29, 29.2, 29.2, 29.4, 29.6, 29.8, 29.8, 29.8, 29.8, 29.8, 29.8, 29.8, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30.2, 30.4, 30.6, 30.8, 31, 31, 31, 31, 31, 31, 31, 31, 31.2, 31.2, 31.2, 31.2, 31.4, 31.2, 31.4, 31.6, 31.8, 31.8, 32, 32, 32, 32, 32.2, 32.4, 32.4, 32.4, 32.6, 32.6, 32.6, 32.8, 33, 33, 33, 33, 33, 33.2, 33.4, 33.6, 33.8, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 33.8, 33.6, 33.4, 33, 32.6, 32.4, 32.2, 32, 32, 32, 32, 32, 32, 31.8, 31.6, 31.4, 31.2, 30.8, 30.6, 30.4, 30.2, 29.8, 29.6, 29.4, 29.2, 29, 29, 29, 29, 29, 29, 29, 29.2, 29.4, 29.6, 29.8, 30, 30, 30, 30, 30, 30, 30, 29.8, 29.6, 29.4, 29.2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28.8, 28.6, 28.4, 28.2, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28.2, 28.4, 28.6, 28.8, 29, 29, 29, 29.2, 29.4, 29.6, 29.8, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29.8, 29.8, 29.6, 29.4, 29.4, 29.6, 29.6, 29.8, 30, 30, 30.2, 30.4, 30.6, 30.8, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31.2, 31.4, 31.6, 31.8, 32, 32.2, 32.4, 32.6, 32.8, 33.2, 33.4, 33.6, 33.8, 34, 34, 34, 34, 34.2, 34.4, 34.6, 34.8, 35, 35, 35, 35.2, 35.4, 35.6, 35.8, 36, 36, 36, 36, 36, 35.8]
]
},
point: {
focus : {
only: true
}
},
clipPath: false,
axis: {
x: {
tick: {
count: 5
}
}
}
}
}
},

Expand Down
87 changes: 71 additions & 16 deletions dist/billboard.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/ChartInternal/data/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@ export default {

/**
* Get total hidden data sum
* @return {Number}
* @private
* @returns {number}
* @private
*/
getHiddenTotalDataSum() {
const $$ = this;
Expand Down
14 changes: 11 additions & 3 deletions src/ChartInternal/internals/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,14 +414,20 @@ export default {
});

smoothLines(focusEl, "grid");

$$.showCircleFocus(selectedData);
},

hideGridFocus(): void {
const $$ = this;
const {state, $el} = $$;
const {state: {inputType}, $el: {main}} = $$;

if (inputType === "mouse") {
main.selectAll(`line.${CLASS.xgridFocus}, line.${CLASS.ygridFocus}`)
.style("visibility", "hidden");

state.inputType === "mouse" && $el.main.selectAll(`line.${CLASS.xgridFocus}, line.${CLASS.ygridFocus}`)
.style("visibility", "hidden");
$$.hideCircleFocus();
}
},

updateGridFocus(): boolean {
Expand All @@ -435,6 +441,8 @@ export default {

d && $$.showGridFocus([d]);
}

$$.showCircleFocus();
} else {
const isRotated = $$.config.axis_rotated;

Expand Down
87 changes: 70 additions & 17 deletions src/ChartInternal/shape/point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export default {
},

opacityForCircle(d): "0.5" | "1" | "0" {
const opacity = this.config.point_show ? "1" : "0";
const {config} = this;
const opacity = config.point_show && !config.point_focus_only ? "1" : "0";

return isValue(this.getBaseValue(d)) ?
(this.isBubbleType(d) || this.isScatterType(d) ?
Expand Down Expand Up @@ -93,29 +94,34 @@ export default {
updateCircle(): void {
const $$ = this;
const {config, $el} = $$;
const focusOnly = config.point_focus_only;

if (!config.point_show) {
return;
}
if (config.point_show) {
const circles = $el.main.selectAll(`.${CLASS.circles}`)
.selectAll(`.${CLASS.circle}`)
.data(d => {
const data = !$$.isBarType(d) && (
!$$.isLineType(d) || $$.shouldDrawPointsForLine(d)
) && $$.labelishData(d);

return focusOnly ? [data[0]] : data;
});

const circles = $el.main.selectAll(`.${CLASS.circles}`).selectAll(`.${CLASS.circle}`)
.data(d => !$$.isBarType(d) && (
!$$.isLineType(d) || $$.shouldDrawPointsForLine(d)
) && $$.labelishData(d)
);
circles.exit().remove();

circles.exit().remove();
const fn = $$.point("create", this, $$.pointR.bind($$), $$.color);

const fn = $$.point("create", this, $$.pointR.bind($$), $$.color);
circles.enter()
.append(fn)
.merge(circles)
.style("stroke", $$.color)
.style("opacity", $$.initialOpacityForCircle.bind($$));

$el.circle = circles.enter()
.append(fn)
.merge(circles)
.style("stroke", $$.color)
.style("opacity", $$.initialOpacityForCircle.bind($$));
$el.circle = $el.main.selectAll(`.${CLASS.circles} .${CLASS.circle}`);
}
},

redrawCircle(cx: number, cy: number, withTransition: boolean, flow) {
redrawCircle(cx: Function, cy: Function, withTransition: boolean, flow) {
const $$ = this;
const {state: {rendered}, $el: {circle, main}} = $$;
const selectedCircles = main.selectAll(`.${CLASS.selectedCircle}`);
Expand Down Expand Up @@ -149,6 +155,53 @@ export default {
];
},

/**
* Show focused data point circle
* @param {object} d Selected data
* @private
*/
showCircleFocus(d?): void {
const $$ = this;
const {config, state, $el} = $$;

if (state.transiting === false && config.point_focus_only) {
let {circle} = $el;
const cx = $$.circleX.bind($$);
const cy = $$.circleY.bind($$);
const fn = $$.point("update", $$, cx, cy, $$.color);

if (d) {
const data = d.filter(d => d && isValue(d.value));

circle = circle
.filter(d => data.some(v => v.id === d.id))
.data(data);
}

circle
.attr("class", this.updatePointClass.bind(this))
.style("opacity", "1")
.each(function(d) {
fn.bind(this)(d);
$$.expandCircles(d.index, d.id);
})
.style("visibility", null);
}
},

/**
* Hide focused data point circle
* @private
*/
hideCircleFocus(): void {
const $$ = this;
const {config, $el} = $$;

if (config.point_focus_only) {
$el.circle.style("visibility", "hidden");
}
},

circleX(d): number | null {
const $$ = this;
const {x, zoom} = $$.scale;
Expand Down
5 changes: 4 additions & 1 deletion src/config/Options/common/point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default {
* @property {boolean} [point.focus.expand.enabled=true] Whether to expand each point on focus.
* @property {number} [point.focus.expand.r=point.r*1.75] The radius size of each point on focus.
* - **NOTE:** For 'bubble' type, the default is `bubbleSize*1.15`
* @property {boolean} [point.focus.only=false] Show point only when is focused.
* @property {number} [point.sensitivity=10] The senstivity value for interaction boundary.
* @property {number} [point.select.r=point.r*4] The radius size of each point on selected.
* @property {string} [point.type="circle"] The type of point to be drawn
Expand Down Expand Up @@ -53,7 +54,8 @@ export default {
* expand: {
* enabled: true,
* r: 1
* }
* },
* only: true
* },
* select: {
* r: 3
Expand All @@ -78,6 +80,7 @@ export default {
point_sensitivity: 10,
point_focus_expand_enabled: true,
point_focus_expand_r: <number|undefined> undefined,
point_focus_only: false,
point_pattern: <string[]> [],
point_select_r: <number|undefined> undefined,
point_type: "circle"
Expand Down
101 changes: 101 additions & 0 deletions test/shape/point-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,105 @@ describe("SHAPE POINT", () => {
expect(chart.$.tooltip.selectAll(".name").size()).to.be.equal(1);
});
});

describe("point.focus.only", () => {
before(() => {
args = {
data: {
columns: [
["data1", 100, 350, null, 300, 250],
["data2", 130, 100, 140, 200, 150]
]
},
point: {
focus: {
only: true
}
}
};
});

it("circle visibility", () => {
const {circles} = chart.$;
const pos = {};
let x = 3;

circles.each(function(d) {
pos[d.id] = [+this.getAttribute("cx"), +this.getAttribute("cy")];
});

expect(circles.size()).to.be.equal(chart.data().length);

// when
chart.tooltip.show({x});
const cx = chart.internal.scale.x(x);

circles.each(function(d) {
const p = pos[d.id];

expect(+this.getAttribute("cx")).to.be.above(p[0]);
expect(+this.getAttribute("cy")).to.be.below(p[1]);
expect(d.x).to.be.equal(x);
expect(+this.getAttribute("cx")).to.be.equal(cx);
});

// when
x = 2;
chart.tooltip.show({x});

// 'null' data point shoudn't be displayed
expect(circles.filter(`.${CLASS.EXPANDED}`).size()).to.be.equal(1);
});

it("visibility with data toggle", () => {
const {circles} = chart.$;
let x = 2;

// when
chart.toggle("data1");
chart.tooltip.show({x});

circles.each(function(d, i) {
if (i === 0) {
expect(this.style.opacity).to.be.equal("0");
} else {
expect(d.id).to.be.equal("data2");
expect(d.x).to.be.equal(x);
}
});
});

it("visibility with data load", done => {
let {circles} = chart.$;
const size = circles.size();

expect(size).to.be.equal(chart.data().length);

chart.load({
columns: [["data3", 100, 100, null, 100]],
done: function() {
circles = chart.$.circles;
expect(circles.size()).to.be.equal(size + 1);

circles.each(function() {
expect(+this.style.opacity).to.be.equal(0);
});

// when
const x = 3;
const cx = chart.internal.scale.x(x);

chart.tooltip.show({x});

circles.each(function(d) {
expect(+this.style.opacity).to.be.equal(1);
expect(d.x).to.be.equal(x);
expect(+this.getAttribute("cx")).to.be.equal(cx);
});

done();
}
});
});
});
});
5 changes: 5 additions & 0 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,11 @@ export interface PointOptions {
*/
r?: number;
};

/**
* Show point only when is focused.
*/
only?: boolean;
};

select?: {
Expand Down

0 comments on commit bb70347

Please sign in to comment.