From 9f1d9c2a4101d5ca1d1629cbbb0554e8a6aa0fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Mon, 5 Apr 2021 12:26:51 +0200 Subject: [PATCH] Separate legends (including main axes) from marks. This allows to add a global color or radius legend to the plot as in https://observablehq.com/@data-workflows/plot-radiuslegend An issue is that the axes are below the marks, but I would tend to put the color and radius legends above them. I kept "unshift" to maintain the exact same order as in the test plots --- src/plot.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plot.js b/src/plot.js index 2665465c66..069b435833 100644 --- a/src/plot.js +++ b/src/plot.js @@ -15,6 +15,7 @@ export function plot(options = {}) { } // Flatten any nested marks. + const legends = options.legends === undefined ? [] : options.legends.flat(Infinity); const marks = options.marks === undefined ? [] : options.marks.flat(Infinity); // A Map from Mark instance to an object of named channel values. @@ -62,8 +63,8 @@ export function plot(options = {}) { // When faceting, render axes for fx and fy instead of x and y. const x = facet !== undefined && scales.fx ? "fx" : "x"; const y = facet !== undefined && scales.fy ? "fy" : "y"; - if (axes[x]) marks.unshift(axes[x]); - if (axes[y]) marks.unshift(axes[y]); + if (axes[x]) legends.unshift(axes[x]); + if (axes[y]) legends.unshift(axes[y]); const {width, height} = dimensions; @@ -79,6 +80,10 @@ export function plot(options = {}) { else Object.assign(this.style, style); }); + for (const legend of legends) { + const node = legend.render([], scales, [], dimensions, axes); + if (node != null) svg.append(() => node); + } for (const mark of marks) { const channels = markChannels.get(mark); const index = markIndex.get(mark);