Skip to content

Commit

Permalink
Refactoring for clusterer
Browse files Browse the repository at this point in the history
  • Loading branch information
xdan committed Sep 28, 2023
1 parent c067903 commit e97a777
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 98 deletions.
17 changes: 8 additions & 9 deletions example/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,33 @@ body,

.circle {
position: relative;
display: inline-block;

width: var(--radius, 20px);
height: var(--radius, 20px);
width: fit-content;
aspect-ratio: 1;

color: #8a64eb;
border: 2px solid currentColor;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.7);

transform: translate(-50%, -50%);
padding: 5px;
box-sizing: border-box;
}

.circle-content {
position: absolute;
top: 50%;
left: 50%;

display: flex;
justify-content: center;
align-items: center;

width: 70%;
height: 70%;

border-radius: 50%;
background-color: currentColor;

transform: translate3d(-50%, -50%, 0);
min-width: 16px;
aspect-ratio: 1;
padding: 5px;
}

.circle-text {
Expand Down
8 changes: 5 additions & 3 deletions example/common.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */

mappable.import.loaders.unshift(async (pkg) => {
if (!pkg.includes('@mappable-world/mappable-clusterer')) {
return;
Expand All @@ -9,17 +11,17 @@ mappable.import.loaders.unshift(async (pkg) => {
await mappable.import.script(`https://unpkg.com/${pkg}/dist/index.js`);
}

Object.assign(mappable, window[`${pkg}`]);
return window[`${pkg}`];
Object.assign(mappable, window[`@mappable-world/mappable-clusterer`]);
return window[`@mappable-world/mappable-clusterer`];
});

const BOUNDS = [
[-73.95184497632046, 40.71517531718148],
[-73.79379690161176, 40.676480480724436]
];

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const LOCATION = {bounds: BOUNDS};
const DEFAULT_POINTS_COUNT = 4000;

const seed = (s) => () => {
s = Math.sin(s) * 10000;
Expand Down
4 changes: 2 additions & 2 deletions example/react.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

const {MMapClusterer, clusterByGrid} = reactify.module(await mappable.import("@mappable-world/[email protected]"));
const {useState, useCallback, useMemo} = React;
const initialPoints = getRandomPoints(100, BOUNDS);
const initialPoints = getRandomPoints(DEFAULT_POINTS_COUNT, BOUNDS);
const gridSizedMethod = clusterByGrid({gridSize: 64})

function App() {
Expand Down Expand Up @@ -64,7 +64,7 @@

return <React.Fragment>
<div className="toolbar">
<input id="pointsCount" defaultValue="100" placeholder="Count"></input>
<input id="pointsCount" defaultValue={DEFAULT_POINTS_COUNT} placeholder="Count"></input>
<button type="button" onClick={updatePoints}>Update points</button>
<button type="button" onClick={toggleClusterer}>Delete/Add Clusterer</button>
</div>
Expand Down
8 changes: 6 additions & 2 deletions example/vanilla.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
await mappable.ready;
const {MMap, MMapDefaultSchemeLayer, MMapLayer, MMapFeatureDataSource} = mappable;

const {MMapClusterer, clusterByGrid} = await mappable.import('@mappable-world/[email protected]');
const {MMapClusterer, clusterByGrid} = await mappable.import(
'@mappable-world/[email protected]'
);

map = new MMap(document.getElementById('app'), {location: LOCATION});
map.addChild(new MMapDefaultSchemeLayer())
Expand Down Expand Up @@ -55,7 +57,7 @@

const clusterer = new MMapClusterer({
method: clusterByGrid({gridSize: 64}),
features: getRandomPoints(100, BOUNDS),
features: getRandomPoints(DEFAULT_POINTS_COUNT, BOUNDS),
marker,
cluster
});
Expand All @@ -76,6 +78,8 @@

changePoints.onclick = updatePoints;
changeClusterer.onclick = toggleClusterer;

pointsCount.value = DEFAULT_POINTS_COUNT;
}
</script>

Expand Down
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@types/got": "9.6.12",
"@types/jest": "29.5.3",
"@types/jsdom": "21.1.1",
"@types/lodash": "^4.14.199",
"@types/react": "18.2.14",
"@types/react-dom": "18.2.6",
"@typescript-eslint/eslint-plugin": "6.0.0",
Expand All @@ -53,5 +54,8 @@
"webpack-cli": "5.1.4",
"webpack-dev-server": "4.15.1"
},
"license": "Apache-2"
"license": "Apache-2",
"dependencies": {
"lodash.throttle": "^4.1.1"
}
}
48 changes: 13 additions & 35 deletions src/MMapClusterer/MMapClusterer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type {MMapEntity, MMapCollection, MMapListener} from '@mappable-world/mappable-types';
import type {LngLat, LngLatBounds, Projection} from '@mappable-world/mappable-types/common/types';
import type {MMapEntity, MMapCollection, MMapListener, LngLat} from '@mappable-world/mappable-types';

import throttle from 'lodash/throttle';

import type {ClustererObject, EntitiesMap, Feature, IClusterMethod} from './interface';
import {THROTTLE_DEFAULT_TIMEOUT_MS} from './constants';
import {throttle} from './helpers/throttle';
import {MMapClustererReactifyOverride} from './react/MMapClusterer';

/**
Expand Down Expand Up @@ -33,7 +33,6 @@ const defaultProps = Object.freeze({
/**
* Display clustered features on a map.
*
* @example
* ```javascript
* const clusterer = new MMapClusterer({
* method: clusterByGrid({gridSize: 64}),
Expand Down Expand Up @@ -68,31 +67,13 @@ class MMapClusterer extends mappable.MMapComplexEntity<MMapClustererProps, Defau
private _mapListener!: MMapListener;

constructor(props: MMapClustererProps) {
super(props);
super(props, {container: true});
this._render = this._render.bind(this);
}

/**
* Compare feature coordinates with bounds
*
* @param feature
* @param bounds
* @param projection
* @returns either feature belongs to viewport or not
*/
private _isVisible(feature: Feature, bounds: LngLatBounds, projection: Projection): boolean {
const {x, y} = projection.toWorldCoordinates(feature.geometry.coordinates as LngLat);
const {x: x1, y: y1} = projection.toWorldCoordinates(bounds[0]);
const {x: x2, y: y2} = projection.toWorldCoordinates(bounds[1]);
return x1 <= x && y1 >= y && x2 >= x && y2 <= y;
}

/**
* Get entity from store or create it
*
* @param feature
* @param entityId
* @param length count of entities in the cluster
* @returns ready to add to map entity
*/
private _getEntity({lnglat, features, clusterId: entityId}: ClustererObject): MMapEntity<unknown> {
Expand Down Expand Up @@ -120,8 +101,7 @@ class MMapClusterer extends mappable.MMapComplexEntity<MMapClustererProps, Defau
const nextVisibleEntities: EntitiesMap = {};

nextViewportObjects.forEach((object: ClustererObject) => {
const entity = this._getEntity(object);
nextVisibleEntities[object.clusterId] = entity;
nextVisibleEntities[object.clusterId] = this._getEntity(object);
});

return nextVisibleEntities;
Expand All @@ -146,18 +126,16 @@ class MMapClusterer extends mappable.MMapComplexEntity<MMapClustererProps, Defau
}
}

private _render({mapInAction}: {mapInAction?: boolean} = {}): void {
private _render(): void {
const map = this.root;

if (!map || mapInAction) return;
if (!map) return;

const visibleFeatures = this._props.features.filter((feature) =>
this._isVisible(feature, map.bounds, map.projection)
);
const {features} = this._props;

const nextViewportObjects = this._props.method.render({
map,
features: visibleFeatures
features: features
});

if (this._props.onRender && this._props.onRender(nextViewportObjects) === false) {
Expand All @@ -178,18 +156,18 @@ class MMapClusterer extends mappable.MMapComplexEntity<MMapClustererProps, Defau
this._visibleEntities = {};

this._container = new mappable.MMapCollection({});
this.addChild(this._container);
this._addDirectChild(this._container);

const onUpdateRender = this._props.tickTimeout ? throttle(this._render, this._props.tickTimeout) : this._render;
this._mapListener = new mappable.MMapListener({onUpdate: onUpdateRender, onResize: onUpdateRender});
this.addChild(this._mapListener);
this._addDirectChild(this._mapListener);

this._render();
}

protected _onDetach(): void {
this.removeChild(this._container);
this.removeChild(this._mapListener);
this._removeDirectChild(this._container);
this._removeDirectChild(this._mapListener);

this._entitiesCache = {};
this._visibleEntities = {};
Expand Down
4 changes: 3 additions & 1 deletion src/MMapClusterer/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const THROTTLE_DEFAULT_TIMEOUT_MS = 200;
export const THROTTLE_DEFAULT_TIMEOUT_MS = 300;
export const DEFAULT_SCREEN_OFFSET = 256;

32 changes: 0 additions & 32 deletions src/MMapClusterer/helpers/throttle.ts

This file was deleted.

8 changes: 4 additions & 4 deletions src/MMapClusterer/helpers/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Vec2, WorldCoordinates} from '@mappable-world/mappable-types/common/types';
import type {Vec2, WorldCoordinates} from '@mappable-world/mappable-types';

// World at 0 zoom is always 256x256 pixels.
const worldPixelSize = 256;
Expand All @@ -12,7 +12,7 @@ const worldPixelSize = 256;
* @param dst The vector the result will be stored to.
* @returns `dst`.
*/
function divv(a: Vec2, b: Vec2, dst: Vec2 = {x: 0, y: 0} as Vec2): Vec2 {
function divv<T extends Vec2>(a: T, b: T, dst: T = {x: 0, y: 0} as T): T {
dst.x = a.x / b.x;
dst.y = a.y / b.y;
return dst;
Expand All @@ -26,10 +26,10 @@ function divv(a: Vec2, b: Vec2, dst: Vec2 = {x: 0, y: 0} as Vec2): Vec2 {
* @param dst The vector the result will be stored to.
* @returns `dst`.
*/
export function divn(v: Vec2, n: number, dst: Vec2 = {x: 0, y: 0}): Vec2 {
export function divn<T extends Vec2>(v: T, n: number, dst: Vec2 = {x: 0, y: 0}): T {
dst.x = v.x / n;
dst.y = v.y / n;
return dst;
return dst as T;
}

export function convertPixelSizeToWorldSize(pixel: Vec2, zoom: number, dst?: Vec2): WorldCoordinates {
Expand Down
Loading

0 comments on commit e97a777

Please sign in to comment.