chart.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  2. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  3. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  4. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  5. return c > 3 && r && Object.defineProperty(target, key, r), r;
  6. };
  7. var __rest = (this && this.__rest) || function (s, e) {
  8. var t = {};
  9. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  10. t[p] = s[p];
  11. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  12. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  13. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  14. t[p[i]] = s[p[i]];
  15. }
  16. return t;
  17. };
  18. import { Canvas as GCanvas } from '@antv/g';
  19. import { Renderer as CanvasRenderer } from '@antv/g-canvas';
  20. import { Plugin as DragAndDropPlugin } from '@antv/g-plugin-dragndrop';
  21. import { debounce } from '@antv/util';
  22. import EventEmitter from '@antv/event-emitter';
  23. import { render, destroy } from '../runtime';
  24. import { ChartEvent } from '../utils/event';
  25. import { defineProps, nodeProps, containerProps, } from './props';
  26. import { mark } from './mark';
  27. import { composition, View } from './composition';
  28. import { library } from './library';
  29. import { normalizeContainer, removeContainer, sizeOf, optionsOf, updateRoot, createEmptyPromise, } from './utils';
  30. export const G2_CHART_KEY = 'G2_CHART_KEY';
  31. export const props = [
  32. { name: 'data', type: 'value' },
  33. { name: 'width', type: 'value' },
  34. { name: 'height', type: 'value' },
  35. { name: 'coordinate', type: 'value' },
  36. { name: 'interaction', type: 'object' },
  37. { name: 'theme', type: 'object' },
  38. { name: 'title', type: 'value' },
  39. { name: 'transform', type: 'array' },
  40. { name: 'scale', type: 'object' },
  41. { name: 'axis', type: 'object' },
  42. { name: 'legend', type: 'object' },
  43. { name: 'style', type: 'object' },
  44. { name: 'labelTransform', type: 'array' },
  45. ...nodeProps(mark),
  46. ...containerProps(composition),
  47. ];
  48. let Chart = class Chart extends View {
  49. constructor(options) {
  50. const _a = options || {}, { container, canvas, renderer, plugins } = _a, rest = __rest(_a, ["container", "canvas", "renderer", "plugins"]);
  51. super(rest, 'view');
  52. // Identifies whether bindAutoFit.
  53. this._hasBindAutoFit = false;
  54. this._rendering = false;
  55. this._trailing = false;
  56. this._trailingResolve = null;
  57. this._trailingReject = null;
  58. this._previousDefinedType = null;
  59. this._onResize = debounce(() => {
  60. this.forceFit();
  61. }, 300);
  62. this._renderer = renderer || new CanvasRenderer();
  63. this._plugins = plugins || [];
  64. this._container = normalizeContainer(container);
  65. this._emitter = new EventEmitter();
  66. this._context = { library, emitter: this._emitter, canvas };
  67. }
  68. render() {
  69. if (this._rendering)
  70. return this._addToTrailing();
  71. if (!this._context.canvas)
  72. this._createCanvas();
  73. this._bindAutoFit();
  74. this._rendering = true;
  75. const finished = new Promise((resolve, reject) => render(this._computedOptions(), this._context, this._createResolve(resolve), this._createReject(reject)));
  76. const [finished1, resolve, reject] = createEmptyPromise();
  77. finished
  78. .then(resolve)
  79. .catch(reject)
  80. .then(() => this._renderTrailing());
  81. return finished1;
  82. }
  83. /**
  84. * @overload
  85. * @param {G2ViewTree} [options]
  86. * @returns {Chart|G2ViewTree}
  87. */
  88. options(options) {
  89. if (arguments.length === 0)
  90. return optionsOf(this);
  91. const { type } = options;
  92. if (type)
  93. this._previousDefinedType = type;
  94. updateRoot(this, options, this._previousDefinedType);
  95. return this;
  96. }
  97. getContainer() {
  98. return this._container;
  99. }
  100. getContext() {
  101. return this._context;
  102. }
  103. on(event, callback, once) {
  104. this._emitter.on(event, callback, once);
  105. return this;
  106. }
  107. once(event, callback) {
  108. this._emitter.once(event, callback);
  109. return this;
  110. }
  111. emit(event, ...args) {
  112. this._emitter.emit(event, ...args);
  113. return this;
  114. }
  115. off(event, callback) {
  116. this._emitter.off(event, callback);
  117. return this;
  118. }
  119. clear() {
  120. const options = this.options();
  121. this.emit(ChartEvent.BEFORE_CLEAR);
  122. this._reset();
  123. destroy(options, this._context, false);
  124. this.emit(ChartEvent.AFTER_CLEAR);
  125. }
  126. destroy() {
  127. const options = this.options();
  128. this.emit(ChartEvent.BEFORE_DESTROY);
  129. this._unbindAutoFit();
  130. this._reset();
  131. destroy(options, this._context, true);
  132. removeContainer(this._container);
  133. this.emit(ChartEvent.AFTER_DESTROY);
  134. }
  135. forceFit() {
  136. // Don't fit if size do not change.
  137. this.options['autoFit'] = true;
  138. const { width, height } = sizeOf(this.options(), this._container);
  139. if (width === this._width && height === this._height) {
  140. return Promise.resolve(this);
  141. }
  142. // Don't call changeSize to prevent update width and height of options.
  143. this.emit(ChartEvent.BEFORE_CHANGE_SIZE);
  144. const finished = this.render();
  145. finished.then(() => {
  146. this.emit(ChartEvent.AFTER_CHANGE_SIZE);
  147. });
  148. return finished;
  149. }
  150. changeSize(width, height) {
  151. if (width === this._width && height === this._height) {
  152. return Promise.resolve(this);
  153. }
  154. this.emit(ChartEvent.BEFORE_CHANGE_SIZE);
  155. this.width(width);
  156. this.height(height);
  157. const finished = this.render();
  158. finished.then(() => {
  159. this.emit(ChartEvent.AFTER_CHANGE_SIZE);
  160. });
  161. return finished;
  162. }
  163. _reset() {
  164. this.type = 'view';
  165. this.value = {};
  166. this.children = [];
  167. }
  168. _renderTrailing() {
  169. if (!this._trailing)
  170. return;
  171. this._trailing = false;
  172. this.render()
  173. .then(() => {
  174. const trailingResolve = this._trailingResolve.bind(this);
  175. this._trailingResolve = null;
  176. trailingResolve(this);
  177. })
  178. .catch((error) => {
  179. const trailingReject = this._trailingReject.bind(this);
  180. this._trailingReject = null;
  181. trailingReject(error);
  182. });
  183. }
  184. _createResolve(resolve) {
  185. return () => {
  186. this._rendering = false;
  187. resolve(this);
  188. };
  189. }
  190. _createReject(reject) {
  191. return (error) => {
  192. this._rendering = false;
  193. reject(error);
  194. };
  195. }
  196. // Update actual size and key.
  197. _computedOptions() {
  198. const options = this.options();
  199. const { key = G2_CHART_KEY } = options;
  200. const { width, height } = sizeOf(options, this._container);
  201. this._width = width;
  202. this._height = height;
  203. this._key = key;
  204. return Object.assign(Object.assign({ key: this._key }, options), { width, height });
  205. }
  206. // Create canvas if it does not exist.
  207. // DragAndDropPlugin is for interaction.
  208. // It is OK to register more than one time, G will handle this.
  209. _createCanvas() {
  210. const { width, height } = sizeOf(this.options(), this._container);
  211. this._plugins.push(new DragAndDropPlugin());
  212. this._plugins.forEach((d) => this._renderer.registerPlugin(d));
  213. this._context.canvas = new GCanvas({
  214. container: this._container,
  215. width,
  216. height,
  217. renderer: this._renderer,
  218. });
  219. }
  220. _addToTrailing() {
  221. var _a;
  222. // Resolve previous promise, and give up this task.
  223. (_a = this._trailingResolve) === null || _a === void 0 ? void 0 : _a.call(this, this);
  224. // Create new task.
  225. this._trailing = true;
  226. const promise = new Promise((resolve, reject) => {
  227. this._trailingResolve = resolve;
  228. this._trailingReject = reject;
  229. });
  230. return promise;
  231. }
  232. _bindAutoFit() {
  233. const options = this.options();
  234. const { autoFit } = options;
  235. if (this._hasBindAutoFit) {
  236. // If it was bind before, unbind it now.
  237. if (!autoFit)
  238. this._unbindAutoFit();
  239. return;
  240. }
  241. if (autoFit) {
  242. this._hasBindAutoFit = true;
  243. window.addEventListener('resize', this._onResize);
  244. }
  245. }
  246. _unbindAutoFit() {
  247. if (this._hasBindAutoFit) {
  248. this._hasBindAutoFit = false;
  249. window.removeEventListener('resize', this._onResize);
  250. }
  251. }
  252. };
  253. Chart = __decorate([
  254. defineProps(props)
  255. ], Chart);
  256. export { Chart };
  257. //# sourceMappingURL=chart.js.map