|
|
"use strict";
|
|
|
|
|
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
value: true
|
|
|
});
|
|
|
exports["default"] = void 0;
|
|
|
|
|
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
|
|
|
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
|
|
|
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
|
|
|
|
|
|
var _color = _interopRequireDefault(require("@jiaminghi/color"));
|
|
|
|
|
|
var _bezierCurve = _interopRequireDefault(require("@jiaminghi/bezier-curve"));
|
|
|
|
|
|
var _util = require("../plugin/util");
|
|
|
|
|
|
var _graphs = _interopRequireDefault(require("../config/graphs"));
|
|
|
|
|
|
var _graph = _interopRequireDefault(require("./graph.class"));
|
|
|
|
|
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
|
|
|
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
|
|
|
|
/**
|
|
|
* @description Class of CRender
|
|
|
* @param {Object} canvas Canvas DOM
|
|
|
* @return {CRender} Instance of CRender
|
|
|
*/
|
|
|
var CRender = function CRender(canvas) {
|
|
|
(0, _classCallCheck2["default"])(this, CRender);
|
|
|
|
|
|
if (!canvas) {
|
|
|
console.error('CRender Missing parameters!');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var ctx = canvas.getContext('2d');
|
|
|
var clientWidth = canvas.clientWidth,
|
|
|
clientHeight = canvas.clientHeight;
|
|
|
var area = [clientWidth, clientHeight];
|
|
|
canvas.setAttribute('width', clientWidth);
|
|
|
canvas.setAttribute('height', clientHeight);
|
|
|
/**
|
|
|
* @description Context of the canvas
|
|
|
* @type {Object}
|
|
|
* @example ctx = canvas.getContext('2d')
|
|
|
*/
|
|
|
|
|
|
this.ctx = ctx;
|
|
|
/**
|
|
|
* @description Width and height of the canvas
|
|
|
* @type {Array}
|
|
|
* @example area = [300,100]
|
|
|
*/
|
|
|
|
|
|
this.area = area;
|
|
|
/**
|
|
|
* @description Whether render is in animation rendering
|
|
|
* @type {Boolean}
|
|
|
* @example animationStatus = true|false
|
|
|
*/
|
|
|
|
|
|
this.animationStatus = false;
|
|
|
/**
|
|
|
* @description Added graph
|
|
|
* @type {[Graph]}
|
|
|
* @example graphs = [Graph, Graph, ...]
|
|
|
*/
|
|
|
|
|
|
this.graphs = [];
|
|
|
/**
|
|
|
* @description Color plugin
|
|
|
* @type {Object}
|
|
|
* @link https://github.com/jiaming743/color
|
|
|
*/
|
|
|
|
|
|
this.color = _color["default"];
|
|
|
/**
|
|
|
* @description Bezier Curve plugin
|
|
|
* @type {Object}
|
|
|
* @link https://github.com/jiaming743/BezierCurve
|
|
|
*/
|
|
|
|
|
|
this.bezierCurve = _bezierCurve["default"]; // bind event handler
|
|
|
|
|
|
canvas.addEventListener('mousedown', mouseDown.bind(this));
|
|
|
canvas.addEventListener('mousemove', mouseMove.bind(this));
|
|
|
canvas.addEventListener('mouseup', mouseUp.bind(this));
|
|
|
};
|
|
|
/**
|
|
|
* @description Clear canvas drawing area
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
exports["default"] = CRender;
|
|
|
|
|
|
CRender.prototype.clearArea = function () {
|
|
|
var _this$ctx;
|
|
|
|
|
|
var area = this.area;
|
|
|
|
|
|
(_this$ctx = this.ctx).clearRect.apply(_this$ctx, [0, 0].concat((0, _toConsumableArray2["default"])(area)));
|
|
|
};
|
|
|
/**
|
|
|
* @description Add graph to render
|
|
|
* @param {Object} config Graph configuration
|
|
|
* @return {Graph} Graph instance
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.add = function () {
|
|
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
|
var name = config.name;
|
|
|
|
|
|
if (!name) {
|
|
|
console.error('add Missing parameters!');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var graphConfig = _graphs["default"].get(name);
|
|
|
|
|
|
if (!graphConfig) {
|
|
|
console.warn('No corresponding graph configuration found!');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var graph = new _graph["default"](graphConfig, config);
|
|
|
if (!graph.validator(graph)) return;
|
|
|
graph.render = this;
|
|
|
this.graphs.push(graph);
|
|
|
this.sortGraphsByIndex();
|
|
|
this.drawAllGraph();
|
|
|
return graph;
|
|
|
};
|
|
|
/**
|
|
|
* @description Sort the graph by index
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.sortGraphsByIndex = function () {
|
|
|
var graphs = this.graphs;
|
|
|
graphs.sort(function (a, b) {
|
|
|
if (a.index > b.index) return 1;
|
|
|
if (a.index === b.index) return 0;
|
|
|
if (a.index < b.index) return -1;
|
|
|
});
|
|
|
};
|
|
|
/**
|
|
|
* @description Delete graph in render
|
|
|
* @param {Graph} graph The graph to be deleted
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.delGraph = function (graph) {
|
|
|
if (typeof graph.delProcessor !== 'function') return;
|
|
|
graph.delProcessor(this);
|
|
|
this.graphs = this.graphs.filter(function (graph) {
|
|
|
return graph;
|
|
|
});
|
|
|
this.drawAllGraph();
|
|
|
};
|
|
|
/**
|
|
|
* @description Delete all graph in render
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.delAllGraph = function () {
|
|
|
var _this = this;
|
|
|
|
|
|
this.graphs.forEach(function (graph) {
|
|
|
return graph.delProcessor(_this);
|
|
|
});
|
|
|
this.graphs = this.graphs.filter(function (graph) {
|
|
|
return graph;
|
|
|
});
|
|
|
this.drawAllGraph();
|
|
|
};
|
|
|
/**
|
|
|
* @description Draw all the graphs in the render
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.drawAllGraph = function () {
|
|
|
var _this2 = this;
|
|
|
|
|
|
this.clearArea();
|
|
|
this.graphs.filter(function (graph) {
|
|
|
return graph && graph.visible;
|
|
|
}).forEach(function (graph) {
|
|
|
return graph.drawProcessor(_this2, graph);
|
|
|
});
|
|
|
};
|
|
|
/**
|
|
|
* @description Animate the graph whose animation queue is not empty
|
|
|
* and the animationPause is equal to false
|
|
|
* @return {Promise} Animation Promise
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.launchAnimation = function () {
|
|
|
var _this3 = this;
|
|
|
|
|
|
var animationStatus = this.animationStatus;
|
|
|
if (animationStatus) return;
|
|
|
this.animationStatus = true;
|
|
|
return new Promise(function (resolve) {
|
|
|
animation.call(_this3, function () {
|
|
|
_this3.animationStatus = false;
|
|
|
resolve();
|
|
|
}, Date.now());
|
|
|
});
|
|
|
};
|
|
|
/**
|
|
|
* @description Try to animate every graph
|
|
|
* @param {Function} callback Callback in animation end
|
|
|
* @param {Number} timeStamp Time stamp of animation start
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
function animation(callback, timeStamp) {
|
|
|
var graphs = this.graphs;
|
|
|
|
|
|
if (!animationAble(graphs)) {
|
|
|
callback();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
graphs.forEach(function (graph) {
|
|
|
return graph.turnNextAnimationFrame(timeStamp);
|
|
|
});
|
|
|
this.drawAllGraph();
|
|
|
requestAnimationFrame(animation.bind(this, callback, timeStamp));
|
|
|
}
|
|
|
/**
|
|
|
* @description Find if there are graph that can be animated
|
|
|
* @param {[Graph]} graphs
|
|
|
* @return {Boolean}
|
|
|
*/
|
|
|
|
|
|
|
|
|
function animationAble(graphs) {
|
|
|
return graphs.find(function (graph) {
|
|
|
return !graph.animationPause && graph.animationFrameState.length;
|
|
|
});
|
|
|
}
|
|
|
/**
|
|
|
* @description Handler of CRender mousedown event
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
function mouseDown(e) {
|
|
|
var graphs = this.graphs;
|
|
|
var hoverGraph = graphs.find(function (graph) {
|
|
|
return graph.status === 'hover';
|
|
|
});
|
|
|
if (!hoverGraph) return;
|
|
|
hoverGraph.status = 'active';
|
|
|
}
|
|
|
/**
|
|
|
* @description Handler of CRender mousemove event
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
function mouseMove(e) {
|
|
|
var offsetX = e.offsetX,
|
|
|
offsetY = e.offsetY;
|
|
|
var position = [offsetX, offsetY];
|
|
|
var graphs = this.graphs;
|
|
|
var activeGraph = graphs.find(function (graph) {
|
|
|
return graph.status === 'active' || graph.status === 'drag';
|
|
|
});
|
|
|
|
|
|
if (activeGraph) {
|
|
|
if (!activeGraph.drag) return;
|
|
|
|
|
|
if (typeof activeGraph.move !== 'function') {
|
|
|
console.error('No move method is provided, cannot be dragged!');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
activeGraph.moveProcessor(e);
|
|
|
activeGraph.status = 'drag';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
var hoverGraph = graphs.find(function (graph) {
|
|
|
return graph.status === 'hover';
|
|
|
});
|
|
|
var hoverAbleGraphs = graphs.filter(function (graph) {
|
|
|
return graph.hover && (typeof graph.hoverCheck === 'function' || graph.hoverRect);
|
|
|
});
|
|
|
var hoveredGraph = hoverAbleGraphs.find(function (graph) {
|
|
|
return graph.hoverCheckProcessor(position, graph);
|
|
|
});
|
|
|
|
|
|
if (hoveredGraph) {
|
|
|
document.body.style.cursor = hoveredGraph.style.hoverCursor;
|
|
|
} else {
|
|
|
document.body.style.cursor = 'default';
|
|
|
}
|
|
|
|
|
|
var hoverGraphMouseOuterIsFun = false,
|
|
|
hoveredGraphMouseEnterIsFun = false;
|
|
|
if (hoverGraph) hoverGraphMouseOuterIsFun = typeof hoverGraph.mouseOuter === 'function';
|
|
|
if (hoveredGraph) hoveredGraphMouseEnterIsFun = typeof hoveredGraph.mouseEnter === 'function';
|
|
|
if (!hoveredGraph && !hoverGraph) return;
|
|
|
|
|
|
if (!hoveredGraph && hoverGraph) {
|
|
|
if (hoverGraphMouseOuterIsFun) hoverGraph.mouseOuter(e, hoverGraph);
|
|
|
hoverGraph.status = 'static';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (hoveredGraph && hoveredGraph === hoverGraph) return;
|
|
|
|
|
|
if (hoveredGraph && !hoverGraph) {
|
|
|
if (hoveredGraphMouseEnterIsFun) hoveredGraph.mouseEnter(e, hoveredGraph);
|
|
|
hoveredGraph.status = 'hover';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (hoveredGraph && hoverGraph && hoveredGraph !== hoverGraph) {
|
|
|
if (hoverGraphMouseOuterIsFun) hoverGraph.mouseOuter(e, hoverGraph);
|
|
|
hoverGraph.status = 'static';
|
|
|
if (hoveredGraphMouseEnterIsFun) hoveredGraph.mouseEnter(e, hoveredGraph);
|
|
|
hoveredGraph.status = 'hover';
|
|
|
}
|
|
|
}
|
|
|
/**
|
|
|
* @description Handler of CRender mouseup event
|
|
|
* @return {Undefined} Void
|
|
|
*/
|
|
|
|
|
|
|
|
|
function mouseUp(e) {
|
|
|
var graphs = this.graphs;
|
|
|
var activeGraph = graphs.find(function (graph) {
|
|
|
return graph.status === 'active';
|
|
|
});
|
|
|
var dragGraph = graphs.find(function (graph) {
|
|
|
return graph.status === 'drag';
|
|
|
});
|
|
|
if (activeGraph && typeof activeGraph.click === 'function') activeGraph.click(e, activeGraph);
|
|
|
graphs.forEach(function (graph) {
|
|
|
return graph && (graph.status = 'static');
|
|
|
});
|
|
|
if (activeGraph) activeGraph.status = 'hover';
|
|
|
if (dragGraph) dragGraph.status = 'hover';
|
|
|
}
|
|
|
/**
|
|
|
* @description Clone Graph
|
|
|
* @param {Graph} graph The target to be cloned
|
|
|
* @return {Graph} Cloned graph
|
|
|
*/
|
|
|
|
|
|
|
|
|
CRender.prototype.clone = function (graph) {
|
|
|
var style = graph.style.getStyle();
|
|
|
|
|
|
var clonedGraph = _objectSpread({}, graph, {
|
|
|
style: style
|
|
|
});
|
|
|
|
|
|
delete clonedGraph.render;
|
|
|
clonedGraph = (0, _util.deepClone)(clonedGraph, true);
|
|
|
return this.add(clonedGraph);
|
|
|
}; |