Skip to content

Commit

Permalink
fix: GridAlgorithm respects maxZoom (#368)
Browse files Browse the repository at this point in the history
* Fixed bug with grid algo on max zoom

 * grid algo continue display clustered marker after reaching max zoom

* Added tests for grid algo after reaching max zoom

* removed GridAlgorithm.filterMarkersToPaddedViewport

* removes map projection mocking from grid algo test

* fix linter errors
  • Loading branch information
mbv committed Aug 2, 2022
1 parent f08b24b commit abcefdf
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 1 deletion.
109 changes: 109 additions & 0 deletions src/algorithms/grid.test.ts
@@ -0,0 +1,109 @@
/**
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { GridAlgorithm } from "./grid";
import { initialize, MapCanvasProjection } from "@googlemaps/jest-mocks";

let map: google.maps.Map;

beforeEach(() => {
initialize();

map = new google.maps.Map(document.createElement("div"));
});

test("calculate should return changed: true for first call when zoom > max zoom", () => {
const mapCanvasProjection = new MapCanvasProjection();
const markers: google.maps.Marker[] = [new google.maps.Marker()];

const grid = new GridAlgorithm({ maxZoom: 16 });
grid["noop"] = jest.fn();
grid["cluster"] = jest.fn();

map.getZoom = jest.fn().mockReturnValue(15);

grid.calculate({
markers,
map,
mapCanvasProjection,
});

map.getZoom = jest.fn().mockReturnValue(17);

const { changed } = grid.calculate({
markers,
map,
mapCanvasProjection,
});

expect(changed).toBe(true);
});

test("calculate should return changed: false for next calls above max zoom", () => {
const mapCanvasProjection =
jest.fn() as unknown as google.maps.MapCanvasProjection;
const markers: google.maps.Marker[] = [new google.maps.Marker()];

const grid = new GridAlgorithm({ maxZoom: 16 });
grid["noop"] = jest.fn();

map.getZoom = jest.fn().mockReturnValue(16);

let result = grid.calculate({
markers,
map,
mapCanvasProjection,
});

expect(result.changed).toBe(true);

result = grid.calculate({
markers,
map,
mapCanvasProjection,
});

expect(result.changed).toBe(false);
});

test("calculate should return changed: false for next calls above max zoom, even if zoom changed", () => {
const mapCanvasProjection =
jest.fn() as unknown as google.maps.MapCanvasProjection;
const markers: google.maps.Marker[] = [new google.maps.Marker()];

const grid = new GridAlgorithm({ maxZoom: 16 });
grid["noop"] = jest.fn();

map.getZoom = jest.fn().mockReturnValue(17);

let result = grid.calculate({
markers,
map,
mapCanvasProjection,
});

expect(result.changed).toBe(true);

map.getZoom = jest.fn().mockReturnValue(18);

result = grid.calculate({
markers,
map,
mapCanvasProjection,
});

expect(result.changed).toBe(false);
});
48 changes: 47 additions & 1 deletion src/algorithms/grid.ts
Expand Up @@ -17,11 +17,17 @@
import {
AbstractViewportAlgorithm,
AlgorithmInput,
AlgorithmOutput,
ViewportAlgorithmOptions,
} from "./core";
import { distanceBetweenPoints, extendBoundsToPaddedViewport } from "./utils";
import {
distanceBetweenPoints,
extendBoundsToPaddedViewport,
filterMarkersToPaddedViewport,
} from "./utils";

import { Cluster } from "../cluster";
import equal from "fast-deep-equal";

export interface GridOptions extends ViewportAlgorithmOptions {
gridSize?: number;
Expand All @@ -43,12 +49,52 @@ export class GridAlgorithm extends AbstractViewportAlgorithm {
protected gridSize: number;
protected maxDistance: number;
protected clusters: Cluster[] = [];
protected state: { zoom: number };

constructor({ maxDistance = 40000, gridSize = 40, ...options }: GridOptions) {
super(options);

this.maxDistance = maxDistance;
this.gridSize = gridSize;
this.state = { zoom: null };
}

public calculate({
markers,
map,
mapCanvasProjection,
}: AlgorithmInput): AlgorithmOutput {
const state = { zoom: map.getZoom() };
let changed = false;
if (this.state.zoom > this.maxZoom && state.zoom > this.maxZoom) {
// still beyond maxZoom, no change
} else {
changed = !equal(this.state, state);
}
this.state = state;
if (map.getZoom() >= this.maxZoom) {
return {
clusters: this.noop({
markers,
map,
mapCanvasProjection,
}),
changed: changed,
};
}

return {
clusters: this.cluster({
markers: filterMarkersToPaddedViewport(
map,
mapCanvasProjection,
markers,
this.viewportPadding
),
map,
mapCanvasProjection,
}),
};
}

protected cluster({
Expand Down
2 changes: 2 additions & 0 deletions src/algorithms/supercluster.ts
Expand Up @@ -21,7 +21,9 @@ import { Cluster } from "../cluster";
import equal from "fast-deep-equal";

export type SuperClusterOptions = SuperCluster.Options<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ [name: string]: any },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ [name: string]: any }
>;

Expand Down

0 comments on commit abcefdf

Please sign in to comment.