Skip to content

Commit

Permalink
Merge branch 'main' into feature/1-move-example-to-runes
Browse files Browse the repository at this point in the history
  • Loading branch information
Fil authored Nov 24, 2024
2 parents 19b6a85 + b2b587a commit 7a855a6
Show file tree
Hide file tree
Showing 41 changed files with 9,308 additions and 211 deletions.
3 changes: 2 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export default defineConfig({
items: [
{text: "What is Plot?", link: "/what-is-plot"},
{text: "Why Plot?", link: "/why-plot"},
{text: "Getting started", link: "/getting-started"}
{text: "Getting started", link: "/getting-started"},
{text: "Examples", link: "https://observablehq.com/@observablehq/plot-gallery"}
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/features/marks.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ All marks support the following style options:
* **clip** - whether and how to clip the mark
* **tip** - whether to generate an implicit [pointer](../interactions/pointer.md) [tip](../marks/tip.md) <VersionBadge version="0.6.7" />

If the **clip** option is *frame* (or equivalently true), the mark is clipped to the frame’s dimensions; if the **clip** option is null (or equivalently false), the mark is not clipped. If the **clip** option is *sphere*, then a [geographic projection](./projections.md) is required and the mark will be clipped to the projected sphere (_e.g._, the front hemisphere when using the orthographic projection).
If the **clip** option is *frame* (or equivalently true), the mark is clipped to the frame’s dimensions. If the **clip** option is null (or equivalently false), the mark is not clipped. If the **clip** option is *sphere*, the mark will be clipped to the projected sphere (_e.g._, the front hemisphere when using the orthographic projection); a [geographic projection](./projections.md) is required in this case. Lastly if the **clip** option is a GeoJSON object <VersionBadge pr="2243" />, the mark will be clipped to the projected geometry.

If the **tip** option is true, a [tip mark](../marks/tip.md) with the [pointer transform](../interactions/pointer.md) will be derived from this mark and placed atop all other marks, offering details on demand. If the **tip** option is set to an options object, these options will be passed to the derived tip mark. If the **tip** option (or, if an object, its **pointer** option) is set to *x*, *y*, or *xy*, [pointerX](../interactions/pointer.md#pointerX), [pointerY](../interactions/pointer.md#pointerY), or [pointer](../interactions/pointer.md#pointer) will be used, respectively; otherwise the pointing mode will be chosen automatically. (If the **tip** mark option is truthy, the **title** channel is no longer applied using an SVG title element as this would conflict with the tip mark.)

Expand Down
6 changes: 6 additions & 0 deletions docs/features/plots.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
---
prev:
text: Getting started
link: /getting-started
---

<script setup>

import * as Plot from "@observablehq/plot";
Expand Down
6 changes: 6 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
---
next:
text: Plots
link: /features/plots
---

<script setup>

import * as Plot from "@observablehq/plot";
Expand Down
5 changes: 4 additions & 1 deletion src/context.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {GeoStreamWrapper} from "d3";
import type {GeoPath, GeoStreamWrapper} from "d3";
import type {MarkOptions} from "./mark.js";

/** Additional rendering context provided to marks and initializers. */
Expand All @@ -18,6 +18,9 @@ export interface Context {
/** The current projection, if any. */
projection?: GeoStreamWrapper;

/** A function to draw GeoJSON with the current projection, if any, otherwise with the x and y scales. */
path: () => GeoPath;

/** The default clip for all marks. */
clip?: MarkOptions["clip"];
}
7 changes: 5 additions & 2 deletions src/mark.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type {GeoPermissibleObjects} from "d3";
import type {Channel, ChannelDomainSort, ChannelValue, ChannelValues, ChannelValueSpec} from "./channel.js";
import type {Context} from "./context.js";
import type {Dimensions} from "./dimensions.js";
import type {PointerOptions} from "./interactions/pointer.js";
import type {TipOptions} from "./marks/tip.js";
import type {plot} from "./plot.js";
import type {ScaleFunctions} from "./scales.js";
Expand Down Expand Up @@ -288,18 +290,19 @@ export interface MarkOptions {
title?: ChannelValue;

/** Whether to generate a tooltip for this mark, and any tip options. */
tip?: boolean | TipPointer | (TipOptions & {pointer?: TipPointer});
tip?: boolean | TipPointer | (TipOptions & PointerOptions & {pointer?: TipPointer});

/**
* How to clip the mark; one of:
*
* - *frame* or true - clip to the plot’s frame (inner area)
* - *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)
* - geojson - a GeoJSON object, typically with polygonal geometry
* - null or false - do not clip
*
* The *sphere* clip option requires a geographic projection.
*/
clip?: "frame" | "sphere" | boolean | null;
clip?: "frame" | "sphere" | GeoPermissibleObjects | boolean | null;

/**
* The horizontal offset in pixels; a constant option. On low-density screens,
Expand Down
18 changes: 2 additions & 16 deletions src/marks/geo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {geoGraticule10, geoPath, geoTransform} from "d3";
import {geoGraticule10} from "d3";
import {create} from "../context.js";
import {negative, positive} from "../defined.js";
import {Mark} from "../mark.js";
Expand Down Expand Up @@ -35,7 +35,7 @@ export class Geo extends Mark {
}
render(index, scales, channels, dimensions, context) {
const {geometry: G, r: R} = channels;
const path = geoPath(context.projection ?? scaleProjection(scales));
const path = context.path();
const {r} = this;
if (negative(r)) index = [];
else if (r !== undefined) path.pointRadius(r);
Expand All @@ -55,20 +55,6 @@ export class Geo extends Mark {
}
}

// If no projection is specified, default to a projection that passes points
// through the x and y scales, if any.
function scaleProjection({x: X, y: Y}) {
if (X || Y) {
X ??= (x) => x;
Y ??= (y) => y;
return geoTransform({
point(x, y) {
this.stream.point(X(x), Y(y));
}
});
}
}

export function geo(data, options = {}) {
if (options.tip && options.x === undefined && options.y === undefined) options = centroid(options);
else if (options.geometry === undefined) options = {...options, geometry: identity};
Expand Down
Loading

0 comments on commit 7a855a6

Please sign in to comment.