| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- import {line as shapeLine} from "d3";
- import {create} from "../context.js";
- import {curveAuto, maybeCurveAuto} from "../curve.js";
- import {Mark} from "../mark.js";
- import {applyGroupedMarkers, markers} from "../marker.js";
- import {coerceNumbers, indexOf, identity, maybeTuple, maybeZ} from "../options.js";
- import {
- applyDirectStyles,
- applyIndirectStyles,
- applyTransform,
- applyGroupedChannelStyles,
- groupIndex
- } from "../style.js";
- import {maybeDenseIntervalX, maybeDenseIntervalY} from "../transforms/bin.js";
- const defaults = {
- ariaLabel: "line",
- fill: "none",
- stroke: "currentColor",
- strokeWidth: 1.5,
- strokeLinecap: "round",
- strokeLinejoin: "round",
- strokeMiterlimit: 1
- };
- export class Line extends Mark {
- constructor(data, options = {}) {
- const {x, y, z, curve, tension} = options;
- super(
- data,
- {
- x: {value: x, scale: "x"},
- y: {value: y, scale: "y"},
- z: {value: maybeZ(options), optional: true}
- },
- options,
- defaults
- );
- this.z = z;
- this.curve = maybeCurveAuto(curve, tension);
- markers(this, options);
- }
- filter(index) {
- return index;
- }
- project(channels, values, context) {
- // For the auto curve, projection is handled at render.
- if (this.curve !== curveAuto) {
- super.project(channels, values, context);
- }
- }
- render(index, scales, channels, dimensions, context) {
- const {x: X, y: Y} = channels;
- const {curve} = this;
- return create("svg:g", context)
- .call(applyIndirectStyles, this, dimensions, context)
- .call(applyTransform, this, scales)
- .call((g) =>
- g
- .selectAll()
- .data(groupIndex(index, [X, Y], this, channels))
- .enter()
- .append("path")
- .call(applyDirectStyles, this)
- .call(applyGroupedChannelStyles, this, channels)
- .call(applyGroupedMarkers, this, channels, context)
- .attr(
- "d",
- curve === curveAuto && context.projection
- ? sphereLine(context.path(), X, Y)
- : shapeLine()
- .curve(curve)
- .defined((i) => i >= 0)
- .x((i) => X[i])
- .y((i) => Y[i])
- )
- )
- .node();
- }
- }
- function sphereLine(path, X, Y) {
- X = coerceNumbers(X);
- Y = coerceNumbers(Y);
- return (I) => {
- let line = [];
- const lines = [line];
- for (const i of I) {
- // Check for undefined value; see groupIndex.
- if (i === -1) {
- line = [];
- lines.push(line);
- } else {
- line.push([X[i], Y[i]]);
- }
- }
- return path({type: "MultiLineString", coordinates: lines});
- };
- }
- export function line(data, {x, y, ...options} = {}) {
- [x, y] = maybeTuple(x, y);
- return new Line(data, {...options, x, y});
- }
- export function lineX(data, {x = identity, y = indexOf, ...options} = {}) {
- return new Line(data, maybeDenseIntervalY({...options, x, y}));
- }
- export function lineY(data, {x = indexOf, y = identity, ...options} = {}) {
- return new Line(data, maybeDenseIntervalX({...options, x, y}));
- }
|