|
1 | | -import {extent, format, timeFormat, utcFormat} from "d3"; |
| 1 | +import {extent, format, scaleIdentity, timeFormat, utcFormat} from "d3"; |
2 | 2 | import {formatDefault} from "../format.js"; |
3 | 3 | import {marks} from "../mark.js"; |
4 | 4 | import {radians} from "../math.js"; |
@@ -129,32 +129,35 @@ function axisKy( |
129 | 129 | }) |
130 | 130 | : null, |
131 | 131 | !isNoneish(fill) && label !== null |
132 | | - ? text( |
133 | | - [], |
134 | | - labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
135 | | - const scale = scales[k]; |
136 | | - const {marginTop, marginRight, marginBottom, marginLeft} = (k === "y" && dimensions.inset) || dimensions; |
137 | | - const cla = labelAnchor ?? (scale.bandwidth ? "center" : "top"); |
138 | | - const clo = labelOffset ?? (anchor === "right" ? marginRight : marginLeft) - 3; |
139 | | - if (cla === "center") { |
140 | | - this.textAnchor = undefined; // middle |
141 | | - this.lineAnchor = anchor === "right" ? "bottom" : "top"; |
142 | | - this.frameAnchor = anchor; |
143 | | - this.rotate = -90; |
144 | | - } else { |
145 | | - this.textAnchor = anchor === "right" ? "end" : "start"; |
146 | | - this.lineAnchor = cla; |
147 | | - this.frameAnchor = `${cla}-${anchor}`; |
148 | | - this.rotate = 0; |
149 | | - } |
150 | | - this.dy = cla === "top" ? 3 - marginTop : cla === "bottom" ? marginBottom - 3 : 0; |
151 | | - this.dx = anchor === "right" ? clo : -clo; |
152 | | - this.ariaLabel = `${k}-axis label`; |
153 | | - return { |
154 | | - facets: [[0]], |
155 | | - channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
156 | | - }; |
157 | | - }) |
| 132 | + ? Object.assign( |
| 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 | + }) |
| 159 | + ), |
| 160 | + {zoom: null} |
158 | 161 | ) |
159 | 162 | : null |
160 | 163 | ); |
@@ -230,29 +233,32 @@ function axisKx( |
230 | 233 | }) |
231 | 234 | : null, |
232 | 235 | !isNoneish(fill) && label !== null |
233 | | - ? text( |
234 | | - [], |
235 | | - labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
236 | | - const scale = scales[k]; |
237 | | - const {marginTop, marginRight, marginBottom, marginLeft} = (k === "x" && dimensions.inset) || dimensions; |
238 | | - const cla = labelAnchor ?? (scale.bandwidth ? "center" : "right"); |
239 | | - const clo = labelOffset ?? (anchor === "top" ? marginTop : marginBottom) - 3; |
240 | | - if (cla === "center") { |
241 | | - this.frameAnchor = anchor; |
242 | | - this.textAnchor = undefined; // middle |
243 | | - } else { |
244 | | - this.frameAnchor = `${anchor}-${cla}`; |
245 | | - this.textAnchor = cla === "right" ? "end" : "start"; |
246 | | - } |
247 | | - this.lineAnchor = anchor; |
248 | | - this.dy = anchor === "top" ? -clo : clo; |
249 | | - this.dx = cla === "right" ? marginRight - 3 : cla === "left" ? 3 - marginLeft : 0; |
250 | | - this.ariaLabel = `${k}-axis label`; |
251 | | - return { |
252 | | - facets: [[0]], |
253 | | - channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
254 | | - }; |
255 | | - }) |
| 236 | + ? Object.assign( |
| 237 | + text( |
| 238 | + [], |
| 239 | + labelOptions({fill, fillOpacity, ...options}, function (data, facets, channels, scales, dimensions) { |
| 240 | + const scale = scales[k]; |
| 241 | + const {marginTop, marginRight, marginBottom, marginLeft} = (k === "x" && dimensions.inset) || dimensions; |
| 242 | + const cla = labelAnchor ?? (scale.bandwidth ? "center" : "right"); |
| 243 | + const clo = labelOffset ?? (anchor === "top" ? marginTop : marginBottom) - 3; |
| 244 | + if (cla === "center") { |
| 245 | + this.frameAnchor = anchor; |
| 246 | + this.textAnchor = undefined; // middle |
| 247 | + } else { |
| 248 | + this.frameAnchor = `${anchor}-${cla}`; |
| 249 | + this.textAnchor = cla === "right" ? "end" : "start"; |
| 250 | + } |
| 251 | + this.lineAnchor = anchor; |
| 252 | + this.dy = anchor === "top" ? -clo : clo; |
| 253 | + this.dx = cla === "right" ? marginRight - 3 : cla === "left" ? 3 - marginLeft : 0; |
| 254 | + this.ariaLabel = `${k}-axis label`; |
| 255 | + return { |
| 256 | + facets: [[0]], |
| 257 | + channels: {text: {value: [formatAxisLabel(k, scale, {anchor, label, labelAnchor: cla, labelArrow})]}} |
| 258 | + }; |
| 259 | + }) |
| 260 | + ), |
| 261 | + {zoom: null} |
256 | 262 | ) |
257 | 263 | : null |
258 | 264 | ); |
@@ -507,8 +513,10 @@ function labelOptions( |
507 | 513 |
|
508 | 514 | function axisMark(mark, k, ariaLabel, data, options, initialize) { |
509 | 515 | let channels; |
| 516 | + let u; |
510 | 517 |
|
511 | 518 | function axisInitializer(data, facets, _channels, scales, dimensions, context) { |
| 519 | + u = arguments; |
512 | 520 | const initializeFacets = data == null && (k === "fx" || k === "fy"); |
513 | 521 | const {[k]: scale} = scales; |
514 | 522 | if (!scale) throw new Error(`missing scale: ${k}`); |
@@ -564,6 +572,24 @@ function axisMark(mark, k, ariaLabel, data, options, initialize) { |
564 | 572 | channels = {}; |
565 | 573 | } |
566 | 574 | m.ariaLabel = ariaLabel; |
| 575 | + m.zoom = function (g, transform) { |
| 576 | + if (!(k === "x" || k === "y")) return g; |
| 577 | + const [, , , {[k]: scale}, dimensions, context] = [...u]; |
| 578 | + if (scale.bandwidth) return g; // TODO ordinal scales? |
| 579 | + const scale2 = transform[k === "x" ? "rescaleX" : "rescaleY"](scale ?? scaleIdentity()); |
| 580 | + const ticks = scale2.ticks(); |
| 581 | + g.replaceWith( |
| 582 | + (g = m.render.call( |
| 583 | + m, |
| 584 | + ticks.map((d, i) => i), |
| 585 | + {[k]: scale2}, |
| 586 | + {[k]: ticks.map(scale2), text: ticks}, |
| 587 | + dimensions, |
| 588 | + context |
| 589 | + )) |
| 590 | + ); |
| 591 | + return g; |
| 592 | + }; |
567 | 593 | return m; |
568 | 594 | } |
569 | 595 |
|
|
0 commit comments