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

area line option #2133

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
6 changes: 6 additions & 0 deletions docs/marks/area.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ Plot.plot((() => {
```
:::

The **line** option draws a line connecting the points with coordinates **x2** and **y2** (the “top of the area”).

Example TK.

See also the [ridgeline chart](https://observablehq.com/@observablehq/plot-ridgeline) example.

Interpolation is controlled by the [**curve** option](../features/curves.md). The default curve is *linear*, which draws straight line segments between pairs of adjacent points. A *step* curve is nice for emphasizing when the value changes, while *basis* and *catmull–rom* are nice for smoothing.
Expand Down Expand Up @@ -292,6 +296,8 @@ Points along the baseline and topline are connected in input order. Likewise, if

The area mark supports [curve options](../features/curves.md) to control interpolation between points. If any of the **x1**, **y1**, **x2**, or **y2** values are invalid (undefined, null, or NaN), the baseline and topline will be interrupted, resulting in a break that divides the area shape into multiple segments. (See [d3-shape’s *area*.defined](https://d3js.org/d3-shape/area#area_defined) for more.) If an area segment consists of only a single point, it may appear invisible unless rendered with rounded or square line caps. In addition, some curves such as *cardinal-open* only render a visible segment if it contains multiple points.

The **line** option <VersionBadge pr="2133" /> (boolean, defaults to false) indicates whether the mark should draw a line connecting the points with coordinates **x2** and **y2** (the “top of the area”). In that case, the **stroke** attribute defaults to *currentColor* and is applied to the line only, as well as the stroke opacity. The line uses the same **curve** as the area.

## areaY(*data*, *options*) {#areaY}

```js
Expand Down
6 changes: 6 additions & 0 deletions src/marks/area.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ export interface AreaOptions extends MarkOptions, StackOptions, CurveOptions {
* **stroke** if a channel.
*/
z?: ChannelValue;

/**
* Whether a line should be drawn connecting the points with coordinates *x2*,
* *y2*; the **stroke** then applies to that line and defaults to *currentColor*.
*/
line?: boolean;
}

/** Options for the areaX mark. */
Expand Down
35 changes: 27 additions & 8 deletions src/marks/area.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {area as shapeArea} from "d3";
import {area as shapeArea, line as shapeLine} from "d3";
import {create} from "../context.js";
import {maybeCurve} from "../curve.js";
import {Mark} from "../mark.js";
Expand All @@ -24,7 +24,7 @@ const defaults = {

export class Area extends Mark {
constructor(data, options = {}) {
const {x1, y1, x2, y2, z, curve, tension} = options;
const {x1, y1, x2, y2, z, curve, tension, line} = options;
super(
data,
{
Expand All @@ -35,10 +35,11 @@ export class Area extends Mark {
z: {value: maybeZ(options), optional: true}
},
options,
defaults
line ? {...defaults, stroke: "currentColor"} : defaults
);
this.z = z;
this.curve = maybeCurve(curve, tension);
this.line = !!line;
}
filter(index) {
return index;
Expand All @@ -48,11 +49,14 @@ export class Area extends Mark {
return create("svg:g", context)
.call(applyIndirectStyles, this, dimensions, context)
.call(applyTransform, this, scales, 0, 0)
.call((g) =>
g
.call((g) => {
g = g
.selectAll()
.data(groupIndex(index, [X1, Y1, X2, Y2], this, channels))
.enter()
.enter();

if (this.line) g = g.append("g");
const area = g
.append("path")
.call(applyDirectStyles, this)
.call(applyGroupedChannelStyles, this, channels)
Expand All @@ -65,8 +69,23 @@ export class Area extends Mark {
.y0((i) => Y1[i])
.x1((i) => X2[i])
.y1((i) => Y2[i])
)
)
);
if (this.line) {
area.attr("stroke", "none");
g.append("path")
.call(applyDirectStyles, this)
.call(applyGroupedChannelStyles, this, channels)
.attr(
"d",
shapeLine()
.curve(this.curve)
.defined((i) => i >= 0)
.x((i) => X2[i])
.y((i) => Y2[i])
)
.attr("fill", "none");
}
})
.node();
}
}
Expand Down
80 changes: 80 additions & 0 deletions test/output/aaplCloseLine.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading