| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527 | 
/** 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.*/var zrUtil = require("zrender/lib/core/util");var pathTool = require("zrender/lib/tool/path");var colorTool = require("zrender/lib/tool/color");var matrix = require("zrender/lib/core/matrix");var vector = require("zrender/lib/core/vector");var Path = require("zrender/lib/graphic/Path");var Transformable = require("zrender/lib/mixin/Transformable");var ZImage = require("zrender/lib/graphic/Image");exports.Image = ZImage;var Group = require("zrender/lib/container/Group");exports.Group = Group;var Text = require("zrender/lib/graphic/Text");exports.Text = Text;var Circle = require("zrender/lib/graphic/shape/Circle");exports.Circle = Circle;var Sector = require("zrender/lib/graphic/shape/Sector");exports.Sector = Sector;var Ring = require("zrender/lib/graphic/shape/Ring");exports.Ring = Ring;var Polygon = require("zrender/lib/graphic/shape/Polygon");exports.Polygon = Polygon;var Polyline = require("zrender/lib/graphic/shape/Polyline");exports.Polyline = Polyline;var Rect = require("zrender/lib/graphic/shape/Rect");exports.Rect = Rect;var Line = require("zrender/lib/graphic/shape/Line");exports.Line = Line;var BezierCurve = require("zrender/lib/graphic/shape/BezierCurve");exports.BezierCurve = BezierCurve;var Arc = require("zrender/lib/graphic/shape/Arc");exports.Arc = Arc;var CompoundPath = require("zrender/lib/graphic/CompoundPath");exports.CompoundPath = CompoundPath;var LinearGradient = require("zrender/lib/graphic/LinearGradient");exports.LinearGradient = LinearGradient;var RadialGradient = require("zrender/lib/graphic/RadialGradient");exports.RadialGradient = RadialGradient;var BoundingRect = require("zrender/lib/core/BoundingRect");exports.BoundingRect = BoundingRect;var IncrementalDisplayable = require("zrender/lib/graphic/IncrementalDisplayable");exports.IncrementalDisplayable = IncrementalDisplayable;var subPixelOptimizeUtil = require("zrender/lib/graphic/helper/subPixelOptimize");/** 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.*/var mathMax = Math.max;var mathMin = Math.min;var EMPTY_OBJ = {};var Z2_EMPHASIS_LIFT = 1; // key: label model property nane, value: style property name.var CACHED_LABEL_STYLE_PROPERTIES = {  color: 'textFill',  textBorderColor: 'textStroke',  textBorderWidth: 'textStrokeWidth'};var EMPHASIS = 'emphasis';var NORMAL = 'normal'; // Reserve 0 as default.var _highlightNextDigit = 1;var _highlightKeyMap = {};var _customShapeMap = {};/** * Extend shape with parameters */function extendShape(opts) {  return Path.extend(opts);}/** * Extend path */function extendPath(pathData, opts) {  return pathTool.extendFromString(pathData, opts);}/** * Register a user defined shape. * The shape class can be fetched by `getShapeClass` * This method will overwrite the registered shapes, including * the registered built-in shapes, if using the same `name`. * The shape can be used in `custom series` and * `graphic component` by declaring `{type: name}`. * * @param {string} name * @param {Object} ShapeClass Can be generated by `extendShape`. */function registerShape(name, ShapeClass) {  _customShapeMap[name] = ShapeClass;}/** * Find shape class registered by `registerShape`. Usually used in * fetching user defined shape. * * [Caution]: * (1) This method **MUST NOT be used inside echarts !!!**, unless it is prepared * to use user registered shapes. * Because the built-in shape (see `getBuiltInShape`) will be registered by * `registerShape` by default. That enables users to get both built-in * shapes as well as the shapes belonging to themsleves. But users can overwrite * the built-in shapes by using names like 'circle', 'rect' via calling * `registerShape`. So the echarts inner featrues should not fetch shapes from here * in case that it is overwritten by users, except that some features, like * `custom series`, `graphic component`, do it deliberately. * * (2) In the features like `custom series`, `graphic component`, the user input * `{tpye: 'xxx'}` does not only specify shapes but also specify other graphic * elements like `'group'`, `'text'`, `'image'` or event `'path'`. Those names * are reserved names, that is, if some user register a shape named `'image'`, * the shape will not be used. If we intending to add some more reserved names * in feature, that might bring break changes (disable some existing user shape * names). But that case probably rearly happen. So we dont make more mechanism * to resolve this issue here. * * @param {string} name * @return {Object} The shape class. If not found, return nothing. */function getShapeClass(name) {  if (_customShapeMap.hasOwnProperty(name)) {    return _customShapeMap[name];  }}/** * Create a path element from path data string * @param {string} pathData * @param {Object} opts * @param {module:zrender/core/BoundingRect} rect * @param {string} [layout=cover] 'center' or 'cover' */function makePath(pathData, opts, rect, layout) {  var path = pathTool.createFromString(pathData, opts);  if (rect) {    if (layout === 'center') {      rect = centerGraphic(rect, path.getBoundingRect());    }    resizePath(path, rect);  }  return path;}/** * Create a image element from image url * @param {string} imageUrl image url * @param {Object} opts options * @param {module:zrender/core/BoundingRect} rect constrain rect * @param {string} [layout=cover] 'center' or 'cover' */function makeImage(imageUrl, rect, layout) {  var path = new ZImage({    style: {      image: imageUrl,      x: rect.x,      y: rect.y,      width: rect.width,      height: rect.height    },    onload: function (img) {      if (layout === 'center') {        var boundingRect = {          width: img.width,          height: img.height        };        path.setStyle(centerGraphic(rect, boundingRect));      }    }  });  return path;}/** * Get position of centered element in bounding box. * * @param  {Object} rect         element local bounding box * @param  {Object} boundingRect constraint bounding box * @return {Object} element position containing x, y, width, and height */function centerGraphic(rect, boundingRect) {  // Set rect to center, keep width / height ratio.  var aspect = boundingRect.width / boundingRect.height;  var width = rect.height * aspect;  var height;  if (width <= rect.width) {    height = rect.height;  } else {    width = rect.width;    height = width / aspect;  }  var cx = rect.x + rect.width / 2;  var cy = rect.y + rect.height / 2;  return {    x: cx - width / 2,    y: cy - height / 2,    width: width,    height: height  };}var mergePath = pathTool.mergePath;/** * Resize a path to fit the rect * @param {module:zrender/graphic/Path} path * @param {Object} rect */function resizePath(path, rect) {  if (!path.applyTransform) {    return;  }  var pathRect = path.getBoundingRect();  var m = pathRect.calculateTransform(rect);  path.applyTransform(m);}/** * Sub pixel optimize line for canvas * * @param {Object} param * @param {Object} [param.shape] * @param {number} [param.shape.x1] * @param {number} [param.shape.y1] * @param {number} [param.shape.x2] * @param {number} [param.shape.y2] * @param {Object} [param.style] * @param {number} [param.style.lineWidth] * @return {Object} Modified param */function subPixelOptimizeLine(param) {  subPixelOptimizeUtil.subPixelOptimizeLine(param.shape, param.shape, param.style);  return param;}/** * Sub pixel optimize rect for canvas * * @param {Object} param * @param {Object} [param.shape] * @param {number} [param.shape.x] * @param {number} [param.shape.y] * @param {number} [param.shape.width] * @param {number} [param.shape.height] * @param {Object} [param.style] * @param {number} [param.style.lineWidth] * @return {Object} Modified param */function subPixelOptimizeRect(param) {  subPixelOptimizeUtil.subPixelOptimizeRect(param.shape, param.shape, param.style);  return param;}/** * Sub pixel optimize for canvas * * @param {number} position Coordinate, such as x, y * @param {number} lineWidth Should be nonnegative integer. * @param {boolean=} positiveOrNegative Default false (negative). * @return {number} Optimized position. */var subPixelOptimize = subPixelOptimizeUtil.subPixelOptimize;function hasFillOrStroke(fillOrStroke) {  return fillOrStroke != null && fillOrStroke !== 'none';} // Most lifted color are duplicated.var liftedColorMap = zrUtil.createHashMap();var liftedColorCount = 0;function liftColor(color) {  if (typeof color !== 'string') {    return color;  }  var liftedColor = liftedColorMap.get(color);  if (!liftedColor) {    liftedColor = colorTool.lift(color, -0.1);    if (liftedColorCount < 10000) {      liftedColorMap.set(color, liftedColor);      liftedColorCount++;    }  }  return liftedColor;}function cacheElementStl(el) {  if (!el.__hoverStlDirty) {    return;  }  el.__hoverStlDirty = false;  var hoverStyle = el.__hoverStl;  if (!hoverStyle) {    el.__cachedNormalStl = el.__cachedNormalZ2 = null;    return;  }  var normalStyle = el.__cachedNormalStl = {};  el.__cachedNormalZ2 = el.z2;  var elStyle = el.style;  for (var name in hoverStyle) {    // See comment in `singleEnterEmphasis`.    if (hoverStyle[name] != null) {      normalStyle[name] = elStyle[name];    }  } // Always cache fill and stroke to normalStyle for lifting color.  normalStyle.fill = elStyle.fill;  normalStyle.stroke = elStyle.stroke;}function singleEnterEmphasis(el) {  var hoverStl = el.__hoverStl;  if (!hoverStl || el.__highlighted) {    return;  }  var zr = el.__zr;  var useHoverLayer = el.useHoverLayer && zr && zr.painter.type === 'canvas';  el.__highlighted = useHoverLayer ? 'layer' : 'plain';  if (el.isGroup || !zr && el.useHoverLayer) {    return;  }  var elTarget = el;  var targetStyle = el.style;  if (useHoverLayer) {    elTarget = zr.addHover(el);    targetStyle = elTarget.style;  }  rollbackDefaultTextStyle(targetStyle);  if (!useHoverLayer) {    cacheElementStl(elTarget);  } // styles can be:  // {  //    label: {  //        show: false,  //        position: 'outside',  //        fontSize: 18  //    },  //    emphasis: {  //        label: {  //            show: true  //        }  //    }  // },  // where properties of `emphasis` may not appear in `normal`. We previously use  // module:echarts/util/model#defaultEmphasis to merge `normal` to `emphasis`.  // But consider rich text and setOption in merge mode, it is impossible to cover  // all properties in merge. So we use merge mode when setting style here.  // But we choose the merge strategy that only properties that is not `null/undefined`.  // Because when making a textStyle (espacially rich text), it is not easy to distinguish  // `hasOwnProperty` and `null/undefined` in code, so we trade them as the same for simplicity.  // But this strategy brings a trouble that `null/undefined` can not be used to remove  // style any more in `emphasis`. Users can both set properties directly on normal and  // emphasis to avoid this issue, or we might support `'none'` for this case if required.  targetStyle.extendFrom(hoverStl);  setDefaultHoverFillStroke(targetStyle, hoverStl, 'fill');  setDefaultHoverFillStroke(targetStyle, hoverStl, 'stroke');  applyDefaultTextStyle(targetStyle);  if (!useHoverLayer) {    el.dirty(false);    el.z2 += Z2_EMPHASIS_LIFT;  }}function setDefaultHoverFillStroke(targetStyle, hoverStyle, prop) {  if (!hasFillOrStroke(hoverStyle[prop]) && hasFillOrStroke(targetStyle[prop])) {    targetStyle[prop] = liftColor(targetStyle[prop]);  }}function singleEnterNormal(el) {  var highlighted = el.__highlighted;  if (!highlighted) {    return;  }  el.__highlighted = false;  if (el.isGroup) {    return;  }  if (highlighted === 'layer') {    el.__zr && el.__zr.removeHover(el);  } else {    var style = el.style;    var normalStl = el.__cachedNormalStl;    if (normalStl) {      rollbackDefaultTextStyle(style);      el.setStyle(normalStl);      applyDefaultTextStyle(style);    } // `__cachedNormalZ2` will not be reset if calling `setElementHoverStyle`    // when `el` is on emphasis state. So here by comparing with 1, we try    // hard to make the bug case rare.    var normalZ2 = el.__cachedNormalZ2;    if (normalZ2 != null && el.z2 - normalZ2 === Z2_EMPHASIS_LIFT) {      el.z2 = normalZ2;    }  }}function traverseUpdate(el, updater, commonParam) {  // If root is group, also enter updater for `highDownOnUpdate`.  var fromState = NORMAL;  var toState = NORMAL;  var trigger; // See the rule of `highDownOnUpdate` on `graphic.setAsHighDownDispatcher`.  el.__highlighted && (fromState = EMPHASIS, trigger = true);  updater(el, commonParam);  el.__highlighted && (toState = EMPHASIS, trigger = true);  el.isGroup && el.traverse(function (child) {    !child.isGroup && updater(child, commonParam);  });  trigger && el.__highDownOnUpdate && el.__highDownOnUpdate(fromState, toState);}/** * Set hover style (namely "emphasis style") of element, based on the current * style of the given `el`. * This method should be called after all of the normal styles have been adopted * to the `el`. See the reason on `setHoverStyle`. * * @param {module:zrender/Element} el Should not be `zrender/container/Group`. * @param {Object} [el.hoverStyle] Can be set on el or its descendants, *        e.g., `el.hoverStyle = ...; graphic.setHoverStyle(el); `. *        Often used when item group has a label element and it's hoverStyle is different. * @param {Object|boolean} [hoverStl] The specified hover style. *        If set as `false`, disable the hover style. *        Similarly, The `el.hoverStyle` can alse be set *        as `false` to disable the hover style. *        Otherwise, use the default hover style if not provided. */function setElementHoverStyle(el, hoverStl) {  // For performance consideration, it might be better to make the "hover style" only the  // difference properties from the "normal style", but not a entire copy of all styles.  hoverStl = el.__hoverStl = hoverStl !== false && (el.hoverStyle || hoverStl || {});  el.__hoverStlDirty = true; // FIXME  // It is not completely right to save "normal"/"emphasis" flag on elements.  // It probably should be saved on `data` of series. Consider the cases:  // (1) A highlighted elements are moved out of the view port and re-enter  // again by dataZoom.  // (2) call `setOption` and replace elements totally when they are highlighted.  if (el.__highlighted) {    // Consider the case:    // The styles of a highlighted `el` is being updated. The new "emphasis style"    // should be adapted to the `el`. Notice here new "normal styles" should have    // been set outside and the cached "normal style" is out of date.    el.__cachedNormalStl = null; // Do not clear `__cachedNormalZ2` here, because setting `z2` is not a constraint    // of this method. In most cases, `z2` is not set and hover style should be able    // to rollback. Of course, that would bring bug, but only in a rare case, see    // `doSingleLeaveHover` for details.    singleEnterNormal(el);    singleEnterEmphasis(el);  }}function onElementMouseOver(e) {  !shouldSilent(this, e) // "emphasis" event highlight has higher priority than mouse highlight.  && !this.__highByOuter && traverseUpdate(this, singleEnterEmphasis);}function onElementMouseOut(e) {  !shouldSilent(this, e) // "emphasis" event highlight has higher priority than mouse highlight.  && !this.__highByOuter && traverseUpdate(this, singleEnterNormal);}function onElementEmphasisEvent(highlightDigit) {  this.__highByOuter |= 1 << (highlightDigit || 0);  traverseUpdate(this, singleEnterEmphasis);}function onElementNormalEvent(highlightDigit) {  !(this.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdate(this, singleEnterNormal);}function shouldSilent(el, e) {  return el.__highDownSilentOnTouch && e.zrByTouch;}/** * Set hover style (namely "emphasis style") of element, * based on the current style of the given `el`. * * (1) * **CONSTRAINTS** for this method: * <A> This method MUST be called after all of the normal styles having been adopted * to the `el`. * <B> The input `hoverStyle` (that is, "emphasis style") MUST be the subset of the * "normal style" having been set to the el. * <C> `color` MUST be one of the "normal styles" (because color might be lifted as * a default hover style). * * The reason: this method treat the current style of the `el` as the "normal style" * and cache them when enter/update the "emphasis style". Consider the case: the `el` * is in "emphasis" state and `setOption`/`dispatchAction` trigger the style updating * logic, where the el should shift from the original emphasis style to the new * "emphasis style" and should be able to "downplay" back to the new "normal style". * * Indeed, it is error-prone to make a interface has so many constraints, but I have * not found a better solution yet to fit the backward compatibility, performance and * the current programming style. * * (2) * Call the method for a "root" element once. Do not call it for each descendants. * If the descendants elemenets of a group has itself hover style different from the * root group, we can simply mount the style on `el.hoverStyle` for them, but should * not call this method for them. * * (3) These input parameters can be set directly on `el`: * * @param {module:zrender/Element} el * @param {Object} [el.hoverStyle] See `graphic.setElementHoverStyle`. * @param {boolean} [el.highDownSilentOnTouch=false] See `graphic.setAsHighDownDispatcher`. * @param {Function} [el.highDownOnUpdate] See `graphic.setAsHighDownDispatcher`. * @param {Object|boolean} [hoverStyle] See `graphic.setElementHoverStyle`. */function setHoverStyle(el, hoverStyle) {  setAsHighDownDispatcher(el, true);  traverseUpdate(el, setElementHoverStyle, hoverStyle);}/** * @param {module:zrender/Element} el * @param {Function} [el.highDownOnUpdate] Called when state updated. *        Since `setHoverStyle` has the constraint that it must be called after *        all of the normal style updated, `highDownOnUpdate` is not needed to *        trigger if both `fromState` and `toState` is 'normal', and needed to *        trigger if both `fromState` and `toState` is 'emphasis', which enables *        to sync outside style settings to "emphasis" state. *        @this {string} This dispatcher `el`. *        @param {string} fromState Can be "normal" or "emphasis". *               `fromState` might equal to `toState`, *               for example, when this method is called when `el` is *               on "emphasis" state. *        @param {string} toState Can be "normal" or "emphasis". * *        FIXME *        CAUTION: Do not expose `highDownOnUpdate` outside echarts. *        Because it is not a complete solution. The update *        listener should not have been mount in element, *        and the normal/emphasis state should not have *        mantained on elements. * * @param {boolean} [el.highDownSilentOnTouch=false] *        In touch device, mouseover event will be trigger on touchstart event *        (see module:zrender/dom/HandlerProxy). By this mechanism, we can *        conveniently use hoverStyle when tap on touch screen without additional *        code for compatibility. *        But if the chart/component has select feature, which usually also use *        hoverStyle, there might be conflict between 'select-highlight' and *        'hover-highlight' especially when roam is enabled (see geo for example). *        In this case, `highDownSilentOnTouch` should be used to disable *        hover-highlight on touch device. * @param {boolean} [asDispatcher=true] If `false`, do not set as "highDownDispatcher". */function setAsHighDownDispatcher(el, asDispatcher) {  var disable = asDispatcher === false; // Make `highDownSilentOnTouch` and `highDownOnUpdate` only work after  // `setAsHighDownDispatcher` called. Avoid it is modified by user unexpectedly.  el.__highDownSilentOnTouch = el.highDownSilentOnTouch;  el.__highDownOnUpdate = el.highDownOnUpdate; // Simple optimize, since this method might be  // called for each elements of a group in some cases.  if (!disable || el.__highDownDispatcher) {    var method = disable ? 'off' : 'on'; // Duplicated function will be auto-ignored, see Eventful.js.    el[method]('mouseover', onElementMouseOver)[method]('mouseout', onElementMouseOut); // Emphasis, normal can be triggered manually by API or other components like hover link.    el[method]('emphasis', onElementEmphasisEvent)[method]('normal', onElementNormalEvent); // Also keep previous record.    el.__highByOuter = el.__highByOuter || 0;    el.__highDownDispatcher = !disable;  }}/** * @param {module:zrender/src/Element} el * @return {boolean} */function isHighDownDispatcher(el) {  return !!(el && el.__highDownDispatcher);}/** * Support hightlight/downplay record on each elements. * For the case: hover highlight/downplay (legend, visualMap, ...) and * user triggerred hightlight/downplay should not conflict. * Only all of the highlightDigit cleared, return to normal. * @param {string} highlightKey * @return {number} highlightDigit */function getHighlightDigit(highlightKey) {  var highlightDigit = _highlightKeyMap[highlightKey];  if (highlightDigit == null && _highlightNextDigit <= 32) {    highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++;  }  return highlightDigit;}/** * See more info in `setTextStyleCommon`. * @param {Object|module:zrender/graphic/Style} normalStyle * @param {Object} emphasisStyle * @param {module:echarts/model/Model} normalModel * @param {module:echarts/model/Model} emphasisModel * @param {Object} opt Check `opt` of `setTextStyleCommon` to find other props. * @param {string|Function} [opt.defaultText] * @param {module:echarts/model/Model} [opt.labelFetcher] Fetch text by *      `opt.labelFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)` * @param {number} [opt.labelDataIndex] Fetch text by *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)` * @param {number} [opt.labelDimIndex] Fetch text by *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)` * @param {string} [opt.labelProp] Fetch text by *      `opt.textFetcher.getFormattedLabel(opt.labelDataIndex, 'normal'/'emphasis', null, opt.labelDimIndex, opt.labelProp)` * @param {Object} [normalSpecified] * @param {Object} [emphasisSpecified] */function setLabelStyle(normalStyle, emphasisStyle, normalModel, emphasisModel, opt, normalSpecified, emphasisSpecified) {  opt = opt || EMPTY_OBJ;  var labelFetcher = opt.labelFetcher;  var labelDataIndex = opt.labelDataIndex;  var labelDimIndex = opt.labelDimIndex;  var labelProp = opt.labelProp; // This scenario, `label.normal.show = true; label.emphasis.show = false`,  // is not supported util someone requests.  var showNormal = normalModel.getShallow('show');  var showEmphasis = emphasisModel.getShallow('show'); // Consider performance, only fetch label when necessary.  // If `normal.show` is `false` and `emphasis.show` is `true` and `emphasis.formatter` is not set,  // label should be displayed, where text is fetched by `normal.formatter` or `opt.defaultText`.  var baseText;  if (showNormal || showEmphasis) {    if (labelFetcher) {      baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, labelProp);    }    if (baseText == null) {      baseText = zrUtil.isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt) : opt.defaultText;    }  }  var normalStyleText = showNormal ? baseText : null;  var emphasisStyleText = showEmphasis ? zrUtil.retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, 'emphasis', null, labelDimIndex, labelProp) : null, baseText) : null; // Optimize: If style.text is null, text will not be drawn.  if (normalStyleText != null || emphasisStyleText != null) {    // Always set `textStyle` even if `normalStyle.text` is null, because default    // values have to be set on `normalStyle`.    // If we set default values on `emphasisStyle`, consider case:    // Firstly, `setOption(... label: {normal: {text: null}, emphasis: {show: true}} ...);`    // Secondly, `setOption(... label: {noraml: {show: true, text: 'abc', color: 'red'} ...);`    // Then the 'red' will not work on emphasis.    setTextStyle(normalStyle, normalModel, normalSpecified, opt);    setTextStyle(emphasisStyle, emphasisModel, emphasisSpecified, opt, true);  }  normalStyle.text = normalStyleText;  emphasisStyle.text = emphasisStyleText;}/** * Modify label style manually. * Only works after `setLabelStyle` and `setElementHoverStyle` called. * * @param {module:zrender/src/Element} el * @param {Object} [normalStyleProps] optional * @param {Object} [emphasisStyleProps] optional */function modifyLabelStyle(el, normalStyleProps, emphasisStyleProps) {  var elStyle = el.style;  if (normalStyleProps) {    rollbackDefaultTextStyle(elStyle);    el.setStyle(normalStyleProps);    applyDefaultTextStyle(elStyle);  }  elStyle = el.__hoverStl;  if (emphasisStyleProps && elStyle) {    rollbackDefaultTextStyle(elStyle);    zrUtil.extend(elStyle, emphasisStyleProps);    applyDefaultTextStyle(elStyle);  }}/** * Set basic textStyle properties. * See more info in `setTextStyleCommon`. * @param {Object|module:zrender/graphic/Style} textStyle * @param {module:echarts/model/Model} model * @param {Object} [specifiedTextStyle] Can be overrided by settings in model. * @param {Object} [opt] See `opt` of `setTextStyleCommon`. * @param {boolean} [isEmphasis] */function setTextStyle(textStyle, textStyleModel, specifiedTextStyle, opt, isEmphasis) {  setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis);  specifiedTextStyle && zrUtil.extend(textStyle, specifiedTextStyle); // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);  return textStyle;}/** * Set text option in the style. * See more info in `setTextStyleCommon`. * @deprecated * @param {Object} textStyle * @param {module:echarts/model/Model} labelModel * @param {string|boolean} defaultColor Default text color. *        If set as false, it will be processed as a emphasis style. */function setText(textStyle, labelModel, defaultColor) {  var opt = {    isRectText: true  };  var isEmphasis;  if (defaultColor === false) {    isEmphasis = true;  } else {    // Support setting color as 'auto' to get visual color.    opt.autoColor = defaultColor;  }  setTextStyleCommon(textStyle, labelModel, opt, isEmphasis); // textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);}/** * The uniform entry of set text style, that is, retrieve style definitions * from `model` and set to `textStyle` object. * * Never in merge mode, but in overwrite mode, that is, all of the text style * properties will be set. (Consider the states of normal and emphasis and * default value can be adopted, merge would make the logic too complicated * to manage.) * * The `textStyle` object can either be a plain object or an instance of * `zrender/src/graphic/Style`, and either be the style of normal or emphasis. * After this mothod called, the `textStyle` object can then be used in * `el.setStyle(textStyle)` or `el.hoverStyle = textStyle`. * * Default value will be adopted and `insideRollbackOpt` will be created. * See `applyDefaultTextStyle` `rollbackDefaultTextStyle` for more details. * * opt: { *      disableBox: boolean, Whether diable drawing box of block (outer most). *      isRectText: boolean, *      autoColor: string, specify a color when color is 'auto', *              for textFill, textStroke, textBackgroundColor, and textBorderColor. *              If autoColor specified, it is used as default textFill. *      useInsideStyle: *              `true`: Use inside style (textFill, textStroke, textStrokeWidth) *                  if `textFill` is not specified. *              `false`: Do not use inside style. *              `null/undefined`: use inside style if `isRectText` is true and *                  `textFill` is not specified and textPosition contains `'inside'`. *      forceRich: boolean * } */function setTextStyleCommon(textStyle, textStyleModel, opt, isEmphasis) {  // Consider there will be abnormal when merge hover style to normal style if given default value.  opt = opt || EMPTY_OBJ;  if (opt.isRectText) {    var textPosition;    if (opt.getTextPosition) {      textPosition = opt.getTextPosition(textStyleModel, isEmphasis);    } else {      textPosition = textStyleModel.getShallow('position') || (isEmphasis ? null : 'inside'); // 'outside' is not a valid zr textPostion value, but used      // in bar series, and magric type should be considered.      textPosition === 'outside' && (textPosition = 'top');    }    textStyle.textPosition = textPosition;    textStyle.textOffset = textStyleModel.getShallow('offset');    var labelRotate = textStyleModel.getShallow('rotate');    labelRotate != null && (labelRotate *= Math.PI / 180);    textStyle.textRotation = labelRotate;    textStyle.textDistance = zrUtil.retrieve2(textStyleModel.getShallow('distance'), isEmphasis ? null : 5);  }  var ecModel = textStyleModel.ecModel;  var globalTextStyle = ecModel && ecModel.option.textStyle; // Consider case:  // {  //     data: [{  //         value: 12,  //         label: {  //             rich: {  //                 // no 'a' here but using parent 'a'.  //             }  //         }  //     }],  //     rich: {  //         a: { ... }  //     }  // }  var richItemNames = getRichItemNames(textStyleModel);  var richResult;  if (richItemNames) {    richResult = {};    for (var name in richItemNames) {      if (richItemNames.hasOwnProperty(name)) {        // Cascade is supported in rich.        var richTextStyle = textStyleModel.getModel(['rich', name]); // In rich, never `disableBox`.        // FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`,        // the default color `'blue'` will not be adopted if no color declared in `rich`.        // That might confuses users. So probably we should put `textStyleModel` as the        // root ancestor of the `richTextStyle`. But that would be a break change.        setTokenTextStyle(richResult[name] = {}, richTextStyle, globalTextStyle, opt, isEmphasis);      }    }  }  textStyle.rich = richResult;  setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, true);  if (opt.forceRich && !opt.textStyle) {    opt.textStyle = {};  }  return textStyle;} // Consider case:// {//     data: [{//         value: 12,//         label: {//             rich: {//                 // no 'a' here but using parent 'a'.//             }//         }//     }],//     rich: {//         a: { ... }//     }// }function getRichItemNames(textStyleModel) {  // Use object to remove duplicated names.  var richItemNameMap;  while (textStyleModel && textStyleModel !== textStyleModel.ecModel) {    var rich = (textStyleModel.option || EMPTY_OBJ).rich;    if (rich) {      richItemNameMap = richItemNameMap || {};      for (var name in rich) {        if (rich.hasOwnProperty(name)) {          richItemNameMap[name] = 1;        }      }    }    textStyleModel = textStyleModel.parentModel;  }  return richItemNameMap;}function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isEmphasis, isBlock) {  // In merge mode, default value should not be given.  globalTextStyle = !isEmphasis && globalTextStyle || EMPTY_OBJ;  textStyle.textFill = getAutoColor(textStyleModel.getShallow('color'), opt) || globalTextStyle.color;  textStyle.textStroke = getAutoColor(textStyleModel.getShallow('textBorderColor'), opt) || globalTextStyle.textBorderColor;  textStyle.textStrokeWidth = zrUtil.retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth);  if (!isEmphasis) {    if (isBlock) {      textStyle.insideRollbackOpt = opt;      applyDefaultTextStyle(textStyle);    } // Set default finally.    if (textStyle.textFill == null) {      textStyle.textFill = opt.autoColor;    }  } // Do not use `getFont` here, because merge should be supported, where  // part of these properties may be changed in emphasis style, and the  // others should remain their original value got from normal style.  textStyle.fontStyle = textStyleModel.getShallow('fontStyle') || globalTextStyle.fontStyle;  textStyle.fontWeight = textStyleModel.getShallow('fontWeight') || globalTextStyle.fontWeight;  textStyle.fontSize = textStyleModel.getShallow('fontSize') || globalTextStyle.fontSize;  textStyle.fontFamily = textStyleModel.getShallow('fontFamily') || globalTextStyle.fontFamily;  textStyle.textAlign = textStyleModel.getShallow('align');  textStyle.textVerticalAlign = textStyleModel.getShallow('verticalAlign') || textStyleModel.getShallow('baseline');  textStyle.textLineHeight = textStyleModel.getShallow('lineHeight');  textStyle.textWidth = textStyleModel.getShallow('width');  textStyle.textHeight = textStyleModel.getShallow('height');  textStyle.textTag = textStyleModel.getShallow('tag');  if (!isBlock || !opt.disableBox) {    textStyle.textBackgroundColor = getAutoColor(textStyleModel.getShallow('backgroundColor'), opt);    textStyle.textPadding = textStyleModel.getShallow('padding');    textStyle.textBorderColor = getAutoColor(textStyleModel.getShallow('borderColor'), opt);    textStyle.textBorderWidth = textStyleModel.getShallow('borderWidth');    textStyle.textBorderRadius = textStyleModel.getShallow('borderRadius');    textStyle.textBoxShadowColor = textStyleModel.getShallow('shadowColor');    textStyle.textBoxShadowBlur = textStyleModel.getShallow('shadowBlur');    textStyle.textBoxShadowOffsetX = textStyleModel.getShallow('shadowOffsetX');    textStyle.textBoxShadowOffsetY = textStyleModel.getShallow('shadowOffsetY');  }  textStyle.textShadowColor = textStyleModel.getShallow('textShadowColor') || globalTextStyle.textShadowColor;  textStyle.textShadowBlur = textStyleModel.getShallow('textShadowBlur') || globalTextStyle.textShadowBlur;  textStyle.textShadowOffsetX = textStyleModel.getShallow('textShadowOffsetX') || globalTextStyle.textShadowOffsetX;  textStyle.textShadowOffsetY = textStyleModel.getShallow('textShadowOffsetY') || globalTextStyle.textShadowOffsetY;}function getAutoColor(color, opt) {  return color !== 'auto' ? color : opt && opt.autoColor ? opt.autoColor : null;}/** * Give some default value to the input `textStyle` object, based on the current settings * in this `textStyle` object. * * The Scenario: * when text position is `inside` and `textFill` is not specified, we show * text border by default for better view. But it should be considered that text position * might be changed when hovering or being emphasis, where the `insideRollback` is used to * restore the style. * * Usage (& NOTICE): * When a style object (eithor plain object or instance of `zrender/src/graphic/Style`) is * about to be modified on its text related properties, `rollbackDefaultTextStyle` should * be called before the modification and `applyDefaultTextStyle` should be called after that. * (For the case that all of the text related properties is reset, like `setTextStyleCommon` * does, `rollbackDefaultTextStyle` is not needed to be called). */function applyDefaultTextStyle(textStyle) {  var textPosition = textStyle.textPosition;  var opt = textStyle.insideRollbackOpt;  var insideRollback;  if (opt && textStyle.textFill == null) {    var autoColor = opt.autoColor;    var isRectText = opt.isRectText;    var useInsideStyle = opt.useInsideStyle;    var useInsideStyleCache = useInsideStyle !== false && (useInsideStyle === true || isRectText && textPosition // textPosition can be [10, 30]    && typeof textPosition === 'string' && textPosition.indexOf('inside') >= 0);    var useAutoColorCache = !useInsideStyleCache && autoColor != null; // All of the props declared in `CACHED_LABEL_STYLE_PROPERTIES` are to be cached.    if (useInsideStyleCache || useAutoColorCache) {      insideRollback = {        textFill: textStyle.textFill,        textStroke: textStyle.textStroke,        textStrokeWidth: textStyle.textStrokeWidth      };    }    if (useInsideStyleCache) {      textStyle.textFill = '#fff'; // Consider text with #fff overflow its container.      if (textStyle.textStroke == null) {        textStyle.textStroke = autoColor;        textStyle.textStrokeWidth == null && (textStyle.textStrokeWidth = 2);      }    }    if (useAutoColorCache) {      textStyle.textFill = autoColor;    }  } // Always set `insideRollback`, so that the previous one can be cleared.  textStyle.insideRollback = insideRollback;}/** * Consider the case: in a scatter, * label: { *     normal: {position: 'inside'}, *     emphasis: {position: 'top'} * } * In the normal state, the `textFill` will be set as '#fff' for pretty view (see * `applyDefaultTextStyle`), but when switching to emphasis state, the `textFill` * should be retured to 'autoColor', but not keep '#fff'. */function rollbackDefaultTextStyle(style) {  var insideRollback = style.insideRollback;  if (insideRollback) {    // Reset all of the props in `CACHED_LABEL_STYLE_PROPERTIES`.    style.textFill = insideRollback.textFill;    style.textStroke = insideRollback.textStroke;    style.textStrokeWidth = insideRollback.textStrokeWidth;    style.insideRollback = null;  }}function getFont(opt, ecModel) {  var gTextStyleModel = ecModel && ecModel.getModel('textStyle');  return zrUtil.trim([// FIXME in node-canvas fontWeight is before fontStyle  opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' '));}function animateOrSetProps(isUpdate, el, props, animatableModel, dataIndex, cb) {  if (typeof dataIndex === 'function') {    cb = dataIndex;    dataIndex = null;  } // Do not check 'animation' property directly here. Consider this case:  // animation model is an `itemModel`, whose does not have `isAnimationEnabled`  // but its parent model (`seriesModel`) does.  var animationEnabled = animatableModel && animatableModel.isAnimationEnabled();  if (animationEnabled) {    var postfix = isUpdate ? 'Update' : '';    var duration = animatableModel.getShallow('animationDuration' + postfix);    var animationEasing = animatableModel.getShallow('animationEasing' + postfix);    var animationDelay = animatableModel.getShallow('animationDelay' + postfix);    if (typeof animationDelay === 'function') {      animationDelay = animationDelay(dataIndex, animatableModel.getAnimationDelayParams ? animatableModel.getAnimationDelayParams(el, dataIndex) : null);    }    if (typeof duration === 'function') {      duration = duration(dataIndex);    }    duration > 0 ? el.animateTo(props, duration, animationDelay || 0, animationEasing, cb, !!cb) : (el.stopAnimation(), el.attr(props), cb && cb());  } else {    el.stopAnimation();    el.attr(props);    cb && cb();  }}/** * Update graphic element properties with or without animation according to the * configuration in series. * * Caution: this method will stop previous animation. * So do not use this method to one element twice before * animation starts, unless you know what you are doing. * * @param {module:zrender/Element} el * @param {Object} props * @param {module:echarts/model/Model} [animatableModel] * @param {number} [dataIndex] * @param {Function} [cb] * @example *     graphic.updateProps(el, { *         position: [100, 100] *     }, seriesModel, dataIndex, function () { console.log('Animation done!'); }); *     // Or *     graphic.updateProps(el, { *         position: [100, 100] *     }, seriesModel, function () { console.log('Animation done!'); }); */function updateProps(el, props, animatableModel, dataIndex, cb) {  animateOrSetProps(true, el, props, animatableModel, dataIndex, cb);}/** * Init graphic element properties with or without animation according to the * configuration in series. * * Caution: this method will stop previous animation. * So do not use this method to one element twice before * animation starts, unless you know what you are doing. * * @param {module:zrender/Element} el * @param {Object} props * @param {module:echarts/model/Model} [animatableModel] * @param {number} [dataIndex] * @param {Function} cb */function initProps(el, props, animatableModel, dataIndex, cb) {  animateOrSetProps(false, el, props, animatableModel, dataIndex, cb);}/** * Get transform matrix of target (param target), * in coordinate of its ancestor (param ancestor) * * @param {module:zrender/mixin/Transformable} target * @param {module:zrender/mixin/Transformable} [ancestor] */function getTransform(target, ancestor) {  var mat = matrix.identity([]);  while (target && target !== ancestor) {    matrix.mul(mat, target.getLocalTransform(), mat);    target = target.parent;  }  return mat;}/** * Apply transform to an vertex. * @param {Array.<number>} target [x, y] * @param {Array.<number>|TypedArray.<number>|Object} transform Can be: *      + Transform matrix: like [1, 0, 0, 1, 0, 0] *      + {position, rotation, scale}, the same as `zrender/Transformable`. * @param {boolean=} invert Whether use invert matrix. * @return {Array.<number>} [x, y] */function applyTransform(target, transform, invert) {  if (transform && !zrUtil.isArrayLike(transform)) {    transform = Transformable.getLocalTransform(transform);  }  if (invert) {    transform = matrix.invert([], transform);  }  return vector.applyTransform([], target, transform);}/** * @param {string} direction 'left' 'right' 'top' 'bottom' * @param {Array.<number>} transform Transform matrix: like [1, 0, 0, 1, 0, 0] * @param {boolean=} invert Whether use invert matrix. * @return {string} Transformed direction. 'left' 'right' 'top' 'bottom' */function transformDirection(direction, transform, invert) {  // Pick a base, ensure that transform result will not be (0, 0).  var hBase = transform[4] === 0 || transform[5] === 0 || transform[0] === 0 ? 1 : Math.abs(2 * transform[4] / transform[0]);  var vBase = transform[4] === 0 || transform[5] === 0 || transform[2] === 0 ? 1 : Math.abs(2 * transform[4] / transform[2]);  var vertex = [direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0];  vertex = applyTransform(vertex, transform, invert);  return Math.abs(vertex[0]) > Math.abs(vertex[1]) ? vertex[0] > 0 ? 'right' : 'left' : vertex[1] > 0 ? 'bottom' : 'top';}/** * Apply group transition animation from g1 to g2. * If no animatableModel, no animation. */function groupTransition(g1, g2, animatableModel, cb) {  if (!g1 || !g2) {    return;  }  function getElMap(g) {    var elMap = {};    g.traverse(function (el) {      if (!el.isGroup && el.anid) {        elMap[el.anid] = el;      }    });    return elMap;  }  function getAnimatableProps(el) {    var obj = {      position: vector.clone(el.position),      rotation: el.rotation    };    if (el.shape) {      obj.shape = zrUtil.extend({}, el.shape);    }    return obj;  }  var elMap1 = getElMap(g1);  g2.traverse(function (el) {    if (!el.isGroup && el.anid) {      var oldEl = elMap1[el.anid];      if (oldEl) {        var newProp = getAnimatableProps(el);        el.attr(getAnimatableProps(oldEl));        updateProps(el, newProp, animatableModel, el.dataIndex);      } // else {      //     if (el.previousProps) {      //         graphic.updateProps      //     }      // }    }  });}/** * @param {Array.<Array.<number>>} points Like: [[23, 44], [53, 66], ...] * @param {Object} rect {x, y, width, height} * @return {Array.<Array.<number>>} A new clipped points. */function clipPointsByRect(points, rect) {  // FIXME: this way migth be incorrect when grpahic clipped by a corner.  // and when element have border.  return zrUtil.map(points, function (point) {    var x = point[0];    x = mathMax(x, rect.x);    x = mathMin(x, rect.x + rect.width);    var y = point[1];    y = mathMax(y, rect.y);    y = mathMin(y, rect.y + rect.height);    return [x, y];  });}/** * @param {Object} targetRect {x, y, width, height} * @param {Object} rect {x, y, width, height} * @return {Object} A new clipped rect. If rect size are negative, return undefined. */function clipRectByRect(targetRect, rect) {  var x = mathMax(targetRect.x, rect.x);  var x2 = mathMin(targetRect.x + targetRect.width, rect.x + rect.width);  var y = mathMax(targetRect.y, rect.y);  var y2 = mathMin(targetRect.y + targetRect.height, rect.y + rect.height); // If the total rect is cliped, nothing, including the border,  // should be painted. So return undefined.  if (x2 >= x && y2 >= y) {    return {      x: x,      y: y,      width: x2 - x,      height: y2 - y    };  }}/** * @param {string} iconStr Support 'image://' or 'path://' or direct svg path. * @param {Object} [opt] Properties of `module:zrender/Element`, except `style`. * @param {Object} [rect] {x, y, width, height} * @return {module:zrender/Element} Icon path or image element. */function createIcon(iconStr, opt, rect) {  opt = zrUtil.extend({    rectHover: true  }, opt);  var style = opt.style = {    strokeNoScale: true  };  rect = rect || {    x: -1,    y: -1,    width: 2,    height: 2  };  if (iconStr) {    return iconStr.indexOf('image://') === 0 ? (style.image = iconStr.slice(8), zrUtil.defaults(style, rect), new ZImage(opt)) : makePath(iconStr.replace('path://', ''), opt, rect, 'center');  }}/** * Return `true` if the given line (line `a`) and the given polygon * are intersect. * Note that we do not count colinear as intersect here because no * requirement for that. We could do that if required in future. * * @param {number} a1x * @param {number} a1y * @param {number} a2x * @param {number} a2y * @param {Array.<Array.<number>>} points Points of the polygon. * @return {boolean} */function linePolygonIntersect(a1x, a1y, a2x, a2y, points) {  for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) {    var p = points[i];    if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) {      return true;    }    p2 = p;  }}/** * Return `true` if the given two lines (line `a` and line `b`) * are intersect. * Note that we do not count colinear as intersect here because no * requirement for that. We could do that if required in future. * * @param {number} a1x * @param {number} a1y * @param {number} a2x * @param {number} a2y * @param {number} b1x * @param {number} b1y * @param {number} b2x * @param {number} b2y * @return {boolean} */function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) {  // let `vec_m` to be `vec_a2 - vec_a1` and `vec_n` to be `vec_b2 - vec_b1`.  var mx = a2x - a1x;  var my = a2y - a1y;  var nx = b2x - b1x;  var ny = b2y - b1y; // `vec_m` and `vec_n` are parallel iff  //     exising `k` such that `vec_m = k · vec_n`, equivalent to `vec_m X vec_n = 0`.  var nmCrossProduct = crossProduct2d(nx, ny, mx, my);  if (nearZero(nmCrossProduct)) {    return false;  } // `vec_m` and `vec_n` are intersect iff  //     existing `p` and `q` in [0, 1] such that `vec_a1 + p * vec_m = vec_b1 + q * vec_n`,  //     such that `q = ((vec_a1 - vec_b1) X vec_m) / (vec_n X vec_m)`  //           and `p = ((vec_a1 - vec_b1) X vec_n) / (vec_n X vec_m)`.  var b1a1x = a1x - b1x;  var b1a1y = a1y - b1y;  var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct;  if (q < 0 || q > 1) {    return false;  }  var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct;  if (p < 0 || p > 1) {    return false;  }  return true;}/** * Cross product of 2-dimension vector. */function crossProduct2d(x1, y1, x2, y2) {  return x1 * y2 - x2 * y1;}function nearZero(val) {  return val <= 1e-6 && val >= -1e-6;} // Register built-in shapes. These shapes might be overwirtten// by users, although we do not recommend that.registerShape('circle', Circle);registerShape('sector', Sector);registerShape('ring', Ring);registerShape('polygon', Polygon);registerShape('polyline', Polyline);registerShape('rect', Rect);registerShape('line', Line);registerShape('bezierCurve', BezierCurve);registerShape('arc', Arc);exports.Z2_EMPHASIS_LIFT = Z2_EMPHASIS_LIFT;exports.CACHED_LABEL_STYLE_PROPERTIES = CACHED_LABEL_STYLE_PROPERTIES;exports.extendShape = extendShape;exports.extendPath = extendPath;exports.registerShape = registerShape;exports.getShapeClass = getShapeClass;exports.makePath = makePath;exports.makeImage = makeImage;exports.mergePath = mergePath;exports.resizePath = resizePath;exports.subPixelOptimizeLine = subPixelOptimizeLine;exports.subPixelOptimizeRect = subPixelOptimizeRect;exports.subPixelOptimize = subPixelOptimize;exports.setElementHoverStyle = setElementHoverStyle;exports.setHoverStyle = setHoverStyle;exports.setAsHighDownDispatcher = setAsHighDownDispatcher;exports.isHighDownDispatcher = isHighDownDispatcher;exports.getHighlightDigit = getHighlightDigit;exports.setLabelStyle = setLabelStyle;exports.modifyLabelStyle = modifyLabelStyle;exports.setTextStyle = setTextStyle;exports.setText = setText;exports.getFont = getFont;exports.updateProps = updateProps;exports.initProps = initProps;exports.getTransform = getTransform;exports.applyTransform = applyTransform;exports.transformDirection = transformDirection;exports.groupTransition = groupTransition;exports.clipPointsByRect = clipPointsByRect;exports.clipRectByRect = clipRectByRect;exports.createIcon = createIcon;exports.linePolygonIntersect = linePolygonIntersect;exports.lineLineIntersect = lineLineIntersect;
 |