@antv/f-react
Version:
FEngine for React
183 lines • 5.8 kB
JavaScript
import { __assign, __extends } from "tslib";
import React, { createRef, Component } from 'react';
// 对 f-engine 只有类型引用
import { Children } from '@antv/f-engine';
function pickElement(children) {
if (!children) return children;
var result = Children.map(children, function (item) {
if (!item) return item;
var key = item.key,
ref = item.ref,
type = item.type,
props = item.props;
return {
key: key,
ref: ref,
type: type,
props: __assign(__assign({}, props), {
children: pickElement(props.children)
})
};
});
return result;
}
var createCanvas = function createCanvas(CanvasClass) {
var FCanvas = /** @class */function (_super) {
__extends(FCanvas, _super);
function FCanvas() {
return _super !== null && _super.apply(this, arguments) || this;
}
// override
FCanvas.prototype.toRawChildren = function (children) {
return pickElement(children);
};
return FCanvas;
}(CanvasClass);
return /** @class */function (_super) {
__extends(ReactCanvas, _super);
function ReactCanvas(props) {
var _this = _super.call(this, props) || this;
_this.getProps = function () {
var _a = _this,
canvasRef = _a.canvasRef,
props = _a.props;
var canvasEl = canvasRef.current;
var context = canvasEl.getContext('2d');
// 去掉 react 生成的 element 中无用属性
var children = pickElement(props.children);
return __assign(__assign({
// 已经有高清方案,这里默认用1
pixelRatio: 1
}, props), {
children: children,
// context 内部创建,不能被覆盖
context: context
});
};
var canvasRef = props.canvasRef;
_this.canvasRef = canvasRef || /*#__PURE__*/createRef();
_this.state = {
error: null
};
return _this;
}
ReactCanvas.prototype.catchError = function (error) {
var onError = this.props.onError;
this.setState({
error: error
});
console.error('图表渲染失败: ', error);
if (typeof onError === 'function') {
onError(error);
}
// 重新抛出,为了让 window.onerror 捕获
setTimeout(function () {
throw error;
}, 0);
};
ReactCanvas.prototype.componentDidMount = function () {
var _this = this;
var _a;
var pickProps = this.getProps();
var canvas = new FCanvas(pickProps);
this.canvas = canvas;
canvas.render().catch(function (error) {
_this.catchError(error);
});
var targetNode = (_a = this.canvasRef.current) === null || _a === void 0 ? void 0 : _a.parentElement;
if (!targetNode) return;
var _b = targetNode.getBoundingClientRect(),
width = _b.width,
height = _b.height;
this.parentNode = {
width: Math.round(width),
height: Math.round(height)
};
this.observeElement();
};
ReactCanvas.prototype.observeElement = function () {
var _this = this;
var _a, _b;
if (!((_a = this.props) === null || _a === void 0 ? void 0 : _a.autoFit)) return;
var targetNode = (_b = this.canvasRef.current) === null || _b === void 0 ? void 0 : _b.parentElement;
window === null || window === void 0 ? void 0 : window.addEventListener('resize', function () {
_this.resize();
});
if (typeof ResizeObserver !== 'undefined') {
this.observer = new ResizeObserver(function () {
_this.resize();
});
this.observer.observe(targetNode);
}
};
ReactCanvas.prototype.resize = function () {
var _a;
var targetNode = (_a = this.canvasRef.current) === null || _a === void 0 ? void 0 : _a.parentElement;
if (!targetNode) return;
var _b = targetNode.getBoundingClientRect(),
width = _b.width,
height = _b.height;
var lastWidth = Math.round(width);
var lastHeight = Math.round(height);
if (lastWidth === this.parentNode.width && lastHeight === this.parentNode.height || !lastWidth || !lastHeight) return;
this.parentNode = {
width: lastWidth,
height: lastHeight
};
this.canvas.resize(lastWidth, lastHeight);
};
ReactCanvas.prototype.componentDidUpdate = function () {
var _this = this;
var _a = this,
state = _a.state,
canvas = _a.canvas;
var error = state.error;
if (error) {
return;
}
var pickProps = this.getProps();
canvas.update(pickProps).catch(function (error) {
_this.catchError(error);
});
};
ReactCanvas.prototype.render = function () {
var _a = this,
props = _a.props,
state = _a.state;
var _b = props.className,
className = _b === void 0 ? '' : _b,
fallback = props.fallback;
var error = state.error;
if (error) {
// 直接销毁
this.destroy();
return fallback || null;
}
return /*#__PURE__*/React.createElement('canvas', {
className: "f-chart ".concat(className),
ref: this.canvasRef,
style: {
width: '100%',
height: '100%',
display: 'block',
padding: 0,
margin: 0
}
});
};
ReactCanvas.prototype.componentWillUnmount = function () {
this.destroy();
};
ReactCanvas.prototype.destroy = function () {
var canvas = this.canvas;
if (!canvas) return;
canvas.destroy();
this.canvas = null;
if (!this.observer) return;
this.observer.disconnect();
this.observer = null;
};
return ReactCanvas;
}(Component);
};
export { createCanvas };