UNPKG

@antv/f2

Version:

Charts for mobile visualization.

319 lines 9.94 kB
import { __assign, __extends } from "tslib"; import { isEqual, Component, Children, jsx, createRef } from '@antv/f-engine'; import { each, findIndex, isArray, deepMix } from '@antv/util'; import CoordController from '../controller/coord'; import ScaleController from '../controller/scale'; import Theme from '../theme'; // 统计图表 var Chart = /** @class */function (_super) { __extends(Chart, _super); function Chart(props, context) { var _this = _super.call(this, props) || this; // 坐标系 _this.componentsPosition = []; var theme = context.theme, px2hd = context.px2hd; // hack 处理,设置默认的主题样式 // 目前没想到其他更合适的方式,只能先这样处理 context.theme = deepMix(px2hd(Theme), theme); var data = props.data; _this.scale = new ScaleController(data); _this.coord = new CoordController(); _this.coordRef = createRef(); // state _this.state = { filters: {} }; return _this; } Chart.prototype.getStyle = function (props) { var _a = this, context = _a.context, layout = _a.layout; var theme = context.theme, px2hd = context.px2hd; var left = layout.left, top = layout.top, width = layout.width, height = layout.height; var customStyle = props.style; return px2hd(__assign(__assign({ left: left, top: top, width: width, height: height }, theme.chart), customStyle)); }; Chart.prototype.willMount = function () { var _a = this, props = _a.props, coord = _a.coord, scale = _a.scale; var scaleOptions = props.scale, coordOption = props.coord; this.resetCoordLayout(); // 初始化 scale scale.create(scaleOptions); // 初始化 coord coord.create(coordOption); }; // props 更新 Chart.prototype.willReceiveProps = function (nextProps, context) { var _a = this, scale = _a.scale, coord = _a.coord, lastProps = _a.props; var nextStyle = nextProps.style, nextData = nextProps.data, nextScale = nextProps.scale; var lastStyle = lastProps.style, lastData = lastProps.data, lastScale = lastProps.scale; // style 更新 if (!isEqual(nextStyle, lastStyle) || context !== this.context) { var style = this.getStyle(nextProps); coord.updateLayout(style); } if (nextData !== lastData) { scale.changeData(nextData); } // scale if (!isEqual(nextScale, lastScale)) { scale.update(nextScale); } }; Chart.prototype.willUpdate = function () { this.coord.create(this.props.coord); }; Chart.prototype.on = function (eventName, listener) { var roolEl = this.coordRef.current; if (!roolEl || !roolEl.gesture) return; var gesture = roolEl.gesture; gesture.on(eventName, listener); }; Chart.prototype.off = function (eventName, listener) { var roolEl = this.coordRef.current; if (!roolEl || !roolEl.gesture) return; var gesture = roolEl.gesture; gesture.off(eventName, listener); }; // 给需要显示的组件留空 Chart.prototype.layoutCoord = function (layout) { this.coord.useLayout(layout); }; Chart.prototype.resetCoordLayout = function () { var _a = this, coord = _a.coord, props = _a.props; var style = this.getStyle(props); coord.updateLayout(style); }; Chart.prototype.updateAdjust = function (adjust) { this.adjust = adjust; }; Chart.prototype.updateCoordLayout = function (layout) { var _this = this; if (isArray(layout)) { layout.forEach(function (item) { _this.layoutCoord(item); }); return; } this.layoutCoord(layout); }; Chart.prototype.updateCoordFor = function (component, layout) { var _this = this; if (!layout) return; var componentsPosition = this.componentsPosition; var componentPosition = { component: component, layout: layout }; var existIndex = findIndex(componentsPosition, function (item) { return item.component === component; }); // 说明是已经存在的组件 if (existIndex > -1) { componentsPosition.splice(existIndex, 1, componentPosition); // 先重置,然后整体重新算一次 this.resetCoordLayout(); // 再整体计算前,需要去掉已经销毁的组件 this.removeComponentsPositionCache(); componentsPosition.forEach(function (componentPosition) { var layout = componentPosition.layout; _this.updateCoordLayout(layout); }); return; } // 是新组件,直接添加 componentsPosition.push(componentPosition); this.updateCoordLayout(layout); }; Chart.prototype.removeComponentsPositionCache = function () { var _a; if (!((_a = this.componentsPosition) === null || _a === void 0 ? void 0 : _a.length)) return; for (var i = this.componentsPosition.length; i > -1; i--) { var item = this.componentsPosition[i]; if (item && item.component && item.component.destroyed) { this.componentsPosition.splice(i, 1); } } }; Chart.prototype.getGeometrys = function () { // @ts-ignore var children = this.children.children; var geometrys = []; Children.toArray(children).forEach(function (element) { if (!element) return false; var component = element.component; // @ts-ignore if (component && component.isGeometry) { geometrys.push(component); } }); return geometrys; }; /** * calculate dataset's position on canvas * @param {Object} record the dataset * @return {Object} return the position */ Chart.prototype.getPosition = function (record) { var coord = this.getCoord(); var xScale = this.getXScales()[0]; var xField = xScale.field; var yScales = this.getYScales(); // default first var yScale = yScales[0]; var yField = yScale.field; for (var i = 0, len = yScales.length; i < len; i++) { var scale = yScales[i]; var field = scale.field; if (record[field]) { yScale = scale; yField = field; break; } } var x = xScale.scale(record[xField]); var y = yScale.scale(record[yField]); return coord.convertPoint({ x: x, y: y }); }; Chart.prototype.getSnapRecords = function (point, inCoordRange) { var geometrys = this.getGeometrys(); if (!geometrys.length) return; // @ts-ignore return geometrys[0].getSnapRecords(point, inCoordRange); }; Chart.prototype.getRecords = function (data, field) { var geometrys = this.getGeometrys(); if (!geometrys.length) return; // @ts-ignore return geometrys[0].getRecords(data, field); }; Chart.prototype.getLegendItems = function (point) { var geometrys = this.getGeometrys(); if (!geometrys.length) return; // @ts-ignore return geometrys[0].getLegendItems(point); }; Chart.prototype.setScale = function (field, option) { this.scale.setScale(field, option); }; Chart.prototype.getScale = function (field) { return this.scale.getScale(field); }; Chart.prototype.getScales = function () { return this.scale.getScales(); }; Chart.prototype.getXScales = function () { var geometrys = this.getGeometrys(); return geometrys.map(function (component) { // @ts-ignore return component.getXScale(); }); }; Chart.prototype.getYScales = function () { var geometrys = this.getGeometrys(); return geometrys.map(function (component) { // @ts-ignore return component.getYScale(); }); }; Chart.prototype.getColorScales = function () { var geometrys = this.getGeometrys(); return geometrys.map(function (component) { // @ts-ignore return component.getColorScale(); }); }; Chart.prototype.getLayout = function () { return this.coord.layout; }; Chart.prototype.getCoord = function () { return this.coord.coord; }; Chart.prototype.filter = function (field, condition) { var _a; var filters = this.state.filters; this.setState({ filters: __assign(__assign({}, filters), (_a = {}, _a[field] = condition, _a)) }); }; Chart.prototype._getRenderData = function () { var _a = this, props = _a.props, state = _a.state; var data = props.data; var filters = state.filters; if (!filters || !Object.keys(filters).length) { return data; } var filteredData = data; each(filters, function (condition, field) { if (!condition) return; filteredData = filteredData.filter(function (record) { return condition(record[field], record); }); }); return filteredData; }; Chart.prototype.render = function () { var _this = this; var _a = this, props = _a.props, scale = _a.scale, chartLayout = _a.layout; var children = props.children, originData = props.data; if (!originData) return null; var data = this._getRenderData(); var layout = this.getLayout(); var coord = this.getCoord(); var scaleOptions = scale.getOptions(); var width = chartLayout.width, height = chartLayout.height; return jsx("group", { ref: this.coordRef, style: { width: width, height: height, fill: 'transparent' } }, Children.map(children, function (child) { return Children.cloneElement(child, { data: data, chart: _this, layout: layout, coord: coord, // 传 scaleOptions 是为了让 child 感知到 props 的的变化,合理的做法的应该是传递 scale,但是现在无法感知到 scale 的变化, 所以暂时只能先这么处理,scaleOptions 子组件目前是使用不到的。 scaleOptions: scaleOptions }); })); }; return Chart; }(Component); export default Chart;