echarts GeoJSONResource 源码

  • 2022-10-20
  • 浏览 (340)

echarts GeoJSONResource 代码

文件路径:/src/coord/geo/GeoJSONResource.ts

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 { each, isString, createHashMap, hasOwn } from 'zrender/src/core/util';
import parseGeoJson from './parseGeoJson';
// Built-in GEO fixer.
import fixNanhai from './fix/nanhai';
import fixTextCoord from './fix/textCoord';
import fixDiaoyuIsland from './fix/diaoyuIsland';
import BoundingRect from 'zrender/src/core/BoundingRect';
import { GeoJSONRegion } from './Region';
import { GeoJSON, GeoJSONCompressed, GeoJSONSourceInput, GeoResource, GeoSpecialAreas, NameMap } from './geoTypes';


const DEFAULT_NAME_PROPERTY = 'name' as const;

export class GeoJSONResource implements GeoResource {

    readonly type = 'geoJSON';
    private _geoJSON: GeoJSON | GeoJSONCompressed;
    private _specialAreas: GeoSpecialAreas;
    private _mapName: string;

    private _parsedMap = createHashMap<{
        regions: GeoJSONRegion[];
        boundingRect: BoundingRect;
    }, string>();

    constructor(
        mapName: string,
        geoJSON: GeoJSONSourceInput,
        specialAreas: GeoSpecialAreas
    ) {
        this._mapName = mapName;
        this._specialAreas = specialAreas;

        // PENDING: delay the parse to the first usage to rapid up the FMP?
        this._geoJSON = parseInput(geoJSON);
    }

    /**
     * @param nameMap can be null/undefined
     * @param nameProperty can be null/undefined
     */
    load(nameMap: NameMap, nameProperty: string) {

        nameProperty = nameProperty || DEFAULT_NAME_PROPERTY;

        let parsed = this._parsedMap.get(nameProperty);
        if (!parsed) {
            const rawRegions = this._parseToRegions(nameProperty);
            parsed = this._parsedMap.set(nameProperty, {
                regions: rawRegions,
                boundingRect: calculateBoundingRect(rawRegions)
            });
        }

        const regionsMap = createHashMap<GeoJSONRegion>();

        const finalRegions: GeoJSONRegion[] = [];
        each(parsed.regions, function (region) {
            let regionName = region.name;

            // Try use the alias in geoNameMap
            if (nameMap && hasOwn(nameMap, regionName)) {
                region = region.cloneShallow(regionName = nameMap[regionName]);
            }

            finalRegions.push(region);
            regionsMap.set(regionName, region);
        });

        return {
            regions: finalRegions,
            boundingRect: parsed.boundingRect || new BoundingRect(0, 0, 0, 0),
            regionsMap: regionsMap
        };
    }

    private _parseToRegions(nameProperty: string): GeoJSONRegion[] {
        const mapName = this._mapName;
        const geoJSON = this._geoJSON;
        let rawRegions;

        // https://jsperf.com/try-catch-performance-overhead
        try {
            rawRegions = geoJSON ? parseGeoJson(geoJSON, nameProperty) : [];
        }
        catch (e) {
            throw new Error('Invalid geoJson format\n' + e.message);
        }

        fixNanhai(mapName, rawRegions);

        each(rawRegions, function (region) {
            const regionName = region.name;

            fixTextCoord(mapName, region);
            fixDiaoyuIsland(mapName, region);

            // Some area like Alaska in USA map needs to be tansformed
            // to look better
            const specialArea = this._specialAreas && this._specialAreas[regionName];
            if (specialArea) {
                region.transformTo(
                    specialArea.left, specialArea.top, specialArea.width, specialArea.height
                );
            }
        }, this);

        return rawRegions;
    }

    /**
     * Only for exporting to users.
     * **MUST NOT** used internally.
     */
    getMapForUser(): {
        // backward compat.
        geoJson: GeoJSON | GeoJSONCompressed;
        geoJSON: GeoJSON | GeoJSONCompressed;
        specialAreas: GeoSpecialAreas;
    } {
        return {
            // For backward compatibility, use geoJson
            // PENDING: it has been returning them without clone.
            // do we need to avoid outsite modification?
            geoJson: this._geoJSON,
            geoJSON: this._geoJSON,
            specialAreas: this._specialAreas
        };
    }

}

function calculateBoundingRect(regions: GeoJSONRegion[]): BoundingRect {
    let rect;
    for (let i = 0; i < regions.length; i++) {
        const regionRect = regions[i].getBoundingRect();
        rect = rect || regionRect.clone();
        rect.union(regionRect);
    }
    return rect;
}

function parseInput(source: GeoJSONSourceInput): GeoJSON | GeoJSONCompressed {
    return !isString(source)
        ? source
        : (typeof JSON !== 'undefined' && JSON.parse)
        ? JSON.parse(source)
        : (new Function('return (' + source + ');'))();
}

相关信息

echarts 源码目录

相关文章

echarts Geo 源码

echarts GeoModel 源码

echarts GeoSVGResource 源码

echarts Region 源码

echarts geoCreator 源码

echarts geoSourceManager 源码

echarts geoTypes 源码

echarts parseGeoJson 源码

echarts prepareCustom 源码

0  赞