@guardian/interactive-component-library 0.1.0-alpha.43 → 0.1.0-alpha.45

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.
@@ -145,10 +145,10 @@ const LegendItem = ({
145
145
  })]
146
146
  });
147
147
  };
148
- const bar$2 = "_bar_1jxh9_1";
149
- const label$1 = "_label_1jxh9_5";
150
- const labelStroke = "_labelStroke_1jxh9_11";
151
- const backgroundRect = "_backgroundRect_1jxh9_17";
148
+ const bar$2 = "_bar_1b3uz_1";
149
+ const label$1 = "_label_1b3uz_5";
150
+ const labelStroke = "_labelStroke_1b3uz_12";
151
+ const backgroundRect = "_backgroundRect_1b3uz_18";
152
152
  const defaultStyles$v = {
153
153
  bar: bar$2,
154
154
  label: label$1,
@@ -5921,32 +5921,6 @@ let Map$2 = class Map2 {
5921
5921
  this._renderer = new MapRenderer(this);
5922
5922
  this._resizeObserver = new ResizeObserver(() => this._updateSize());
5923
5923
  this._resizeObserver.observe(this.target);
5924
- this.view.transform = zoomIdentity;
5925
- this._zoomBypassKey = navigator.userAgent.indexOf("Mac") !== -1 ? "metaKey" : "ctrlKey";
5926
- this._zoomBehaviour = zoom().scaleExtent(this.view.scaleExtent).filter((event) => {
5927
- const filterEvent = (filter) => {
5928
- this._filterEventCallback(filter);
5929
- return !filter;
5930
- };
5931
- if (event.type === "wheel" && !event[this._zoomBypassKey]) {
5932
- return filterEvent(true);
5933
- }
5934
- if ("targetTouches" in event && this.collaborativeGesturesEnabled) {
5935
- if (event.targetTouches.length < 2) {
5936
- return false;
5937
- }
5938
- event.preventDefault();
5939
- return filterEvent(false);
5940
- }
5941
- return (!event.ctrlKey || event.type === "wheel") && !event.button;
5942
- }).on("zoom", (event) => {
5943
- this.view.transform = event.transform;
5944
- this._requestRender();
5945
- this.dispatcher.dispatch(MapEvent.ZOOM, {
5946
- currentZoomLevel: event.transform.k
5947
- });
5948
- });
5949
- select(this._viewport).call(this._zoomBehaviour);
5950
5924
  this._viewport.addEventListener("touchmove", (event) => {
5951
5925
  if (event.targetTouches.length < 2) {
5952
5926
  this._filterEventCallback(true);
@@ -6031,7 +6005,7 @@ let Map$2 = class Map2 {
6031
6005
  const paddedViewPortWidth = viewPortWidth - padding.left - padding.right;
6032
6006
  const paddedViewPortHeight = viewPortHeight - padding.top - padding.bottom;
6033
6007
  const featureScale = Math.min(paddedViewPortWidth / featureWidth, paddedViewPortHeight / featureHeight);
6034
- const zoomScale = Math.min(this.view.maxZoom, featureScale);
6008
+ const zoomScale = Math.min(this.view.scaleExtent[1], featureScale);
6035
6009
  const scaledPadding = {
6036
6010
  top: padding.top / zoomScale,
6037
6011
  right: padding.right / zoomScale,
@@ -6110,11 +6084,40 @@ let Map$2 = class Map2 {
6110
6084
  const view = this.view;
6111
6085
  if (view) {
6112
6086
  view.viewPortSize = size;
6087
+ this._createZoomBehaviour(size);
6113
6088
  }
6114
- this._zoomBehaviour.extent([[0, 0], size]);
6115
- this._zoomBehaviour.translateExtent([[0, 0], size]);
6116
6089
  this._requestRender();
6117
6090
  }
6091
+ _createZoomBehaviour(viewPortSize) {
6092
+ if (this._zoomBehaviour) {
6093
+ this._zoomBehaviour.on("zoom", null);
6094
+ }
6095
+ this._zoomBypassKey = navigator.userAgent.indexOf("Mac") !== -1 ? "metaKey" : "ctrlKey";
6096
+ this._zoomBehaviour = zoom().extent([[0, 0], viewPortSize]).translateExtent([[0, 0], viewPortSize]).scaleExtent(this.view.scaleExtent).filter((event) => {
6097
+ const filterEvent = (filter) => {
6098
+ this._filterEventCallback(filter);
6099
+ return !filter;
6100
+ };
6101
+ if (event.type === "wheel" && !event[this._zoomBypassKey]) {
6102
+ return filterEvent(true);
6103
+ }
6104
+ if ("targetTouches" in event) {
6105
+ if (event.targetTouches.length < 2) {
6106
+ return false;
6107
+ }
6108
+ event.preventDefault();
6109
+ return filterEvent(false);
6110
+ }
6111
+ return (!event.ctrlKey || event.type === "wheel") && !event.button;
6112
+ }).on("zoom", (event) => {
6113
+ this.view.transform = event.transform;
6114
+ this._requestRender();
6115
+ this.dispatcher.dispatch(MapEvent.ZOOM, {
6116
+ zoomScale: event.transform.k
6117
+ });
6118
+ });
6119
+ select(this._viewport).call(this._zoomBehaviour);
6120
+ }
6118
6121
  _requestRender() {
6119
6122
  if (!this._renderer || !!this._animationFrameRequestID || this._isTransitioning)
6120
6123
  return;
@@ -6144,6 +6147,32 @@ function bboxFeature(bounds) {
6144
6147
  };
6145
6148
  return feature;
6146
6149
  }
6150
+ const BASE_RESOLUTION = 156543.03392;
6151
+ function zoomLevelToZoomScale(zoomLevel, initialResolution) {
6152
+ const resolution = BASE_RESOLUTION / Math.pow(2, zoomLevel);
6153
+ const zoomScale = initialResolution / resolution;
6154
+ return zoomScale;
6155
+ }
6156
+ function zoomLevelForResolution(currentResolution) {
6157
+ const zoomLevel = Math.log2(BASE_RESOLUTION / currentResolution);
6158
+ return zoomLevel;
6159
+ }
6160
+ function haversineDistance(lat1, lon1, lat2, lon2) {
6161
+ const R2 = 6371e3;
6162
+ const toRadians = (degrees2) => degrees2 * Math.PI / 180;
6163
+ const dLat = toRadians(lat2 - lat1);
6164
+ const dLon = toRadians(lon2 - lon1);
6165
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
6166
+ const c2 = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
6167
+ return R2 * c2;
6168
+ }
6169
+ function resolutionForExtent(extent, viewportSize) {
6170
+ const [lonMin, latMin, lonMax, latMax] = extent;
6171
+ const latMid = (latMin + latMax) / 2;
6172
+ const distance = haversineDistance(latMid, lonMin, latMid, lonMax);
6173
+ const resolution = distance / viewportSize[0];
6174
+ return resolution;
6175
+ }
6147
6176
  class View {
6148
6177
  constructor({
6149
6178
  projection,
@@ -6157,6 +6186,7 @@ class View {
6157
6186
  this.extent = extent;
6158
6187
  this.minZoom = minZoom;
6159
6188
  this.maxZoom = maxZoom;
6189
+ this._transform = zoomIdentity;
6160
6190
  this._padding = padding;
6161
6191
  this._viewPortSize = [0, 0];
6162
6192
  this.pixelRatio = window.devicePixelRatio;
@@ -6166,6 +6196,8 @@ class View {
6166
6196
  this._viewPortSize = size;
6167
6197
  if (previousSize !== size) {
6168
6198
  this.fitObject(bboxFeature(this.extent));
6199
+ const initialExtent = this.getVisibleExtent(zoomIdentity, this.projection);
6200
+ this.initialResolution = resolutionForExtent(initialExtent, size);
6169
6201
  }
6170
6202
  }
6171
6203
  get viewPortSize() {
@@ -6191,9 +6223,10 @@ class View {
6191
6223
  };
6192
6224
  return scalePadding(scaledPadding, this.pixelRatio);
6193
6225
  }
6194
- // defines the upper and lower limits for zoom behaviour
6226
+ // calculates the upper and lower zoom scales
6195
6227
  get scaleExtent() {
6196
- return [this.minZoom, this.maxZoom];
6228
+ const maxScale = zoomLevelToZoomScale(this.maxZoom, this.initialResolution);
6229
+ return [1, maxScale];
6197
6230
  }
6198
6231
  setProjection(projection) {
6199
6232
  this.projection = projection;
@@ -6239,6 +6272,14 @@ class View {
6239
6272
  const points = [topLeft, topRight, bottomRight, bottomLeft, topLeft];
6240
6273
  return points.map((d2) => this.invert(d2));
6241
6274
  }
6275
+ // map resolution (meters per pixel)
6276
+ getResolution() {
6277
+ return resolutionForExtent(this.getVisibleExtent(this.transform, this.projection), this.viewPortSize);
6278
+ }
6279
+ // map zoom level (0 = the entire world)
6280
+ getZoomLevel() {
6281
+ return zoomLevelForResolution(this.getResolution());
6282
+ }
6242
6283
  // get extent for drawn map
6243
6284
  getMapExtent() {
6244
6285
  const mapSizeInPixels = this.mapSize;
@@ -6265,6 +6306,7 @@ class View {
6265
6306
  zoomLevel: transform.k,
6266
6307
  pixelRatio: this.pixelRatio,
6267
6308
  padding: this.padding,
6309
+ viewPortSize: this.viewPortSize,
6268
6310
  sizeInPixels: scaleSize(this.viewPortSize, this.pixelRatio),
6269
6311
  visibleExtent: this.getVisibleExtent(transform, projection)
6270
6312
  };
@@ -6468,30 +6510,33 @@ class FeatureRenderer {
6468
6510
  this.style = style2;
6469
6511
  }
6470
6512
  render(frameState, feature, context) {
6513
+ if (!this.style) {
6514
+ return;
6515
+ }
6471
6516
  const {
6472
6517
  projection,
6473
6518
  transform,
6474
6519
  pixelRatio
6475
6520
  } = frameState.viewState;
6521
+ const {
6522
+ stroke,
6523
+ fill
6524
+ } = this.style;
6476
6525
  this.drawingFunction.context(context);
6477
6526
  context.beginPath();
6478
6527
  const geometries = feature.getProjectedGeometries(projection);
6479
6528
  for (const geometry of geometries) {
6480
6529
  this.drawingFunction(geometry);
6481
6530
  }
6482
- const {
6483
- stroke,
6484
- fill
6485
- } = this.style;
6531
+ if (fill) {
6532
+ context.fillStyle = fill.getRgba();
6533
+ context.fill();
6534
+ }
6486
6535
  if (stroke) {
6487
6536
  context.lineWidth = stroke.width * pixelRatio / transform.k;
6488
6537
  context.strokeStyle = stroke.getRgba();
6489
6538
  context.stroke();
6490
6539
  }
6491
- if (fill) {
6492
- context.fillStyle = fill.getRgba();
6493
- context.fill();
6494
- }
6495
6540
  }
6496
6541
  }
6497
6542
  const textPadding = {
@@ -6513,12 +6558,15 @@ class TextLayerRenderer {
6513
6558
  style2.pointerEvents = "none";
6514
6559
  style2.overflow = "hidden";
6515
6560
  }
6516
- renderFrame(frameState) {
6561
+ renderFrame(frameState, targetElement) {
6562
+ if (this.layer.opacity === 0)
6563
+ return targetElement;
6517
6564
  const {
6518
6565
  declutterTree
6519
6566
  } = frameState;
6520
6567
  const {
6521
6568
  projection,
6569
+ viewPortSize,
6522
6570
  sizeInPixels,
6523
6571
  visibleExtent,
6524
6572
  transform
@@ -6537,15 +6585,15 @@ class TextLayerRenderer {
6537
6585
  const featureStyle = styleFunction2(feature);
6538
6586
  const textElement = this.getTextElementWithID(feature.uid);
6539
6587
  textElement.innerText = featureStyle.text.content;
6540
- const [x, y] = transform.apply(point.coordinates);
6588
+ const [relativeX, relativeY] = transform.apply(point.coordinates).map((d2, i) => d2 / sizeInPixels[i]);
6541
6589
  const position = {
6542
- left: `${x / sizeInPixels[0] * 100}%`,
6543
- top: `${y / sizeInPixels[1] * 100}%`
6590
+ left: `${relativeX * 100}%`,
6591
+ top: `${relativeY * 100}%`
6544
6592
  };
6545
6593
  this.styleTextElement(textElement, featureStyle.text, position);
6546
6594
  const bbox = this.getElementBBox(textElement, {
6547
- x,
6548
- y
6595
+ x: relativeX * viewPortSize[0],
6596
+ y: relativeY * viewPortSize[1]
6549
6597
  });
6550
6598
  if (declutterTree.collides(bbox)) {
6551
6599
  continue;
@@ -6611,7 +6659,7 @@ class TextLayerRenderer {
6611
6659
  style2.top = `${bbox.minY}px`;
6612
6660
  style2.width = `${bbox.maxX - bbox.minX}px`;
6613
6661
  style2.height = `${bbox.maxY - bbox.minY}px`;
6614
- style2.border = "1px solid black";
6662
+ style2.border = "2px solid black";
6615
6663
  return element;
6616
6664
  }
6617
6665
  }
@@ -6621,6 +6669,13 @@ class Style {
6621
6669
  this.fill = options == null ? void 0 : options.fill;
6622
6670
  this.text = options == null ? void 0 : options.text;
6623
6671
  }
6672
+ clone() {
6673
+ return new Style({
6674
+ stroke: this.stroke,
6675
+ fill: this.fill,
6676
+ text: this.text
6677
+ });
6678
+ }
6624
6679
  }
6625
6680
  function memoise(fn) {
6626
6681
  let called = false;