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(bubble): expand bubble chart feature with plugin #1153

Closed
wants to merge 2 commits 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
37 changes: 37 additions & 0 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,43 @@ d3.select(".chart_area")
}
}]
}
},
BubbleCompare: {
description: 'compare data 3-dimensional ways, x-axis, y-axis, bubble-size',
options: {
data: {
"type": "bubble",
"xs": {
"Country-A": "x0",
"Country-B": "x1",
"Country-C": "x2",
"Country-D": "x3",
"Country-E": "x4"
},
// value x: population density
// value y: Area
// value z: population
"columns": [
["x0", 30],
["x1", 515],
["x2", 319],
["x3", 337],
["x4", 164],
["Country-A", {"y": 9631418, "z": 295734134}],
["Country-B", {"y": 100210, "z": 51635256}],
["Country-C", {"y": 547030, "z": 67022000}],
["Country-D", {"y": 377835, "z": 127417244}],
["Country-E", {"y": 464, "z": 76177}],
]
},
axis: {
x: {padding: {left: 100, right: 20}},
y: {padding: {top: 150, bottom: 100}},
},
_plugins: [{
bubblecompare: {minR: 11, maxR: 74, expandScale: 1.1}
}]
}
}
},

Expand Down
3 changes: 3 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ <h4 class="sub_tit">Sample code</h4>
}),
plugins_textoverlap: path.map(function(p) {
return p + "plugin/billboardjs-plugin-textoverlap.js"
}),
plugins_bubblecompare: path.map(function(p) {
return p + "plugin/billboardjs-plugin-bubblecompare.js"
})
});

Expand Down
50 changes: 50 additions & 0 deletions spec/plugin/bubble-compare/bubble-compare-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable */
import {select as d3Select} from "d3-selection";
import BubbleCompare from "../../../src/plugin/bubblecompare";
import util from "../../assets/util";

describe("PLUGIN: BUBBLE-COMPARE", () => {
let chart;
const args = {
data: {
"type": "bubble",
"xs": {
"United States": "x0",
"Korea": "x1",
"France": "x2",
"Japan": "x3",
"Andorra": "x4"
},
// value x: population density
// value y: Area
// value z: population
"columns": [
["x0", 30],
["x1", 515],
["x2", 319],
["x3", 337],
["x4", 164],
["United States", {"y": 9631418, "z": 295734134}],
["Korea", {"y": 100210, "z": 51635256}],
["France", {"y": 547030, "z": 67022000}],
["Japan", {"y": 377835, "z": 127417244}],
["Andorra", {"y": 464, "z": 76177}],
]
},
plugins: [new BubbleCompare({minR: 11, maxR: 74, expandScale: 1.1})]
};

beforeEach(() => {
chart = util.generate(args);
});

it("Every bubble radius should be in given radius range", () => {
chart.$.main.selectAll("circle").each(function() {
const circle = d3Select(this);
const {minR, maxR} = chart.plugins[0].options;
const circleRadius = parseInt(circle.attr("r"), 10);

expect(circleRadius).to.be.within(minR, maxR);
});
});
});
50 changes: 50 additions & 0 deletions src/plugin/bubblecompare/Options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
/**
* Bubble compare plugin option class
* @class BubblecompareOptions
* @param {Options} options Bubblecompare plugin options
* @extends Plugin
* @return {BubblecompareOptions}
* @private
*/
export default class Options {
constructor() {
return {
/**
* Set minimum size of bubble radius. (px)
* @name minR
* @memberof plugin-bubblecompare
* @type {number}
* @default 11
* @example
* minR: 11
*/
minR: 11,

/**
* Set maximum size of bubble radius. (px)
* @name maxR
* @memberof plugin-bubblecompare
* @type {number}
* @default 11
* @example
* maxR: 74
*/
maxR: 11,

/**
* Specify bubble expand ratio when focused
* @name expandScale
* @memberof plugin-bubblecompare
* @type {number}
* @default 1
* @example
* expandScale: 1.2
*/
expandScale: 1
};
}
}
100 changes: 100 additions & 0 deletions src/plugin/bubblecompare/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {select} from "d3-selection";
import Plugin from "../Plugin";

/**
* Bubble compare diagram plugin
* - **NOTE:**
* - Plugins aren't built-in. Need to be loaded or imported to be used.
* @class plugin-bubblecompare
* @param {Object} options bubble compare plugin options
* @extends Plugin
* @return {BubbleCompare}
* @example
* var chart = bb.generate({
* data: {
* columns: [ ... ],
* type: "bubble"
* }
* ...
* plugins: [
* new bb.plugin.bubblecompare({
* minR: 11,
* maxR: 74,
* expandScale: 1.1
* }),
* ]
* });
*/

export default class BubbleCompare extends Plugin {
static version = `0.0.1`;

constructor(options) {
super(options);

return this;
}

$init() {
const {$$} = this;

$$.findClosest = this.findClosest.bind(this);
$$.getBubbleR = this.getBubbleR.bind(this);
$$.pointExpandedR = this.pointExpandedR.bind(this);
}

pointExpandedR(d) {
const baseR = this.getBubbleR(d);
const {expandScale = 1} = this.options;

BubbleCompare.raiseFocusedBubbleLayer(d);
this.changeCursorPoint();

return baseR * expandScale;
}

static raiseFocusedBubbleLayer(d) {
if (d.raise) select(d.node().parentNode.parentNode).raise();
}

changeCursorPoint() {
this.$$.svg.select(`.bb-event-rect`).style("cursor", "pointer");
}

findClosest(values, pos) {
const {$$} = this;

return values
.filter(v => v && !$$.isBarType(v.id))
.reduce((acc, cur) => {
const d = $$.dist(cur, pos);

return d < this.getBubbleR(cur) ? cur : acc;
}, 0);
}

getBubbleR(d) {
const {minR, maxR} = this.options;
const curVal = this.getZData(d);

if (!curVal) return minR;

const [min, max] = this.$$.data.targets.reduce(
([accMin, accMax], cur) => {
const val = this.getZData(cur.values[0]);

return [Math.min(accMin, val), Math.max(accMax, val)];
},
[10000, 0]
);
const size = min > 0 && max === min ? 0 : curVal / max;

return Math.abs(size) * (maxR - minR) + minR;
}

getZData(d) {
return this.$$.isBubbleZType(d) ?
this.$$.getBubbleZData(d.value, "z") :
d.value;
}
}
13 changes: 13 additions & 0 deletions types/plugin/bubblecompare/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*/
import { Plugin } from "../plugin";
import { BubblecompareOptions } from "./options";

export default class Stanford extends Plugin {
/**
* Generate stanford diagram
*/
constructor(options: BubblecompareOptions);
}
14 changes: 14 additions & 0 deletions types/plugin/bubblecompare/options.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface BubblecompareOptions {
/**
* Minimum bubble radius (px, default: 11)
*/
minR?: number;
/**
* Maximum bubble radius (px, default: 11)
*/
maxR?: number;
/**
* expand ratio when bubble focused (default: 1)
*/
expandScale?: number;
}