@visactor/vchart
Version:
charts lib based @visactor/VGrammar
415 lines (411 loc) • 22.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.Compiler = void 0;
const event_1 = require("./../constant/event"), interface_1 = require("./interface"), env_1 = require("../util/env"), type_1 = require("../util/type"), vutils_1 = require("@visactor/vutils"), vrender_core_1 = require("@visactor/vrender-core"), factory_1 = require("../core/factory"), mark_1 = require("../util/mark"), util_1 = require("./util"), debug_1 = require("../util/debug"), interface_2 = require("../animation/interface"), animate_1 = require("../constant/animate");
class Compiler {
get stateAnimationConfig() {
return this._stateAnimationConfig;
}
getRootGroup() {
return this._rootGroup;
}
getOption() {
return this._option;
}
constructor(container, option) {
this._count = 0, this._rootMarks = [], this._viewListeners = new Map, this._windowListeners = new Map,
this._canvasListeners = new Map, this.isInited = !1, this._released = !1, this._compileChart = null,
this.handleLayoutEnd = () => {
var _a, _b;
null === (_b = null === (_a = this._compileChart) || void 0 === _a ? void 0 : _a.getEvent()) || void 0 === _b || _b.emit(event_1.ChartEvent.afterMarkLayoutEnd, {
chart: this._compileChart
});
}, this.handleStageRender = () => {
var _a, _b;
null === (_b = null === (_a = this._compileChart) || void 0 === _a ? void 0 : _a.getEvent()) || void 0 === _b || _b.emit(event_1.ChartEvent.afterRender, {
chart: this._compileChart
});
}, this._handleAfterNextRender = () => {
var _a, _b, _c, _d;
this._stage && !this._option.disableDirtyBounds && this._stage.enableDirtyBounds(),
this._compileChart && (null === (_a = this._compileChart.getEvent()) || void 0 === _a || _a.emit(event_1.ChartEvent.renderFinished, {
chart: this._compileChart,
vchart: null === (_b = this._compileChart.getOption()) || void 0 === _b ? void 0 : _b.globalInstance
})), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.afterVRenderDraw) || void 0 === _d || _d.call(_c, this._compileChart.getOption().globalInstance);
}, this.handleProgressiveFrame = () => {
this._progressiveMarks.length && this._progressiveMarks.forEach((mark => {
mark.isDoingProgressive() && mark.renderProgressive();
})), this.doPreProgressive();
}, this._container = container, this._option = option;
}
getChart() {
return this._compileChart;
}
getCanvas() {
var _a;
return null === (_a = this._stage) || void 0 === _a ? void 0 : _a.window.getNativeHandler().nativeCanvas;
}
getStage() {
return this._stage;
}
initView() {
var _a, _b, _c, _d;
if (this._released) return;
if (this.isInited = !0, this._stage) return;
const {autoRefreshDpr: autoRefreshDpr, dpr: dpr, mode: mode, modeParams: modeParams, gestureConfig: gestureConfig, interactive: interactive, clickInterval: clickInterval, autoPreventDefault: autoPreventDefault, background: background} = this._option;
vrender_core_1.vglobal.setEnv((0, util_1.toRenderMode)(mode), null != modeParams ? modeParams : {}),
this._stage = null !== (_a = this._option.stage) && void 0 !== _a ? _a : new vrender_core_1.Stage(Object.assign({
background: background,
width: this._width,
height: this._height,
container: null !== (_b = this._container.dom) && void 0 !== _b ? _b : null,
canvas: null !== (_c = this._container.canvas) && void 0 !== _c ? _c : null,
dpr: dpr,
viewBox: this._option.viewBox,
canvasControled: this._option.canvasControled,
beforeRender: stage => {
var _a, _b, _c;
null === (_a = this._compileChart) || void 0 === _a || _a.onBeforeRender(), null === (_c = (_b = this._option).beforeRender) || void 0 === _c || _c.call(_b, stage);
},
afterRender: this._option.afterRender,
disableDirtyBounds: !0,
autoRender: !0,
ticker: this._option.ticker,
pluginList: this._option.pluginList,
enableHtmlAttribute: this._option.enableHtmlAttribute,
optimize: this._option.optimize,
supportsTouchEvents: this._option.supportsTouchEvents,
supportsPointerEvents: this._option.supportsPointerEvents,
event: {
clickInterval: clickInterval,
autoPreventDefault: autoPreventDefault
},
ReactDOM: this._option.ReactDOM,
autoRefresh: (0, vutils_1.isValid)(autoRefreshDpr) ? autoRefreshDpr : !(0, vutils_1.isValid)(dpr)
}, null !== (_d = this._option.renderHooks) && void 0 !== _d ? _d : {})), this._stage.enableIncrementalAutoRender(),
this._stage.setTheme({
symbol: {
shape: "circle",
size: 8
},
text: {
fontSize: 14,
fill: "#000000"
}
});
const group = (0, vrender_core_1.createGroup)({
x: 0,
y: 0,
width: this._width,
height: this._height
});
group.name = "root", this._stage.defaultLayer.appendChild(group), this._rootGroup = group;
const GestureController = ((0, vutils_1.isValid)(gestureConfig) ? gestureConfig : (0,
env_1.isMobileLikeMode)(mode)) && !1 !== interactive && factory_1.Factory.getStageEventPlugin("gesture");
GestureController && (this._gestureController = new GestureController(this._stage, (0,
vutils_1.isObject)(gestureConfig) ? gestureConfig : {})), this._setCanvasStyle(),
this.getStage().hooks.afterRender.tap("chart-event", this.handleStageRender), !1 !== interactive && this._viewListeners.forEach((listener => {}));
}
getLayoutState() {
return this._layoutState;
}
updateLayoutTag() {
this._layoutState = interface_1.LayoutState.before;
}
_setCanvasStyle() {
if (this._stage && this._container.dom && !(0, type_1.isString)(this._container.dom)) {
this._container.dom.style.display = "block", this._container.dom.style.position = "relative";
const canvas = this.getCanvas();
canvas && (canvas.style.display = "block");
}
}
compile(ctx, option) {
if (this._released) return;
const {chart: chart} = ctx;
this._compileChart = chart, this.initView(), this._stage && ("render" !== (null == option ? void 0 : option.actionSource) && this._cachedMarks && (this.reuseOrMorphing(option.morphConfig),
this._cachedMarks = null), chart.compile(), chart.afterCompile());
}
clearNextRender() {
return !!this._nextRafId && (vrender_core_1.vglobal.getSpecifiedCancelAnimationFrame(10)(this._nextRafId),
this._nextRafId = null, !0);
}
clear(ctx) {
const {chart: chart} = ctx;
this.clearNextRender(), chart.clear();
}
renderNextTick(morphConfig) {
this._released || (this._nextRafId && this.clearNextRender(), this._nextRafId = vrender_core_1.vglobal.getSpecifiedRequestAnimationFrame(10)((() => {
this._nextRafId = null, this.render(morphConfig);
})));
}
_commitedAll() {
return this._rootMarks.some((mark => (0, util_1.traverseGroupMark)(mark, (m => m.commit()))));
}
_hasCommitedMark() {
return this._rootMarks.some((mark => (0, util_1.traverseGroupMark)(mark, (m => m.isCommited()), null, null, !0)));
}
_doRender(immediately) {
var _a, _b, _c, _d, _e, _f;
null === (_b = null === (_a = this._option.performanceHook) || void 0 === _a ? void 0 : _a.beforeDoRender) || void 0 === _b || _b.call(_a, this._compileChart.getOption().globalInstance),
this._stage && (this._rootMarks.forEach((g => {
(0, util_1.traverseGroupMark)(g, (m => {
m.needClear && (this._progressiveMarks || m.runAnimation(), m.clearExitGraphics(),
m.needClear = !1);
}), null, !0);
})), null === (_d = null === (_c = this._option.performanceHook) || void 0 === _c ? void 0 : _c.beforeVRenderDraw) || void 0 === _d || _d.call(_c, this._compileChart.getOption().globalInstance),
this._stage.disableDirtyBounds(), this._stage.afterNextRender(this._handleAfterNextRender),
immediately && (this._stage.render(), null === (_f = null === (_e = this._option.performanceHook) || void 0 === _e ? void 0 : _e.afterVRenderDraw) || void 0 === _f || _f.call(_e, this._compileChart.getOption().globalInstance)));
}
renderMarks() {
var _a;
this._hasCommitedMark() && ((0, debug_1.log)(`--- start of renderMarks(${this._count}) ---`),
this.clearProgressive(), this._rootMarks.forEach((mark => {
mark.render();
})), this._layoutState === interface_1.LayoutState.before && (this._layoutState = interface_1.LayoutState.layouting,
null === (_a = this._compileChart) || void 0 === _a || _a.onLayout(), this._layoutState = interface_1.LayoutState.reevaluate,
this._hasCommitedMark() && this._rootMarks.forEach((mark => {
mark.render();
})), this.handleLayoutEnd()), this.findProgressiveMarks(), this.updateStateAnimation(),
this._doRender(!0), this.doPreProgressive(), (0, debug_1.log)(`--- start of renderMarks(${this._count}) ---`),
this._count++);
}
reuseOrMorphing(morphConfig = {}) {
const {reuse: reuse = !0, morph: morph = !0, morphAll: morphAll = !1, animation: animation = {}, enableExitAnimation: enableExitAnimation = !1} = morphConfig, newMarks = (0,
util_1.findSimpleMarks)(this._rootMarks), {update: update, exit: exit} = (0, util_1.diffMarks)(this._cachedMarks, newMarks, {
morph: morph,
morphAll: morphAll,
reuse: reuse
});
update.forEach((({prev: prev, next: next}) => {
if (reuse && 1 === prev.length && 1 === next.length && prev[0].type === next[0].type) next[0].reuse(prev[0]); else {
const prevMark = prev.filter((item => item.getMarkConfig().morph))[0];
prevMark && next.forEach((item => {
item.getMarkConfig().morph && item.prepareMorph(prevMark);
}));
}
})), exit.forEach((({prev: prev}) => {
prev.forEach((m => {
m.removeProduct();
}));
}));
}
render(morphConfig) {
if (this._released) return;
if (this.clearNextRender(), this.initView(), !this._stage) return;
const {width: width, height: height} = this._rootGroup.attribute;
this._width === width && this._height === height || this._rootGroup.setAttributes({
width: this._width,
height: this._height
}), this.renderMarks(), this.clearNextRender() && this.renderMarks();
}
setStageAnimationConfig(config) {
const animationConfig = {};
Object.keys(config).forEach((key => {
const value = config[key];
(0, vutils_1.isArray)(value) ? animationConfig[key] = "disappear" === key ? value.map((item => (0,
type_1.isClass)(item.callBack) ? Object.assign(Object.assign({}, item), {
custom: item.callBack
}) : Object.assign(Object.assign({}, item), {
type: animate_1.BuiltIn_DISAPPEAR_ANIMATE_NAME,
customParameters: {
callBack: item.callBack
}
}))) : value.map((item => {
var _a;
const options = null !== (_a = item.options) && void 0 !== _a ? _a : {};
return Object.assign(Object.assign({}, item), {
options: (...args) => {
const _options = "function" == typeof options ? options(...args) : options;
return Object.assign({}, _options);
}
});
})) : animationConfig[key] = Object.assign({}, config[key]);
})), this._stateAnimationConfig = animationConfig;
}
updateStateAnimation() {
const allMarks = [];
this._rootMarks.forEach((mark => {
(0, util_1.traverseGroupMark)(mark, (m => {
allMarks.push(m);
}));
}));
const markAnimationStates = allMarks.map((mark => mark.getAnimationState())), animationState = markAnimationStates.every((state => state === interface_2.AnimationStateEnum.appear)) ? interface_2.AnimationStateEnum.appear : markAnimationStates.every((state => state === interface_2.AnimationStateEnum.disappear)) ? interface_2.AnimationStateEnum.disappear : interface_2.AnimationStateEnum.none;
this._stage.context || (this._stage.context = {}), this._stage.context.animationState = animationState;
}
updateViewBox(viewBox, reRender = !0) {
if (!this._stage) return;
const prevViewBox = this._stage.viewBox;
!viewBox || prevViewBox && prevViewBox.x1 === viewBox.x1 && prevViewBox.y1 === viewBox.y1 && prevViewBox.x2 === viewBox.x2 && prevViewBox.y2 === viewBox.y2 || this._stage.setViewBox(viewBox, reRender);
}
resize(width, height, reRender = !0) {
if (!this._stage) return;
const hasChange = this._width !== width || this._height !== height;
this._width = width, this._height = height, hasChange && (this._stage.resize(width, height),
this._commitedAll(), reRender && this.render({
morph: !1
}));
}
setBackground(color) {
this._stage && (this._stage.background = color);
}
setSize(width, height) {
this._width = width, this._height = height, this._stage;
}
setViewBox(viewBox, reRender = !0) {
this.updateViewBox(viewBox, reRender);
}
addEventListener(source, type, callback) {
var _a, _b;
if (!1 !== this._option.interactive) if (source === event_1.Event_Source_Type.chart) {
const rootGroup = this.getRootGroup(), wrappedCallback = function(event) {
var _a;
const graphic = event.target;
let markGraphic = null;
graphic && (markGraphic = (0, vutils_1.isValid)(graphic.context) ? graphic : (0,
mark_1.findMarkGraphic)(rootGroup, graphic));
const context = null !== (_a = null == markGraphic ? void 0 : markGraphic.context) && void 0 !== _a ? _a : {}, markId = (0,
vutils_1.isValid)(context.markId) ? context.markId : null, modelId = (0, vutils_1.isValid)(context.modelId) ? context.modelId : null, modelUserId = (0,
vutils_1.isValid)(context.modelUserId) ? context.modelUserId : null, markUserId = (0,
vutils_1.isValid)(context.markUserId) ? context.markUserId : null, params = {
event: event,
type: type,
source: source,
item: markGraphic,
datum: (0, mark_1.getDatumOfGraphic)(markGraphic),
markId: markId,
modelId: modelId,
markUserId: markUserId,
modelUserId: modelUserId
};
callback.call(null, params);
}.bind(this);
this._viewListeners.set(callback, {
type: type,
callback: wrappedCallback
}), null === (_a = this._stage) || void 0 === _a || _a.addEventListener(type, wrappedCallback);
} else if (source === event_1.Event_Source_Type.window) {
const wrappedCallback = function(event) {
const params = {
event: event,
type: type,
source: source,
item: null,
datum: null,
markId: null,
modelId: null,
markUserId: null,
modelUserId: null
};
callback.call(null, params);
}.bind(this);
this._windowListeners.set(callback, {
type: type,
callback: wrappedCallback
});
const windowObject = this._getGlobalThis();
null == windowObject || windowObject.addEventListener(type, wrappedCallback);
} else if (source === event_1.Event_Source_Type.canvas) {
const wrappedCallback = function(event) {
const params = {
event: event,
type: type,
source: source,
item: null,
datum: null,
markId: null,
modelId: null,
markUserId: null,
modelUserId: null
};
callback.call(null, params);
}.bind(this);
this._canvasListeners.set(callback, {
type: type,
callback: wrappedCallback
});
const canvasObject = null === (_b = this.getStage()) || void 0 === _b ? void 0 : _b.window;
null == canvasObject || canvasObject.addEventListener(type, wrappedCallback);
}
}
removeEventListener(source, type, callback) {
var _a, _b, _c, _d, _e;
if (!1 !== this._option.interactive) if (source === event_1.Event_Source_Type.chart) {
const wrappedCallback = null === (_a = this._viewListeners.get(callback)) || void 0 === _a ? void 0 : _a.callback;
wrappedCallback && (null === (_b = this._stage) || void 0 === _b || _b.removeEventListener(type, wrappedCallback)),
this._viewListeners.delete(callback);
} else if (source === event_1.Event_Source_Type.window) {
const windowObject = this._getGlobalThis(), wrappedCallback = null === (_c = this._windowListeners.get(callback)) || void 0 === _c ? void 0 : _c.callback;
wrappedCallback && (null == windowObject || windowObject.removeEventListener(type, wrappedCallback)),
this._windowListeners.delete(callback);
} else if (source === event_1.Event_Source_Type.canvas) {
const canvasObject = null === (_d = this.getStage()) || void 0 === _d ? void 0 : _d.window, wrappedCallback = null === (_e = this._canvasListeners.get(callback)) || void 0 === _e ? void 0 : _e.callback;
canvasObject && wrappedCallback && (null == canvasObject || canvasObject.removeEventListener(type, wrappedCallback)),
this._canvasListeners.delete(callback);
}
}
releaseEvent() {
const stage = this.getStage();
stage && stage.hooks.afterRender.unTap("chart-event", this.handleStageRender), this._viewListeners.clear(),
this._windowListeners.clear(), this._canvasListeners.clear();
}
release() {
var _a;
this.clearNextRender(), this.releaseEvent(), this._option = this._container = null,
this.releaseGrammar(!0), this._stage !== (null === (_a = this._option) || void 0 === _a ? void 0 : _a.stage) && this._stage.release(),
this._stage = null, this.isInited = !1, this._compileChart = null, this._released = !0;
}
releaseGrammar(removeGraphicItems = !1) {
removeGraphicItems ? this._rootMarks.forEach((g => {
(0, util_1.traverseGroupMark)(g, (m => {
m.removeProduct();
}), null, !0);
})) : this._cachedMarks = (0, util_1.findSimpleMarks)(this._rootMarks), this._rootMarks = [];
}
addRootMark(mark) {
this._rootMarks.includes(mark) || this._rootMarks.push(mark);
}
getRootMarks() {
return this._rootMarks;
}
removeRootMark(mark) {
const index = this._rootMarks.findIndex((m => m === mark));
return index >= 0 && (this._rootMarks.splice(index, 1), !0);
}
_getGlobalThis() {
var _a;
return (0, env_1.isTrueBrowser)(this._option.mode) ? globalThis : null === (_a = this.getStage()) || void 0 === _a ? void 0 : _a.window;
}
_combineIncrementalLayers() {
this._stage && (0, vrender_core_1.waitForAllSubLayers)(this._stage).then((() => {
this._stage && this._stage.defaultLayer.combineSubLayer();
}));
}
findProgressiveMarks() {
const marks = [];
return this._rootMarks.forEach((mark => {
(0, util_1.traverseGroupMark)(mark, (m => {
m.isProgressive() && marks.push(m);
}));
})), marks.length ? (this._progressiveMarks = marks, this._combineIncrementalLayers(),
marks) : (this._progressiveMarks = null, null);
}
doPreProgressive() {
if (this._progressiveMarks && this._progressiveMarks.some((mark => mark.isDoingProgressive()))) {
const raf = vrender_core_1.vglobal.getSpecifiedRequestAnimationFrame(10);
this._progressiveRafId = raf(this.handleProgressiveFrame);
} else this._progressiveMarks && this._progressiveMarks.every((mark => mark.canAnimateAfterProgressive())) ? this._progressiveMarks.forEach((mark => {
mark.runAnimation(), mark.clearExitGraphics();
})) : this._progressiveMarks && (this._progressiveMarks = null);
}
clearProgressive() {
if (this._progressiveRafId) {
vrender_core_1.vglobal.getSpecifiedCancelAnimationFrame(10)(this._progressiveRafId);
}
this._progressiveMarks && this._progressiveMarks.length && (this._progressiveMarks.forEach((entry => {
entry.clearProgressive();
})), this._progressiveMarks = null);
}
}
exports.Compiler = Compiler;
//# sourceMappingURL=compiler.js.map