Skip to content

Commit

Permalink
implements shapeSort method and example
Browse files Browse the repository at this point in the history
  • Loading branch information
davelandry committed Aug 3, 2018
1 parent 1149879 commit bd360f9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
58 changes: 58 additions & 0 deletions example/shapeSort.md
@@ -0,0 +1,58 @@
# Sorting Shapes on an X/Y Plot

By using the [Plot](https://github.com/d3plus/d3plus-plot#Plot) class directly, it is possible to render different shapes on the same graph. Let's say we have the following data, where we want the "alpha" data points to be [Circles](https://github.com/d3plus/d3plus-shape#Circle) and the "delta" data points to be [Lines](https://github.com/d3plus/d3plus-shape#Line):

```js
var data = [
{id: "alpha", time: 4, value: 240},
{id: "alpha", time: 5, value: 120},
{id: "alpha", time: 6, value: 180},
{id: "delta", time: 4, value: 240},
{id: "delta", time: 5, value: 120},
{id: "delta", time: 6, value: 180}
];
```

First, when creating a new [Plot](https://github.com/d3plus/d3plus-plot#Plot) visualization, we need to describe how the chart should be using our data keys:

```js
var chart = new d3plus.Plot()
.data(data)
.groupBy("id")
.x("time")
.y("value")
```

In addition to using the [shape](https://github.com/d3plus/d3plus-plot#Plot.shape) method to define which data points should be which shapes, we need to set the X-axis to be [discrete](https://github.com/d3plus/d3plus-plot#Plot.discrete) in order for the Lines to render correctly. This tells d3plus that it should treat all X values as separate data points, which allows for drawing charts like Line Plots and Bar Charts.

```js
chart
.shape(function(d) {
if (d.id === "delta") {
return "Line";
}
else {
return "Circle";
}
})
.discrete("x");
```

Finally, we can use the [shapeSort](https://github.com/d3plus/d3plus-plot#Plot.shapeSort) to modify the default ordering of the shapes. Shapes are drawn in groups, so when moving a certain shape on top of another, all shapes of that type will move together. By default, [Circles](https://github.com/d3plus/d3plus-shape#Circle) are drawn on top of [Lines](https://github.com/d3plus/d3plus-shape#Line), but in our case here, let's reverse that:

```js
var order = ["Circle", "Line"];

chart
.shapeConfig({
Line: {
strokeLinecap: "round",
strokeWidth: 5
}
})
.shapeSort(function(a, b) {
return order.indexOf(a) - order.indexOf(b);
})
.sizeMin(20)
.render();
```
18 changes: 17 additions & 1 deletion src/Plot.js
Expand Up @@ -85,6 +85,8 @@ export default class Plot extends Viz {
width: d => defaultSize.bind(this)(d) * 2
}
});
this._shapeOrder = ["Area", "Path", "Bar", "Box", "Line", "Rect", "Circle"];
this._shapeSort = (a, b) => this._shapeOrder.indexOf(a) - this._shapeOrder.indexOf(b);
this._sizeMax = 20;
this._sizeMin = 5;
this._sizeScale = "sqrt";
Expand Down Expand Up @@ -368,7 +370,11 @@ export default class Plot extends Viz {
y = scales[`scale${yScale}`]().domain(domains.y.reverse()).range(range(0, height + 1, height / (domains.y.length - 1))),
y2 = scales[`scale${y2Scale}`]().domain(domains.y2.reverse()).range(range(0, height + 1, height / (domains.y2.length - 1)));

const shapeData = nest().key(d => d.shape).entries(data);
const shapeData = nest()
.key(d => d.shape)
.entries(data)
.sort((a, b) => this._shapeSort(a.key, b.key));

const oppScale = this._discrete === "x" ? yScale : xScale;
if (this._xConfig.scale !== "log" && this._yConfig.scale !== "log" && oppScale !== "Ordinal") {
shapeData.forEach(d => {
Expand Down Expand Up @@ -841,6 +847,16 @@ export default class Plot extends Viz {
return arguments.length ? (this._groupPadding = _, this) : this._groupPadding;
}

/**
@memberof Plot
@desc A JavaScript [sort comparator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) that receives each shape Class (ie. "Circle", "Line", etc) as it's comparator arguments. Shapes are drawn in groups based on their type, so you are defining the layering order for all shapes of said type.
@param {Function} *value*
@chainable
*/
shapeSort(_) {
return arguments.length ? (this._shapeSort = _, this) : this._shapeSort;
}

/**
@memberof Plot
@desc Sets the size of bubbles to the given Number, data key, or function.
Expand Down

0 comments on commit bd360f9

Please sign in to comment.