Skip to content

Commit

Permalink
Merge pull request apache#16364 from apache/enhance-map
Browse files Browse the repository at this point in the history
feature: introduce projection to map
  • Loading branch information
pissang authored Jan 15, 2022
2 parents 36012be + 1f2ea20 commit 50fd888
Show file tree
Hide file tree
Showing 26 changed files with 2,585 additions and 261 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
},
"dependencies": {
"tslib": "2.3.0",
"zrender": "npm:zrender-nightly@^5.3.0-dev.20211224"
"zrender": "npm:zrender-nightly@^5.3.0-dev.20220109"
},
"devDependencies": {
"@babel/code-frame": "7.10.4",
Expand Down
20 changes: 15 additions & 5 deletions src/action/roamHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
* under the License.
*/

import View from '../coord/View';
import { Payload } from '../util/types';
import type Geo from '../coord/geo/Geo';
import type View from '../coord/View';
import type { Payload } from '../util/types';

export interface RoamPaylod extends Payload {
dx: number
Expand All @@ -28,6 +29,13 @@ export interface RoamPaylod extends Payload {
originY: number
}

function getCenterCoord(view: View, point: number[]) {
// Use projected coord as center because it's linear.
return (view as Geo).pointToProjected
? (view as Geo).pointToProjected(point)
: view.pointToData(point);
}

export function updateCenterAndZoom(
view: View,
payload: RoamPaylod,
Expand All @@ -40,13 +48,15 @@ export function updateCenterAndZoom(
const center = view.getCenter();
let zoom = payload.zoom;

const point = view.dataToPoint(center);
const point = (view as Geo).projectedToPoint
? (view as Geo).projectedToPoint(center)
: view.dataToPoint(center);

if (payload.dx != null && payload.dy != null) {
point[0] -= payload.dx;
point[1] -= payload.dy;

view.setCenter(view.pointToData(point));
view.setCenter(getCenterCoord(view, point));
}
if (zoom != null) {
if (zoomLimit) {
Expand All @@ -69,7 +79,7 @@ export function updateCenterAndZoom(

view.updateTransform();
// Get the new center
view.setCenter(view.pointToData(point));
view.setCenter(getCenterCoord(view, point));
view.setZoom(zoom * previousZoom);
}

Expand Down
2 changes: 0 additions & 2 deletions src/chart/bar/BarView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ import {createSectorCalculateTextPosition, SectorTextPosition, setSectorTextRota
import { saveOldStyle } from '../../animation/basicTrasition';
import Element from 'zrender/src/Element';

const _eventPos = [0, 0];

const mathMax = Math.max;
const mathMin = Math.min;

Expand Down
15 changes: 15 additions & 0 deletions src/component/geo/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ import GlobalModel from '../../model/Global';
import { updateCenterAndZoom, RoamPaylod } from '../../action/roamHelper';
import MapSeries from '../../chart/map/MapSeries';
import GeoView from './GeoView';
import geoSourceManager from '../../coord/geo/geoSourceManager';

type RegisterMapParams = Parameters<typeof geoSourceManager.registerMap>;
function registerMap(
mapName: RegisterMapParams[0],
geoJson: RegisterMapParams[1],
specialAreas?: RegisterMapParams[2]
) {
geoSourceManager.registerMap(mapName, geoJson, specialAreas);
}

export function install(registers: EChartsExtensionInstallRegisters) {

Expand All @@ -34,6 +44,11 @@ export function install(registers: EChartsExtensionInstallRegisters) {
registers.registerComponentModel(GeoModel);
registers.registerComponentView(GeoView);

registers.registerImpl('registerMap', registerMap);
registers.registerImpl('getMap', (mapName: string) => {
geoSourceManager.getMapForUser(mapName);
});


function makeAction(
method: 'toggleSelected' | 'select' | 'unSelect',
Expand Down
166 changes: 125 additions & 41 deletions src/component/helper/MapDraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import SeriesData from '../../data/SeriesData';
import { GeoJSONRegion } from '../../coord/geo/Region';
import { SVGNodeTagLower } from 'zrender/src/tool/parseSVG';
import { makeInner } from '../../util/model';
import { GeoProjection, ProjectionStream } from '../../coord/geo/geoTypes';

interface RegionsGroup extends graphic.Group {
}
Expand Down Expand Up @@ -108,6 +109,17 @@ function getFixedItemStyle(model: Model<GeoItemStyleOption>) {

return itemStyle;
}
// Only stroke can be used for line.
// Using fill in style if stroke not exits.
// TODO Not sure yet. Perhaps a separate `lineStyle`?
function fixLineStyle(styleHost: { style: graphic.Path['style'] }) {
const style = styleHost.style;
if (style) {
style.stroke = (style.stroke || style.fill);
style.fill = null;
}
}

class MapDraw {

private uid: string;
Expand Down Expand Up @@ -234,14 +246,39 @@ class MapDraw {
const transformInfoRaw = viewBuildCtx.transformInfoRaw;
const mapOrGeoModel = viewBuildCtx.mapOrGeoModel;
const data = viewBuildCtx.data;
const projection = viewBuildCtx.geo.projection;
const projectionStream = projection && projection.stream;

const transformPoint = function (point: number[]): number[] {
return [
function transformPoint(point: number[], project: GeoProjection['project']): number[] {
if (project) {
// projection may return null point.
point = project(point);
}
return point && [
point[0] * transformInfoRaw.scaleX + transformInfoRaw.x,
point[1] * transformInfoRaw.scaleY + transformInfoRaw.y
];
};

function transformPolygonPoints(inPoints: number[][]): number[][] {
const outPoints = [];
// If projectionStream is provided. Use it instead of single point project.
const project = !projectionStream && projection && projection.project;
for (let i = 0; i < inPoints.length; ++i) {
const newPt = transformPoint(inPoints[i], project);
newPt && outPoints.push(newPt);
}
return outPoints;
}

function getPolyShape(points: number[][]) {
return {
shape: {
points: transformPolygonPoints(points)
}
};
}

regionsGroup.removeAll();

// Only when the resource is GeoJSON, there is `geo.regions`.
Expand All @@ -268,56 +305,61 @@ class MapDraw {
regionsInfoByName.set(regionName, { dataIdx, regionModel });
}

const compoundPath = new graphic.CompoundPath({
segmentIgnoreThreshold: 1,
shape: {
paths: []
const polygonSubpaths: graphic.Polygon[] = [];
const polylineSubpaths: graphic.Polyline[] = [];

zrUtil.each(region.geometries, function (geometry) {
// Polygon and MultiPolygon
if (geometry.type === 'polygon') {
let polys = [geometry.exterior].concat(geometry.interiors || []);
if (projectionStream) {
polys = projectPolys(polys, projectionStream);
}
zrUtil.each(polys, (poly) => {
polygonSubpaths.push(new graphic.Polygon(getPolyShape(poly)));
});
}
// LineString and MultiLineString
else {
let points = geometry.points;
if (projectionStream) {
points = projectPolys(points, projectionStream, true);
}
zrUtil.each(points, points => {
polylineSubpaths.push(new graphic.Polyline(getPolyShape(points)));
});
}
});
regionGroup.add(compoundPath);

zrUtil.each(region.geometries, function (geometry) {
if (geometry.type !== 'polygon') {
const centerPt = transformPoint(region.getCenter(), projection && projection.project);

function createCompoundPath(subpaths: graphic.Path[], isLine?: boolean) {
if (!subpaths.length) {
return;
}
const points = [];
for (let i = 0; i < geometry.exterior.length; ++i) {
points.push(transformPoint(geometry.exterior[i]));
}
compoundPath.shape.paths.push(new graphic.Polygon({
const compoundPath = new graphic.CompoundPath({
culling: true,
segmentIgnoreThreshold: 1,
shape: {
points: points
paths: subpaths
}
}));
});
regionGroup.add(compoundPath);
applyOptionStyleForRegion(
viewBuildCtx, compoundPath, dataIdx, regionModel
);
resetLabelForRegion(
viewBuildCtx, compoundPath, regionName, regionModel, mapOrGeoModel, dataIdx, centerPt
);

for (let i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); ++i) {
const interior = geometry.interiors[i];
const points = [];
for (let j = 0; j < interior.length; ++j) {
points.push(transformPoint(interior[j]));
}
compoundPath.shape.paths.push(new graphic.Polygon({
segmentIgnoreThreshold: 1,
shape: {
points: points
}
}));
if (isLine) {
fixLineStyle(compoundPath);
zrUtil.each(compoundPath.states, fixLineStyle);
}
});

applyOptionStyleForRegion(
viewBuildCtx, compoundPath, dataIdx, regionModel
);

if (compoundPath instanceof Displayable) {
compoundPath.culling = true;
}

const centerPt = transformPoint(region.getCenter());
resetLabelForRegion(
viewBuildCtx, compoundPath, regionName, regionModel, mapOrGeoModel, dataIdx, centerPt
);
createCompoundPath(polygonSubpaths);
createCompoundPath(polylineSubpaths, true);
});

// Ensure children have been added to `regionGroup` before calling them.
Expand Down Expand Up @@ -726,7 +768,7 @@ function resetLabelForRegion(
el,
getLabelStatesModels(regionModel),
{
labelFetcher: labelFetcher,
labelFetcher,
labelDataIndex: query,
defaultText: regionName
},
Expand Down Expand Up @@ -844,6 +886,48 @@ function resetStateTriggerForRegion(
return focus;
}

function projectPolys(
rings: number[][][], // Polygons include exterior and interiors. Or polylines.
createStream: (outStream: ProjectionStream) => ProjectionStream,
isLine?: boolean
) {
const polygons: number[][][] = [];
let curPoly: number[][];

function startPolygon() {
curPoly = [];
}
function endPolygon() {
if (curPoly.length) {
polygons.push(curPoly);
curPoly = [];
}
}
const stream = createStream({
polygonStart: startPolygon,
polygonEnd: endPolygon,
lineStart: startPolygon,
lineEnd: endPolygon,
point(x, y) {
// May have NaN values from stream.
if (isFinite(x) && isFinite(y)) {
curPoly.push([x, y]);
}
},
sphere() {}
});
!isLine && stream.polygonStart();
zrUtil.each(rings, ring => {
stream.lineStart();
for (let i = 0; i < ring.length; i++) {
stream.point(ring[i][0], ring[i][1]);
}
stream.lineEnd();
});
!isLine && stream.polygonEnd();
return polygons;
}

export default MapDraw;


Expand Down
Loading

0 comments on commit 50fd888

Please sign in to comment.