Skip to content

Commit

Permalink
Merge pull request #153 from d3/two
Browse files Browse the repository at this point in the history
Accept iterables.
  • Loading branch information
Fil authored Aug 19, 2020
2 parents 2bbc6bc + b490be6 commit a1d22ee
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 68 deletions.
52 changes: 26 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ For more, read [Introducing d3-shape](https://medium.com/@mbostock/introducing-d

## Installing

If you use NPM, `npm install d3-shape`. Otherwise, download the [latest release](https://github.com/d3/d3-shape/releases/latest). You can also load directly from [d3js.org](https://d3js.org), either as a [standalone library](https://d3js.org/d3-shape.v1.min.js) or as part of [D3](https://github.com/d3/d3). AMD, CommonJS, and vanilla environments are supported. In vanilla, a `d3` global is exported:
If you use NPM, `npm install d3-shape`. Otherwise, download the [latest release](https://github.com/d3/d3-shape/releases/latest). You can also load directly from [d3js.org](https://d3js.org), either as a [standalone library](https://d3js.org/d3-shape.v2.min.js) or as part of [D3](https://github.com/d3/d3). AMD, CommonJS, and vanilla environments are supported. In vanilla, a `d3` global is exported:

```html
<script src="https://d3js.org/d3-path.v1.min.js"></script>
<script src="https://d3js.org/d3-shape.v1.min.js"></script>
<script src="https://d3js.org/d3-path.v2.min.js"></script>
<script src="https://d3js.org/d3-shape.v2.min.js"></script>
<script>
var line = d3.line();
Expand All @@ -52,6 +52,8 @@ var line = d3.line();
* [Custom Symbol Types](#custom-symbol-types)
* [Stacks](#stacks)

Note: all the methods that accept arrays also accept iterables and convert them to arrays internally.

### Arcs

[<img alt="Pie Chart" src="https://raw.githubusercontent.com/d3/d3-shape/master/img/pie.png" width="295" height="295">](http://bl.ocks.org/mbostock/8878e7fd82034f1d63cf)[<img alt="Donut Chart" src="https://raw.githubusercontent.com/d3/d3-shape/master/img/donut.png" width="295" height="295">](http://bl.ocks.org/mbostock/2394b23da1994fc202e1)
Expand Down Expand Up @@ -349,9 +351,9 @@ The pad angle here means the angular separation between each adjacent arc. The t

The line generator produces a [spline](https://en.wikipedia.org/wiki/Spline_\(mathematics\)) or [polyline](https://en.wikipedia.org/wiki/Polygonal_chain), as in a line chart. Lines also appear in many other visualization types, such as the links in [hierarchical edge bundling](https://observablehq.com/@d3/hierarchical-edge-bundling).

<a name="line" href="#line">#</a> d3.<b>line</b>() · [Source](https://github.com/d3/d3-shape/blob/master/src/line.js), [Examples](https://observablehq.com/@d3/d3-line)
<a name="line" href="#line">#</a> d3.<b>line</b>([<i>x</i>][, <i>y</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/line.js), [Examples](https://observablehq.com/@d3/d3-line)

Constructs a new line generator with the default settings.
Constructs a new line generator with the default settings. If *x* or *y* are specified, sets the corresponding accessors to the specified function or number and returns this line generator.

<a name="_line" href="#_line">#</a> <i>line</i>(<i>data</i>) · [Source](https://github.com/d3/d3-shape/blob/master/src/line.js), [Examples](https://observablehq.com/@d3/d3-line)

Expand Down Expand Up @@ -457,9 +459,9 @@ Equivalent to [*line*.context](#line_context).

The area generator produces an area, as in an area chart. An area is defined by two bounding [lines](#lines), either splines or polylines. Typically, the two lines share the same [*x*-values](#area_x) ([x0](#area_x0) = [x1](#area_x1)), differing only in *y*-value ([y0](#area_y0) and [y1](#area_y1)); most commonly, y0 is defined as a constant representing [zero](http://www.vox.com/2015/11/19/9758062/y-axis-zero-chart). The first line (the <i>topline</i>) is defined by x1 and y1 and is rendered first; the second line (the <i>baseline</i>) is defined by x0 and y0 and is rendered second, with the points in reverse order. With a [curveLinear](#curveLinear) [curve](#area_curve), this produces a clockwise polygon.

<a name="area" href="#area">#</a> d3.<b>area</b>() · [Source](https://github.com/d3/d3-shape/blob/master/src/area.js)
<a name="area" href="#area">#</a> d3.<b>area</b>([<i>x</i>][, <i>y0</i>][, <i>y1</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/area.js)

Constructs a new area generator with the default settings.
Constructs a new area generator with the default settings. If *x*, *y0* or *y1* are specified, sets the corresponding accessors to the specified function or number and returns this area generator.

<a name="_area" href="#_area">#</a> <i>area</i>(<i>data</i>) · [Source](https://github.com/d3/d3-shape/blob/master/src/area.js)

Expand Down Expand Up @@ -493,8 +495,8 @@ var data = [
];

var area = d3.area()
.x(function(d) { return x(d.date); })
.y1(function(d) { return y(d.value); })
.x(d => x(d.date))
.y1(d => y(d.value))
.y0(y(0));
```

Expand Down Expand Up @@ -635,9 +637,7 @@ While [lines](#lines) are defined as a sequence of two-dimensional [*x*, *y*] po
Curves are typically not constructed or used directly, instead being passed to [*line*.curve](#line_curve) and [*area*.curve](#area_curve). For example:

```js
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.value); })
var line = d3.line(d => d.date, d => d.value)
.curve(d3.curveCatmullRom.alpha(0.5));
```

Expand Down Expand Up @@ -902,15 +902,15 @@ Equivalent to [*link*.y](#link_y), except the accessor returns the radius: the d

Symbols provide a categorical shape encoding as is commonly used in scatterplots. Symbols are always centered at ⟨0,0⟩; use a transform (see: [SVG](http://www.w3.org/TR/SVG/coords.html#TransformAttribute), [Canvas](http://www.w3.org/TR/2dcontext/#transformations)) to move the symbol to a different position.

<a name="symbol" href="#symbol">#</a> d3.<b>symbol</b>() · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js)
<a name="symbol" href="#symbol">#</a> d3.<b>symbol</b>([<i>type</i>][, <i>size</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

Constructs a new symbol generator with the default settings.
Constructs a new symbol generator of the specified [type](#symbol_type) and [size](#symbol_size). If not specified, *type* defaults to a circle, and *size* defaults to 64.

<a name="_symbol" href="#_symbol">#</a> <i>symbol</i>(<i>arguments</i>…) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js)
<a name="_symbol" href="#_symbol">#</a> <i>symbol</i>(<i>arguments</i>…) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

Generates a symbol for the given *arguments*. The *arguments* are arbitrary; they are simply propagated to the symbol generator’s accessor functions along with the `this` object. For example, with the default settings, no arguments are needed to produce a circle with area 64 square pixels. If the symbol generator has a [context](#symbol_context), then the symbol is rendered to this context as a sequence of [path method](http://www.w3.org/TR/2dcontext/#canvaspathmethods) calls and this function returns void. Otherwise, a [path data](http://www.w3.org/TR/SVG/paths.html#PathData) string is returned.

<a name="symbol_type" href="#symbol_type">#</a> <i>symbol</i>.<b>type</b>([<i>type</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js)
<a name="symbol_type" href="#symbol_type">#</a> <i>symbol</i>.<b>type</b>([<i>type</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

If *type* is specified, sets the symbol type to the specified function or symbol type and returns this symbol generator. If *type* is a function, the symbol generator’s arguments and *this* are passed through. (See [*selection*.attr](https://github.com/d3/d3-selection/blob/master/README.md#selection_attr) if you are using d3-selection.) If *type* is not specified, returns the current symbol type accessor, which defaults to:

Expand All @@ -922,7 +922,7 @@ function type() {

See [symbols](#symbols) for the set of built-in symbol types. To implement a custom symbol type, pass an object that implements [*symbolType*.draw](#symbolType_draw).

<a name="symbol_size" href="#symbol_size">#</a> <i>symbol</i>.<b>size</b>([<i>size</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js)
<a name="symbol_size" href="#symbol_size">#</a> <i>symbol</i>.<b>size</b>([<i>size</i>]) · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

If *size* is specified, sets the size to the specified function or number and returns this symbol generator. If *size* is a function, the symbol generator’s arguments and *this* are passed through. (See [*selection*.attr](https://github.com/d3/d3-selection/blob/master/README.md#selection_attr) if you are using d3-selection.) If *size* is not specified, returns the current size accessor, which defaults to:

Expand All @@ -938,39 +938,39 @@ Specifying the size as a function is useful for constructing a scatterplot with

If *context* is specified, sets the context and returns this symbol generator. If *context* is not specified, returns the current context, which defaults to null. If the context is not null, then the [generated symbol](#_symbol) is rendered to this context as a sequence of [path method](http://www.w3.org/TR/2dcontext/#canvaspathmethods) calls. Otherwise, a [path data](http://www.w3.org/TR/SVG/paths.html#PathData) string representing the generated symbol is returned.

<a name="symbols" href="#symbols">#</a> d3.<b>symbols</b>
<a name="symbols" href="#symbols">#</a> d3.<b>symbols</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

An array containing the set of all built-in symbol types: [circle](#symbolCircle), [cross](#symbolCross), [diamond](#symbolDiamond), [square](#symbolSquare), [star](#symbolStar), [triangle](#symbolTriangle), and [wye](#symbolWye). Useful for constructing the range of an [ordinal scale](https://github.com/d3/d3-scale#ordinal-scales) should you wish to use a shape encoding for categorical data.

<a name="symbolCircle" href="#symbolCircle">#</a> d3.<b>symbolCircle</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/circle.js)
<a name="symbolCircle" href="#symbolCircle">#</a> d3.<b>symbolCircle</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/circle.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The circle symbol type.

<a name="symbolCross" href="#symbolCross">#</a> d3.<b>symbolCross</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/cross.js)
<a name="symbolCross" href="#symbolCross">#</a> d3.<b>symbolCross</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/cross.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The Greek cross symbol type, with arms of equal length.

<a name="symbolDiamond" href="#symbolDiamond">#</a> d3.<b>symbolDiamond</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/diamond.js)
<a name="symbolDiamond" href="#symbolDiamond">#</a> d3.<b>symbolDiamond</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/diamond.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The rhombus symbol type.

<a name="symbolSquare" href="#symbolSquare">#</a> d3.<b>symbolSquare</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/square.js)
<a name="symbolSquare" href="#symbolSquare">#</a> d3.<b>symbolSquare</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/square.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The square symbol type.

<a name="symbolStar" href="#symbolStar">#</a> d3.<b>symbolStar</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/star.js)
<a name="symbolStar" href="#symbolStar">#</a> d3.<b>symbolStar</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/star.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The pentagonal star (pentagram) symbol type.

<a name="symbolTriangle" href="#symbolTriangle">#</a> d3.<b>symbolTriangle</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/triangle.js)
<a name="symbolTriangle" href="#symbolTriangle">#</a> d3.<b>symbolTriangle</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/triangle.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The up-pointing triangle symbol type.

<a name="symbolWye" href="#symbolWye">#</a> d3.<b>symbolWye</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/wye.js)
<a name="symbolWye" href="#symbolWye">#</a> d3.<b>symbolWye</b> · [Source](https://github.com/d3/d3-shape/blob/master/src/symbol/wye.js), [Examples](https://observablehq.com/@d3/fitted-symbols)

The Y-shape symbol type.

<a name="pointRadial" href="#pointRadial">#</a> d3.<b>pointRadial</b>(<i>angle</i>, <i>radius</i>) · [Source](https://github.com/d3/d3-shape/blob/master/src/pointRadial.js)
<a name="pointRadial" href="#pointRadial">#</a> d3.<b>pointRadial</b>(<i>angle</i>, <i>radius</i>) · [Source](https://github.com/d3/d3-shape/blob/master/src/pointRadial.js), [Examples](https://observablehq.com/@d3/radial-area-chart)

Returns the point [<i>x</i>, <i>y</i>] for the given *angle* in radians, with 0 at -*y* (12 o’clock) and positive angles proceeding clockwise, and the given *radius*.

Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
{
"name": "d3-shape",
"version": "1.3.7",
"version": "2.0.0-rc.1",
"publishConfig": {
"tag": "next"
},
"description": "Graphical primitives for visualization, such as lines and areas.",
"keywords": [
"d3",
Expand Down Expand Up @@ -35,11 +38,11 @@
"postpublish": "git push && git push --tags && cd ../d3.github.com && git pull && cp ../${npm_package_name}/dist/${npm_package_name}.js ${npm_package_name}.v${npm_package_version%%.*}.js && cp ../${npm_package_name}/dist/${npm_package_name}.min.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git add ${npm_package_name}.v${npm_package_version%%.*}.js ${npm_package_name}.v${npm_package_version%%.*}.min.js && git commit -m \"${npm_package_name} ${npm_package_version}\" && git push && cd - && zip -j dist/${npm_package_name}.zip -- LICENSE README.md dist/${npm_package_name}.js dist/${npm_package_name}.min.js"
},
"dependencies": {
"d3-path": "1"
"d3-path": ">=2.0.0-rc.1"
},
"sideEffects": false,
"devDependencies": {
"d3-polygon": "1",
"d3-polygon": ">=2.0.0-rc.1",
"eslint": "6",
"rollup": "1",
"rollup-plugin-terser": "5",
Expand Down
14 changes: 8 additions & 6 deletions src/area.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import {path} from "d3-path";
import array from "./array.js";
import constant from "./constant.js";
import curveLinear from "./curve/linear.js";
import line from "./line.js";
import {x as pointX, y as pointY} from "./point.js";

export default function() {
var x0 = pointX,
x1 = null,
y0 = constant(0),
y1 = pointY,
export default function(x0, y0, y1) {
var x1 = null,
defined = constant(true),
context = null,
curve = curveLinear,
output = null;

x0 = typeof x0 === "function" ? x0 : (x0 === undefined) ? pointX : constant(+x0);
y0 = typeof y0 === "function" ? y0 : (y0 === undefined) ? constant(0) : constant(+y0);
y1 = typeof y1 === "function" ? y1 : (y1 === undefined) ? pointY : constant(+y1);

function area(data) {
var i,
j,
k,
n = data.length,
n = (data = array(data)).length,
d,
defined0 = false,
buffer,
Expand Down
6 changes: 6 additions & 0 deletions src/array.js
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export var slice = Array.prototype.slice;

export default function(x) {
return typeof x === "object" && "length" in x
? x // Array, TypedArray, NodeList, array-like
: Array.from(x); // Map, Set, iterable, string, or anything else
}
12 changes: 7 additions & 5 deletions src/line.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import {path} from "d3-path";
import array from "./array.js";
import constant from "./constant.js";
import curveLinear from "./curve/linear.js";
import {x as pointX, y as pointY} from "./point.js";

export default function() {
var x = pointX,
y = pointY,
defined = constant(true),
export default function(x, y) {
var defined = constant(true),
context = null,
curve = curveLinear,
output = null;

x = typeof x === "function" ? x : (x === undefined) ? pointX : constant(x);
y = typeof y === "function" ? y : (y === undefined) ? pointY : constant(y);

function line(data) {
var i,
n = data.length,
n = (data = array(data)).length,
d,
defined0 = false,
buffer;
Expand Down
3 changes: 2 additions & 1 deletion src/pie.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import array from "./array.js";
import constant from "./constant.js";
import descending from "./descending.js";
import identity from "./identity.js";
Expand All @@ -13,7 +14,7 @@ export default function() {

function pie(data) {
var i,
n = data.length,
n = (data = array(data)).length,
j,
k,
sum = 0,
Expand Down
29 changes: 15 additions & 14 deletions src/stack.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {slice} from "./array.js";
import array from "./array.js";
import constant from "./constant.js";
import offsetNone from "./offset/none.js";
import orderNone from "./order/none.js";
Expand All @@ -7,29 +7,30 @@ function stackValue(d, key) {
return d[key];
}

function stackSeries(key) {
const series = [];
series.key = key;
return series;
}

export default function() {
var keys = constant([]),
order = orderNone,
offset = offsetNone,
value = stackValue;

function stack(data) {
var kz = keys.apply(this, arguments),
i,
m = data.length,
n = kz.length,
sz = new Array(n),
var sz = Array.from(keys.apply(this, arguments), stackSeries),
i, n = sz.length, j = -1,
oz;

for (i = 0; i < n; ++i) {
for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
si[j] = sij = [0, +value(data[j], ki, j, data)];
sij.data = data[j];
for (const d of data) {
for (i = 0, ++j; i < n; ++i) {
(sz[i][j] = [0, +value(d, sz[i].key, j, data)]).data = d;
}
si.key = ki;
}

for (i = 0, oz = order(sz); i < n; ++i) {
for (i = 0, oz = array(order(sz)); i < n; ++i) {
sz[oz[i]].index = i;
}

Expand All @@ -38,15 +39,15 @@ export default function() {
}

stack.keys = function(_) {
return arguments.length ? (keys = typeof _ === "function" ? _ : constant(slice.call(_)), stack) : keys;
return arguments.length ? (keys = typeof _ === "function" ? _ : constant(Array.from(_)), stack) : keys;
};

stack.value = function(_) {
return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), stack) : value;
};

stack.order = function(_) {
return arguments.length ? (order = _ == null ? orderNone : typeof _ === "function" ? _ : constant(slice.call(_)), stack) : order;
return arguments.length ? (order = _ == null ? orderNone : typeof _ === "function" ? _ : constant(Array.from(_)), stack) : order;
};

stack.offset = function(_) {
Expand Down
8 changes: 4 additions & 4 deletions src/symbol.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export var symbols = [
wye
];

export default function() {
var type = constant(circle),
size = constant(64),
context = null;
export default function(type, size) {
var context = null;
type = typeof type === "function" ? type : constant(type || circle);
size = typeof size === "function" ? size : constant(size === undefined ? 64 : +size);

function symbol() {
var buffer;
Expand Down
11 changes: 11 additions & 0 deletions test/area-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ tape("area() returns a default area shape", function(test) {
test.end();
});

tape("area(x, y0, y1) sets x0, y0 and y1", function(test) {
var x = function() {}, y = function() {};
test.equal(shape.area(x).x0(), x);
test.equal(shape.area(x, y).y0(), y);
test.equal(shape.area(x, 0, y).y1(), y);
test.equal(shape.area(3, 2, 1).x0()("aa"), 3);
test.equal(shape.area(3, 2, 1).y0()("aa"), 2);
test.equal(shape.area(3, 2, 1).y1()("aa"), 1);
test.end();
});

tape("area.x(f)(data) passes d, i and data to the specified function f", function(test) {
var data = ["a", "b"], actual = [];
shape.area().x(function() { actual.push([].slice.call(arguments)); })(data);
Expand Down
Loading

0 comments on commit a1d22ee

Please sign in to comment.