@antv/g2
Version:
the Grammar of Graphics in Javascript
246 lines • 9.32 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeoView = void 0;
const scale_1 = require("@antv/scale");
const util_1 = require("@antv/util");
const d3_geo_1 = require("d3-geo");
const mark_1 = require("../utils/mark");
const d3Projection = __importStar(require("./d3Projection"));
/**
* Get projection factory from d3-projection.
*/
function normalizeProjection(type) {
if (typeof type === 'function')
return type;
const name = `geo${(0, util_1.upperFirst)(type)}`;
const projection = d3Projection[name];
if (!projection)
throw new Error(`Unknown coordinate: ${type}`);
return projection;
}
/**
* @see https://github.com/mapbox/geojson-merge/blob/master/index.js
*/
function mergeGeoJSON(gjs) {
return {
type: 'FeatureCollection',
features: gjs.flatMap((gj) => normalizeGeoJSON(gj).features),
};
}
function normalizeGeoJSON(gj) {
const types = {
Point: 'geometry',
MultiPoint: 'geometry',
LineString: 'geometry',
MultiLineString: 'geometry',
Polygon: 'geometry',
MultiPolygon: 'geometry',
GeometryCollection: 'geometry',
Feature: 'feature',
FeatureCollection: 'featureCollection',
};
if (!gj || !gj.type)
return null;
const type = types[gj.type];
if (!type)
return null;
if (type === 'geometry') {
return {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: gj,
},
],
};
}
else if (type === 'feature') {
return {
type: 'FeatureCollection',
features: [gj],
};
}
else if (type === 'featureCollection') {
return gj;
}
}
/**
* Specify the options for d3 projection
* @see https://github.com/d3/d3-geo#projections
* @todo Specify key each by each.
*/
function setProjectionOptions(projection, options) {
var _a;
for (const [key, value] of Object.entries(options)) {
(_a = projection[key]) === null || _a === void 0 ? void 0 : _a.call(projection, value);
}
}
function setProjectionSize(projection, nodes, layout, options) {
const defaultOutline = () => {
const geoNodes = nodes.filter(isGeoPath);
// For geoPath with sphere mark, use it as outline.
const sphere = geoNodes.find((d) => d.sphere);
if (sphere)
return { type: 'Sphere' };
// Merge all GeoJSON as the outline.
return mergeGeoJSON(geoNodes.filter((d) => !d.sphere).flatMap((d) => d.data.value));
};
const { outline = defaultOutline() } = options;
const { size = 'fitExtent' } = options;
if (size === 'fitExtent') {
return setFitExtent(projection, outline, layout);
}
else if (size === 'fitWidth') {
return setFitWidth(projection, outline, layout);
}
}
function setFitExtent(projection, object, layout) {
const { x, y, width, height } = layout;
projection.fitExtent([
[x, y],
[width, height],
], object);
}
function setFitWidth(projection, object, layout) {
const { width, height } = layout;
const [[x0, y0], [x1, y1]] = (0, d3_geo_1.geoPath)(projection.fitWidth(width, object)).bounds(object);
const dy = Math.ceil(y1 - y0);
const l = Math.min(Math.ceil(x1 - x0), dy);
const s = (projection.scale() * (l - 1)) / l;
const [tx, ty] = projection.translate();
const t = ty + (height - dy) / 2;
projection.scale(s).translate([tx, t]).precision(0.2);
}
/**
* @todo Remove this.
*/
function normalizeDataSource(node) {
const { data } = node;
if (Array.isArray(data))
return Object.assign(Object.assign({}, node), { data: { value: data } });
const { type } = data;
if (type === 'graticule10') {
return Object.assign(Object.assign({}, node), { data: { value: [(0, d3_geo_1.geoGraticule10)()] } });
}
else if (type === 'sphere') {
// Sphere is not a standard type of GeoJSON.
// Mark this geoPath as sphere geoPath.
return Object.assign(Object.assign({}, node), { sphere: true, data: { value: [{ type: 'Sphere' }] } });
}
return node;
}
function isGeoPath(d) {
return d.type === 'geoPath';
}
/**
* A view with geo coordinate.
*/
const GeoView = () => {
return (options) => {
const { children, coordinate: projection = {} } = options;
if (!Array.isArray(children))
return [];
// Get projection factory.
const { type = 'equalEarth' } = projection, projectionOptions = __rest(projection, ["type"]);
const createProjection = normalizeProjection(type);
const nodes = children.map(normalizeDataSource);
// Set path generator lazily.
let path;
// A custom geo coordinate.
function Geo() {
return [
[
'custom',
(x, y, width, height) => {
// Create and set projection.
const visual = createProjection();
const layout = { x, y, width, height };
setProjectionSize(visual, nodes, layout, projectionOptions);
setProjectionOptions(visual, projectionOptions);
// Create path generator.
path = (0, d3_geo_1.geoPath)(visual);
// Normalize projection and projection.invert,
// which normalize projected points.
const scaleX = new scale_1.Linear({
domain: [x, x + width],
});
const scaleY = new scale_1.Linear({
domain: [y, y + height],
});
const normalize = (point) => {
const visualPoint = visual(point);
if (!visualPoint)
return [null, null];
const [vx, vy] = visualPoint;
return [scaleX.map(vx), scaleY.map(vy)];
};
const normalizeInvert = (point) => {
if (!point)
return null;
const [px, py] = point;
const visualPoint = [scaleX.invert(px), scaleY.invert(py)];
return visual.invert(visualPoint);
};
return {
transform: (point) => normalize(point),
untransform: (point) => normalizeInvert(point),
};
},
],
];
}
function GeoPath(options) {
const { style, tooltip = {} } = options;
return Object.assign(Object.assign({}, options), { type: 'path', tooltip: (0, mark_1.maybeTooltip)(tooltip, {
title: 'id',
items: [{ channel: 'color' }],
}), style: Object.assign(Object.assign({}, style), { d: (d) => path(d) || [] }) });
}
const t = (d) => (isGeoPath(d) ? GeoPath(d) : d);
return [
Object.assign(Object.assign({}, options), { type: 'view', scale: {
x: { type: 'identity' },
y: { type: 'identity' },
}, axis: false, coordinate: { type: Geo }, children: nodes.flatMap(t) }),
];
};
};
exports.GeoView = GeoView;
exports.GeoView.props = {};
//# sourceMappingURL=geoView.js.map
;