plot.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. import { __assign, __extends, __spreadArray } from "tslib";
  2. import EE from '@antv/event-emitter';
  3. import { Chart } from '@antv/g2';
  4. import { each } from '@antv/util';
  5. import { bind } from 'size-sensor';
  6. import { deepAssign, getAllElementsRecursively, getContainerSize, pick } from '../utils';
  7. var SOURCE_ATTRIBUTE_NAME = 'data-chart-source-type';
  8. /** plot 图表容器的配置 */
  9. export var PLOT_CONTAINER_OPTIONS = [
  10. 'padding',
  11. 'appendPadding',
  12. 'renderer',
  13. 'pixelRatio',
  14. 'syncViewPadding',
  15. 'supportCSSTransform',
  16. 'limitInPlot',
  17. ];
  18. /**
  19. * 所有 plot 的基类
  20. */
  21. var Plot = /** @class */ (function (_super) {
  22. __extends(Plot, _super);
  23. function Plot(container, options) {
  24. var _this = _super.call(this) || this;
  25. _this.container = typeof container === 'string' ? document.getElementById(container) : container;
  26. _this.options = deepAssign({}, _this.getDefaultOptions(), options);
  27. _this.createG2();
  28. _this.bindEvents();
  29. return _this;
  30. }
  31. /**
  32. * 获取默认的 options 配置项
  33. * 每个组件都可以复写
  34. */
  35. Plot.getDefaultOptions = function () {
  36. return {
  37. renderer: 'canvas',
  38. xAxis: {
  39. nice: true,
  40. label: {
  41. autoRotate: false,
  42. autoHide: { type: 'equidistance', cfg: { minGap: 6 } },
  43. },
  44. },
  45. yAxis: {
  46. nice: true,
  47. label: {
  48. autoHide: true,
  49. autoRotate: false,
  50. },
  51. },
  52. animation: true,
  53. };
  54. };
  55. /**
  56. * 创建 G2 实例
  57. */
  58. Plot.prototype.createG2 = function () {
  59. var _a = this.options, width = _a.width, height = _a.height, defaultInteractions = _a.defaultInteractions;
  60. this.chart = new Chart(__assign(__assign(__assign(__assign({ container: this.container, autoFit: false }, this.getChartSize(width, height)), { localRefresh: false }), pick(this.options, PLOT_CONTAINER_OPTIONS)), { defaultInteractions: defaultInteractions }));
  61. // 给容器增加标识,知道图表的来源区别于 G2
  62. this.container.setAttribute(SOURCE_ATTRIBUTE_NAME, 'G2Plot');
  63. };
  64. /**
  65. * 计算默认的 chart 大小。逻辑简化:如果存在 width 或 height,则直接使用,否则使用容器大小
  66. * @param width
  67. * @param height
  68. */
  69. Plot.prototype.getChartSize = function (width, height) {
  70. var chartSize = getContainerSize(this.container);
  71. return { width: width || chartSize.width || 400, height: height || chartSize.height || 400 };
  72. };
  73. /**
  74. * 绑定代理所有 G2 的事件
  75. */
  76. Plot.prototype.bindEvents = function () {
  77. var _this = this;
  78. if (this.chart) {
  79. this.chart.on('*', function (e) {
  80. if (e === null || e === void 0 ? void 0 : e.type) {
  81. _this.emit(e.type, e);
  82. }
  83. });
  84. }
  85. };
  86. /**
  87. * 获取默认的 options 配置项
  88. * 每个组件都可以复写
  89. */
  90. Plot.prototype.getDefaultOptions = function () {
  91. return Plot.getDefaultOptions();
  92. };
  93. /**
  94. * 绘制
  95. */
  96. Plot.prototype.render = function () {
  97. // 暴力处理,先清空再渲染,需要 G2 层自行做好更新渲染
  98. this.chart.clear();
  99. // 因为子 view 会继承父 view 的 options 配置(包括 legend,所以会导致 legend 重复创建)
  100. // 所以这里给 chart 实例的 options 配置清空
  101. // 最好的解法是在 G2 view.clear 方法的时候,重置 options 配置。或者提供方法去 resetOptions
  102. // #1684 理论上在多 view 图形上,只要存在 custom legend,都存在类似问题(子弹图、双轴图)
  103. // @ts-ignore
  104. this.chart.options = {
  105. data: [],
  106. animate: true,
  107. };
  108. this.chart.views = []; // 删除已有的 views
  109. // 执行 adaptor
  110. this.execAdaptor();
  111. // 渲染
  112. this.chart.render();
  113. // 绑定
  114. this.bindSizeSensor();
  115. };
  116. /**
  117. * 更新: 更新配置且重新渲染
  118. * @param options
  119. */
  120. Plot.prototype.update = function (options) {
  121. this.updateOption(options);
  122. this.render();
  123. };
  124. /**
  125. * 更新配置
  126. * @param options
  127. */
  128. Plot.prototype.updateOption = function (options) {
  129. this.options = deepAssign({}, this.options, options);
  130. };
  131. /**
  132. * 设置状态
  133. * @param type 状态类型,支持 'active' | 'inactive' | 'selected' 三种
  134. * @param conditions 条件,支持数组
  135. * @param status 是否激活,默认 true
  136. */
  137. Plot.prototype.setState = function (type, condition, status) {
  138. if (status === void 0) { status = true; }
  139. var elements = getAllElementsRecursively(this.chart);
  140. each(elements, function (ele) {
  141. if (condition(ele.getData())) {
  142. ele.setState(type, status);
  143. }
  144. });
  145. };
  146. /**
  147. * 获取状态
  148. */
  149. Plot.prototype.getStates = function () {
  150. var elements = getAllElementsRecursively(this.chart);
  151. var stateObjects = [];
  152. each(elements, function (element) {
  153. var data = element.getData();
  154. var states = element.getStates();
  155. each(states, function (state) {
  156. stateObjects.push({ data: data, state: state, geometry: element.geometry, element: element });
  157. });
  158. });
  159. return stateObjects;
  160. };
  161. /**
  162. * 更新数据
  163. * @override
  164. * @param options
  165. */
  166. Plot.prototype.changeData = function (data) {
  167. // @ts-ignore
  168. this.update({ data: data });
  169. // TODO: 临时方案,最好使用下面的方式去更新数据
  170. // this.chart.changeData(data);
  171. };
  172. /**
  173. * 修改画布大小
  174. * @param width
  175. * @param height
  176. */
  177. Plot.prototype.changeSize = function (width, height) {
  178. this.chart.changeSize(width, height);
  179. };
  180. /**
  181. * 增加图表标注。通过 id 标识,如果匹配到,就做更新
  182. */
  183. Plot.prototype.addAnnotations = function (annotations, view) {
  184. view = view ? view : this.chart;
  185. var incoming = __spreadArray([], annotations, true);
  186. var controller = view.getController('annotation');
  187. var current = controller.getComponents().map(function (co) { return co.extra; });
  188. controller.clear(true);
  189. var _loop_1 = function (i) {
  190. var annotation = current[i];
  191. var findIndex = incoming.findIndex(function (item) { return item.id && item.id === annotation.id; });
  192. if (findIndex !== -1) {
  193. annotation = deepAssign({}, annotation, incoming[findIndex]);
  194. incoming.splice(findIndex, 1);
  195. }
  196. controller.annotation(annotation);
  197. };
  198. for (var i = 0; i < current.length; i++) {
  199. _loop_1(i);
  200. }
  201. incoming.forEach(function (annotation) { return controller.annotation(annotation); });
  202. view.render(true);
  203. };
  204. /**
  205. * 删除图表标注。通过 id 标识,如果匹配到,就做删除
  206. */
  207. Plot.prototype.removeAnnotations = function (annotations) {
  208. var controller = this.chart.getController('annotation');
  209. var current = controller.getComponents().map(function (co) { return co.extra; });
  210. controller.clear(true);
  211. var _loop_2 = function (i) {
  212. var annotation = current[i];
  213. if (!annotations.find(function (item) { return item.id && item.id === annotation.id; })) {
  214. controller.annotation(annotation);
  215. }
  216. };
  217. for (var i = 0; i < current.length; i++) {
  218. _loop_2(i);
  219. }
  220. this.chart.render(true);
  221. };
  222. /**
  223. * 销毁
  224. */
  225. Plot.prototype.destroy = function () {
  226. // 取消 size-sensor 的绑定
  227. this.unbindSizeSensor();
  228. // G2 的销毁
  229. this.chart.destroy();
  230. // 清空已经绑定的事件
  231. this.off();
  232. this.container.removeAttribute(SOURCE_ATTRIBUTE_NAME);
  233. };
  234. /**
  235. * 执行 adaptor 操作
  236. */
  237. Plot.prototype.execAdaptor = function () {
  238. var adaptor = this.getSchemaAdaptor();
  239. var _a = this.options, padding = _a.padding, appendPadding = _a.appendPadding;
  240. // 更新 padding
  241. this.chart.padding = padding;
  242. // 更新 appendPadding
  243. this.chart.appendPadding = appendPadding;
  244. // 转化成 G2 API
  245. adaptor({
  246. chart: this.chart,
  247. options: this.options,
  248. });
  249. };
  250. /**
  251. * 当图表容器大小变化的时候,执行的函数
  252. */
  253. Plot.prototype.triggerResize = function () {
  254. this.chart.forceFit();
  255. };
  256. /**
  257. * 绑定 dom 容器大小变化的事件
  258. */
  259. Plot.prototype.bindSizeSensor = function () {
  260. var _this = this;
  261. if (this.unbind) {
  262. return;
  263. }
  264. var _a = this.options.autoFit, autoFit = _a === void 0 ? true : _a;
  265. if (autoFit) {
  266. this.unbind = bind(this.container, function () {
  267. // 获取最新的宽高信息
  268. var _a = getContainerSize(_this.container), width = _a.width, height = _a.height;
  269. // 主要是防止绑定的时候触发 resize 回调
  270. if (width !== _this.chart.width || height !== _this.chart.height) {
  271. _this.triggerResize();
  272. }
  273. });
  274. }
  275. };
  276. /**
  277. * 取消绑定
  278. */
  279. Plot.prototype.unbindSizeSensor = function () {
  280. if (this.unbind) {
  281. this.unbind();
  282. this.unbind = undefined;
  283. }
  284. };
  285. return Plot;
  286. }(EE));
  287. export { Plot };
  288. //# sourceMappingURL=plot.js.map