|
1 |
| -import {InternSet, extent, format, utcFormat} from "d3"; |
| 1 | +import {InternSet, extent, format, scaleIdentity, utcFormat} from "d3"; |
2 | 2 | import {formatDefault} from "../format.js";
|
3 | 3 | import {marks} from "../mark.js";
|
4 | 4 | import {radians} from "../math.js";
|
@@ -130,32 +130,35 @@ function axisKy(
|
130 | 130 | })
|
131 | 131 | : null,
|
132 | 132 | !isNoneish(fill) && label !== null
|
133 |
| - ? text( |
134 |
| - [], |
135 |
| - labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
136 |
| - const scale = scales[k]; |
137 |
| - const {marginTop, marginRight, marginBottom, marginLeft} = (k === "y" && dimensions.inset) || dimensions; |
138 |
| - const cla = labelAnchor ?? (scale.bandwidth ? "center" : "top"); |
139 |
| - const clo = labelOffset ?? (anchor === "right" ? marginRight : marginLeft) - 3; |
140 |
| - if (cla === "center") { |
141 |
| - this.textAnchor = undefined; // middle |
142 |
| - this.lineAnchor = anchor === "right" ? "bottom" : "top"; |
143 |
| - this.frameAnchor = anchor; |
144 |
| - this.rotate = -90; |
145 |
| - } else { |
146 |
| - this.textAnchor = anchor === "right" ? "end" : "start"; |
147 |
| - this.lineAnchor = cla; |
148 |
| - this.frameAnchor = `${cla}-${anchor}`; |
149 |
| - this.rotate = 0; |
150 |
| - } |
151 |
| - this.dy = cla === "top" ? 3 - marginTop : cla === "bottom" ? marginBottom - 3 : 0; |
152 |
| - this.dx = anchor === "right" ? clo : -clo; |
153 |
| - this.ariaLabel = `${k}-axis label`; |
154 |
| - return { |
155 |
| - facets: [[0]], |
156 |
| - channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
157 |
| - }; |
158 |
| - }) |
| 133 | + ? Object.assign( |
| 134 | + text( |
| 135 | + [], |
| 136 | + labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
| 137 | + const scale = scales[k]; |
| 138 | + const {marginTop, marginRight, marginBottom, marginLeft} = (k === "y" && dimensions.inset) || dimensions; |
| 139 | + const cla = labelAnchor ?? (scale.bandwidth ? "center" : "top"); |
| 140 | + const clo = labelOffset ?? (anchor === "right" ? marginRight : marginLeft) - 3; |
| 141 | + if (cla === "center") { |
| 142 | + this.textAnchor = undefined; // middle |
| 143 | + this.lineAnchor = anchor === "right" ? "bottom" : "top"; |
| 144 | + this.frameAnchor = anchor; |
| 145 | + this.rotate = -90; |
| 146 | + } else { |
| 147 | + this.textAnchor = anchor === "right" ? "end" : "start"; |
| 148 | + this.lineAnchor = cla; |
| 149 | + this.frameAnchor = `${cla}-${anchor}`; |
| 150 | + this.rotate = 0; |
| 151 | + } |
| 152 | + this.dy = cla === "top" ? 3 - marginTop : cla === "bottom" ? marginBottom - 3 : 0; |
| 153 | + this.dx = anchor === "right" ? clo : -clo; |
| 154 | + this.ariaLabel = `${k}-axis label`; |
| 155 | + return { |
| 156 | + facets: [[0]], |
| 157 | + channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
| 158 | + }; |
| 159 | + }) |
| 160 | + ), |
| 161 | + {zoom: null} |
159 | 162 | )
|
160 | 163 | : null
|
161 | 164 | );
|
@@ -231,29 +234,32 @@ function axisKx(
|
231 | 234 | })
|
232 | 235 | : null,
|
233 | 236 | !isNoneish(fill) && label !== null
|
234 |
| - ? text( |
235 |
| - [], |
236 |
| - labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
237 |
| - const scale = scales[k]; |
238 |
| - const {marginTop, marginRight, marginBottom, marginLeft} = (k === "x" && dimensions.inset) || dimensions; |
239 |
| - const cla = labelAnchor ?? (scale.bandwidth ? "center" : "right"); |
240 |
| - const clo = labelOffset ?? (anchor === "top" ? marginTop : marginBottom) - 3; |
241 |
| - if (cla === "center") { |
242 |
| - this.frameAnchor = anchor; |
243 |
| - this.textAnchor = undefined; // middle |
244 |
| - } else { |
245 |
| - this.frameAnchor = `${anchor}-${cla}`; |
246 |
| - this.textAnchor = cla === "right" ? "end" : "start"; |
247 |
| - } |
248 |
| - this.lineAnchor = anchor; |
249 |
| - this.dy = anchor === "top" ? -clo : clo; |
250 |
| - this.dx = cla === "right" ? marginRight - 3 : cla === "left" ? 3 - marginLeft : 0; |
251 |
| - this.ariaLabel = `${k}-axis label`; |
252 |
| - return { |
253 |
| - facets: [[0]], |
254 |
| - channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
255 |
| - }; |
256 |
| - }) |
| 237 | + ? Object.assign( |
| 238 | + text( |
| 239 | + [], |
| 240 | + labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
| 241 | + const scale = scales[k]; |
| 242 | + const {marginTop, marginRight, marginBottom, marginLeft} = (k === "x" && dimensions.inset) || dimensions; |
| 243 | + const cla = labelAnchor ?? (scale.bandwidth ? "center" : "right"); |
| 244 | + const clo = labelOffset ?? (anchor === "top" ? marginTop : marginBottom) - 3; |
| 245 | + if (cla === "center") { |
| 246 | + this.frameAnchor = anchor; |
| 247 | + this.textAnchor = undefined; // middle |
| 248 | + } else { |
| 249 | + this.frameAnchor = `${anchor}-${cla}`; |
| 250 | + this.textAnchor = cla === "right" ? "end" : "start"; |
| 251 | + } |
| 252 | + this.lineAnchor = anchor; |
| 253 | + this.dy = anchor === "top" ? -clo : clo; |
| 254 | + this.dx = cla === "right" ? marginRight - 3 : cla === "left" ? 3 - marginLeft : 0; |
| 255 | + this.ariaLabel = `${k}-axis label`; |
| 256 | + return { |
| 257 | + facets: [[0]], |
| 258 | + channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
| 259 | + }; |
| 260 | + }) |
| 261 | + ), |
| 262 | + {zoom: null} |
257 | 263 | )
|
258 | 264 | : null
|
259 | 265 | );
|
@@ -522,8 +528,10 @@ function labelOptions(
|
522 | 528 |
|
523 | 529 | function axisMark(mark, k, anchor, ariaLabel, data, options, initialize) {
|
524 | 530 | let channels;
|
| 531 | + let u; |
525 | 532 |
|
526 | 533 | function axisInitializer(data, facets, _channels, scales, dimensions, context) {
|
| 534 | + u = arguments; |
527 | 535 | const initializeFacets = data == null && (k === "fx" || k === "fy");
|
528 | 536 | const {[k]: scale} = scales;
|
529 | 537 | if (!scale) throw new Error(`missing scale: ${k}`);
|
@@ -617,6 +625,24 @@ function axisMark(mark, k, anchor, ariaLabel, data, options, initialize) {
|
617 | 625 | }
|
618 | 626 | m.ariaLabel = ariaLabel;
|
619 | 627 | if (m.clip === undefined) m.clip = false; // don’t clip axes by default
|
| 628 | + m.zoom = function (g, transform) { |
| 629 | + if (!(k === "x" || k === "y")) return g; |
| 630 | + const [, , , {[k]: scale}, dimensions, context] = [...u]; |
| 631 | + if (scale.bandwidth) return g; // TODO ordinal scales? |
| 632 | + const scale2 = transform[k === "x" ? "rescaleX" : "rescaleY"](scale ?? scaleIdentity()); |
| 633 | + const ticks = scale2.ticks(); |
| 634 | + g.replaceWith( |
| 635 | + (g = m.render.call( |
| 636 | + m, |
| 637 | + ticks.map((d, i) => i), |
| 638 | + {[k]: scale2}, |
| 639 | + {[k]: ticks.map(scale2), text: ticks}, |
| 640 | + dimensions, |
| 641 | + context |
| 642 | + )) |
| 643 | + ); |
| 644 | + return g; |
| 645 | + }; |
620 | 646 | return m;
|
621 | 647 | }
|
622 | 648 |
|
|
0 commit comments