Skip to content

Commit 96e4ea0

Browse files
authored
move Mark class (#1235)
1 parent f49fbcb commit 96e4ea0

23 files changed

+117
-100
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
"_moduleAliases": {
4040
"@observablehq/plot": "./src/index.js"
4141
},
42-
"sideEffects": false,
42+
"sideEffects": [
43+
"./src/plot.js"
44+
],
4345
"devDependencies": {
4446
"@esbuild-kit/core-utils": "^2.0.2",
4547
"@rollup/plugin-commonjs": "^23.0.4",

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export {plot, Mark, marks} from "./plot.js";
1+
export {plot, marks} from "./plot.js";
2+
export {Mark} from "./mark.js";
23
export {Area, area, areaX, areaY} from "./marks/area.js";
34
export {Arrow, arrow} from "./marks/arrow.js";
45
export {BarX, BarY, barX, barY} from "./marks/bar.js";

src/mark.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {Channels, channelDomain, valueObject} from "./channel.js";
2+
import {defined} from "./defined.js";
3+
import {arrayify, isDomainSort, range} from "./options.js";
4+
import {keyword, maybeNamed} from "./options.js";
5+
import {maybeProject} from "./projection.js";
6+
import {maybeClip, styles} from "./style.js";
7+
import {basic, initializer} from "./transforms/basic.js";
8+
9+
export class Mark {
10+
constructor(data, channels = {}, options = {}, defaults) {
11+
const {facet = "auto", fx, fy, sort, dx, dy, clip, channels: extraChannels} = options;
12+
this.data = data;
13+
this.sort = isDomainSort(sort) ? sort : null;
14+
this.initializer = initializer(options).initializer;
15+
this.transform = this.initializer ? options.transform : basic(options).transform;
16+
if (facet === null || facet === false) {
17+
this.facet = null;
18+
} else {
19+
this.facet = keyword(facet === true ? "include" : facet, "facet", ["auto", "include", "exclude"]);
20+
this.fx = fx;
21+
this.fy = fy;
22+
}
23+
channels = maybeNamed(channels);
24+
if (extraChannels !== undefined) channels = {...maybeNamed(extraChannels), ...channels};
25+
if (defaults !== undefined) channels = {...styles(this, options, defaults), ...channels};
26+
this.channels = Object.fromEntries(
27+
Object.entries(channels).filter(([name, {value, optional}]) => {
28+
if (value != null) return true;
29+
if (optional) return false;
30+
throw new Error(`missing channel value: ${name}`);
31+
})
32+
);
33+
this.dx = +dx || 0;
34+
this.dy = +dy || 0;
35+
this.clip = maybeClip(clip);
36+
}
37+
initialize(facets, facetChannels) {
38+
let data = arrayify(this.data);
39+
if (facets === undefined && data != null) facets = [range(data)];
40+
if (this.transform != null) ({facets, data} = this.transform(data, facets)), (data = arrayify(data));
41+
const channels = Channels(this.channels, data);
42+
if (this.sort != null) channelDomain(channels, facetChannels, data, this.sort); // mutates facetChannels!
43+
return {data, facets, channels};
44+
}
45+
filter(index, channels, values) {
46+
for (const name in channels) {
47+
const {filter = defined} = channels[name];
48+
if (filter !== null) {
49+
const value = values[name];
50+
index = index.filter((i) => filter(value[i]));
51+
}
52+
}
53+
return index;
54+
}
55+
// If there is a projection, and there are both x and y channels (or x1 and
56+
// y1, or x2 and y2 channels), and those channels are associated with the x
57+
// and y scale respectively (and not already in screen coordinates as with an
58+
// initializer), then apply the projection, replacing the x and y values. Note
59+
// that the x and y scales themselves don’t exist if there is a projection,
60+
// but whether the channels are associated with scales still determines
61+
// whether the projection should apply; think of the projection as a
62+
// combination xy-scale.
63+
project(channels, values, context) {
64+
maybeProject("x", "y", channels, values, context);
65+
maybeProject("x1", "y1", channels, values, context);
66+
maybeProject("x2", "y2", channels, values, context);
67+
}
68+
scale(channels, scales, context) {
69+
const values = valueObject(channels, scales);
70+
if (context.projection) this.project(channels, values, context);
71+
return values;
72+
}
73+
}

src/marks/area.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {area as shapeArea} from "d3";
22
import {create} from "../context.js";
33
import {Curve} from "../curve.js";
44
import {first, indexOf, maybeZ, second} from "../options.js";
5-
import {Mark} from "../plot.js";
5+
import {Mark} from "../mark.js";
66
import {
77
applyDirectStyles,
88
applyIndirectStyles,

src/marks/arrow.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {create} from "../context.js";
22
import {radians} from "../math.js";
33
import {constant} from "../options.js";
4-
import {Mark} from "../plot.js";
4+
import {Mark} from "../mark.js";
55
import {applyChannelStyles, applyDirectStyles, applyIndirectStyles, applyTransform} from "../style.js";
66
import {maybeSameValue} from "./link.js";
77

src/marks/bar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {create} from "../context.js";
22
import {identity, indexOf, number} from "../options.js";
3-
import {Mark} from "../plot.js";
3+
import {Mark} from "../mark.js";
44
import {isCollapsed} from "../scales.js";
55
import {
66
applyDirectStyles,

src/marks/delaunay.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {group, pathRound as path, select, Delaunay} from "d3";
22
import {create} from "../context.js";
33
import {Curve} from "../curve.js";
44
import {constant, maybeTuple, maybeZ} from "../options.js";
5-
import {Mark} from "../plot.js";
5+
import {Mark} from "../mark.js";
66
import {
77
applyChannelStyles,
88
applyDirectStyles,

src/marks/density.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {contourDensity, create, geoPath} from "d3";
22
import {isTypedArray, maybeTuple, maybeZ} from "../options.js";
3-
import {Mark} from "../plot.js";
3+
import {Mark} from "../mark.js";
44
import {Position} from "../projection.js";
55
import {coerceNumbers} from "../scales.js";
66
import {

src/marks/dot.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {pathRound as path, symbolCircle} from "d3";
22
import {create} from "../context.js";
33
import {negative, positive} from "../defined.js";
44
import {identity, maybeFrameAnchor, maybeNumberChannel, maybeTuple} from "../options.js";
5-
import {Mark} from "../plot.js";
5+
import {Mark} from "../mark.js";
66
import {
77
applyChannelStyles,
88
applyDirectStyles,

src/marks/frame.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {create} from "../context.js";
22
import {number} from "../options.js";
3-
import {Mark} from "../plot.js";
3+
import {Mark} from "../mark.js";
44
import {applyDirectStyles, applyIndirectStyles, applyTransform} from "../style.js";
55

66
const defaults = {

0 commit comments

Comments
 (0)