| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 | 
/** 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.*//** * AUTO-GENERATED FILE. DO NOT MODIFY. *//** 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 { parseSVG, makeViewBoxTransform } from 'zrender/lib/tool/parseSVG.js';import Group from 'zrender/lib/graphic/Group.js';import Rect from 'zrender/lib/graphic/shape/Rect.js';import { assert, createHashMap, each } from 'zrender/lib/core/util.js';import BoundingRect from 'zrender/lib/core/BoundingRect.js';import { parseXML } from 'zrender/lib/tool/parseXML.js';import { GeoSVGRegion } from './Region.js';/** * "region available" means that: enable users to set attribute `name="xxx"` on those tags * to make it be a region. * 1. region styles and its label styles can be defined in echarts opton: * ```js * geo: { *     regions: [{ *         name: 'xxx', *         itemStyle: { ... }, *         label: { ... } *     }, { *         ... *     }, *     ...] * }; * ``` * 2. name can be duplicated in different SVG tag. All of the tags with the same name share * a region option. For exampel if there are two <path> representing two lung lobes. They have * no common parents but both of them need to display label "lung" inside. */var REGION_AVAILABLE_SVG_TAG_MAP = createHashMap(['rect', 'circle', 'line', 'ellipse', 'polygon', 'polyline', 'path',// <text> <tspan> are also enabled because some SVG might paint text itself,// but still need to trigger events or tooltip.'text', 'tspan',// <g> is also enabled because this case: if multiple tags share one name// and need label displayed, every tags will display the name, which is not// expected. So we can put them into a <g name="xxx">. Thereby only one label// displayed and located based on the bounding rect of the <g>.'g']);var GeoSVGResource = /** @class */function () {  function GeoSVGResource(mapName, svg) {    this.type = 'geoSVG';    // All used graphics. key: hostKey, value: root    this._usedGraphicMap = createHashMap();    // All unused graphics.    this._freedGraphics = [];    this._mapName = mapName;    // Only perform parse to XML object here, which might be time    // consiming for large SVG.    // Although convert XML to zrender element is also time consiming,    // if we do it here, the clone of zrender elements has to be    // required. So we do it once for each geo instance, util real    // performance issues call for optimizing it.    this._parsedXML = parseXML(svg);  }  GeoSVGResource.prototype.load = function /* nameMap: NameMap */  () {    // In the "load" stage, graphic need to be built to    // get boundingRect for geo coordinate system.    var firstGraphic = this._firstGraphic;    // Create the return data structure only when first graphic created.    // Because they will be used in geo coordinate system update stage,    // and `regions` will be mounted at `geo` coordinate system,    // in which there is no "view" info, so that it should better not to    // make references to graphic elements.    if (!firstGraphic) {      firstGraphic = this._firstGraphic = this._buildGraphic(this._parsedXML);      this._freedGraphics.push(firstGraphic);      this._boundingRect = this._firstGraphic.boundingRect.clone();      // PENDING: `nameMap` will not be supported until some real requirement come.      // if (nameMap) {      //     named = applyNameMap(named, nameMap);      // }      var _a = createRegions(firstGraphic.named),        regions = _a.regions,        regionsMap = _a.regionsMap;      this._regions = regions;      this._regionsMap = regionsMap;    }    return {      boundingRect: this._boundingRect,      regions: this._regions,      regionsMap: this._regionsMap    };  };  GeoSVGResource.prototype._buildGraphic = function (svgXML) {    var result;    var rootFromParse;    try {      result = svgXML && parseSVG(svgXML, {        ignoreViewBox: true,        ignoreRootClip: true      }) || {};      rootFromParse = result.root;      assert(rootFromParse != null);    } catch (e) {      throw new Error('Invalid svg format\n' + e.message);    }    // Note: we keep the covenant that the root has no transform. So always add an extra root.    var root = new Group();    root.add(rootFromParse);    root.isGeoSVGGraphicRoot = true;    // [THE_RULE_OF_VIEWPORT_AND_VIEWBOX]    //    // Consider: `<svg width="..." height="..." viewBox="...">`    // - the `width/height` we call it `svgWidth/svgHeight` for short.    // - `(0, 0, svgWidth, svgHeight)` defines the viewport of the SVG, or say,    //   "viewport boundingRect", or `boundingRect` for short.    // - `viewBox` defines the transform from the real content ot the viewport.    //   `viewBox` has the same unit as the content of SVG.    //   If `viewBox` exists, a transform is defined, so the unit of `svgWidth/svgHeight` become    //   different from the content of SVG. Otherwise, they are the same.    //    // If both `svgWidth/svgHeight/viewBox` are specified in a SVG file, the transform rule will be:    // 0. `boundingRect` is `(0, 0, svgWidth, svgHeight)`. Set it to Geo['_rect'] (View['_rect']).    // 1. Make a transform from `viewBox` to `boundingRect`.    //    Note: only support `preserveAspectRatio 'xMidYMid'` here. That is, this transform will preserve    //    the aspect ratio.    // 2. Make a transform from boundingRect to Geo['_viewRect'] (View['_viewRect'])    //    (`Geo`/`View` will do this job).    //    Note: this transform might not preserve aspect radio, which depending on how users specify    //    viewRect in echarts option (e.g., `geo.left/top/width/height` will not preserve aspect ratio,    //    but `geo.layoutCenter/layoutSize` will preserve aspect ratio).    //    // If `svgWidth/svgHeight` not specified, we use `viewBox` as the `boundingRect` to make the SVG    // layout look good.    //    // If neither `svgWidth/svgHeight` nor `viewBox` are not specified, we calculate the boundingRect    // of the SVG content and use them to make SVG layout look good.    var svgWidth = result.width;    var svgHeight = result.height;    var viewBoxRect = result.viewBoxRect;    var boundingRect = this._boundingRect;    if (!boundingRect) {      var bRectX = void 0;      var bRectY = void 0;      var bRectWidth = void 0;      var bRectHeight = void 0;      if (svgWidth != null) {        bRectX = 0;        bRectWidth = svgWidth;      } else if (viewBoxRect) {        bRectX = viewBoxRect.x;        bRectWidth = viewBoxRect.width;      }      if (svgHeight != null) {        bRectY = 0;        bRectHeight = svgHeight;      } else if (viewBoxRect) {        bRectY = viewBoxRect.y;        bRectHeight = viewBoxRect.height;      }      // If both viewBox and svgWidth/svgHeight not specified,      // we have to determine how to layout those element to make them look good.      if (bRectX == null || bRectY == null) {        var calculatedBoundingRect = rootFromParse.getBoundingRect();        if (bRectX == null) {          bRectX = calculatedBoundingRect.x;          bRectWidth = calculatedBoundingRect.width;        }        if (bRectY == null) {          bRectY = calculatedBoundingRect.y;          bRectHeight = calculatedBoundingRect.height;        }      }      boundingRect = this._boundingRect = new BoundingRect(bRectX, bRectY, bRectWidth, bRectHeight);    }    if (viewBoxRect) {      var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect);      // Only support `preserveAspectRatio 'xMidYMid'`      rootFromParse.scaleX = rootFromParse.scaleY = viewBoxTransform.scale;      rootFromParse.x = viewBoxTransform.x;      rootFromParse.y = viewBoxTransform.y;    }    // SVG needs to clip based on `viewBox`. And some SVG files really rely on this feature.    // They do not strictly confine all of the content inside a display rect, but deliberately    // use a `viewBox` to define a displayable rect.    // PENDING:    // The drawback of the `setClipPath` here is: the region label (genereted by echarts) near the    // edge might also be clipped, because region labels are put as `textContent` of the SVG path.    root.setClipPath(new Rect({      shape: boundingRect.plain()    }));    var named = [];    each(result.named, function (namedItem) {      if (REGION_AVAILABLE_SVG_TAG_MAP.get(namedItem.svgNodeTagLower) != null) {        named.push(namedItem);        setSilent(namedItem.el);      }    });    return {      root: root,      boundingRect: boundingRect,      named: named    };  };  /**   * Consider:   * (1) One graphic element can not be shared by different `geoView` running simultaneously.   *     Notice, also need to consider multiple echarts instances share a `mapRecord`.   * (2) Converting SVG to graphic elements is time consuming.   * (3) In the current architecture, `load` should be called frequently to get boundingRect,   *     and it is called without view info.   * So we maintain graphic elements in this module, and enables `view` to use/return these   * graphics from/to the pool with it's uid.   */  GeoSVGResource.prototype.useGraphic = function (hostKey /* , nameMap: NameMap */) {    var usedRootMap = this._usedGraphicMap;    var svgGraphic = usedRootMap.get(hostKey);    if (svgGraphic) {      return svgGraphic;    }    svgGraphic = this._freedGraphics.pop()    // use the first boundingRect to avoid duplicated boundingRect calculation.    || this._buildGraphic(this._parsedXML);    usedRootMap.set(hostKey, svgGraphic);    // PENDING: `nameMap` will not be supported until some real requirement come.    // `nameMap` can only be obtained from echarts option.    // The original `named` must not be modified.    // if (nameMap) {    //     svgGraphic = extend({}, svgGraphic);    //     svgGraphic.named = applyNameMap(svgGraphic.named, nameMap);    // }    return svgGraphic;  };  GeoSVGResource.prototype.freeGraphic = function (hostKey) {    var usedRootMap = this._usedGraphicMap;    var svgGraphic = usedRootMap.get(hostKey);    if (svgGraphic) {      usedRootMap.removeKey(hostKey);      this._freedGraphics.push(svgGraphic);    }  };  return GeoSVGResource;}();export { GeoSVGResource };function setSilent(el) {  // Only named element has silent: false, other elements should  // act as background and has no user interaction.  el.silent = false;  // text|tspan will be converted to group.  if (el.isGroup) {    el.traverse(function (child) {      child.silent = false;    });  }}function createRegions(named) {  var regions = [];  var regionsMap = createHashMap();  // Create resions only for the first graphic.  each(named, function (namedItem) {    // Region has feature to calculate center for tooltip or other features.    // If there is a <g name="xxx">, the center should be the center of the    // bounding rect of the g.    if (namedItem.namedFrom != null) {      return;    }    var region = new GeoSVGRegion(namedItem.name, namedItem.el);    // PENDING: if `nameMap` supported, this region can not be mounted on    // `this`, but can only be created each time `load()` called.    regions.push(region);    // PENDING: if multiple tag named with the same name, only one will be    // found by `_regionsMap`. `_regionsMap` is used to find a coordinate    // by name. We use `region.getCenter()` as the coordinate.    regionsMap.set(namedItem.name, region);  });  return {    regions: regions,    regionsMap: regionsMap  };}// PENDING: `nameMap` will not be supported until some real requirement come.// /**//  * Use the alias in geoNameMap.//  * The input `named` must not be modified.//  */// function applyNameMap(//     named: GeoSVGGraphicRecord['named'],//     nameMap: NameMap// ): GeoSVGGraphicRecord['named'] {//     const result = [] as GeoSVGGraphicRecord['named'];//     for (let i = 0; i < named.length; i++) {//         let regionGraphic = named[i];//         const name = regionGraphic.name;//         if (nameMap && nameMap.hasOwnProperty(name)) {//             regionGraphic = extend({}, regionGraphic);//             regionGraphic.name = name;//         }//         result.push(regionGraphic);//     }//     return result;// }
 |