@genome-spy/core 0.30.0 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/dist/index.es.js +16373 -0
  2. package/dist/index.js +43 -43
  3. package/package.json +10 -7
  4. package/src/data/collector.js +0 -183
  5. package/src/data/collector.test.js +0 -84
  6. package/src/data/dataFlow.js +0 -148
  7. package/src/data/dataFlow.test.js +0 -5
  8. package/src/data/facetNode.js +0 -17
  9. package/src/data/flow.test.js +0 -72
  10. package/src/data/flowBatch.d.ts +0 -40
  11. package/src/data/flowNode.js +0 -283
  12. package/src/data/flowNode.test.js +0 -50
  13. package/src/data/flowOptimizer.js +0 -123
  14. package/src/data/flowOptimizer.test.js +0 -193
  15. package/src/data/flowTestUtils.js +0 -63
  16. package/src/data/formats/fasta.js +0 -32
  17. package/src/data/formats/fasta.test.js +0 -27
  18. package/src/data/sources/dataSource.js +0 -22
  19. package/src/data/sources/dataSourceFactory.js +0 -24
  20. package/src/data/sources/dataUtils.js +0 -78
  21. package/src/data/sources/dynamicCallbackSource.js +0 -57
  22. package/src/data/sources/dynamicSource.js +0 -37
  23. package/src/data/sources/inlineSource.js +0 -67
  24. package/src/data/sources/inlineSource.test.js +0 -56
  25. package/src/data/sources/namedSource.js +0 -79
  26. package/src/data/sources/sequenceSource.js +0 -46
  27. package/src/data/sources/sequenceSource.test.js +0 -46
  28. package/src/data/sources/urlSource.js +0 -74
  29. package/src/data/transforms/aggregate.js +0 -70
  30. package/src/data/transforms/clone.js +0 -40
  31. package/src/data/transforms/clone.test.js +0 -11
  32. package/src/data/transforms/coverage.js +0 -187
  33. package/src/data/transforms/coverage.test.js +0 -123
  34. package/src/data/transforms/filter.js +0 -37
  35. package/src/data/transforms/filter.test.js +0 -18
  36. package/src/data/transforms/filterScoredLabels.js +0 -134
  37. package/src/data/transforms/flattenCompressedExons.js +0 -57
  38. package/src/data/transforms/flattenDelimited.js +0 -74
  39. package/src/data/transforms/flattenDelimited.test.js +0 -87
  40. package/src/data/transforms/flattenSequence.js +0 -39
  41. package/src/data/transforms/flattenSequence.test.js +0 -34
  42. package/src/data/transforms/formula.js +0 -39
  43. package/src/data/transforms/formula.test.js +0 -19
  44. package/src/data/transforms/identifier.js +0 -108
  45. package/src/data/transforms/identifier.test.js +0 -83
  46. package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
  47. package/src/data/transforms/measureText.js +0 -44
  48. package/src/data/transforms/pileup.js +0 -128
  49. package/src/data/transforms/pileup.test.js +0 -70
  50. package/src/data/transforms/project.js +0 -41
  51. package/src/data/transforms/project.test.js +0 -32
  52. package/src/data/transforms/regexExtract.js +0 -61
  53. package/src/data/transforms/regexExtract.test.js +0 -67
  54. package/src/data/transforms/regexFold.js +0 -141
  55. package/src/data/transforms/regexFold.test.js +0 -160
  56. package/src/data/transforms/sample.js +0 -101
  57. package/src/data/transforms/sample.test.js +0 -38
  58. package/src/data/transforms/stack.js +0 -137
  59. package/src/data/transforms/stack.test.js +0 -91
  60. package/src/data/transforms/transformFactory.js +0 -60
  61. package/src/embedApi.d.ts +0 -67
  62. package/src/encoder/accessor.js +0 -82
  63. package/src/encoder/accessor.test.js +0 -47
  64. package/src/encoder/encoder.js +0 -394
  65. package/src/encoder/encoder.test.js +0 -98
  66. package/src/fonts/Lato-Regular.json +0 -1267
  67. package/src/fonts/Lato-Regular.png +0 -0
  68. package/src/fonts/OFL.txt +0 -93
  69. package/src/fonts/README.md +0 -3
  70. package/src/fonts/bmFont.d.ts +0 -58
  71. package/src/fonts/bmFontManager.js +0 -357
  72. package/src/fonts/bmFontMetrics.js +0 -108
  73. package/src/genome/genome.js +0 -317
  74. package/src/genome/genome.test.js +0 -188
  75. package/src/genome/genomeStore.js +0 -54
  76. package/src/genome/locusFormat.js +0 -31
  77. package/src/genome/scaleIndex.d.ts +0 -38
  78. package/src/genome/scaleIndex.js +0 -166
  79. package/src/genome/scaleIndex.test.js +0 -78
  80. package/src/genome/scaleLocus.d.ts +0 -11
  81. package/src/genome/scaleLocus.js +0 -108
  82. package/src/genome/scaleLocus.test.js +0 -4
  83. package/src/genomeSpy.js +0 -785
  84. package/src/gl/arrayBuilder.js +0 -199
  85. package/src/gl/dataToVertices.js +0 -636
  86. package/src/gl/includes/common.glsl +0 -63
  87. package/src/gl/includes/picking.fragment.glsl +0 -1
  88. package/src/gl/includes/picking.vertex.glsl +0 -27
  89. package/src/gl/includes/sampleFacet.glsl +0 -107
  90. package/src/gl/includes/scales.glsl +0 -112
  91. package/src/gl/link.fragment.glsl +0 -18
  92. package/src/gl/link.vertex.glsl +0 -111
  93. package/src/gl/point.fragment.glsl +0 -123
  94. package/src/gl/point.vertex.glsl +0 -129
  95. package/src/gl/rect.fragment.glsl +0 -51
  96. package/src/gl/rect.vertex.glsl +0 -114
  97. package/src/gl/rule.fragment.glsl +0 -52
  98. package/src/gl/rule.vertex.glsl +0 -89
  99. package/src/gl/text.fragment.glsl +0 -31
  100. package/src/gl/text.vertex.glsl +0 -246
  101. package/src/gl/webGLHelper.js +0 -504
  102. package/src/img/bowtie.svg +0 -1
  103. package/src/img/genomespy-favicon.svg +0 -34
  104. package/src/index.html +0 -11
  105. package/src/index.js +0 -128
  106. package/src/marks/link.js +0 -175
  107. package/src/marks/mark.js +0 -975
  108. package/src/marks/markUtils.js +0 -125
  109. package/src/marks/pointMark.js +0 -251
  110. package/src/marks/rectMark.js +0 -241
  111. package/src/marks/rule.js +0 -250
  112. package/src/marks/text.js +0 -278
  113. package/src/node_modules/.vitest/results.json +0 -1
  114. package/src/scale/colorUtils.js +0 -184
  115. package/src/scale/glslScaleGenerator.js +0 -502
  116. package/src/scale/scale.js +0 -451
  117. package/src/scale/scale.test.js +0 -324
  118. package/src/scale/ticks.js +0 -203
  119. package/src/scale/ticks.test.js +0 -40
  120. package/src/singlePageApp.js +0 -13
  121. package/src/spec/axis.d.ts +0 -296
  122. package/src/spec/channel.d.ts +0 -430
  123. package/src/spec/data.d.ts +0 -196
  124. package/src/spec/font.d.ts +0 -15
  125. package/src/spec/genome.d.ts +0 -35
  126. package/src/spec/mark.d.ts +0 -429
  127. package/src/spec/root.d.ts +0 -17
  128. package/src/spec/sampleView.d.ts +0 -180
  129. package/src/spec/scale.d.ts +0 -273
  130. package/src/spec/title.d.ts +0 -102
  131. package/src/spec/tooltip.d.ts +0 -9
  132. package/src/spec/transform.d.ts +0 -479
  133. package/src/spec/view.d.ts +0 -201
  134. package/src/styles/genome-spy.scss +0 -153
  135. package/src/tooltip/dataTooltipHandler.js +0 -64
  136. package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
  137. package/src/tooltip/tooltipHandler.ts +0 -12
  138. package/src/types/filetypes.d.ts +0 -14
  139. package/src/types/flatqueue.d.ts +0 -53
  140. package/src/types/glsl.d.ts +0 -4
  141. package/src/types/internmap.d.ts +0 -22
  142. package/src/types/object.d.ts +0 -21
  143. package/src/types/vega-loader.d.ts +0 -1
  144. package/src/types/vega-scale.d.ts +0 -60
  145. package/src/utils/addBaseUrl.js +0 -19
  146. package/src/utils/addBaseUrl.test.js +0 -22
  147. package/src/utils/animator.js +0 -83
  148. package/src/utils/arrayUtils.js +0 -61
  149. package/src/utils/binnedIndex.js +0 -167
  150. package/src/utils/binnedIndex.test.js +0 -155
  151. package/src/utils/clamp.js +0 -8
  152. package/src/utils/cloner.js +0 -34
  153. package/src/utils/cloner.test.js +0 -24
  154. package/src/utils/coalesce.js +0 -11
  155. package/src/utils/coalesce.test.js +0 -16
  156. package/src/utils/concatIterables.js +0 -26
  157. package/src/utils/concatIterables.test.js +0 -8
  158. package/src/utils/debounce.js +0 -37
  159. package/src/utils/domainArray.js +0 -216
  160. package/src/utils/domainArray.test.js +0 -130
  161. package/src/utils/eerp.js +0 -13
  162. package/src/utils/expression.js +0 -32
  163. package/src/utils/field.js +0 -28
  164. package/src/utils/formatObject.js +0 -31
  165. package/src/utils/indexer.js +0 -43
  166. package/src/utils/indexer.test.js +0 -47
  167. package/src/utils/inertia.js +0 -124
  168. package/src/utils/interactionEvent.js +0 -33
  169. package/src/utils/iterateNestedMaps.js +0 -21
  170. package/src/utils/iterateNestedMaps.test.js +0 -33
  171. package/src/utils/kWayMerge.js +0 -42
  172. package/src/utils/kWayMerge.test.js +0 -26
  173. package/src/utils/layout/flexLayout.js +0 -368
  174. package/src/utils/layout/flexLayout.test.js +0 -311
  175. package/src/utils/layout/grid.js +0 -95
  176. package/src/utils/layout/grid.test.js +0 -71
  177. package/src/utils/layout/padding.js +0 -120
  178. package/src/utils/layout/point.js +0 -23
  179. package/src/utils/layout/rectangle.js +0 -288
  180. package/src/utils/layout/rectangle.test.js +0 -172
  181. package/src/utils/mergeObjects.js +0 -99
  182. package/src/utils/mergeObjects.test.js +0 -42
  183. package/src/utils/numberExtractor.js +0 -24
  184. package/src/utils/numberExtractor.test.js +0 -6
  185. package/src/utils/point.js +0 -14
  186. package/src/utils/propertyCacher.js +0 -70
  187. package/src/utils/propertyCacher.test.js +0 -85
  188. package/src/utils/propertyCoalescer.js +0 -42
  189. package/src/utils/propertyCoalescer.test.js +0 -22
  190. package/src/utils/reservationMap.js +0 -103
  191. package/src/utils/reservationMap.test.js +0 -20
  192. package/src/utils/scaleNull.js +0 -19
  193. package/src/utils/setOperations.js +0 -75
  194. package/src/utils/smoothstep.js +0 -10
  195. package/src/utils/throttle.js +0 -34
  196. package/src/utils/topK.js +0 -76
  197. package/src/utils/topK.test.js +0 -64
  198. package/src/utils/transition.js +0 -74
  199. package/src/utils/ui/tooltip.js +0 -189
  200. package/src/utils/url.js +0 -22
  201. package/src/utils/variableTools.js +0 -24
  202. package/src/utils/variableTools.test.js +0 -13
  203. package/src/view/axisResolution.js +0 -140
  204. package/src/view/axisResolution.test.js +0 -201
  205. package/src/view/axisView.js +0 -747
  206. package/src/view/concatView.js +0 -45
  207. package/src/view/containerView.js +0 -159
  208. package/src/view/facetView.js +0 -491
  209. package/src/view/flowBuilder.js +0 -367
  210. package/src/view/flowBuilder.test.js +0 -125
  211. package/src/view/gridView.js +0 -786
  212. package/src/view/implicitRootView.js +0 -14
  213. package/src/view/importView.js +0 -19
  214. package/src/view/layerView.js +0 -74
  215. package/src/view/rendering.d.ts +0 -44
  216. package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
  217. package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
  218. package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
  219. package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
  220. package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
  221. package/src/view/renderingContext/viewRenderingContext.js +0 -41
  222. package/src/view/scaleResolution.js +0 -797
  223. package/src/view/scaleResolution.test.js +0 -572
  224. package/src/view/scaleResolutionApi.d.ts +0 -40
  225. package/src/view/testUtils.js +0 -51
  226. package/src/view/title.js +0 -165
  227. package/src/view/unitView.js +0 -382
  228. package/src/view/view.js +0 -612
  229. package/src/view/view.test.js +0 -214
  230. package/src/view/viewContext.d.ts +0 -62
  231. package/src/view/viewFactory.js +0 -181
  232. package/src/view/viewFactory.test.js +0 -17
  233. package/src/view/viewUtils.js +0 -327
  234. package/src/view/zoom.js +0 -89
