UNPKG

@jiaminghi/c-render

Version:

Canvas-based vector graphics rendering plugin

1,741 lines (1,511 loc) 418 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ var CRender = require('../lib/index') window.CRender = CRender },{"../lib/index":6}],2:[function(require,module,exports){ "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); }; },{"../config/graphs":5,"../plugin/util":8,"./graph.class":3,"@babel/runtime/helpers/classCallCheck":12,"@babel/runtime/helpers/defineProperty":13,"@babel/runtime/helpers/interopRequireDefault":14,"@babel/runtime/helpers/toConsumableArray":20,"@jiaminghi/bezier-curve":25,"@jiaminghi/color":27}],3:[function(require,module,exports){ "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); }); } },{"../plugin/util":8,"./style.class":4,"@babel/runtime/helpers/asyncToGenerator":11,"@babel/runtime/helpers/classCallCheck":12,"@babel/runtime/helpers/interopRequireDefault":14,"@babel/runtime/helpers/toConsumableArray":20,"@babel/runtime/helpers/typeof":21,"@babel/runtime/regenerator":22,"@jiaminghi/transition":29}],4:[function(require,module,exports){ "use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _color = require("@jiaminghi/color"); var _util = require("../plugin/util"); /** * @description Class Style * @param {Object} style Style configuration * @return {Style} Instance of Style */ var Style = function Style(style) { (0, _classCallCheck2["default"])(this, Style); this.colorProcessor(style); var defaultStyle = { /** * @description Rgba value of graph fill color * @type {Array} * @default fill = [0, 0, 0, 1] */ fill: [0, 0, 0, 1], /** * @description Rgba value of graph stroke color * @type {Array} * @default stroke = [0, 0, 0, 1] */ stroke: [0, 0, 0, 0], /** * @description Opacity of graph * @type {Number} * @default opacity = 1 */ opacity: 1, /** * @description LineCap of Ctx * @type {String} * @default lineCap = null * @example lineCap = 'butt'|'round'|'square' */ lineCap: null, /** * @description Linejoin of Ctx * @type {String} * @default lineJoin = null * @example lineJoin = 'round'|'bevel'|'miter' */ lineJoin: null, /** * @description LineDash of Ctx * @type {Array} * @default lineDash = null * @example lineDash = [10, 10] */ lineDash: null, /** * @description LineDashOffset of Ctx * @type {Number} * @default lineDashOffset = null * @example lineDashOffset = 10 */ lineDashOffset: null, /** * @description ShadowBlur of Ctx * @type {Number} * @default shadowBlur = 0 */ shadowBlur: 0, /** * @description Rgba value of graph shadow color * @type {Array} * @default shadowColor = [0, 0, 0, 0] */ shadowColor: [0, 0, 0, 0], /** * @description ShadowOffsetX of Ctx * @type {Number} * @default shadowOffsetX = 0 */ shadowOffsetX: 0, /** * @description ShadowOffsetY of Ctx * @type {Number} * @default shadowOffsetY = 0 */ shadowOffsetY: 0, /** * @description LineWidth of Ctx * @type {Number} * @default lineWidth = 0 */ lineWidth: 0, /** * @description Center point of the graph * @type {Array} * @default graphCenter = null * @example graphCenter = [10, 10] */ graphCenter: null, /** * @description Graph scale * @type {Array} * @default scale = null * @example scale = [1.5, 1.5] */ scale: null, /** * @description Graph rotation degree * @type {Number} * @default rotate = null * @example rotate = 10 */ rotate: null, /** * @description Graph translate distance * @type {Array} * @default translate = null * @example translate = [10, 10] */ translate: null, /** * @description Cursor status when hover * @type {String} * @default hoverCursor = 'pointer' * @example hoverCursor = 'default'|'pointer'|'auto'|'crosshair'|'move'|'wait'|... */ hoverCursor: 'pointer', /** * @description Font style of Ctx * @type {String} * @default fontStyle = 'normal' * @example fontStyle = 'normal'|'italic'|'oblique' */ fontStyle: 'normal', /** * @description Font varient of Ctx * @type {String} * @default fontVarient = 'normal' * @example fontVarient = 'normal'|'small-caps' */ fontVarient: 'normal', /** * @description Font weight of Ctx * @type {String|Number} * @default fontWeight = 'normal' * @example fontWeight = 'normal'|'bold'|'bolder'|'lighter'|Number */ fontWeight: 'normal', /** * @description Font size of Ctx * @type {Number} * @default fontSize = 10 */ fontSize: 10, /** * @description Font family of Ctx * @type {String} * @default fontFamily = 'Arial' */ fontFamily: 'Arial', /** * @description TextAlign of Ctx * @type {String} * @default textAlign = 'center' * @example textAlign = 'start'|'end'|'left'|'right'|'center' */ textAlign: 'center', /** * @description TextBaseline of Ctx * @type {String} * @default textBaseline = 'middle' * @example textBaseline = 'top'|'bottom'|'middle'|'alphabetic'|'hanging' */ textBaseline: 'middle', /** * @description The color used to create the gradient * @type {Array} * @default gradientColor = null * @example gradientColor = ['#000', '#111', '#222'] */ gradientColor: null, /** * @description Gradient type * @type {String} * @default gradientType = 'linear' * @example gradientType = 'linear' | 'radial' */ gradientType: 'linear', /** * @description Gradient params * @type {Array} * @default gradientParams = null * @example gradientParams = [x0, y0, x1, y1] (Linear Gradient) * @example gradientParams = [x0, y0, r0, x1, y1, r1] (Radial Gradient) */ gradientParams: null, /** * @description When to use gradients * @type {String} * @default gradientWith = 'stroke' * @example gradientWith = 'stroke' | 'fill' */ gradientWith: 'stroke', /** * @description Gradient color stops * @type {String} * @default gradientStops = 'auto' * @example gradientStops = 'auto' | [0, .2, .3, 1] */ gradientStops: 'auto', /** * @description Extended color that supports animation transition * @type {Array|Object} * @default colors = null * @example colors = ['#000', '#111', '#222', 'red' ] * @example colors = { a: '#000', b: '#111' } */ colors: null }; Object.assign(this, defaultStyle, style); }; /** * @description Set colors to rgba value * @param {Object} style style config * @param {Boolean} reverse Whether to perform reverse operation * @return {Undefined} Void */ exports["default"] = Style; Style.prototype.colorProcessor = function (style) { var reverse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var processor = reverse ? _color.getColorFromRgbValue : _color.getRgbaValue; var colorProcessorKeys = ['fill', 'stroke', 'shadowColor']; var allKeys = Object.keys(style); var colorKeys = allKeys.filter(function (key) { return colorProcessorKeys.find(function (k) { return k === key; }); }); colorKeys.forEach(function (key) { return style[key] = processor(style[key]); }); var gradientColor = style.gradientColor, colors = style.colors; if (gradientColor) style.gradientColor = gradientColor.map(function (c) { return processor(c); }); if (colors) { var colorsKeys = Object.keys(colors); colorsKeys.forEach(function (key) { return colors[key] = processor(colors[key]); }); } }; /** * @description Init graph style * @param {Object} ctx Context of canvas * @return {Undefined} Void */ Style.prototype.initStyle = function (ctx) { initTransform(ctx, this); initGraphStyle(ctx, this); initGradient(ctx, this); }; /** * @description Init canvas transform * @param {Object} ctx Context of canvas * @param {Style} style Instance of Style * @return {Undefined} Void */ function initTransform(ctx, style) { ctx.save(); var graphCenter = style.graphCenter, rotate = style.rotate, scale = style.scale, translate = style.translate; if (!(graphCenter instanceof Array)) return; ctx.translate.apply(ctx, (0, _toConsumableArray2["default"])(graphCenter)); if (rotate) ctx.rotate(rotate * Math.PI / 180); if (scale instanceof Array) ctx.scale.apply(ctx, (0, _toConsumableArray2["default"])(scale)); if (translate) ctx.translate.apply(ctx, (0, _toConsumableArray2["default"])(translate)); ctx.translate(-graphCenter[0], -graphCenter[1]); } var autoSetStyleKeys = ['lineCap', 'lineJoin', 'lineDashOffset', 'shadowOffsetX', 'shadowOffsetY', 'lineWidth', 'textAlign', 'textBaseline']; /** * @description Set the style of canvas ctx * @param {Object} ctx Context of canvas * @param {Style} style Instance of Style * @return {Undefined} Void */ function initGraphStyle(ctx, style) { var fill = style.fill, stroke = style.stroke, shadowColor = style.shadowColor, opacity = style.opacity; autoSetStyleKeys.forEach(function (key) { if (key || typeof key === 'number') ctx[key] = style[key]; }); fill = (0, _toConsumableArray2["default"])(fill); stroke = (0, _toConsumableArray2["default"])(stroke); shadowColor = (0, _toConsumableArray2["default"])(shadowColor); fill[3] *= opacity; stroke[3] *= opacity; shadowColor[3] *= opacity; ctx.fillStyle = (0, _color.getColorFromRgbValue)(fill); ctx.strokeStyle = (0, _color.getColorFromRgbValue)(stroke); ctx.shadowColor = (0, _color.getColorFromRgbValue)(shadowColor); var lineDash = style.lineDash, shadowBlur = style.shadowBlur; if (lineDash) { lineDash = lineDash.map(function (v) { return v >= 0 ? v : 0; }); ctx.setLineDash(lineDash); } if (typeof shadowBlur === 'number') ctx.shadowBlur = shadowBlur > 0 ? shadowBlur : 0.001; var fontStyle = style.fontStyle, fontVarient = style.fontVarient, fontWeight = style.fontWeight, fontSize = style.fontSize, fontFamily = style.fontFamily; ctx.font = fontStyle + ' ' + fontVarient + ' ' + fontWeight + ' ' + fontSize + 'px' + ' ' + fontFamily; } /** * @description Set the gradient color of canvas ctx * @param {Object} ctx Context of canvas * @param {Style} style Instance of Style * @return {Undefined} Void */ function initGradient(ctx, style) { if (!gradientValidator(style)) return; var gradientColor = style.gradientColor, gradientParams = style.gradientParams, gradientType = style.gradientType, gradientWith = style.gradientWith, gradientStops = style.gradientStops, opacity = style.opacity; gradientColor = gradientColor.map(function (color) { var colorOpacity = color[3] * opacity; var clonedColor = (0, _toConsumableArray2["default"])(color); clonedColor[3] = colorOpacity; return clonedColor; }); gradientColor = gradientColor.map(function (c) { return (0, _color.getColorFromRgbValue)(c); }); if (gradientStops === 'auto') gradientStops = getAutoColorStops(gradientColor); var gradient = ctx["create".concat(gradientType.slice(0, 1).toUpperCase() + gradientType.slice(1), "Gradient")].apply(ctx, (0, _toConsumableArray2["default"])(gradientParams)); gradientStops.forEach(function (stop, i) { return gradient.addColorStop(stop, gradientColor[i]); }); ctx["".concat(gradientWith, "Style")] = gradient; } /** * @description Check if the gradient configuration is legal * @param {Style} style Instance of Style * @return {Boolean} Check Result */ function gradientValidator(style) { var gradientColor = style.gradientColor, gradientParams = style.gradientParams, gradientType = style.gradientType, gradientWith = style.gradientWith, gradientStops = style.gradientStops; if (!gradientColor || !gradientParams) return false; if (gradientColor.length === 1) { console.warn('The gradient needs to provide at least two colors'); return false; } if (gradientType !== 'linear' && gradientType !== 'radial') { console.warn('GradientType only supports linear or radial, current value is ' + gradientType); return false; } var gradientParamsLength = gradientParams.length; if (gradientType === 'linear' && gradientParamsLength !== 4 || gradientType === 'radial' && gradientParamsLength !== 6) { console.warn('The expected length of gradientParams is ' + (gradientType === 'linear' ? '4' : '6')); return false; } if (gradientWith !== 'fill' && gradientWith !== 'stroke') { console.warn('GradientWith only supports fill or stroke, current value is ' + gradientWith); return false; } if (gradientStops !== 'auto' && !(gradientStops instanceof Array)) { console.warn("gradientStops only supports 'auto' or Number Array ([0, .5, 1]), current value is " + gradientStops); return false; } return true; } /** * @description Get a uniform gradient color stop * @param {Array} color Gradient color * @return {Array} Gradient color stop */ function getAutoColorStops(color) { var stopGap = 1 / (color.length - 1); return color.map(function (foo, i) { return stopGap * i; }); } /** * @description Restore canvas ctx transform * @param {Object} ctx Context of canvas * @return {Undefined} Void */ Style.prototype.restoreTransform = function (ctx) { ctx.restore(); }; /** * @description Update style data * @param {Object} change Changed data * @return {Undefined} Void */ Style.prototype.update = function (change) { this.colorProcessor(change); Object.assign(this, change); }; /** * @description Get the current style configuration * @return {Object} Style configuration */ Style.prototype.getStyle = function () { var clonedStyle = (0, _util.deepClone)(this, true); this.colorProcessor(clonedStyle, true); return clonedStyle; }; },{"../plugin/util":8,"@babel/runtime/helpers/classCallCheck":12,"@babel/runtime/helpers/interopRequireDefault":14,"@babel/runtime/helpers/toConsumableArray":20,"@jiaminghi/color":27}],5:[function(require,module,exports){ "use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.extendNewGraph = extendNewGraph; exports["default"] = exports.text = exports.bezierCurve = exports.smoothline = exports.polyline = exports.regPolygon = exports.sector = exports.arc = exports.ring = exports.rect = exports.ellipse = exports.circle = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _bezierCurve2 = _interopRequireDefault(require("@jiaminghi/bezier-curve")); var _util = require("../plugin/util"); var _canvas = require("../plugin/canvas"); var polylineToBezierCurve = _bezierCurve2["default"].polylineToBezierCurve, bezierCurveToPolyline = _bezierCurve2["default"].bezierCurveToPolyline; var circle = { shape: { rx: 0, ry: 0, r: 0 }, validator: function validator(_ref) { var shape = _ref.shape; var rx = shape.rx, ry = shape.ry, r = shape.r; if (typeof rx !== 'number' || typeof ry !== 'number' || typeof r !== 'number') { console.error('Circle shape configuration is abnormal!'); return false; } return true; }, draw: function draw(_ref2, _ref3) { var ctx = _ref2.ctx; var shape = _ref3.shape; ctx.beginPath(); var rx = shape.rx, ry = shape.ry, r = shape.r; ctx.arc(rx, ry, r > 0 ? r : 0.01, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); ctx.closePath(); }, hoverCheck: function hoverCheck(position, _ref4) { var shape = _ref4.shape; var rx = shape.rx, ry = shape.ry, r = shape.r; return (0, _util.checkPointIsInCircle)(position, rx, ry, r); }, setGraphCenter: function setGraphCenter(e, _ref5) { var shape = _ref5.shape, style = _ref5.style; var rx = shape.rx, ry = shape.ry; style.graphCenter = [rx, ry]; }, move: function move(_ref6, _ref7) { var movementX = _ref6.movementX, movementY = _ref6.movementY; var shape = _ref7.shape; this.attr('shape', { rx: shape.rx + movementX, ry: shape.ry + movementY }); } }; exports.circle = circle; var ellipse = { shape: { rx: 0, ry: 0, hr: 0, vr: 0 }, validator: function validator(_ref8) { var shape = _ref8.shape; var rx = shape.rx, ry = shape.ry, hr = shape.hr, vr = shape.vr; if (typeof rx !== 'number' || typeof ry !== 'number' || typeof hr !== 'number' || typeof vr !== 'number') { console.error('Ellipse shape configuration is abnormal!'); return false; } return true; }, draw: function draw(_ref9, _ref10) { var ctx = _ref9.ctx; var shape = _ref10.shape; ctx.beginPath(); var rx = shape.rx, ry = shape.ry, hr = shape.hr, vr = shape.vr; ctx.ellipse(rx, ry, hr > 0 ? hr : 0.01, vr > 0 ? vr : 0.01, 0, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); ctx.closePath(); }, hoverCheck: function hoverCheck(position, _ref11) { var shape = _ref11.shape; var rx = shape.rx, ry = shape.ry, hr = shape.hr, vr = shape.vr; var a = Math.max(hr, vr); var b = Math.min(hr, vr); var c = Math.sqrt(a * a - b * b); var leftFocusPoint = [rx - c, ry]; var rightFocusPoint = [rx + c, ry]; var distance = (0, _util.getTwoPointDistance)(position, leftFocusPoint) + (0, _util.getTwoPointDistance)(position, rightFocusPoint); return distance <= 2 * a; }, setGraphCenter: function setGraphCenter(e, _ref12) { var shape = _ref12.shape, style = _ref12.style; var rx = shape.rx, ry = shape.ry; style.graphCenter = [rx, ry]; }, move: function move(_ref13, _ref14) { var movementX = _ref13.movementX, movementY = _ref13.movementY; var shape = _ref14.shape; this.attr('shape', { rx: shape.rx + movementX, ry: shape.ry + movementY }); } }; exports.ellipse = ellipse; var rect = { shape: { x: 0, y: 0, w: 0, h: 0 }, validator: function validator(_ref15) { var shape = _ref15.shape; var x = shape.x, y = shape.y, w = shape.w, h = shape.h; if (typeof x !== 'number' || typeof y !== 'number' || typeof w !== 'number' || typeof h !== 'number') { console.error('Rect shape configuration is abnormal!'); return false; } return true; }, draw: function draw(_ref16, _ref17) { var ctx = _ref16.ctx; var shape = _ref17.shape; ctx.beginPath(); var x = shape.x, y = shape.y, w = shape.w, h = shape.h; ctx.rect(x, y, w, h); ctx.fill(); ctx.stroke(); ctx.closePath(); }, hoverCheck: function hoverCheck(position, _ref18) { var shape = _ref18.shape; var x = shape.x, y = shape.y, w = shape.w, h = shape.h; return (0, _util.checkPointIsInRect)(position, x, y, w, h); }, setGraphCenter: function setGraphCenter(e, _ref19) { var shape = _ref19.shape, style = _ref19.style; var x = shape.x, y = shape.y, w = shape.w, h = shape.h; style.graphCenter = [x + w / 2, y + h / 2]; }, move: function move(_ref20, _ref21) { var movementX = _ref20.movementX, movementY = _ref20.movementY; var shape = _ref21.shape; this.attr('shape', { x: shape.x + movementX, y: shape.y + movementY }); } }; exports.rect = rect; var ring = { shape: { rx: 0, ry: 0, r: 0 }, validator: function validator(_ref22) { var shape = _ref22.shape; var rx = shape.rx, ry = shape.ry, r = shape.r; if (typeof rx !== 'number' || typeof ry !== 'number' || typeof r !== 'number') { console.error('Ring shape configuration is abnormal!'); return false; } return true; }, draw: function draw(_ref23, _ref24) { var ctx = _ref23.ctx; var shape = _ref24.shape; ctx.beginPath(); var rx = shape.rx, ry = shape.ry, r = shape.r; ctx.arc(rx, ry, r > 0 ? r : 0.01, 0, Math.PI * 2); ctx.stroke(); ctx.closePath(); }, hoverCheck: function hoverCheck(position, _ref25) { var shape = _ref25.shape, style = _ref25.style; var rx = shape.rx, ry = shape.ry, r = shape.r; var lineWidth = style.lineWidth; var halfLineWidth = lineWidth / 2; var minDistance = r - halfLineWidth; var maxDistance = r + halfLineWidth; var distance = (0, _util.getTwoPointDistance)(position, [rx, ry]); return distance >= minDistance && distance <= maxDistance; }, setGraphCenter: function setGraphCenter(e, _ref26) { var shape = _ref26.shape, style = _ref26.style; var rx = shape.rx, ry = shape.ry; style.graphCenter = [rx, ry]; }, move: function move(_ref27, _ref28) { var movementX = _ref27.movementX, movementY = _ref27.movementY; var shape = _ref28.shape; this.attr('shape', { rx: shape.rx + movementX, ry: shape.ry + movementY }); } }; exports.ring = ring; var arc = { shape: { rx: 0, ry: 0, r: 0, startAngle: 0, endAngle: 0, clockWise: true }, validator: function validator(_ref29) { var shape = _ref29.shape; var keys = ['rx', 'ry', 'r', 'startAngle', 'endAngle']; if (keys.find(function (key) { return typeof shape[key] !== 'number'; })) { console.error('Arc shape configuration is abnormal!'); return false; } return true; }, draw: function draw(_ref30, _ref31) { var ctx = _ref30.ctx; var shape = _ref31.shape; ctx.beginPath(); var rx = shape.rx, ry = shape.ry, r = shape.r, startAngle = shape.startAngle, endAngle = shape.endAngle, clockWise = shape.clockWise; ctx.arc(rx, ry, r > 0 ? r : 0.001, startAngle, endAngle, !clockWise); ctx.stroke(); ctx.closePath(); }, hoverCheck: function hoverCheck(position, _ref32) { var shape = _ref32.shape, style = _ref32.style; var rx = shape.rx, ry = shape.ry, r = shape.r, startAngle = shape.startAngle, endAngle = shape.endAngle, clockWise = shape.clockWise; var lineWidth = style.lineWidth; var halfLineWidth = lineWidth / 2; var insideRadius = r - halfLineWidth; var outsideRadius = r + halfLineWidth; return !(0, _util.checkPointIsInSector)(position, rx, ry, insideRadius, startAngle, endAngle, clockWise) && (0, _util.checkPointIsInSector)(position, rx, ry, outsideRadius, startAngle, endAngle, clockWise); }, setGraphCenter: function setGraphCenter(e, _ref33) { var shape = _ref33.shape, style = _ref33.style; var rx = shape.rx, ry = shape.ry; style.graphCenter = [rx, ry]; }, move: function move(_ref34, _ref35) { var movementX = _ref34.movementX, movementY = _ref34.movementY; var shape = _ref35.shape; this.attr('shape', { rx: shape.rx + movementX, ry: shape.ry + movementY }); } }; exports.arc = arc; var sector = { shape: { rx: 0, ry: 0, r: 0, startAngle: 0, endAngle: 0, clockWise: true }, validator: function validator(_ref36) { var shape = _ref36.shape; var keys = ['rx', 'ry', 'r', 'startAngle', 'endAngle']; if (keys.find(function (key) { return typeof shape[key] !== 'number'; })) { console.error('Sector shape configuration is abnormal!'); return false; } return true; }, draw: function draw(_ref37, _ref38) { var ctx = _ref37.ctx; var shape = _ref38.shape; ctx.beginPath(); var rx = shape.rx, ry = shape.ry, r = shape.r, startAngle = shape.startAngle, endAngle = shape.endAngle, clockWise = shape.clockWise;