You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

489 lines
14 KiB
JavaScript

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _style = _interopRequireDefault(require("./style.class"));
var _transition = _interopRequireDefault(require("@jiaminghi/transition"));
var _util = require("../plugin/util");
/**
* @description Class Graph
* @param {Object} graph Graph default configuration
* @param {Object} config Graph config
* @return {Graph} Instance of Graph
*/
var Graph = function Graph(graph, config) {
(0, _classCallCheck2["default"])(this, Graph);
config = (0, _util.deepClone)(config, true);
var defaultConfig = {
/**
* @description Weather to render graph
* @type {Boolean}
* @default visible = true
*/
visible: true,
/**
* @description Whether to enable drag
* @type {Boolean}
* @default drag = false
*/
drag: false,
/**
* @description Whether to enable hover
* @type {Boolean}
* @default hover = false
*/
hover: false,
/**
* @description Graph rendering index
* Give priority to index high graph in rendering
* @type {Number}
* @example index = 1
*/
index: 1,
/**
* @description Animation delay time(ms)
* @type {Number}
* @default animationDelay = 0
*/
animationDelay: 0,
/**
* @description Number of animation frames
* @type {Number}
* @default animationFrame = 30
*/
animationFrame: 30,
/**
* @description Animation dynamic curve (Supported by transition)
* @type {String}
* @default animationCurve = 'linear'
* @link https://github.com/jiaming743/Transition
*/
animationCurve: 'linear',
/**
* @description Weather to pause graph animation
* @type {Boolean}
* @default animationPause = false
*/
animationPause: false,
/**
* @description Rectangular hover detection zone
* Use this method for hover detection first
* @type {Null|Array}
* @default hoverRect = null
* @example hoverRect = [0, 0, 100, 100] // [Rect start x, y, Rect width, height]
*/
hoverRect: null,
/**
* @description Mouse enter event handler
* @type {Function|Null}
* @default mouseEnter = null
*/
mouseEnter: null,
/**
* @description Mouse outer event handler
* @type {Function|Null}
* @default mouseOuter = null
*/
mouseOuter: null,
/**
* @description Mouse click event handler
* @type {Function|Null}
* @default click = null
*/
click: null
};
var configAbleNot = {
status: 'static',
animationRoot: [],
animationKeys: [],
animationFrameState: [],
cache: {}
};
if (!config.shape) config.shape = {};
if (!config.style) config.style = {};
var shape = Object.assign({}, graph.shape, config.shape);
Object.assign(defaultConfig, config, configAbleNot);
Object.assign(this, graph, defaultConfig);
this.shape = shape;
this.style = new _style["default"](config.style);
this.addedProcessor();
};
/**
* @description Processor of added
* @return {Undefined} Void
*/
exports["default"] = Graph;
Graph.prototype.addedProcessor = function () {
if (typeof this.setGraphCenter === 'function') this.setGraphCenter(null, this); // The life cycle 'added"
if (typeof this.added === 'function') this.added(this);
};
/**
* @description Processor of draw
* @param {CRender} render Instance of CRender
* @param {Graph} graph Instance of Graph
* @return {Undefined} Void
*/
Graph.prototype.drawProcessor = function (render, graph) {
var ctx = render.ctx;
graph.style.initStyle(ctx);
if (typeof this.beforeDraw === 'function') this.beforeDraw(this, render);
graph.draw(render, graph);
if (typeof this.drawed === 'function') this.drawed(this, render);
graph.style.restoreTransform(ctx);
};
/**
* @description Processor of hover check
* @param {Array} position Mouse Position
* @param {Graph} graph Instance of Graph
* @return {Boolean} Result of hover check
*/
Graph.prototype.hoverCheckProcessor = function (position, _ref) {
var hoverRect = _ref.hoverRect,
style = _ref.style,
hoverCheck = _ref.hoverCheck;
var graphCenter = style.graphCenter,
rotate = style.rotate,
scale = style.scale,
translate = style.translate;
if (graphCenter) {
if (rotate) position = (0, _util.getRotatePointPos)(-rotate, position, graphCenter);
if (scale) position = (0, _util.getScalePointPos)(scale.map(function (s) {
return 1 / s;
}), position, graphCenter);
if (translate) position = (0, _util.getTranslatePointPos)(translate.map(function (v) {
return v * -1;
}), position);
}
if (hoverRect) return _util.checkPointIsInRect.apply(void 0, [position].concat((0, _toConsumableArray2["default"])(hoverRect)));
return hoverCheck(position, this);
};
/**
* @description Processor of move
* @param {Event} e Mouse movement event
* @return {Undefined} Void
*/
Graph.prototype.moveProcessor = function (e) {
this.move(e, this);
if (typeof this.beforeMove === 'function') this.beforeMove(e, this);
if (typeof this.setGraphCenter === 'function') this.setGraphCenter(e, this);
if (typeof this.moved === 'function') this.moved(e, this);
};
/**
* @description Update graph state
* @param {String} attrName Updated attribute name
* @param {Any} change Updated value
* @return {Undefined} Void
*/
Graph.prototype.attr = function (attrName) {
var change = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
if (!attrName || change === undefined) return false;
var isObject = (0, _typeof2["default"])(this[attrName]) === 'object';
if (isObject) change = (0, _util.deepClone)(change, true);
var render = this.render;
if (attrName === 'style') {
this.style.update(change);
} else if (isObject) {
Object.assign(this[attrName], change);
} else {
this[attrName] = change;
}
if (attrName === 'index') render.sortGraphsByIndex();
render.drawAllGraph();
};
/**
* @description Update graphics state (with animation)
* Only shape and style attributes are supported
* @param {String} attrName Updated attribute name
* @param {Any} change Updated value
* @param {Boolean} wait Whether to store the animation waiting
* for the next animation request
* @return {Promise} Animation Promise
*/
Graph.prototype.animation =
/*#__PURE__*/
function () {
var _ref2 = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee2(attrName, change) {
var wait,
changeRoot,
changeKeys,
beforeState,
animationFrame,
animationCurve,
animationDelay,
animationFrameState,
render,
_args2 = arguments;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
wait = _args2.length > 2 && _args2[2] !== undefined ? _args2[2] : false;
if (!(attrName !== 'shape' && attrName !== 'style')) {
_context2.next = 4;
break;
}
console.error('Only supported shape and style animation!');
return _context2.abrupt("return");
case 4:
change = (0, _util.deepClone)(change, true);
if (attrName === 'style') this.style.colorProcessor(change);
changeRoot = this[attrName];
changeKeys = Object.keys(change);
beforeState = {};
changeKeys.forEach(function (key) {
return beforeState[key] = changeRoot[key];
});
animationFrame = this.animationFrame, animationCurve = this.animationCurve, animationDelay = this.animationDelay;
animationFrameState = (0, _transition["default"])(animationCurve, beforeState, change, animationFrame, true);
this.animationRoot.push(changeRoot);
this.animationKeys.push(changeKeys);
this.animationFrameState.push(animationFrameState);
if (!wait) {
_context2.next = 17;
break;
}
return _context2.abrupt("return");
case 17:
if (!(animationDelay > 0)) {
_context2.next = 20;
break;
}
_context2.next = 20;
return delay(animationDelay);
case 20:
render = this.render;
return _context2.abrupt("return", new Promise(
/*#__PURE__*/
function () {
var _ref3 = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee(resolve) {
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return render.launchAnimation();
case 2:
resolve();
case 3:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return function (_x3) {
return _ref3.apply(this, arguments);
};
}()));
case 22:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
return function (_x, _x2) {
return _ref2.apply(this, arguments);
};
}();
/**
* @description Extract the next frame of data from the animation queue
* and update the graph state
* @return {Undefined} Void
*/
Graph.prototype.turnNextAnimationFrame = function (timeStamp) {
var animationDelay = this.animationDelay,
animationRoot = this.animationRoot,
animationKeys = this.animationKeys,
animationFrameState = this.animationFrameState,
animationPause = this.animationPause;
if (animationPause) return;
if (Date.now() - timeStamp < animationDelay) return;
animationRoot.forEach(function (root, i) {
animationKeys[i].forEach(function (key) {
root[key] = animationFrameState[i][0][key];
});
});
animationFrameState.forEach(function (stateItem, i) {
stateItem.shift();
var noFrame = stateItem.length === 0;
if (noFrame) animationRoot[i] = null;
if (noFrame) animationKeys[i] = null;
});
this.animationFrameState = animationFrameState.filter(function (state) {
return state.length;
});
this.animationRoot = animationRoot.filter(function (root) {
return root;
});
this.animationKeys = animationKeys.filter(function (keys) {
return keys;
});
};
/**
* @description Skip to the last frame of animation
* @return {Undefined} Void
*/
Graph.prototype.animationEnd = function () {
var animationFrameState = this.animationFrameState,
animationKeys = this.animationKeys,
animationRoot = this.animationRoot,
render = this.render;
animationRoot.forEach(function (root, i) {
var currentKeys = animationKeys[i];
var lastState = animationFrameState[i].pop();
currentKeys.forEach(function (key) {
return root[key] = lastState[key];
});
});
this.animationFrameState = [];
this.animationKeys = [];
this.animationRoot = [];
return render.drawAllGraph();
};
/**
* @description Pause animation behavior
* @return {Undefined} Void
*/
Graph.prototype.pauseAnimation = function () {
this.attr('animationPause', true);
};
/**
* @description Try animation behavior
* @return {Undefined} Void
*/
Graph.prototype.playAnimation = function () {
var render = this.render;
this.attr('animationPause', false);
return new Promise(
/*#__PURE__*/
function () {
var _ref4 = (0, _asyncToGenerator2["default"])(
/*#__PURE__*/
_regenerator["default"].mark(function _callee3(resolve) {
return _regenerator["default"].wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return render.launchAnimation();
case 2:
resolve();
case 3:
case "end":
return _context3.stop();
}
}
}, _callee3);
}));
return function (_x4) {
return _ref4.apply(this, arguments);
};
}());
};
/**
* @description Processor of delete
* @param {CRender} render Instance of CRender
* @return {Undefined} Void
*/
Graph.prototype.delProcessor = function (render) {
var _this = this;
var graphs = render.graphs;
var index = graphs.findIndex(function (graph) {
return graph === _this;
});
if (index === -1) return;
if (typeof this.beforeDelete === 'function') this.beforeDelete(this);
graphs.splice(index, 1, null);
if (typeof this.deleted === 'function') this.deleted(this);
};
/**
* @description Return a timed release Promise
* @param {Number} time Release time
* @return {Promise} A timed release Promise
*/
function delay(time) {
return new Promise(function (resolve) {
setTimeout(resolve, time);
});
}