install.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { __extends } from "tslib";
  41. import * as zrUtil from 'zrender/lib/core/util';
  42. import * as modelUtil from '../../util/model';
  43. import * as graphicUtil from '../../util/graphic';
  44. import * as layoutUtil from '../../util/layout';
  45. import { parsePercent } from '../../util/number';
  46. import ComponentModel from '../../model/Component';
  47. import ComponentView from '../../view/Component';
  48. import { getECData } from '../../util/innerStore';
  49. import { isEC4CompatibleStyle, convertFromEC4CompatibleStyle } from '../../util/styleCompat';
  50. var TRANSFORM_PROPS = {
  51. x: 1,
  52. y: 1,
  53. scaleX: 1,
  54. scaleY: 1,
  55. originX: 1,
  56. originY: 1,
  57. rotation: 1
  58. };
  59. ;
  60. var inner = modelUtil.makeInner();
  61. var _nonShapeGraphicElements = {
  62. // Reserved but not supported in graphic component.
  63. path: null,
  64. compoundPath: null,
  65. // Supported in graphic component.
  66. group: graphicUtil.Group,
  67. image: graphicUtil.Image,
  68. text: graphicUtil.Text
  69. }; // ------------------------
  70. // Preprocessor
  71. // ------------------------
  72. var preprocessor = function (option) {
  73. var graphicOption = option.graphic; // Convert
  74. // {graphic: [{left: 10, type: 'circle'}, ...]}
  75. // or
  76. // {graphic: {left: 10, type: 'circle'}}
  77. // to
  78. // {graphic: [{elements: [{left: 10, type: 'circle'}, ...]}]}
  79. if (zrUtil.isArray(graphicOption)) {
  80. if (!graphicOption[0] || !graphicOption[0].elements) {
  81. option.graphic = [{
  82. elements: graphicOption
  83. }];
  84. } else {
  85. // Only one graphic instance can be instantiated. (We dont
  86. // want that too many views are created in echarts._viewMap)
  87. option.graphic = [option.graphic[0]];
  88. }
  89. } else if (graphicOption && !graphicOption.elements) {
  90. option.graphic = [{
  91. elements: [graphicOption]
  92. }];
  93. }
  94. };
  95. ;
  96. var GraphicComponentModel =
  97. /** @class */
  98. function (_super) {
  99. __extends(GraphicComponentModel, _super);
  100. function GraphicComponentModel() {
  101. var _this = _super !== null && _super.apply(this, arguments) || this;
  102. _this.type = GraphicComponentModel.type;
  103. _this.preventAutoZ = true;
  104. return _this;
  105. }
  106. GraphicComponentModel.prototype.mergeOption = function (option, ecModel) {
  107. // Prevent default merge to elements
  108. var elements = this.option.elements;
  109. this.option.elements = null;
  110. _super.prototype.mergeOption.call(this, option, ecModel);
  111. this.option.elements = elements;
  112. };
  113. GraphicComponentModel.prototype.optionUpdated = function (newOption, isInit) {
  114. var thisOption = this.option;
  115. var newList = (isInit ? thisOption : newOption).elements;
  116. var existList = thisOption.elements = isInit ? [] : thisOption.elements;
  117. var flattenedList = [];
  118. this._flatten(newList, flattenedList, null);
  119. var mappingResult = modelUtil.mappingToExists(existList, flattenedList, 'normalMerge'); // Clear elOptionsToUpdate
  120. var elOptionsToUpdate = this._elOptionsToUpdate = [];
  121. zrUtil.each(mappingResult, function (resultItem, index) {
  122. var newElOption = resultItem.newOption;
  123. if (process.env.NODE_ENV !== 'production') {
  124. zrUtil.assert(zrUtil.isObject(newElOption) || resultItem.existing, 'Empty graphic option definition');
  125. }
  126. if (!newElOption) {
  127. return;
  128. }
  129. elOptionsToUpdate.push(newElOption);
  130. setKeyInfoToNewElOption(resultItem, newElOption);
  131. mergeNewElOptionToExist(existList, index, newElOption);
  132. setLayoutInfoToExist(existList[index], newElOption);
  133. }, this); // Clean
  134. for (var i = existList.length - 1; i >= 0; i--) {
  135. if (existList[i] == null) {
  136. existList.splice(i, 1);
  137. } else {
  138. // $action should be volatile, otherwise option gotten from
  139. // `getOption` will contain unexpected $action.
  140. delete existList[i].$action;
  141. }
  142. }
  143. };
  144. /**
  145. * Convert
  146. * [{
  147. * type: 'group',
  148. * id: 'xx',
  149. * children: [{type: 'circle'}, {type: 'polygon'}]
  150. * }]
  151. * to
  152. * [
  153. * {type: 'group', id: 'xx'},
  154. * {type: 'circle', parentId: 'xx'},
  155. * {type: 'polygon', parentId: 'xx'}
  156. * ]
  157. */
  158. GraphicComponentModel.prototype._flatten = function (optionList, result, parentOption) {
  159. zrUtil.each(optionList, function (option) {
  160. if (!option) {
  161. return;
  162. }
  163. if (parentOption) {
  164. option.parentOption = parentOption;
  165. }
  166. result.push(option);
  167. var children = option.children;
  168. if (option.type === 'group' && children) {
  169. this._flatten(children, result, option);
  170. } // Deleting for JSON output, and for not affecting group creation.
  171. delete option.children;
  172. }, this);
  173. }; // FIXME
  174. // Pass to view using payload? setOption has a payload?
  175. GraphicComponentModel.prototype.useElOptionsToUpdate = function () {
  176. var els = this._elOptionsToUpdate; // Clear to avoid render duplicately when zooming.
  177. this._elOptionsToUpdate = null;
  178. return els;
  179. };
  180. GraphicComponentModel.type = 'graphic';
  181. GraphicComponentModel.defaultOption = {
  182. elements: [] // parentId: null
  183. };
  184. return GraphicComponentModel;
  185. }(ComponentModel); // ------------------------
  186. // View
  187. // ------------------------
  188. var GraphicComponentView =
  189. /** @class */
  190. function (_super) {
  191. __extends(GraphicComponentView, _super);
  192. function GraphicComponentView() {
  193. var _this = _super !== null && _super.apply(this, arguments) || this;
  194. _this.type = GraphicComponentView.type;
  195. return _this;
  196. }
  197. GraphicComponentView.prototype.init = function () {
  198. this._elMap = zrUtil.createHashMap();
  199. };
  200. GraphicComponentView.prototype.render = function (graphicModel, ecModel, api) {
  201. // Having leveraged between use cases and algorithm complexity, a very
  202. // simple layout mechanism is used:
  203. // The size(width/height) can be determined by itself or its parent (not
  204. // implemented yet), but can not by its children. (Top-down travel)
  205. // The location(x/y) can be determined by the bounding rect of itself
  206. // (can including its descendants or not) and the size of its parent.
  207. // (Bottom-up travel)
  208. // When `chart.clear()` or `chart.setOption({...}, true)` with the same id,
  209. // view will be reused.
  210. if (graphicModel !== this._lastGraphicModel) {
  211. this._clear();
  212. }
  213. this._lastGraphicModel = graphicModel;
  214. this._updateElements(graphicModel);
  215. this._relocate(graphicModel, api);
  216. };
  217. /**
  218. * Update graphic elements.
  219. */
  220. GraphicComponentView.prototype._updateElements = function (graphicModel) {
  221. var elOptionsToUpdate = graphicModel.useElOptionsToUpdate();
  222. if (!elOptionsToUpdate) {
  223. return;
  224. }
  225. var elMap = this._elMap;
  226. var rootGroup = this.group; // Top-down tranverse to assign graphic settings to each elements.
  227. zrUtil.each(elOptionsToUpdate, function (elOption) {
  228. var id = modelUtil.convertOptionIdName(elOption.id, null);
  229. var elExisting = id != null ? elMap.get(id) : null;
  230. var parentId = modelUtil.convertOptionIdName(elOption.parentId, null);
  231. var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup;
  232. var elType = elOption.type;
  233. var elOptionStyle = elOption.style;
  234. if (elType === 'text' && elOptionStyle) {
  235. // In top/bottom mode, textVerticalAlign should not be used, which cause
  236. // inaccurately locating.
  237. if (elOption.hv && elOption.hv[1]) {
  238. elOptionStyle.textVerticalAlign = elOptionStyle.textBaseline = elOptionStyle.verticalAlign = elOptionStyle.align = null;
  239. }
  240. }
  241. var textContentOption = elOption.textContent;
  242. var textConfig = elOption.textConfig;
  243. if (elOptionStyle && isEC4CompatibleStyle(elOptionStyle, elType, !!textConfig, !!textContentOption)) {
  244. var convertResult = convertFromEC4CompatibleStyle(elOptionStyle, elType, true);
  245. if (!textConfig && convertResult.textConfig) {
  246. textConfig = elOption.textConfig = convertResult.textConfig;
  247. }
  248. if (!textContentOption && convertResult.textContent) {
  249. textContentOption = convertResult.textContent;
  250. }
  251. } // Remove unnecessary props to avoid potential problems.
  252. var elOptionCleaned = getCleanedElOption(elOption); // For simple, do not support parent change, otherwise reorder is needed.
  253. if (process.env.NODE_ENV !== 'production') {
  254. elExisting && zrUtil.assert(targetElParent === elExisting.parent, 'Changing parent is not supported.');
  255. }
  256. var $action = elOption.$action || 'merge';
  257. if ($action === 'merge') {
  258. elExisting ? elExisting.attr(elOptionCleaned) : createEl(id, targetElParent, elOptionCleaned, elMap);
  259. } else if ($action === 'replace') {
  260. removeEl(elExisting, elMap);
  261. createEl(id, targetElParent, elOptionCleaned, elMap);
  262. } else if ($action === 'remove') {
  263. removeEl(elExisting, elMap);
  264. }
  265. var el = elMap.get(id);
  266. if (el && textContentOption) {
  267. if ($action === 'merge') {
  268. var textContentExisting = el.getTextContent();
  269. textContentExisting ? textContentExisting.attr(textContentOption) : el.setTextContent(new graphicUtil.Text(textContentOption));
  270. } else if ($action === 'replace') {
  271. el.setTextContent(new graphicUtil.Text(textContentOption));
  272. }
  273. }
  274. if (el) {
  275. var elInner = inner(el);
  276. elInner.__ecGraphicWidthOption = elOption.width;
  277. elInner.__ecGraphicHeightOption = elOption.height;
  278. setEventData(el, graphicModel, elOption);
  279. graphicUtil.setTooltipConfig({
  280. el: el,
  281. componentModel: graphicModel,
  282. itemName: el.name,
  283. itemTooltipOption: elOption.tooltip
  284. });
  285. }
  286. });
  287. };
  288. /**
  289. * Locate graphic elements.
  290. */
  291. GraphicComponentView.prototype._relocate = function (graphicModel, api) {
  292. var elOptions = graphicModel.option.elements;
  293. var rootGroup = this.group;
  294. var elMap = this._elMap;
  295. var apiWidth = api.getWidth();
  296. var apiHeight = api.getHeight(); // Top-down to calculate percentage width/height of group
  297. for (var i = 0; i < elOptions.length; i++) {
  298. var elOption = elOptions[i];
  299. var id = modelUtil.convertOptionIdName(elOption.id, null);
  300. var el = id != null ? elMap.get(id) : null;
  301. if (!el || !el.isGroup) {
  302. continue;
  303. }
  304. var parentEl = el.parent;
  305. var isParentRoot = parentEl === rootGroup; // Like 'position:absolut' in css, default 0.
  306. var elInner = inner(el);
  307. var parentElInner = inner(parentEl);
  308. elInner.__ecGraphicWidth = parsePercent(elInner.__ecGraphicWidthOption, isParentRoot ? apiWidth : parentElInner.__ecGraphicWidth) || 0;
  309. elInner.__ecGraphicHeight = parsePercent(elInner.__ecGraphicHeightOption, isParentRoot ? apiHeight : parentElInner.__ecGraphicHeight) || 0;
  310. } // Bottom-up tranvese all elements (consider ec resize) to locate elements.
  311. for (var i = elOptions.length - 1; i >= 0; i--) {
  312. var elOption = elOptions[i];
  313. var id = modelUtil.convertOptionIdName(elOption.id, null);
  314. var el = id != null ? elMap.get(id) : null;
  315. if (!el) {
  316. continue;
  317. }
  318. var parentEl = el.parent;
  319. var parentElInner = inner(parentEl);
  320. var containerInfo = parentEl === rootGroup ? {
  321. width: apiWidth,
  322. height: apiHeight
  323. } : {
  324. width: parentElInner.__ecGraphicWidth,
  325. height: parentElInner.__ecGraphicHeight
  326. }; // PENDING
  327. // Currently, when `bounding: 'all'`, the union bounding rect of the group
  328. // does not include the rect of [0, 0, group.width, group.height], which
  329. // is probably weird for users. Should we make a break change for it?
  330. layoutUtil.positionElement(el, elOption, containerInfo, null, {
  331. hv: elOption.hv,
  332. boundingMode: elOption.bounding
  333. });
  334. }
  335. };
  336. /**
  337. * Clear all elements.
  338. */
  339. GraphicComponentView.prototype._clear = function () {
  340. var elMap = this._elMap;
  341. elMap.each(function (el) {
  342. removeEl(el, elMap);
  343. });
  344. this._elMap = zrUtil.createHashMap();
  345. };
  346. GraphicComponentView.prototype.dispose = function () {
  347. this._clear();
  348. };
  349. GraphicComponentView.type = 'graphic';
  350. return GraphicComponentView;
  351. }(ComponentView);
  352. function createEl(id, targetElParent, elOption, elMap) {
  353. var graphicType = elOption.type;
  354. if (process.env.NODE_ENV !== 'production') {
  355. zrUtil.assert(graphicType, 'graphic type MUST be set');
  356. }
  357. var Clz = zrUtil.hasOwn(_nonShapeGraphicElements, graphicType) // Those graphic elements are not shapes. They should not be
  358. // overwritten by users, so do them first.
  359. ? _nonShapeGraphicElements[graphicType] : graphicUtil.getShapeClass(graphicType);
  360. if (process.env.NODE_ENV !== 'production') {
  361. zrUtil.assert(Clz, 'graphic type can not be found');
  362. }
  363. var el = new Clz(elOption);
  364. targetElParent.add(el);
  365. elMap.set(id, el);
  366. inner(el).__ecGraphicId = id;
  367. }
  368. function removeEl(elExisting, elMap) {
  369. var existElParent = elExisting && elExisting.parent;
  370. if (existElParent) {
  371. elExisting.type === 'group' && elExisting.traverse(function (el) {
  372. removeEl(el, elMap);
  373. });
  374. elMap.removeKey(inner(elExisting).__ecGraphicId);
  375. existElParent.remove(elExisting);
  376. }
  377. } // Remove unnecessary props to avoid potential problems.
  378. function getCleanedElOption(elOption) {
  379. elOption = zrUtil.extend({}, elOption);
  380. zrUtil.each(['id', 'parentId', '$action', 'hv', 'bounding', 'textContent'].concat(layoutUtil.LOCATION_PARAMS), function (name) {
  381. delete elOption[name];
  382. });
  383. return elOption;
  384. }
  385. function isSetLoc(obj, props) {
  386. var isSet;
  387. zrUtil.each(props, function (prop) {
  388. obj[prop] != null && obj[prop] !== 'auto' && (isSet = true);
  389. });
  390. return isSet;
  391. }
  392. function setKeyInfoToNewElOption(resultItem, newElOption) {
  393. var existElOption = resultItem.existing; // Set id and type after id assigned.
  394. newElOption.id = resultItem.keyInfo.id;
  395. !newElOption.type && existElOption && (newElOption.type = existElOption.type); // Set parent id if not specified
  396. if (newElOption.parentId == null) {
  397. var newElParentOption = newElOption.parentOption;
  398. if (newElParentOption) {
  399. newElOption.parentId = newElParentOption.id;
  400. } else if (existElOption) {
  401. newElOption.parentId = existElOption.parentId;
  402. }
  403. } // Clear
  404. newElOption.parentOption = null;
  405. }
  406. function mergeNewElOptionToExist(existList, index, newElOption) {
  407. // Update existing options, for `getOption` feature.
  408. var newElOptCopy = zrUtil.extend({}, newElOption);
  409. var existElOption = existList[index];
  410. var $action = newElOption.$action || 'merge';
  411. if ($action === 'merge') {
  412. if (existElOption) {
  413. if (process.env.NODE_ENV !== 'production') {
  414. var newType = newElOption.type;
  415. zrUtil.assert(!newType || existElOption.type === newType, 'Please set $action: "replace" to change `type`');
  416. } // We can ensure that newElOptCopy and existElOption are not
  417. // the same object, so `merge` will not change newElOptCopy.
  418. zrUtil.merge(existElOption, newElOptCopy, true); // Rigid body, use ignoreSize.
  419. layoutUtil.mergeLayoutParam(existElOption, newElOptCopy, {
  420. ignoreSize: true
  421. }); // Will be used in render.
  422. layoutUtil.copyLayoutParams(newElOption, existElOption);
  423. } else {
  424. existList[index] = newElOptCopy;
  425. }
  426. } else if ($action === 'replace') {
  427. existList[index] = newElOptCopy;
  428. } else if ($action === 'remove') {
  429. // null will be cleaned later.
  430. existElOption && (existList[index] = null);
  431. }
  432. }
  433. function setLayoutInfoToExist(existItem, newElOption) {
  434. if (!existItem) {
  435. return;
  436. }
  437. existItem.hv = newElOption.hv = [// Rigid body, dont care `width`.
  438. isSetLoc(newElOption, ['left', 'right']), // Rigid body, dont care `height`.
  439. isSetLoc(newElOption, ['top', 'bottom'])]; // Give default group size. Otherwise layout error may occur.
  440. if (existItem.type === 'group') {
  441. var existingGroupOpt = existItem;
  442. var newGroupOpt = newElOption;
  443. existingGroupOpt.width == null && (existingGroupOpt.width = newGroupOpt.width = 0);
  444. existingGroupOpt.height == null && (existingGroupOpt.height = newGroupOpt.height = 0);
  445. }
  446. }
  447. function setEventData(el, graphicModel, elOption) {
  448. var eventData = getECData(el).eventData; // Simple optimize for large amount of elements that no need event.
  449. if (!el.silent && !el.ignore && !eventData) {
  450. eventData = getECData(el).eventData = {
  451. componentType: 'graphic',
  452. componentIndex: graphicModel.componentIndex,
  453. name: el.name
  454. };
  455. } // `elOption.info` enables user to mount some info on
  456. // elements and use them in event handlers.
  457. if (eventData) {
  458. eventData.info = elOption.info;
  459. }
  460. }
  461. export function install(registers) {
  462. registers.registerComponentModel(GraphicComponentModel);
  463. registers.registerComponentView(GraphicComponentView);
  464. registers.registerPreprocessor(preprocessor);
  465. }