@@ -1,327 +0,0 @@
1
- import { isObject, isString } from "vega-util";
2
- import { loader as vegaLoader } from "vega-loader";
3
-
4
- import UnitView from "./unitView";
5
- import ImportView from "./importView";
6
- // eslint-disable-next-line no-unused-vars
7
- import View, { VISIT_SKIP, VISIT_STOP } from "./view";
8
- import { buildDataFlow } from "./flowBuilder";
9
- import { optimizeDataFlow } from "../data/flowOptimizer";
10
- import { isFieldDef, primaryPositionalChannels } from "../encoder/encoder";
11
- import { rollup } from "d3-array";
12
-
13
- /**
14
- * @typedef {import("./viewContext").default} ViewContext
15
- * @typedef {import("../spec/mark").MarkConfig} MarkConfig
16
- * @typedef {import("../spec/channel").ChannelDef} ChannelDef
17
- * @typedef {import("../spec/view").ContainerSpec} ContainerSpec
18
- * @typedef {import("../spec/view").ViewSpec} ViewSpec
19
- * @typedef {import("../spec/view").LayerSpec} LayerSpec
20
- * @typedef {import("../spec/view").FacetSpec} FacetSpec
21
- * @typedef {import("../spec/sampleView").SampleSpec} SampleSpec
22
- * @typedef {import("../spec/view").UnitSpec} UnitSpec
23
- * @typedef {import("../spec/view").VConcatSpec} VConcatSpec
24
- * @typedef {import("../spec/view").HConcatSpec} HConcatSpec
25
- * @typedef {import("../spec/view").ConcatSpec} ConcatSpec
26
- * @typedef {VConcatSpec | HConcatSpec | ConcatSpec} AnyConcatSpec
27
- * @typedef {import("../spec/view").ImportSpec} ImportSpec
28
- * @typedef {import("../spec/view").ImportConfig} ImportConfig
29
- * @typedef {import("../spec/root").RootSpec} RootSpec
30
- *
31
- * @typedef {import("../spec/view").FacetMapping} FacetMapping
32
- * @typedef {import("../spec/channel").FacetFieldDef} FacetFieldDef
33
- */
34
-
35
- /**
36
- *
37
- * @param {ChannelDef | FacetMapping} def
38
- * @returns {spec is FacetFieldDef}
39
- */
40
- export function isFacetFieldDef(def) {
41
- return def && "field" in def && isString(def.field);
42
- }
43
-
44
- /**
45
- *
46
- * @param {FacetFieldDef | FacetMapping} def
47
- * @returns {spec is FacetMapping}
48
- */
49
- export function isFacetMapping(def) {
50
- return (
51
- ("row" in def && isObject(def.row)) ||
52
- ("column" in def && isObject(def.column))
53
- );
54
- }
55
-
56
- /**
57
- *
58
- * @param {object} config
59
- * @returns {config is ImportConfig}
60
- */
61
- export function isImportConfig(config) {
62
- return "name" in config || "url" in config;
63
- }
64
-
65
- /**
66
- * Returns all marks in the order (DFS) they are rendered
67
- * @param {View} root
68
- */
69
- export function getMarks(root) {
70
- return getFlattenedViews(root)
71
- .filter((view) => view instanceof UnitView)
72
- .map((view) => /** @type {UnitView} */ (view).mark);
73
- }
74
-
75
- /**
76
- * Returns the nodes of the view hierarchy in depth-first order.
77
- *
78
- * @param {View} root
79
- */
80
- export function getFlattenedViews(root) {
81
- /** @type {View[]} */
82
- const views = [];
83
- root.visit((view) => {
84
- views.push(view);
85
- });
86
- return views;
87
- }
88
-
89
- /**
90
- * @param {View} root
91
- */
92
- export function resolveScalesAndAxes(root) {
93
- root.visit((view) => {
94
- if (view instanceof UnitView) {
95
- view.resolve("scale");
96
- }
97
- });
98
-
99
- // Check that each scale resolution has a unique name
100
- /** @type {Set<string>} */
101
- const scaleNames = new Set();
102
- root.visit((view) => {
103
- for (const resolution of Object.values(view.resolutions.scale)) {
104
- const name = resolution.name;
105
- if (name && scaleNames.has(name)) {
106
- throw new Error(
107
- `The same scale name "${name}" occurs in multiple scale resolutions!`
108
- );
109
- }
110
- scaleNames.add(name);
111
- }
112
- });
113
-
114
- root.visit((view) => {
115
- if (view instanceof UnitView) {
116
- view.resolve("axis");
117
- }
118
- });
119
- root.visit((view) => view.onScalesResolved());
120
- }
121
-
122
- /**
123
- * Gives names to zoomable scales that have been pulled to the root. This allows
124
- * the zoomed domains to be bookmarked without explicitly specifying the names.
125
- * This only affects the trivial but common cases, e.g., a genome-browser-like
126
- * view with a shared x scale.
127
- *
128
- * @param {View} root
129
- */
130
- export function setImplicitScaleNames(root) {
131
- for (const channel of primaryPositionalChannels) {
132
- const resolution = root.getScaleResolution(channel);
133
- if (resolution && !resolution.name && resolution.isZoomable()) {
134
- // TODO: Should actually check that the name is not already reserved
135
- resolution.name = `${channel}_at_root`;
136
- }
137
- }
138
- }
139
-
140
- /**
141
- * @param {View} root
142
- * @param {import("../data/dataFlow").default<View>} [existingFlow] Add data flow
143
- * graphs to an existing DataFlow object.
144
- */
145
- export async function initializeData(root, existingFlow) {
146
- const flow = buildDataFlow(root, existingFlow);
147
- optimizeDataFlow(flow);
148
- flow.initialize();
149
-
150
- /** @type {Promise<void>[]} */
151
- const promises = flow.dataSources.map((dataSource) => dataSource.load());
152
-
153
- await Promise.all(promises);
154
-
155
- return flow;
156
- }
157
-
158
- /**
159
- *
160
- * @param {View} view
161
- */
162
- export function findEncodedFields(view) {
163
- /** @type {{view: UnitView, channel: import("../spec/channel").Channel, field: import("../spec/channel").Field, type: import("../spec/channel").Type}[]} */
164
- const fieldInfos = [];
165
-
166
- view.visit((view) => {
167
- if (view instanceof UnitView) {
168
- const encoding = view.getEncoding();
169
- for (const [channel, def] of Object.entries(encoding)) {
170
- if (isFieldDef(def) && "type" in def) {
171
- fieldInfos.push({
172
- view,
173
- channel,
174
- field: def.field,
175
- type: def.type,
176
- });
177
- }
178
- }
179
- return VISIT_SKIP; // Skip sample summaries
180
- }
181
- });
182
-
183
- return fieldInfos;
184
- }
185
-
186
- /**
187
- * @param {import("../spec/view").ImportSpec} spec
188
- * @param {string} baseUrl
189
- * @param {ViewContext} viewContext
190
- */
191
- async function loadExternalViewSpec(spec, baseUrl, viewContext) {
192
- if (!spec.import.url) {
193
- throw new Error(
194
- "Cannot import, not an import spec: " + JSON.stringify(spec)
195
- );
196
- }
197
-
198
- const loader = vegaLoader({ baseURL: baseUrl });
199
- const url = spec.import.url;
200
-
201
- const importedSpec = JSON.parse(
202
- await loader.load(url).catch((/** @type {Error} */ e) => {
203
- throw new Error(
204
- `Could not load imported view spec: ${url} \nReason: ${e.message}`
205
- );
206
- })
207
- );
208
-
209
- if (viewContext.isViewSpec(importedSpec)) {
210
- importedSpec.baseUrl = url.match(/^[^?#]*\//)?.[0];
211
- return importedSpec;
212
- } else {
213
- throw new Error(
214
- `The imported spec "${url}" is not a view spec: ${JSON.stringify(
215
- spec
216
- )}`
217
- );
218
- }
219
- }
220
-
221
- /**
222
- * @param {import("./view").default} viewRoot
223
- */
224
- export async function processImports(viewRoot) {
225
- /** @type {ImportView[]} */
226
- const importViews = [];
227
-
228
- viewRoot.visit((view) => {
229
- if (view instanceof ImportView) {
230
- importViews.push(view);
231
- return VISIT_SKIP;
232
- }
233
- });
234
-
235
- for (const view of importViews) {
236
- const context = view.context;
237
-
238
- // TODO: Parallelize using promises, don't use await
239
- const loadedSpec = await loadExternalViewSpec(
240
- view.spec,
241
- view.getBaseUrl(),
242
- context
243
- );
244
-
245
- // TODO: Let importSpec have a name
246
- const importedView = context.createView(
247
- loadedSpec,
248
- view.parent,
249
- view.name
250
- );
251
- view.parent.replaceChild(view, importedView);
252
-
253
- // Import recursively
254
- await processImports(importedView);
255
- }
256
- }
257
-
258
- /**
259
- * @param {function(View, View[]):void} visitor
260
- */
261
- export function stackifyVisitor(visitor) {
262
- /** @type {View[]} */
263
- const stack = [];
264
-
265
- /** @type {import("./view").Visitor} */
266
- const stackified = (view) => visitor(view, stack);
267
-
268
- stackified.beforeChildren = (view) => {
269
- stack.push(view);
270
- };
271
-
272
- stackified.afterChildren = (view) => {
273
- stack.pop();
274
- };
275
-
276
- return stackified;
277
- }
278
-
279
- /**
280
- * Finds the descendants having the given name. The root is included in the search.
281
- *
282
- * @param {View} root
283
- * @param {string} name View name
284
- * @returns {View[]}
285
- */
286
- export function findDescendantsByPath(root, name) {
287
- /** @type {View[]} */
288
- const descendants = [];
289
-
290
- root.visit((view) => {
291
- if (view.name == name) {
292
- descendants.push(view);
293
- }
294
- });
295
-
296
- return descendants;
297
- }
298
-
299
- /**
300
- *
301
- * @param {View} root
302
- */
303
- export function findUniqueViewNames(root) {
304
- /** @type {View[]} */
305
- const descendants = [];
306
-
307
- root.visit((view) => {
308
- descendants.push(view);
309
- });
310
-
311
- return new Set(
312
- [
313
- ...rollup(
314
- descendants,
315
- (views) => views.length,
316
- (view) => view.name
317
- ),
318
- ]
319
- .filter(([name, count]) => count == 1 && name !== undefined)
320
- .map(([name, count]) => name)
321
- );
322
- }
323
-
324
- /**
325
- * @param {string} name
326
- */
327
- export const isCustomViewName = (name) => !/^(layer|concat)\d+$/.test(name);
package/src/view/zoom.js DELETED
@@ -1,89 +0,0 @@
1
- /**
2
- * @typedef {object} ZoomEvent
3
- * @prop {number} x
4
- * @prop {number} y
5
- * @prop {number} xDelta
6
- * @prop {number} yDelta
7
- * @prop {number} zDelta
8
- */
9
-
10
- /**
11
- * @param {import("../utils/interactionEvent").default} event
12
- * @param {import("./renderingContext/layoutRecorderViewRenderingContext").Rectangle} coords The plot area
13
- * @param {(zoomEvent: ZoomEvent) => void} handleZoom
14
- * @param {import("./viewContext").Hover} [hover]
15
- */
16
- export default function interactionToZoom(event, coords, handleZoom, hover) {
17
- if (event.type == "wheel") {
18
- event.uiEvent.preventDefault(); // TODO: Only if there was something zoomable
19
-
20
- const wheelEvent = /** @type {WheelEvent} */ (event.uiEvent);
21
- const wheelMultiplier = wheelEvent.deltaMode ? 120 : 1;
22
-
23
- let { x, y } = event.point;
24
-
25
- // Snapping to the hovered item:
26
- // We find the currently hovered object and move the pointed coordinates
27
- // to its center if the mark has only primary positional channels.
28
- // This allows the user to rapidly zoom closer without having to
29
- // continuously adjust the cursor position.
30
-
31
- if (hover) {
32
- const e = hover.mark.encoders;
33
- if (e.x && !e.x2 && !e.x.constantValue) {
34
- x = +e.x(hover.datum) * coords.width + coords.x;
35
- }
36
- if (e.y && !e.y2 && !e.y.constantValue) {
37
- y = (1 - +e.y(hover.datum)) * coords.height + coords.y;
38
- }
39
- }
40
-
41
- if (Math.abs(wheelEvent.deltaX) < Math.abs(wheelEvent.deltaY)) {
42
- handleZoom({
43
- x,
44
- y,
45
- xDelta: 0,
46
- yDelta: 0,
47
- zDelta: (wheelEvent.deltaY * wheelMultiplier) / 300,
48
- });
49
- } else {
50
- handleZoom({
51
- x,
52
- y,
53
- xDelta: -wheelEvent.deltaX * wheelMultiplier,
54
- yDelta: 0,
55
- zDelta: 0,
56
- });
57
- }
58
- } else if (
59
- event.type == "mousedown" &&
60
- /** @type {MouseEvent} */ (event.uiEvent).button === 0
61
- ) {
62
- const mouseEvent = /** @type {MouseEvent} */ (event.uiEvent);
63
- mouseEvent.preventDefault();
64
-
65
- let prevMouseEvent = mouseEvent;
66
-
67
- const onMousemove = /** @param {MouseEvent} moveEvent */ (
68
- moveEvent
69
- ) => {
70
- handleZoom({
71
- x: prevMouseEvent.clientX,
72
- y: prevMouseEvent.clientY,
73
- xDelta: moveEvent.clientX - prevMouseEvent.clientX,
74
- yDelta: moveEvent.clientY - prevMouseEvent.clientY,
75
- zDelta: 0,
76
- });
77
-
78
- prevMouseEvent = moveEvent;
79
- };
80
-
81
- const onMouseup = /** @param {MouseEvent} upEvent */ (upEvent) => {
82
- document.removeEventListener("mousemove", onMousemove);
83
- document.removeEventListener("mouseup", onMouseup);
84
- };
85
-
86
- document.addEventListener("mouseup", onMouseup, false);
87
- document.addEventListener("mousemove", onMousemove, false);
88
- }
89
- }