UNPKG

@antv/g2plot

Version:

G2 Plot, a market of plots built with the Grammar of Graphics'

509 lines 19.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var g_1 = require("@antv/g"); var G2 = tslib_1.__importStar(require("@antv/g2")); var _ = tslib_1.__importStar(require("@antv/util")); var description_1 = tslib_1.__importDefault(require("../components/description")); var factory_1 = require("../components/factory"); var index_1 = tslib_1.__importDefault(require("../interaction/index")); var event_1 = require("../util/event"); var padding_1 = tslib_1.__importDefault(require("./controller/padding")); var state_1 = tslib_1.__importDefault(require("./controller/state")); var theme_1 = tslib_1.__importDefault(require("./controller/theme")); var layer_1 = tslib_1.__importDefault(require("./layer")); var common_1 = require("../util/common"); var ViewLayer = /** @class */ (function (_super) { tslib_1.__extends(ViewLayer, _super); function ViewLayer(props) { var _this = _super.call(this, props) || this; _this.interactions = []; _this.options = _this.getOptions(props); _this.initialOptions = _.deepMix({}, _this.options); _this.paddingController = new padding_1.default({ plot: _this, }); _this.stateController = new state_1.default({ plot: _this, }); _this.themeController = new theme_1.default(); return _this; } ViewLayer.getDefaultOptions = function (props) { return { title: { visible: false, text: '', }, description: { visible: false, text: '', }, padding: 'auto', legend: { visible: true, position: 'bottom-center', }, tooltip: { visible: true, shared: true, crosshairs: { type: 'y', }, }, xAxis: { visible: true, autoHideLabel: false, autoRotateLabel: false, autoRotateTitle: false, grid: { visible: false, }, line: { visible: true, }, tickLine: { visible: true, }, label: { visible: true, }, title: { visible: false, offset: 12, }, }, yAxis: { visible: true, autoHideLabel: false, autoRotateLabel: false, autoRotateTitle: true, grid: { visible: true, }, line: { visible: false, }, tickLine: { visible: false, }, label: { visible: true, }, title: { visible: false, offset: 12, }, }, label: { visible: false, }, }; }; ViewLayer.prototype.getOptions = function (props) { var options = _super.prototype.getOptions.call(this, props); // @ts-ignore var defaultOptions = this.constructor.getDefaultOptions(props); return _.deepMix({}, options, defaultOptions, props); }; ViewLayer.prototype.beforeInit = function () { _super.prototype.beforeInit.call(this); }; ViewLayer.prototype.init = function () { var _this = this; _super.prototype.init.call(this); this.theme = this.themeController.getTheme(this.options, this.type); this.config = { scales: {}, legends: {}, tooltip: { showTitle: true, triggerOn: 'mousemove', inPanel: true, useHtml: true, }, axes: { fields: {} }, coord: { type: 'cartesian' }, elements: [], annotations: [], interactions: {}, theme: this.theme, panelRange: {}, animate: true, }; this.paddingController.clear(); this.drawTitle(); this.drawDescription(); this.coord(); this.scale(); this.axis(); this.tooltip(); this.legend(); this.addGeometry(); this.annotation(); this.animation(); this.viewRange = this.getViewRange(); this.paddingController.clearOuterComponents(); this.view = new G2.View({ width: this.width, height: this.height, canvas: this.canvas, container: this.container, padding: this.paddingController.getPadding(), data: this.processData(this.options.data), theme: this.theme, options: this.config, start: { x: this.viewRange.minX, y: this.viewRange.minY }, end: { x: this.viewRange.maxX, y: this.viewRange.maxY }, }); this.applyInteractions(); this.view.on('afterrender', function () { _this.afterRender(); }); }; ViewLayer.prototype.afterInit = function () { _super.prototype.afterInit.call(this); if (!this.view || this.view.destroyed) { return; } if (this.options.padding !== 'auto') { this.parseEvents(); } }; ViewLayer.prototype.afterRender = function () { if (!this.view || this.view.destroyed) { return; } var options = this.options; var padding = options.padding ? options.padding : this.config.theme.padding; /** defaultState */ if (options.defaultState && padding !== 'auto') { this.stateController.defaultStates(options.defaultState); } this.addGeomCliper(); /** autopadding */ if (padding === 'auto') { this.paddingController.processAutoPadding(); } }; /** 完整生命周期渲染 */ ViewLayer.prototype.render = function () { _super.prototype.render.call(this); var data = this.options.data; if (!_.isEmpty(data)) { this.view.render(); } }; /** 销毁 */ ViewLayer.prototype.destroy = function () { this.doDestroy(); _super.prototype.destroy.call(this); }; /** 更新配置项 */ ViewLayer.prototype.updateConfig = function (cfg) { this.doDestroy(); if (!cfg.padding && this.initialOptions.padding && this.initialOptions.padding === 'auto') { cfg.padding = 'auto'; } this.options = _.deepMix({}, this.options, cfg); this.processOptions(this.options); }; ViewLayer.prototype.changeData = function (data) { this.options.data = this.processData(data); this.view.changeData(this.options.data); }; // plot 不断销毁重建,需要一个api获取最新的plot ViewLayer.prototype.getPlot = function () { return this.view; }; // 获取对应的G2 Theme ViewLayer.prototype.getTheme = function () { return this.theme; }; ViewLayer.prototype.getResponsiveTheme = function () { return this.themeController.getResponsiveTheme(this.type); }; // 获取对应的Plot Theme ViewLayer.prototype.getPlotTheme = function () { return this.themeController.getPlotTheme(this.options, this.type); }; // 绑定一个外部的stateManager ViewLayer.prototype.bindStateManager = function (stateManager, cfg) { this.stateController.bindStateManager(stateManager, cfg); }; // 响应状态量更新的快捷方法 ViewLayer.prototype.setActive = function (condition, style) { this.stateController.setState({ type: 'active', condition: condition, style: style }); }; ViewLayer.prototype.setSelected = function (condition, style) { this.stateController.setState({ type: 'selected', condition: condition, style: style }); }; ViewLayer.prototype.setDisable = function (condition, style) { this.stateController.setState({ type: 'disable', condition: condition, style: style }); }; ViewLayer.prototype.setNormal = function (condition) { this.stateController.setState({ type: 'normal', condition: condition, style: {} }); }; // 获取 ViewLayer 的数据项 ViewLayer.prototype.getData = function (start, end) { return this.processData((this.options.data || []).slice(start, end)); }; ViewLayer.prototype.processData = function (data) { return data; }; ViewLayer.prototype.scale = function () { /** scale meta配置 */ // 1. this.config.scales中已有子图形在处理xAxis/yAxis是写入的xField/yField对应的scale信息,这里再检查用户设置的meta,将meta信息合并到默认的scale中 // 2. 同时xAxis/yAxis中的type优先级更高,覆盖meta中的type配置 var scaleTypes = _.mapValues(this.config.scales, function (scaleConfig) { var type = scaleConfig.type; return type ? { type: type } : {}; }); var scales = _.deepMix({}, this.config.scales, this.options.meta || {}, scaleTypes); this.setConfig('scales', scales); }; ViewLayer.prototype.axis = function () { var xAxis_parser = factory_1.getComponent('axis', { plot: this, dim: 'x', }); var yAxis_parser = factory_1.getComponent('axis', { plot: this, dim: 'y', }); var axesConfig = { fields: {} }; axesConfig.fields[this.options.xField] = xAxis_parser; axesConfig.fields[this.options.yField] = yAxis_parser; /** 存储坐标轴配置项到config */ this.setConfig('axes', axesConfig); }; ViewLayer.prototype.tooltip = function () { if (this.options.tooltip.visible === false) { this.setConfig('tooltip', false); return; } this.setConfig('tooltip', _.deepMix({}, _.get(this.options, 'tooltip'))); _.deepMix(this.config.theme.tooltip, this.options.tooltip.style); }; ViewLayer.prototype.legend = function () { if (this.options.legend.visible === false) { this.setConfig('legends', false); return; } var flipOption = _.get(this.options, 'legend.flipPage'); var clickable = _.get(this.options, 'legend.clickable'); this.setConfig('legends', { position: _.get(this.options, 'legend.position'), formatter: _.get(this.options, 'legend.formatter'), offsetX: _.get(this.options, 'legend.offsetX'), offsetY: _.get(this.options, 'legend.offsetY'), clickable: _.isUndefined(clickable) ? true : clickable, // wordSpacing: _.get(this.options, 'legend.wordSpacing'), flipPage: flipOption, }); }; ViewLayer.prototype.annotation = function () { var _this = this; var config = []; if (this.config.coord.type === 'cartesian' && this.options.guideLine) { _.each(this.options.guideLine, function (line) { var guideLine = factory_1.getComponent('guideLine', { plot: _this, cfg: line, }); config.push(guideLine); }); } this.setConfig('annotations', config); }; ViewLayer.prototype.animation = function () { if (this.options.animation === false || this.options.padding === 'auto') { this.config.animate = false; } }; ViewLayer.prototype.applyInteractions = function () { var _this = this; var _a = this.options.interactions, interactions = _a === void 0 ? [] : _a; if (this.interactions) { this.interactions.forEach(function (inst) { inst.destroy(); }); } this.interactions = []; interactions.forEach(function (interaction) { var Ctor = index_1.default.getInteraction(interaction.type, _this.type); if (Ctor) { var inst = new Ctor({ view: _this.view }, _this, Ctor.getInteractionRange(_this.layerBBox, interaction.cfg), interaction.cfg); _this.interactions.push(inst); } }); }; /** 设置G2 config,带有类型推导 */ ViewLayer.prototype.setConfig = function (key, config) { if (key === 'element') { this.config.elements.push(config); return; } if (config === false) { this.config[key] = false; return; } _.assign(this.config[key], config); }; ViewLayer.prototype.parseEvents = function (eventParser) { var _this = this; var options = this.options; if (options.events) { _super.prototype.parseEvents.call(this, options.events); var eventmap_1 = eventParser ? eventParser.EVENT_MAP : event_1.EVENT_MAP; _.each(options.events, function (e, k) { if (_.isFunction(e)) { var eventName = eventmap_1[k] || k; var handler = e; event_1.onEvent(_this, eventName, handler); } }); } }; ViewLayer.prototype.drawTitle = function () { var props = this.options; var range = this.layerBBox; if (this.title) { this.title.destroy(); this.title = null; } if (common_1.isTextUsable(props.title)) { var width = this.width; var theme = this.config.theme; var title = new description_1.default({ leftMargin: range.minX + theme.title.padding[3], topMargin: range.minY + theme.title.padding[0], text: props.title.text, style: _.mix(theme.title, props.title.style), wrapperWidth: width - theme.title.padding[3] - theme.title.padding[1], container: this.container.addGroup(), theme: theme, index: common_1.isTextUsable(props.description) ? 0 : 1, plot: this, name: 'title', }); this.title = title; this.paddingController.registerPadding(title, 'outer'); } }; ViewLayer.prototype.drawDescription = function () { var props = this.options; var range = this.layerBBox; if (this.description) { this.description.destroy(); this.description = null; } if (common_1.isTextUsable(props.description)) { var width = this.width; var theme = this.config.theme; var topMargin = 0; if (this.title) { var titleBBox = this.title.getBBox(); topMargin += titleBBox.minY + titleBBox.height; topMargin += theme.description.padding[0]; } else { // 无title的情况下使用title的上padding topMargin += range.minY + theme.title.padding[0]; } var description = new description_1.default({ leftMargin: range.minX + theme.description.padding[3], topMargin: topMargin, text: props.description.text, style: _.mix(theme.description, props.description.style), wrapperWidth: width - theme.description.padding[3] - theme.description.padding[1], container: this.container.addGroup(), theme: theme, index: 1, plot: this, name: 'description', }); this.description = description; this.paddingController.registerPadding(description, 'outer'); } }; /** 抽取destroy和updateConfig共有代码为_destroy方法 */ ViewLayer.prototype.doDestroy = function () { this.doDestroyInteractions(); /** 销毁g2.view实例 */ if (!this.view.destroyed) { this.view.destroy(); } }; ViewLayer.prototype.doDestroyInteractions = function () { // 移除注册的 interactions if (this.interactions) { this.interactions.forEach(function (inst) { inst.destroy(); }); } this.interactions = []; }; ViewLayer.prototype.getViewRange = function () { var _this = this; // 有 Range 的 Interaction 参与 ViewMargin 计算 var _a = this.options.interactions, interactions = _a === void 0 ? [] : _a; var layerBBox = this.layerBBox; interactions.forEach(function (interaction) { var Ctor = index_1.default.getInteraction(interaction.type, _this.type); var range = Ctor && Ctor.getInteractionRange(layerBBox, interaction.cfg); var position = ''; if (range) { // 先只考虑 Range 靠边的情况 if (range.bottom === layerBBox.bottom && range.top > layerBBox.top) { // margin[2] += range.height; position = 'bottom'; } else if (range.right === layerBBox.right && range.left > layerBBox.left) { // margin[1] += range.width; position = 'right'; } else if (range.left === layerBBox.left && range.right > layerBBox.right) { // margin[3] += range.width; position = 'left'; } else if (range.top === layerBBox.top && range.bottom > layerBBox.bottom) { // margin[0] += range.height; position = 'top'; } _this.paddingController.registerPadding({ getBBox: function () { return range; }, position: position, }, 'outer'); } }); var viewRange = this.paddingController.processOuterPadding(); return viewRange; }; // 临时解决scale min & max的图形截取 ViewLayer.prototype.addGeomCliper = function () { var panelRange = this.view.get('panelRange'); var cliper = new g_1.Rect({ attrs: { x: panelRange.minX, y: panelRange.minY, width: panelRange.width, height: panelRange.height, }, }); var geoms = this.view.get('elements'); _.each(geoms, function (geom) { var cliperContainer = geom.get('shapeContainer'); var preCliper = cliperContainer.attr('clip'); if (preCliper) { preCliper.remove(); } cliperContainer.attr('clip', cliper); }); }; return ViewLayer; }(layer_1.default)); exports.default = ViewLayer; //# sourceMappingURL=view-layer.js.map