utils.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. var __rest = (this && this.__rest) || function (s, e) {
  2. var t = {};
  3. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  4. t[p] = s[p];
  5. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  6. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  7. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  8. t[p[i]] = s[p[i]];
  9. }
  10. return t;
  11. };
  12. import { deepMix } from '@antv/util';
  13. import { getContainerSize } from '../utils/size';
  14. import { mark } from './mark';
  15. import { composition } from './composition';
  16. // Keys can specified by new Chart({...}).
  17. // Keys can bubble form mark-level options to view-level options.
  18. export const VIEW_KEYS = [
  19. 'width',
  20. 'height',
  21. 'padding',
  22. 'paddingLeft',
  23. 'paddingRight',
  24. 'paddingBottom',
  25. 'paddingTop',
  26. 'inset',
  27. 'insetLeft',
  28. 'insetRight',
  29. 'insetTop',
  30. 'insetBottom',
  31. 'margin',
  32. 'marginLeft',
  33. 'marginRight',
  34. 'marginTop',
  35. 'marginBottom',
  36. 'autoFit',
  37. 'theme',
  38. 'title',
  39. ];
  40. export function normalizeContainer(container) {
  41. if (container === undefined)
  42. return document.createElement('div');
  43. if (typeof container === 'string') {
  44. const node = document.getElementById(container);
  45. return node;
  46. }
  47. return container;
  48. }
  49. export function removeContainer(container) {
  50. const parent = container.parentNode;
  51. if (parent) {
  52. parent.removeChild(container);
  53. }
  54. }
  55. export function normalizeRoot(node) {
  56. if (node.type !== null)
  57. return node;
  58. const root = node.children[node.children.length - 1];
  59. for (const key of VIEW_KEYS)
  60. root.attr(key, node.attr(key));
  61. return root;
  62. }
  63. export function valueOf(node) {
  64. return Object.assign(Object.assign({}, node.value), { type: node.type });
  65. }
  66. export function sizeOf(options, container) {
  67. const { autoFit } = options;
  68. if (autoFit)
  69. return getContainerSize(container);
  70. const { width = 640, height = 480 } = options;
  71. return { width, height };
  72. }
  73. export function optionsOf(node) {
  74. const root = normalizeRoot(node);
  75. const discovered = [root];
  76. const nodeValue = new Map();
  77. nodeValue.set(root, valueOf(root));
  78. while (discovered.length) {
  79. const node = discovered.pop();
  80. const value = nodeValue.get(node);
  81. const { children = [] } = node;
  82. for (const child of children) {
  83. const childValue = valueOf(child);
  84. const { children = [] } = value;
  85. children.push(childValue);
  86. discovered.push(child);
  87. nodeValue.set(child, childValue);
  88. value.children = children;
  89. }
  90. }
  91. return nodeValue.get(root);
  92. }
  93. function isMark(type) {
  94. return new Set(Object.keys(mark)).has(type);
  95. }
  96. function normalizeRootOptions(node, options, previousType) {
  97. const { type: oldType } = node;
  98. const { type = previousType || oldType } = options;
  99. if (type === 'view')
  100. return options;
  101. if (typeof type !== 'string')
  102. return options;
  103. if (!isMark(type))
  104. return options;
  105. const view = { type: 'view' };
  106. const mark = Object.assign({}, options);
  107. for (const key of VIEW_KEYS) {
  108. if (mark[key] !== undefined) {
  109. view[key] = mark[key];
  110. delete mark[key];
  111. }
  112. }
  113. return Object.assign(Object.assign({}, view), { children: [mark] });
  114. }
  115. function typeCtor(type) {
  116. const node = Object.assign(Object.assign({}, mark), composition);
  117. const ctor = node[type];
  118. if (!ctor)
  119. throw new Error(`Unknown mark: ${type}.`);
  120. return ctor;
  121. }
  122. // Create node from options.
  123. function createNode(options) {
  124. const { type, children } = options, value = __rest(options, ["type", "children"]);
  125. if (typeof type !== 'string')
  126. return;
  127. const Ctor = typeCtor(type);
  128. const node = new Ctor();
  129. node.value = value;
  130. return node;
  131. }
  132. // Update node by options.
  133. function updateNode(node, newOptions) {
  134. const { type, children } = newOptions, value = __rest(newOptions, ["type", "children"]);
  135. if (node.type === type || type === undefined) {
  136. // Update node.
  137. node.value = deepMix(node.value, value);
  138. }
  139. else if (typeof type === 'string') {
  140. // Transform node.
  141. node.type = type;
  142. node.value = value;
  143. }
  144. }
  145. // Create a nested node tree from newOptions, and append it to the parent.
  146. function appendNode(parent, newOptions) {
  147. if (!parent)
  148. return;
  149. const discovered = [[parent, newOptions]];
  150. while (discovered.length) {
  151. const [parent, nodeOptions] = discovered.shift();
  152. const node = createNode(nodeOptions);
  153. if (Array.isArray(parent.children))
  154. parent.push(node);
  155. const { children } = nodeOptions;
  156. if (Array.isArray(children)) {
  157. for (const child of children) {
  158. discovered.push([node, child]);
  159. }
  160. }
  161. }
  162. }
  163. // Update node tree from options.
  164. export function updateRoot(node, options, definedType) {
  165. const rootOptions = normalizeRootOptions(node, options, definedType);
  166. const discovered = [[null, node, rootOptions]];
  167. while (discovered.length) {
  168. const [parent, oldNode, newNode] = discovered.shift();
  169. // If there is no oldNode, create a node tree directly.
  170. if (!oldNode) {
  171. appendNode(parent, newNode);
  172. }
  173. else if (!newNode) {
  174. oldNode.remove();
  175. }
  176. else {
  177. updateNode(oldNode, newNode);
  178. const { children: newChildren } = newNode;
  179. const { children: oldChildren } = oldNode;
  180. if (Array.isArray(newChildren) && Array.isArray(oldChildren)) {
  181. // Only update node specified in newChildren,
  182. // the extra oldChildren will remain still.
  183. const n = Math.max(newChildren.length, oldChildren.length);
  184. for (let i = 0; i < n; i++) {
  185. const newChild = newChildren[i];
  186. const oldChild = oldChildren[i];
  187. discovered.push([oldNode, oldChild, newChild]);
  188. }
  189. }
  190. }
  191. }
  192. }
  193. export function createEmptyPromise() {
  194. let reject;
  195. let resolve;
  196. const cloned = new Promise((res, rej) => {
  197. resolve = res;
  198. reject = rej;
  199. });
  200. return [cloned, resolve, reject];
  201. }
  202. //# sourceMappingURL=utils.js.map