Skip to content

Commit

Permalink
support for fillOpacity in swatch and ramp color legends (observableh…
Browse files Browse the repository at this point in the history
…q#1407)

* support for fillOpacity in swatch and ramp color legends

closes observablehq#1356

* opacity

* fill opacity it is

* use fill-opacity

* minimize diff

* minimize diff; add default

* regenerate test snapshots

---------

Co-authored-by: Mike Bostock <[email protected]>
  • Loading branch information
Fil and mbostock authored Apr 1, 2023
1 parent 1d67219 commit 89657a1
Show file tree
Hide file tree
Showing 12 changed files with 331 additions and 3 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ Categorical and ordinal color legends are rendered as swatches, unless *options*
* *options*.**columns** - the number of swatches per row
* *options*.**marginLeft** - the legend’s left margin
* *options*.**className** - a class name, that defaults to a randomly generated string scoping the styles
* *options*.**opacity** - the swatch fill opacity
* *options*.**width** - the legend’s width (in pixels)

Symbol legends are rendered as swatches and support the options above in addition to the following options:
Expand All @@ -679,6 +680,7 @@ Continuous color legends are rendered as a ramp, and can be configured with the
* *options*.**marginRight** - the legend’s right margin
* *options*.**marginBottom** - the legend’s bottom margin
* *options*.**marginLeft** - the legend’s left margin
* *options*.**opacity** - the ramp’s fill opacity

The **style** legend option allows custom styles to override Plot’s defaults; it has the same behavior as in Plot’s top-level [layout options](#layout-options).

Expand Down
2 changes: 2 additions & 0 deletions src/legends.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export interface LegendOptions {
fill?: string;
/** The desired fill opacity of symbols. For *symbol* legends only. */
fillOpacity?: number;
/** The desired opacity of the color swatches or ramp. For *color* legends only. */
opacity?: number;
/** The desired stroke color of symbols; use *color* for a redundant encoding. For *symbol* legends only. */
stroke?: string;
/** The desired stroke opacity of symbols. For *symbol* legends only. */
Expand Down
7 changes: 6 additions & 1 deletion src/legends/ramp.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {quantize, interpolateNumber, piecewise, format, scaleBand, scaleLinear, axisBottom} from "d3";
import {inferFontVariant} from "../axes.js";
import {createContext, create} from "../context.js";
import {map} from "../options.js";
import {map, maybeNumberChannel} from "../options.js";
import {interpolatePiecewise} from "../scales/quantitative.js";
import {applyInlineStyles, impliedString, maybeClassName} from "../style.js";

Expand All @@ -20,10 +20,12 @@ export function legendRamp(color, options) {
tickFormat,
fontVariant = inferFontVariant(color),
round = true,
opacity,
className
} = options;
const context = createContext(options);
className = maybeClassName(className);
opacity = maybeNumberChannel(opacity)[1];
if (tickFormat === null) tickFormat = () => null;

const svg = create("svg", context)
Expand Down Expand Up @@ -96,6 +98,7 @@ export function legendRamp(color, options) {

svg
.append("image")
.attr("opacity", opacity)
.attr("x", marginLeft)
.attr("y", marginTop)
.attr("width", width - marginLeft - marginRight)
Expand All @@ -117,6 +120,7 @@ export function legendRamp(color, options) {

svg
.append("g")
.attr("fill-opacity", opacity)
.selectAll()
.data(range)
.enter()
Expand All @@ -137,6 +141,7 @@ export function legendRamp(color, options) {

svg
.append("g")
.attr("fill-opacity", opacity)
.selectAll()
.data(domain)
.enter()
Expand Down
10 changes: 8 additions & 2 deletions src/legends/swatches.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@ function maybeScale(scale, key) {
return s;
}

export function legendSwatches(color, options) {
export function legendSwatches(color, {opacity, ...options} = {}) {
if (!isOrdinalScale(color) && !isThresholdScale(color))
throw new Error(`swatches legend requires ordinal or threshold color scale (not ${color.type})`);
return legendItems(
color,
options,
(selection, scale) =>
selection.append("svg").attr("fill", scale.scale).append("rect").attr("width", "100%").attr("height", "100%"),
selection
.append("svg")
.attr("fill", scale.scale)
.attr("fill-opacity", maybeNumberChannel(opacity)[1])
.append("rect")
.attr("width", "100%")
.attr("height", "100%"),
(className) => `.${className}-swatch svg {
width: var(--swatchWidth);
height: var(--swatchHeight);
Expand Down
38 changes: 38 additions & 0 deletions test/output/colorLegendOpacity.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<div class="plot" style="
--swatchWidth: 15px;
--swatchHeight: 15px;
">
<style>
.plot {
font-family: system-ui, sans-serif;
font-size: 10px;
margin-bottom: 0.5em;
margin-left: 0px;
}

.plot-swatch svg {
width: var(--swatchWidth);
height: var(--swatchHeight);
margin-right: 0.5em;
}

.plot {
display: flex;
align-items: center;
min-height: 33px;
flex-wrap: wrap;
}

.plot-swatch {
display: inline-flex;
align-items: center;
margin-right: 1em;
}
</style><span class="plot-swatch"><svg fill="#4e79a7" fill-opacity="0.5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="100%" height="100%"></rect>
</svg>Dream</span><span class="plot-swatch"><svg fill="#f28e2c" fill-opacity="0.5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="100%" height="100%"></rect>
</svg>Torgersen</span><span class="plot-swatch"><svg fill="#e15759" fill-opacity="0.5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="100%" height="100%"></rect>
</svg>Biscoe</span>
</div>
70 changes: 70 additions & 0 deletions test/output/colorLegendOpacityOrdinalRamp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions test/output/colorLegendOpacityRamp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 50 additions & 0 deletions test/output/symbolLegendOpacityColor.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<div class="plot" style="
--swatchWidth: 15px;
--swatchHeight: 15px;
">
<style>
.plot {
font-family: system-ui, sans-serif;
font-size: 10px;
margin-bottom: 0.5em;
margin-left: 0px;
}

.plot-swatch>svg {
width: var(--swatchWidth);
height: var(--swatchHeight);
margin-right: 0.5em;
overflow: visible;
fill: none;
fill-opacity: 1;
stroke: undefined;
stroke-width: 1.5px;
stroke-opacity: 0.5;
}

.plot {
display: flex;
align-items: center;
min-height: 33px;
flex-wrap: wrap;
}

.plot-swatch {
display: inline-flex;
align-items: center;
margin-right: 1em;
}
</style><span class="plot-swatch"><svg viewBox="-8 -8 16 16" stroke="#4e79a7" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M4.5,0A4.5,4.5,0,1,1,-4.5,0A4.5,4.5,0,1,1,4.5,0"></path>
</svg>A</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" stroke="#f28e2c" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M-6.873,0L6.873,0M0,6.873L0,-6.873"></path>
</svg>B</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" stroke="#e15759" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M-4.87,-4.87L4.87,4.87M-4.87,4.87L4.87,-4.87"></path>
</svg>C</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" stroke="#76b7b2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M0,-5.443L4.714,2.721L-4.714,2.721Z"></path>
</svg>D</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" stroke="#59a14f" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M0,4.769L0,-4.769M-4.13,-2.384L4.13,2.384M-4.13,2.384L4.13,-2.384"></path>
</svg>E</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" stroke="#edc949" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M3.534,3.534L3.534,-3.534L-3.534,-3.534L-3.534,3.534Z"></path>
</svg>F</span>
</div>
44 changes: 44 additions & 0 deletions test/output/symbolLegendOpacityFill.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="plot" style="
--swatchWidth: 15px;
--swatchHeight: 15px;
">
<style>
.plot {
font-family: system-ui, sans-serif;
font-size: 10px;
margin-bottom: 0.5em;
margin-left: 0px;
}

.plot-swatch>svg {
width: var(--swatchWidth);
height: var(--swatchHeight);
margin-right: 0.5em;
overflow: visible;
fill: red;
fill-opacity: 0.5;
stroke: none;
stroke-width: 1.5px;
stroke-opacity: 1;
}

.plot {
display: flex;
align-items: center;
min-height: 33px;
flex-wrap: wrap;
}

.plot-swatch {
display: inline-flex;
align-items: center;
margin-right: 1em;
}
</style><span class="plot-swatch"><svg viewBox="-8 -8 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M4.5,0A4.5,4.5,0,1,1,-4.5,0A4.5,4.5,0,1,1,4.5,0"></path>
</svg>Dream</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M-5.35,-1.783L-1.783,-1.783L-1.783,-5.35L1.783,-5.35L1.783,-1.783L5.35,-1.783L5.35,1.783L1.783,1.783L1.783,5.35L-1.783,5.35L-1.783,1.783L-5.35,1.783Z"></path>
</svg>Torgersen</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M0,-7.423L4.285,0L0,7.423L-4.285,0Z"></path>
</svg>Biscoe</span>
</div>
44 changes: 44 additions & 0 deletions test/output/symbolLegendOpacityStroke.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="plot" style="
--swatchWidth: 15px;
--swatchHeight: 15px;
">
<style>
.plot {
font-family: system-ui, sans-serif;
font-size: 10px;
margin-bottom: 0.5em;
margin-left: 0px;
}

.plot-swatch>svg {
width: var(--swatchWidth);
height: var(--swatchHeight);
margin-right: 0.5em;
overflow: visible;
fill: none;
fill-opacity: 1;
stroke: red;
stroke-width: 1.5px;
stroke-opacity: 0.5;
}

.plot {
display: flex;
align-items: center;
min-height: 33px;
flex-wrap: wrap;
}

.plot-swatch {
display: inline-flex;
align-items: center;
margin-right: 1em;
}
</style><span class="plot-swatch"><svg viewBox="-8 -8 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M4.5,0A4.5,4.5,0,1,1,-4.5,0A4.5,4.5,0,1,1,4.5,0"></path>
</svg>Dream</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M-6.873,0L6.873,0M0,6.873L0,-6.873"></path>
</svg>Torgersen</span><span class="plot-swatch"><svg viewBox="-8 -8 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="M-4.87,-4.87L4.87,4.87M-4.87,4.87L4.87,-4.87"></path>
</svg>Biscoe</span>
</div>
Loading

0 comments on commit 89657a1

Please sign in to comment.