├── .babelrc ├── .gitignore ├── .npmignore ├── README.md ├── demo_dist ├── bundle.js └── index.html ├── example └── src │ ├── index.html │ └── index.jsx ├── npm_dist ├── css │ └── main.css ├── img │ ├── clear_333.png │ ├── clear_ccc.png │ ├── dropdown_b.png │ ├── dropdown_w.png │ ├── dropup_b.png │ ├── dropup_w.png │ ├── size.png │ ├── size_d.png │ ├── size_l.png │ ├── tool_d_normal.png │ ├── tool_d_push.png │ ├── tool_l_normal.png │ └── tool_l_push.png ├── index.js └── js │ ├── areas.js │ ├── chart.js │ ├── chart_manager.js │ ├── chart_settings.js │ ├── cname.js │ ├── control.js │ ├── cpoint.js │ ├── ctool_manager.js │ ├── ctools.js │ ├── data_providers.js │ ├── data_sources.js │ ├── exprs.js │ ├── indicators.js │ ├── kline.js │ ├── layouts.js │ ├── mevent.js │ ├── named_object.js │ ├── plotters.js │ ├── ranges.js │ ├── templates.js │ ├── themes.js │ ├── timeline.js │ └── util.js ├── package-lock.json ├── package.json ├── src ├── css │ └── main.css ├── img │ ├── clear_333.png │ ├── clear_ccc.png │ ├── dropdown_b.png │ ├── dropdown_w.png │ ├── dropup_b.png │ ├── dropup_w.png │ ├── size.png │ ├── size_d.png │ ├── size_l.png │ ├── tool_d_normal.png │ ├── tool_d_push.png │ ├── tool_l_normal.png │ └── tool_l_push.png ├── index.jsx └── js │ ├── areas.js │ ├── chart.js │ ├── chart_manager.js │ ├── chart_settings.js │ ├── cname.js │ ├── control.js │ ├── cpoint.js │ ├── ctool_manager.js │ ├── ctools.js │ ├── data_providers.js │ ├── data_sources.js │ ├── exprs.js │ ├── indicators.js │ ├── kline.js │ ├── layouts.js │ ├── mevent.js │ ├── named_object.js │ ├── plotters.js │ ├── ranges.js │ ├── templates.js │ ├── themes.js │ ├── timeline.js │ └── util.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.git 3 | /node_modules -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .git 3 | src 4 | examples 5 | node_modules 6 | .babelrc 7 | .gitignore 8 | .npmignore 9 | webpack.config.js 10 | demo_dist -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-kline [![npm version](https://badge.fury.io/js/react-kline.svg)](https://badge.fury.io/js/react-kline) 2 | 3 | [![NPM](https://nodei.co/npm/react-kline.png)](https://www.npmjs.com/package/react-kline) 4 | 5 | > 基于React的K线图组件 6 | 7 | ### 演示地址 8 | 9 | * [Demo](https://lindakai2016.github.io/react-kline/index.html) 10 | 11 | ### 安装和使用 12 | 13 | 安装 14 | 15 | ```bash 16 | $ npm install react-kline 17 | ``` 18 | 19 | * 使用 20 | 21 | ```html 22 | import React from 'react'; 23 | import ReactDOM from 'react-dom'; 24 | import ReactKline from 'react-kline'; 25 | 26 | class App extends React.Component { 27 | 28 | onRequestData(param,callback){ 29 | let data={}; 30 | //请求数据 31 | //... 32 | callback(data); 33 | } 34 | 35 | render() { 36 | return ( 37 | 47 | ); 48 | } 49 | } 50 | 51 | ReactDOM.render( 52 | , 53 | document.getElementById('root') 54 | ); 55 | ``` 56 | 57 | ### 构建选项 58 | 59 | | 参数名称 | 参数说明 | 默认值 60 | |:---------|:-----------------|:------------ 61 | |`width` | 宽度 (px) | 600 62 | |`height` | 高度度 (px) | 400 63 | |`theme` | 主题 dark(暗色)/light(亮色)| dark 64 | |`language` | 语言 zh-cn(简体中文)/en-us(英文)/zh-tw(繁体中文)| zh-cn 65 | |`ranges` | 聚合选项 1w/1d/12h/6h/4h/2h/1h/30m/15m/5m/3m/1m/line (w:周, d:天, h:小时, m:分钟, line:分时数据)| ["1w", "1d", "1h", "30m", "15m", "5m", "1m", "line"] 66 | |`symbol` | 交易代号| 67 | |`symbolName` | 交易名称 | 68 | |`limit` | 分页大小 | 1000 69 | |`intervalTime` | 请求间隔时间(ms) | 3000 70 | |`debug` | 是否开启调试模式 true/false | true 71 | |`depthWidth` | 深度图宽度 | 最小50,小于50则取50,默认50 72 | 73 | 74 | ### 方法 75 | 76 | * resize(int width, int height) 77 | 78 | 设置画布大小 79 | 80 | ```javascript 81 | resize(1200, 550); 82 | ``` 83 | 84 | * setSymbol(string symbol, string symbolName) 85 | 86 | 设置交易品种 87 | 88 | ```javascript 89 | setSymbol('usd/btc', 'USD/BTC'); 90 | ``` 91 | 92 | * setTheme(string style) 93 | 94 | 设置主题 95 | 96 | ```javascript 97 | setTheme('dark'); // dark/light 98 | ``` 99 | 100 | * setLanguage(string lang) 101 | 102 | 设置语言 103 | 104 | ```javascript 105 | setLanguage('en-us'); // en-us/zh-ch/zh-tw 106 | ``` 107 | 108 | * setIntervalTime: function (intervalTime) 109 | 110 | 设置请求间隔时间(ms) 111 | 112 | ```javascript 113 | setIntervalTime(5000); 114 | ``` 115 | 116 | * setDepthWidth: function (width) 117 | 118 | 设置深度图宽度 119 | 120 | ```javascript 121 | setDepthWidth(100); 122 | ``` 123 | 124 | 125 | ### 事件 126 | 127 | | 事件函数 | 说明 128 | |:-----------------------|:------------ 129 | | `onResize: function(width, height)` | 画布尺寸改变时触发 130 | | `onLangChange: function(lang)` | 语言改变时触发 131 | | `onSymbolChange: function(symbol, symbolName)` | 交易品种改变时触发 132 | | `onThemeChange: function(theme)` | 主题改变时触发 133 | | `onRangeChange: function(range)` | 聚合时间改变时触发 134 | | `onRequestData: function(param,callback)`| 请求数据时触发,触发时间间隔由`intervalTime`指定,`param`请求参数,`callback(res)`结果回调函数。无论请求是否成功,必须在`onRequestData`里调用`callback`,否则会中断数据请求。 135 | 136 | ### 数据请求param格式 137 | 138 | ```json 139 | { 140 | "symbol": "BTC", // 交易品种 141 | "range": 900000, // range类型,毫秒 142 | "limit": 1000, 143 | "since": "1512205140000" // 时间 144 | } 145 | ``` 146 | 147 | ### 回调函数res格式 148 | 149 | > 数据请求成功 150 | 151 | 当success为true,请求成功。 152 | 153 | ```json 154 | { 155 | "success": true, 156 | "data": { 157 | "lines": [ 158 | [ 159 | 1.50790476E12, 160 | 99.30597249871, 161 | 99.30597249871, 162 | 99.30597249871, 163 | 99.30597249871, 164 | 66.9905449283 165 | ] 166 | ], 167 | "depths": { 168 | "asks": [ 169 | [ 170 | 500654.27, 171 | 0.5 172 | ] 173 | ], 174 | "bids": [ 175 | [ 176 | 5798.79, 177 | 0.013 178 | ] 179 | ] 180 | } 181 | } 182 | } 183 | ``` 184 | 185 | > 数据请求失败 186 | 187 | 当res为空,或者success为false,请求失败。 188 | 189 | ```json 190 | { 191 | "success": false, 192 | "data": null, // success为false,则忽略data 193 | } 194 | ``` 195 | 196 | 197 | * res参数说明: 198 | 199 | * `lines`: K线图, 依次是: 时间(ms), 开盘价, 最高价, 最低价, 收盘价, 成交量 200 | * `depths`深度图数据,`asks`: 一定比例的卖单列表, `bids`:一定比例的买单列表, 其中每项的值依次是 : 成交价, 成交量 -------------------------------------------------------------------------------- /demo_dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | react kline Demo 4 | 5 | 6 | 7 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /example/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | react kline Demo 4 | 5 | 6 | 7 | 8 |
9 | 10 | -------------------------------------------------------------------------------- /npm_dist/img/clear_333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/clear_333.png -------------------------------------------------------------------------------- /npm_dist/img/clear_ccc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/clear_ccc.png -------------------------------------------------------------------------------- /npm_dist/img/dropdown_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/dropdown_b.png -------------------------------------------------------------------------------- /npm_dist/img/dropdown_w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/dropdown_w.png -------------------------------------------------------------------------------- /npm_dist/img/dropup_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/dropup_b.png -------------------------------------------------------------------------------- /npm_dist/img/dropup_w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/dropup_w.png -------------------------------------------------------------------------------- /npm_dist/img/size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/size.png -------------------------------------------------------------------------------- /npm_dist/img/size_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/size_d.png -------------------------------------------------------------------------------- /npm_dist/img/size_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/size_l.png -------------------------------------------------------------------------------- /npm_dist/img/tool_d_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/tool_d_normal.png -------------------------------------------------------------------------------- /npm_dist/img/tool_d_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/tool_d_push.png -------------------------------------------------------------------------------- /npm_dist/img/tool_l_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/tool_l_normal.png -------------------------------------------------------------------------------- /npm_dist/img/tool_l_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/npm_dist/img/tool_l_push.png -------------------------------------------------------------------------------- /npm_dist/js/chart.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.Chart = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _chart_manager = require('./chart_manager'); 11 | 12 | var _control = require('./control'); 13 | 14 | var _kline = require('./kline'); 15 | 16 | var _kline2 = _interopRequireDefault(_kline); 17 | 18 | var _templates = require('./templates'); 19 | 20 | var _jquery = require('jquery'); 21 | 22 | var _jquery2 = _interopRequireDefault(_jquery); 23 | 24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 25 | 26 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 27 | 28 | var Chart = exports.Chart = function () { 29 | function Chart() { 30 | _classCallCheck(this, Chart); 31 | 32 | this._data = null; 33 | this._charStyle = "CandleStick"; 34 | this._depthData = { 35 | array: null, 36 | asks_count: 0, 37 | bids_count: 0, 38 | asks_si: 0, 39 | asks_ei: 0, 40 | bids_si: 0, 41 | bids_ei: 0 42 | }; 43 | this.strIsLine = false; 44 | this._range = _kline2.default.instance.range; 45 | this._symbol = _kline2.default.instance.symbol; 46 | } 47 | 48 | _createClass(Chart, [{ 49 | key: 'setTitle', 50 | value: function setTitle() { 51 | var lang = _chart_manager.ChartManager.instance.getLanguage(); 52 | var title = _kline2.default.instance.symbolName; 53 | title += ' '; 54 | title += this.strIsLine ? Chart.strPeriod[lang]['line'] : Chart.strPeriod[lang][this._range]; 55 | title += (this._contract_unit + '/' + this._money_type).toUpperCase(); 56 | _chart_manager.ChartManager.instance.setTitle('frame0.k0', title); 57 | } 58 | }, { 59 | key: 'setSymbol', 60 | value: function setSymbol(symbol) { 61 | this._symbol = symbol; 62 | this.updateDataAndDisplay(); 63 | } 64 | }, { 65 | key: 'updateDataAndDisplay', 66 | value: function updateDataAndDisplay() { 67 | _kline2.default.instance.symbol = this._symbol; 68 | _kline2.default.instance.range = this._range; 69 | _chart_manager.ChartManager.instance.setCurrentDataSource('frame0.k0', this._symbol + '.' + this._range); 70 | _chart_manager.ChartManager.instance.setNormalMode(); 71 | var f = _kline2.default.instance.chartMgr.getDataSource("frame0.k0").getLastDate(); 72 | if (f === -1) { 73 | _kline2.default.instance.requestParam = _control.Control.setHttpRequestParam(_kline2.default.instance.symbol, _kline2.default.instance.range, _kline2.default.instance.limit, null); 74 | _control.Control.requestData(true); 75 | } else { 76 | _kline2.default.instance.requestParam = _control.Control.setHttpRequestParam(_kline2.default.instance.symbol, _kline2.default.instance.range, null, f.toString()); 77 | _control.Control.requestData(); 78 | } 79 | _chart_manager.ChartManager.instance.redraw('All', false); 80 | } 81 | }, { 82 | key: 'setCurrentContractUnit', 83 | value: function setCurrentContractUnit(contractUnit) { 84 | this._contract_unit = contractUnit; 85 | this.updateDataAndDisplay(); 86 | } 87 | }, { 88 | key: 'setCurrentMoneyType', 89 | value: function setCurrentMoneyType(moneyType) { 90 | this._money_type = moneyType; 91 | this.updateDataAndDisplay(); 92 | } 93 | }, { 94 | key: 'setCurrentPeriod', 95 | value: function setCurrentPeriod(period) { 96 | this._range = _kline2.default.instance.periodMap[period]; 97 | if (_kline2.default.instance.type === "stomp" && _kline2.default.instance.stompClient.ws.readyState === 1) { 98 | _kline2.default.instance.subscribed.unsubscribe(); 99 | _kline2.default.instance.subscribed = _kline2.default.instance.stompClient.subscribe(_kline2.default.instance.subscribePath + '/' + _kline2.default.instance.symbol + '/' + this._range, _control.Control.subscribeCallback); 100 | } 101 | this.updateDataAndDisplay(); 102 | _kline2.default.instance.onRangeChangeFunc(this._range); 103 | } 104 | }, { 105 | key: 'updateDataSource', 106 | value: function updateDataSource(data) { 107 | this._data = data; 108 | _chart_manager.ChartManager.instance.updateData("frame0.k0", this._data); 109 | } 110 | }, { 111 | key: 'updateDepth', 112 | value: function updateDepth(array) { 113 | if (array == null) { 114 | this._depthData.array = []; 115 | _chart_manager.ChartManager.instance.redraw('All', false); 116 | return; 117 | } 118 | if (!array.asks || !array.bids || array.asks === '' || array.bids === '') return; 119 | var _data = this._depthData; 120 | _data.array = []; 121 | for (var i = 0; i < array.asks.length; i++) { 122 | var data = {}; 123 | data.rate = array.asks[i][0]; 124 | data.amount = array.asks[i][1]; 125 | _data.array.push(data); 126 | } 127 | for (var _i = 0; _i < array.bids.length; _i++) { 128 | var _data2 = {}; 129 | _data2.rate = array.bids[_i][0]; 130 | _data2.amount = array.bids[_i][1]; 131 | _data.array.push(_data2); 132 | } 133 | _data.asks_count = array.asks.length; 134 | _data.bids_count = array.bids.length; 135 | _data.asks_si = _data.asks_count - 1; 136 | _data.asks_ei = 0; 137 | _data.bids_si = _data.asks_count - 1; 138 | _data.bids_ei = _data.asks_count + _data.bids_count - 2; 139 | for (var _i2 = _data.asks_si; _i2 >= _data.asks_ei; _i2--) { 140 | if (_i2 === _data.asks_si && _data.array[_i2] !== undefined) { 141 | _data.array[_i2].amounts = _data.array[_i2].amount; 142 | } else if (_data.array[_i2 + 1] !== undefined) { 143 | _data.array[_i2].amounts = _data.array[_i2 + 1].amounts + _data.array[_i2].amount; 144 | } 145 | } 146 | for (var _i3 = _data.bids_si; _i3 <= _data.bids_ei; _i3++) { 147 | if (_i3 === _data.bids_si && _data.array[_i3] !== undefined) { 148 | _data.array[_i3].amounts = _data.array[_i3].amount; 149 | } else if (_data.array[_i3 - 1] !== undefined) { 150 | _data.array[_i3].amounts = _data.array[_i3 - 1].amounts + _data.array[_i3].amount; 151 | } 152 | } 153 | _chart_manager.ChartManager.instance.redraw('All', false); 154 | } 155 | }, { 156 | key: 'setMainIndicator', 157 | value: function setMainIndicator(indicName) { 158 | this._mainIndicator = indicName; 159 | if (indicName === 'NONE') { 160 | _chart_manager.ChartManager.instance.removeMainIndicator('frame0.k0'); 161 | } else { 162 | _chart_manager.ChartManager.instance.setMainIndicator('frame0.k0', indicName); 163 | } 164 | _chart_manager.ChartManager.instance.redraw('All', true); 165 | } 166 | }, { 167 | key: 'setIndicator', 168 | value: function setIndicator(index, indicName) { 169 | if (indicName === 'NONE') { 170 | /* 171 | let index = 2; 172 | if (Template.displayVolume === false) 173 | index = 1; 174 | */ 175 | var _index = 1; 176 | var areaName = _chart_manager.ChartManager.instance.getIndicatorAreaName('frame0.k0', _index); 177 | if (areaName !== '') _chart_manager.ChartManager.instance.removeIndicator(areaName); 178 | } else { 179 | /* 180 | let index = 2; 181 | if (Template.displayVolume === false) 182 | index = 1; 183 | */ 184 | var _index2 = 1; 185 | var _areaName = _chart_manager.ChartManager.instance.getIndicatorAreaName('frame0.k0', _index2); 186 | if (_areaName === '') { 187 | _templates.Template.createIndicatorChartComps('frame0.k0', indicName); 188 | } else { 189 | _chart_manager.ChartManager.instance.setIndicator(_areaName, indicName); 190 | } 191 | } 192 | _chart_manager.ChartManager.instance.redraw('All', true); 193 | } 194 | }, { 195 | key: 'addIndicator', 196 | value: function addIndicator(indicName) { 197 | _chart_manager.ChartManager.instance.addIndicator(indicName); 198 | _chart_manager.ChartManager.instance.redraw('All', true); 199 | } 200 | }, { 201 | key: 'removeIndicator', 202 | value: function removeIndicator(indicName) { 203 | var areaName = _chart_manager.ChartManager.instance.getIndicatorAreaName(2); 204 | _chart_manager.ChartManager.instance.removeIndicator(areaName); 205 | _chart_manager.ChartManager.instance.redraw('All', true); 206 | } 207 | }]); 208 | 209 | return Chart; 210 | }(); 211 | 212 | Chart.strPeriod = { 213 | 'zh-cn': { 214 | 'line': '(分时)', 215 | '1min': '(1分钟)', 216 | '5min': '(5分钟)', 217 | '15min': '(15分钟)', 218 | '30min': '(30分钟)', 219 | '1hour': '(1小时)', 220 | '1day': '(日线)', 221 | '1week': '(周线)', 222 | '3min': '(3分钟)', 223 | '2hour': '(2小时)', 224 | '4hour': '(4小时)', 225 | '6hour': '(6小时)', 226 | '12hour': '(12小时)', 227 | '3day': '(3天)' 228 | }, 229 | 'en-us': { 230 | 'line': '(Line)', 231 | '1min': '(1m)', 232 | '5min': '(5m)', 233 | '15min': '(15m)', 234 | '30min': '(30m)', 235 | '1hour': '(1h)', 236 | '1day': '(1d)', 237 | '1week': '(1w)', 238 | '3min': '(3m)', 239 | '2hour': '(2h)', 240 | '4hour': '(4h)', 241 | '6hour': '(6h)', 242 | '12hour': '(12h)', 243 | '3day': '(3d)' 244 | }, 245 | 'zh-tw': { 246 | 'line': '(分時)', 247 | '1min': '(1分鐘)', 248 | '5min': '(5分鐘)', 249 | '15min': '(15分鐘)', 250 | '30min': '(30分鐘)', 251 | '1hour': '(1小時)', 252 | '1day': '(日線)', 253 | '1week': '(周線)', 254 | '3min': '(3分鐘)', 255 | '2hour': '(2小時)', 256 | '4hour': '(4小時)', 257 | '6hour': '(6小時)', 258 | '12hour': '(12小時)', 259 | '3day': '(3天)' 260 | } 261 | }; -------------------------------------------------------------------------------- /npm_dist/js/chart_settings.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.ChartSettings = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _chart_manager = require('./chart_manager'); 11 | 12 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 13 | 14 | var ChartSettings = exports.ChartSettings = function () { 15 | function ChartSettings() { 16 | _classCallCheck(this, ChartSettings); 17 | } 18 | 19 | _createClass(ChartSettings, null, [{ 20 | key: 'checkVersion', 21 | value: function checkVersion() { 22 | if (ChartSettings._data.ver < 2) { 23 | ChartSettings._data.ver = 2; 24 | var charts = ChartSettings._data.charts; 25 | charts.period_weight = {}; 26 | charts.period_weight['line'] = 8; 27 | charts.period_weight['1min'] = 7; 28 | charts.period_weight['5min'] = 6; 29 | charts.period_weight['15min'] = 5; 30 | charts.period_weight['30min'] = 4; 31 | charts.period_weight['1hour'] = 3; 32 | charts.period_weight['1day'] = 2; 33 | charts.period_weight['1week'] = 1; 34 | charts.period_weight['3min'] = 0; 35 | charts.period_weight['2hour'] = 0; 36 | charts.period_weight['4hour'] = 0; 37 | charts.period_weight['6hour'] = 0; 38 | charts.period_weight['12hour'] = 0; 39 | charts.period_weight['3day'] = 0; 40 | } 41 | if (ChartSettings._data.ver < 3) { 42 | ChartSettings._data.ver = 3; 43 | var _charts = ChartSettings._data.charts; 44 | _charts.areaHeight = []; 45 | } 46 | } 47 | }, { 48 | key: 'get', 49 | value: function get() { 50 | if (ChartSettings._data === undefined) { 51 | ChartSettings.init(); 52 | ChartSettings.load(); 53 | ChartSettings.checkVersion(); 54 | } 55 | return ChartSettings._data; 56 | } 57 | }, { 58 | key: 'init', 59 | value: function init() { 60 | var _indic_param = {}; 61 | var _name = ['MA', 'EMA', 'VOLUME', 'MACD', 'KDJ', 'StochRSI', 'RSI', 'DMI', 'OBV', 'BOLL', 'DMA', 'TRIX', 'BRAR', 'VR', 'EMV', 'WR', 'ROC', 'MTM', 'PSY']; 62 | for (var i = 0; i < _name.length; i++) { 63 | var _value = _chart_manager.ChartManager.instance.createIndicatorAndRange('', _name[i], true); 64 | if (_value === null) continue; 65 | _indic_param[_name[i]] = []; 66 | var param = _value.indic.getParameters(); 67 | for (var j = 0; j < param.length; j++) { 68 | _indic_param[_name[i]].push(param[j]); 69 | } 70 | } 71 | var _chart_style = 'CandleStick'; 72 | var _m_indic = 'MA'; 73 | var _indic = ['VOLUME', 'VOLUME']; 74 | var _range = '15m'; 75 | var _frame = {}; 76 | _frame.chartStyle = _chart_style; 77 | _frame.mIndic = _m_indic; 78 | _frame.indics = _indic; 79 | _frame.indicsStatus = 'open'; 80 | _frame.period = _range; 81 | _frame.depthStatus = 'close'; 82 | ChartSettings._data = { 83 | ver: 1, 84 | charts: _frame, 85 | indics: _indic_param, 86 | theme: "Dark" 87 | }; 88 | ChartSettings.checkVersion(); 89 | } 90 | }, { 91 | key: 'load', 92 | value: function load() { 93 | if (document.cookie.length <= 0) return; 94 | var start = document.cookie.indexOf("chartSettings="); 95 | if (start < 0) return; 96 | start += "chartSettings=".length; 97 | var end = document.cookie.indexOf(";", start); 98 | if (end < 0) end = document.cookie.length; 99 | var json = unescape(document.cookie.substring(start, end)); 100 | ChartSettings._data = JSON.parse(json); 101 | } 102 | }, { 103 | key: 'save', 104 | value: function save() { 105 | var exdate = new Date(); 106 | exdate.setDate(exdate.getDate() + 2); 107 | document.cookie = "chartSettings=" + escape(JSON.stringify(ChartSettings._data)) + ";expires=" + exdate.toGMTString(); 108 | } 109 | }]); 110 | 111 | return ChartSettings; 112 | }(); -------------------------------------------------------------------------------- /npm_dist/js/cname.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10 | 11 | var CName = exports.CName = function () { 12 | function CName(name) { 13 | _classCallCheck(this, CName); 14 | 15 | this._names = []; 16 | this._comps = []; 17 | if (name instanceof CName) { 18 | this._names = name._names; 19 | this._comps = name._comps; 20 | } else { 21 | var comps = name.split("."); 22 | var dotNum = comps.length - 1; 23 | if (dotNum > 0) { 24 | this._comps = comps; 25 | this._names.push(comps[0]); 26 | for (var i = 1; i <= dotNum; i++) { 27 | this._names.push(this._names[i - 1] + "." + comps[i]); 28 | } 29 | } else { 30 | this._comps.push(name); 31 | this._names.push(name); 32 | } 33 | } 34 | } 35 | 36 | _createClass(CName, [{ 37 | key: "getCompAt", 38 | value: function getCompAt(index) { 39 | if (index >= 0 && index < this._comps.length) return this._comps[index]; 40 | return ""; 41 | } 42 | }, { 43 | key: "getName", 44 | value: function getName(index) { 45 | if (index < 0) { 46 | if (this._names.length > 0) return this._names[this._names.length - 1]; 47 | } else if (index < this._names.length) { 48 | return this._names[index]; 49 | } 50 | return ""; 51 | } 52 | }]); 53 | 54 | return CName; 55 | }(); -------------------------------------------------------------------------------- /npm_dist/js/cpoint.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.CPoint = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _chart_manager = require('./chart_manager'); 11 | 12 | var _named_object = require('./named_object'); 13 | 14 | var _data_sources = require('./data_sources'); 15 | 16 | var data_sources = _interopRequireWildcard(_data_sources); 17 | 18 | var _util = require('./util'); 19 | 20 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 21 | 22 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 23 | 24 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 25 | 26 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 27 | 28 | var CPoint = exports.CPoint = function (_NamedObject) { 29 | _inherits(CPoint, _NamedObject); 30 | 31 | function CPoint(name) { 32 | _classCallCheck(this, CPoint); 33 | 34 | var _this = _possibleConstructorReturn(this, (CPoint.__proto__ || Object.getPrototypeOf(CPoint)).call(this, name)); 35 | 36 | _this.pos = { index: -1, value: -1 }; 37 | 38 | _this.state = CPoint.state.Hide; 39 | return _this; 40 | } 41 | 42 | _createClass(CPoint, [{ 43 | key: 'getChartObjects', 44 | value: function getChartObjects() { 45 | var ppMgr = _chart_manager.ChartManager.instance; 46 | var ppCDS = ppMgr.getDataSource("frame0.k0"); 47 | if (ppCDS === null || !_util.Util.isInstance(ppCDS, data_sources.MainDataSource)) return null; 48 | var ppTimeline = ppMgr.getTimeline("frame0.k0"); 49 | if (ppTimeline === null) return null; 50 | var ppRange = ppMgr.getRange("frame0.k0.main"); 51 | if (ppRange === null) return null; 52 | return { pMgr: ppMgr, pCDS: ppCDS, pTimeline: ppTimeline, pRange: ppRange }; 53 | } 54 | }, { 55 | key: 'setPosXY', 56 | value: function setPosXY(x, y) { 57 | var pObj = this.getChartObjects(); 58 | var i = pObj.pTimeline.toIndex(x); 59 | var v = pObj.pRange.toValue(y); 60 | var result = this.snapValue(i, v); 61 | if (result !== null) v = result; 62 | this.setPosIV(i, v); 63 | } 64 | }, { 65 | key: 'setPosXYNoSnap', 66 | value: function setPosXYNoSnap(x, y) { 67 | var pObj = this.getChartObjects(); 68 | var i = pObj.pTimeline.toIndex(x); 69 | var v = pObj.pRange.toValue(y); 70 | this.setPosIV(i, v); 71 | } 72 | }, { 73 | key: 'setPosIV', 74 | value: function setPosIV(i, v) { 75 | this.pos = { index: i, value: v }; 76 | } 77 | }, { 78 | key: 'getPosXY', 79 | value: function getPosXY() { 80 | var pObj = this.getChartObjects(); 81 | var _x = pObj.pTimeline.toItemCenter(this.pos.index); 82 | var _y = pObj.pRange.toY(this.pos.value); 83 | return { x: _x, y: _y }; 84 | } 85 | }, { 86 | key: 'getPosIV', 87 | value: function getPosIV() { 88 | return { i: this.pos.index, v: this.pos.value }; 89 | } 90 | }, { 91 | key: 'setState', 92 | value: function setState(s) { 93 | this.state = s; 94 | } 95 | }, { 96 | key: 'getState', 97 | value: function getState() { 98 | return this.state; 99 | } 100 | }, { 101 | key: 'isSelected', 102 | value: function isSelected(x, y) { 103 | var xy = this.getPosXY(); 104 | if (x < xy.x - 4 || x > xy.x + 4 || y < xy.y - 4 || y > xy.y + 4) return false; 105 | this.setState(CPoint.state.Highlight); 106 | return true; 107 | } 108 | }, { 109 | key: 'snapValue', 110 | value: function snapValue(i, v) { 111 | var pObj = this.getChartObjects(); 112 | var result = null; 113 | var first = Math.floor(pObj.pTimeline.getFirstIndex()); 114 | var last = Math.floor(pObj.pTimeline.getLastIndex()); 115 | if (i < first || i > last) return result; 116 | var y = pObj.pRange.toY(v); 117 | var pData = pObj.pCDS.getDataAt(i); 118 | if (pData === null || pData === undefined) return result; 119 | var pDataPre = null; 120 | if (i > 0) pDataPre = pObj.pCDS.getDataAt(i - 1);else pDataPre = pObj.pCDS.getDataAt(i); 121 | var candleStickStyle = pObj.pMgr.getChartStyle(pObj.pCDS.getFrameName()); 122 | var open = pObj.pRange.toY(pData.open); 123 | var high = pObj.pRange.toY(pData.high); 124 | var low = pObj.pRange.toY(pData.low); 125 | var close = pObj.pRange.toY(pData.close); 126 | if (candleStickStyle === "CandleStickHLC") { 127 | open = pObj.pRange.toY(pDataPre.close); 128 | } 129 | var dif_open = Math.abs(open - y); 130 | var dif_high = Math.abs(high - y); 131 | var dif_low = Math.abs(low - y); 132 | var dif_close = Math.abs(close - y); 133 | if (dif_open <= dif_high && dif_open <= dif_low && dif_open <= dif_close) { 134 | if (dif_open < 6) result = pData.open; 135 | } 136 | if (dif_high <= dif_open && dif_high <= dif_low && dif_high <= dif_close) { 137 | if (dif_high < 6) result = pData.high; 138 | } 139 | if (dif_low <= dif_open && dif_low <= dif_high && dif_low <= dif_close) { 140 | if (dif_low < 6) result = pData.low; 141 | } 142 | if (dif_close <= dif_open && dif_close <= dif_high && dif_close <= dif_low) { 143 | if (dif_close < 6) result = pData.close; 144 | } 145 | return result; 146 | } 147 | }]); 148 | 149 | return CPoint; 150 | }(_named_object.NamedObject); 151 | 152 | CPoint.state = { 153 | Hide: 0, 154 | Show: 1, 155 | Highlight: 2 156 | }; -------------------------------------------------------------------------------- /npm_dist/js/ctool_manager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.CToolManager = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _named_object = require('./named_object'); 11 | 12 | var _cpoint = require('./cpoint'); 13 | 14 | var _ctools = require('./ctools'); 15 | 16 | var ctools = _interopRequireWildcard(_ctools); 17 | 18 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 19 | 20 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 21 | 22 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 23 | 24 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 25 | 26 | var CToolManager = exports.CToolManager = function (_NamedObject) { 27 | _inherits(CToolManager, _NamedObject); 28 | 29 | function CToolManager(name) { 30 | _classCallCheck(this, CToolManager); 31 | 32 | var _this = _possibleConstructorReturn(this, (CToolManager.__proto__ || Object.getPrototypeOf(CToolManager)).call(this, name)); 33 | 34 | _this.selectedObject = -1; 35 | _this.toolObjects = []; 36 | return _this; 37 | } 38 | 39 | _createClass(CToolManager, [{ 40 | key: 'getToolObjectCount', 41 | value: function getToolObjectCount() { 42 | return this.toolObjects.length; 43 | } 44 | }, { 45 | key: 'addToolObject', 46 | value: function addToolObject(o) { 47 | this.toolObjects.push(o); 48 | } 49 | }, { 50 | key: 'getToolObject', 51 | value: function getToolObject(i) { 52 | if (i < this.toolObjects.length && i >= 0) { 53 | return this.toolObjects[i]; 54 | } 55 | return null; 56 | } 57 | }, { 58 | key: 'getCurrentObject', 59 | value: function getCurrentObject() { 60 | return this.getToolObject(this.getToolObjectCount() - 1); 61 | } 62 | }, { 63 | key: 'getSelectedObject', 64 | value: function getSelectedObject() { 65 | return this.getToolObject(this.selectedObject); 66 | } 67 | }, { 68 | key: 'delCurrentObject', 69 | value: function delCurrentObject() { 70 | this.toolObjects.splice(this.getToolObjectCount() - 1, 1); 71 | } 72 | }, { 73 | key: 'delSelectedObject', 74 | value: function delSelectedObject() { 75 | this.toolObjects.splice(this.selectedObject, 1); 76 | this.selectedObject = -1; 77 | } 78 | }, { 79 | key: 'acceptMouseMoveEvent', 80 | value: function acceptMouseMoveEvent(x, y) { 81 | if (this.selectedObject === -1) { 82 | var curr = this.toolObjects[this.getToolObjectCount() - 1]; 83 | if (curr !== null && curr !== undefined && curr.getState() !== ctools.CToolObject.state.AfterDraw) return curr.acceptMouseMoveEvent(x, y); 84 | } else { 85 | var sel = this.toolObjects[this.selectedObject]; 86 | if (sel.getState() === ctools.CToolObject.state.Draw) { 87 | return sel.acceptMouseMoveEvent(x, y); 88 | } 89 | sel.unselect(); 90 | this.selectedObject = -1; 91 | } 92 | for (var index in this.toolObjects) { 93 | if (this.toolObjects[index].isSelected(x, y)) { 94 | this.selectedObject = index; 95 | return false; 96 | } 97 | } 98 | return false; 99 | } 100 | }, { 101 | key: 'acceptMouseDownEvent', 102 | value: function acceptMouseDownEvent(x, y) { 103 | this.mouseDownMove = false; 104 | if (this.selectedObject === -1) { 105 | var curr = this.toolObjects[this.getToolObjectCount() - 1]; 106 | if (curr !== null && curr !== undefined && curr.getState() !== ctools.CToolObject.state.AfterDraw) return curr.acceptMouseDownEvent(x, y); 107 | } else { 108 | var sel = this.toolObjects[this.selectedObject]; 109 | if (sel.getState() !== ctools.CToolObject.state.BeforeDraw) return sel.acceptMouseDownEvent(x, y); 110 | } 111 | return false; 112 | } 113 | }, { 114 | key: 'acceptMouseDownMoveEvent', 115 | value: function acceptMouseDownMoveEvent(x, y) { 116 | this.mouseDownMove = true; 117 | if (this.selectedObject === -1) { 118 | var curr = this.toolObjects[this.getToolObjectCount() - 1]; 119 | if (curr !== null && curr !== undefined && curr.getState() === ctools.CToolObject.state.Draw) return curr.acceptMouseDownMoveEvent(x, y); 120 | return false; 121 | } else { 122 | var sel = this.toolObjects[this.selectedObject]; 123 | if (sel.getState() !== ctools.CToolObject.state.BeforeDraw) { 124 | if (sel.acceptMouseDownMoveEvent(x, y) === true) { 125 | var point = this.toolObjects[this.selectedObject].points; 126 | for (var i = 0; i < point.length; i++) { 127 | if (point[i].state === _cpoint.CPoint.state.Highlight || point[i].state === _cpoint.CPoint.state.Show) { 128 | return true; 129 | } 130 | } 131 | } 132 | return true; 133 | } 134 | } 135 | } 136 | }, { 137 | key: 'acceptMouseUpEvent', 138 | value: function acceptMouseUpEvent(x, y) { 139 | if (this.mouseDownMove === true) { 140 | if (this.selectedObject === -1) { 141 | var _curr = this.toolObjects[this.getToolObjectCount() - 1]; 142 | if (_curr !== null && _curr !== undefined && _curr.getState() === ctools.CToolObject.state.Draw) return _curr.acceptMouseUpEvent(x, y); 143 | return true; 144 | } else { 145 | var sel = this.toolObjects[this.selectedObject]; 146 | if (sel.getState() !== ctools.CToolObject.state.BeforeDraw) return sel.acceptMouseUpEvent(x, y); 147 | } 148 | } 149 | if (this.selectedObject !== -1) { 150 | return true; 151 | } 152 | var curr = this.toolObjects[this.getToolObjectCount() - 1]; 153 | if (curr !== null && curr !== undefined) { 154 | if (curr.getState() === ctools.CToolObject.state.Draw) return true; 155 | if (!curr.isValidMouseXY(x, y)) { 156 | return false; 157 | } 158 | if (curr.isSelected(x, y)) { 159 | return true; 160 | } 161 | } 162 | return false; 163 | } 164 | }]); 165 | 166 | return CToolManager; 167 | }(_named_object.NamedObject); -------------------------------------------------------------------------------- /npm_dist/js/data_providers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.IndicatorDataProvider = exports.MainDataProvider = exports.DataProvider = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _named_object = require('./named_object'); 11 | 12 | var _chart_manager = require('./chart_manager'); 13 | 14 | var _util = require('./util'); 15 | 16 | var _data_sources = require('./data_sources'); 17 | 18 | var data_sources = _interopRequireWildcard(_data_sources); 19 | 20 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 21 | 22 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 23 | 24 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 25 | 26 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 27 | 28 | var DataProvider = exports.DataProvider = function (_NamedObject) { 29 | _inherits(DataProvider, _NamedObject); 30 | 31 | function DataProvider(name) { 32 | _classCallCheck(this, DataProvider); 33 | 34 | var _this = _possibleConstructorReturn(this, (DataProvider.__proto__ || Object.getPrototypeOf(DataProvider)).call(this, name)); 35 | 36 | _this._minValue = 0; 37 | _this._maxValue = 0; 38 | _this._minValueIndex = -1; 39 | _this._maxValueIndex = -1; 40 | return _this; 41 | } 42 | 43 | _createClass(DataProvider, [{ 44 | key: 'getMinValue', 45 | value: function getMinValue() { 46 | return this._minValue; 47 | } 48 | }, { 49 | key: 'getMaxValue', 50 | value: function getMaxValue() { 51 | return this._maxValue; 52 | } 53 | }, { 54 | key: 'getMinValueIndex', 55 | value: function getMinValueIndex() { 56 | return this._minValueIndex; 57 | } 58 | }, { 59 | key: 'getMaxValueIndex', 60 | value: function getMaxValueIndex() { 61 | return this._maxValueIndex; 62 | } 63 | }, { 64 | key: 'getMinMaxAt', 65 | value: function getMinMaxAt(index, minmax) { 66 | return true; 67 | } 68 | }, { 69 | key: 'calcRange', 70 | value: function calcRange(firstIndexes, lastIndex, minmaxes, indexes) { 71 | var min = Number.MAX_VALUE; 72 | var max = -Number.MAX_VALUE; 73 | var minIndex = -1; 74 | var maxIndex = -1; 75 | var minmax = {}; 76 | var i = lastIndex - 1; 77 | var n = firstIndexes.length - 1; 78 | for (; n >= 0; n--) { 79 | var first = firstIndexes[n]; 80 | if (i < first) { 81 | minmaxes[n] = { "min": min, "max": max }; 82 | } else { 83 | for (; i >= first; i--) { 84 | if (this.getMinMaxAt(i, minmax) === false) { 85 | continue; 86 | } 87 | if (min > minmax.min) { 88 | min = minmax.min; 89 | minIndex = i; 90 | } 91 | if (max < minmax.max) { 92 | max = minmax.max; 93 | maxIndex = i; 94 | } 95 | } 96 | minmaxes[n] = { "min": min, "max": max }; 97 | } 98 | if (indexes !== null && indexes !== undefined) { 99 | indexes[n] = { "minIndex": minIndex, "maxIndex": maxIndex }; 100 | } 101 | } 102 | } 103 | }, { 104 | key: 'updateRange', 105 | value: function updateRange() { 106 | var mgr = _chart_manager.ChartManager.instance; 107 | var timeline = mgr.getTimeline(this.getDataSourceName()); 108 | var firstIndexes = [timeline.getFirstIndex()]; 109 | var minmaxes = [{}]; 110 | var indexes = [{}]; 111 | this.calcRange(firstIndexes, timeline.getLastIndex(), minmaxes, indexes); 112 | this._minValue = minmaxes[0].min; 113 | this._maxValue = minmaxes[0].max; 114 | this._minValueIndex = indexes[0].minIndex; 115 | this._maxValueIndex = indexes[0].maxIndex; 116 | } 117 | }]); 118 | 119 | return DataProvider; 120 | }(_named_object.NamedObject); 121 | 122 | var MainDataProvider = exports.MainDataProvider = function (_DataProvider) { 123 | _inherits(MainDataProvider, _DataProvider); 124 | 125 | function MainDataProvider(name) { 126 | _classCallCheck(this, MainDataProvider); 127 | 128 | var _this2 = _possibleConstructorReturn(this, (MainDataProvider.__proto__ || Object.getPrototypeOf(MainDataProvider)).call(this, name)); 129 | 130 | _this2._candlestickDS = null; 131 | return _this2; 132 | } 133 | 134 | _createClass(MainDataProvider, [{ 135 | key: 'updateData', 136 | value: function updateData() { 137 | var mgr = _chart_manager.ChartManager.instance; 138 | var ds = mgr.getDataSource(this.getDataSourceName()); 139 | if (!_util.Util.isInstance(ds, data_sources.MainDataSource)) { 140 | return; 141 | } 142 | this._candlestickDS = ds; 143 | } 144 | }, { 145 | key: 'getMinMaxAt', 146 | value: function getMinMaxAt(index, minmax) { 147 | var data = this._candlestickDS.getDataAt(index); 148 | minmax.min = data.low; 149 | minmax.max = data.high; 150 | return true; 151 | } 152 | }]); 153 | 154 | return MainDataProvider; 155 | }(DataProvider); 156 | 157 | var IndicatorDataProvider = exports.IndicatorDataProvider = function (_DataProvider2) { 158 | _inherits(IndicatorDataProvider, _DataProvider2); 159 | 160 | function IndicatorDataProvider() { 161 | _classCallCheck(this, IndicatorDataProvider); 162 | 163 | return _possibleConstructorReturn(this, (IndicatorDataProvider.__proto__ || Object.getPrototypeOf(IndicatorDataProvider)).apply(this, arguments)); 164 | } 165 | 166 | _createClass(IndicatorDataProvider, [{ 167 | key: 'getIndicator', 168 | value: function getIndicator() { 169 | return this._indicator; 170 | } 171 | }, { 172 | key: 'setIndicator', 173 | value: function setIndicator(v) { 174 | this._indicator = v; 175 | this.refresh(); 176 | } 177 | }, { 178 | key: 'refresh', 179 | value: function refresh() { 180 | var mgr = _chart_manager.ChartManager.instance; 181 | var ds = mgr.getDataSource(this.getDataSourceName()); 182 | if (ds.getDataCount() < 1) { 183 | return; 184 | } 185 | var indic = this._indicator; 186 | var i = void 0, 187 | last = ds.getDataCount(); 188 | indic.clear(); 189 | indic.reserve(last); 190 | for (i = 0; i < last; i++) { 191 | indic.execute(ds, i); 192 | } 193 | } 194 | }, { 195 | key: 'updateData', 196 | value: function updateData() { 197 | var mgr = _chart_manager.ChartManager.instance; 198 | var ds = mgr.getDataSource(this.getDataSourceName()); 199 | if (ds.getDataCount() < 1) { 200 | return; 201 | } 202 | var indic = this._indicator; 203 | var mode = ds.getUpdateMode(); 204 | switch (mode) { 205 | case data_sources.DataSource.UpdateMode.Refresh: 206 | { 207 | this.refresh(); 208 | break; 209 | } 210 | case data_sources.DataSource.UpdateMode.Append: 211 | { 212 | indic.reserve(ds.getAppendedCount()); 213 | break; 214 | } 215 | case data_sources.DataSource.UpdateMode.Update: 216 | { 217 | var i = void 0, 218 | last = ds.getDataCount(); 219 | var cnt = ds.getUpdatedCount() + ds.getAppendedCount(); 220 | for (i = last - cnt; i < last; i++) { 221 | indic.execute(ds, i); 222 | } 223 | break; 224 | } 225 | } 226 | } 227 | }, { 228 | key: 'getMinMaxAt', 229 | value: function getMinMaxAt(index, minmax) { 230 | minmax.min = Number.MAX_VALUE; 231 | minmax.max = -Number.MAX_VALUE; 232 | var result = void 0, 233 | valid = false; 234 | var i = void 0, 235 | cnt = this._indicator.getOutputCount(); 236 | for (i = 0; i < cnt; i++) { 237 | result = this._indicator.getOutputAt(i).execute(index); 238 | if (isNaN(result) === false) { 239 | valid = true; 240 | if (minmax.min > result) { 241 | minmax.min = result; 242 | } 243 | if (minmax.max < result) { 244 | minmax.max = result; 245 | } 246 | } 247 | } 248 | return valid; 249 | } 250 | }]); 251 | 252 | return IndicatorDataProvider; 253 | }(DataProvider); -------------------------------------------------------------------------------- /npm_dist/js/data_sources.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.MainDataSource = exports.DataSource = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _named_object = require('./named_object'); 11 | 12 | var _ctool_manager = require('./ctool_manager'); 13 | 14 | var _kline = require('./kline'); 15 | 16 | var _kline2 = _interopRequireDefault(_kline); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 19 | 20 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 21 | 22 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 23 | 24 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 25 | 26 | var DataSource = exports.DataSource = function (_NamedObject) { 27 | _inherits(DataSource, _NamedObject); 28 | 29 | function DataSource(name) { 30 | _classCallCheck(this, DataSource); 31 | 32 | return _possibleConstructorReturn(this, (DataSource.__proto__ || Object.getPrototypeOf(DataSource)).call(this, name)); 33 | } 34 | 35 | _createClass(DataSource, [{ 36 | key: 'getUpdateMode', 37 | value: function getUpdateMode() { 38 | return this._updateMode; 39 | } 40 | }, { 41 | key: 'setUpdateMode', 42 | value: function setUpdateMode(mode) { 43 | this._updateMode = mode; 44 | } 45 | }, { 46 | key: 'getCacheSize', 47 | value: function getCacheSize() { 48 | return 0; 49 | } 50 | }, { 51 | key: 'getDataCount', 52 | value: function getDataCount() { 53 | return 0; 54 | } 55 | }, { 56 | key: 'getDataAt', 57 | value: function getDataAt(index) { 58 | return this._dataItems[index]; 59 | } 60 | }]); 61 | 62 | return DataSource; 63 | }(_named_object.NamedObject); 64 | 65 | DataSource.UpdateMode = { 66 | DoNothing: 0, 67 | Refresh: 1, 68 | Update: 2, 69 | Append: 3 70 | }; 71 | 72 | var MainDataSource = exports.MainDataSource = function (_DataSource) { 73 | _inherits(MainDataSource, _DataSource); 74 | 75 | function MainDataSource(name) { 76 | _classCallCheck(this, MainDataSource); 77 | 78 | var _this2 = _possibleConstructorReturn(this, (MainDataSource.__proto__ || Object.getPrototypeOf(MainDataSource)).call(this, name)); 79 | 80 | _this2._erasedCount = 0; 81 | _this2._dataItems = []; 82 | _this2._decimalDigits = 0; 83 | _this2.toolManager = new _ctool_manager.CToolManager(name); 84 | return _this2; 85 | } 86 | 87 | _createClass(MainDataSource, [{ 88 | key: 'getCacheSize', 89 | value: function getCacheSize() { 90 | return this._dataItems.length; 91 | } 92 | }, { 93 | key: 'getDataCount', 94 | value: function getDataCount() { 95 | return this._dataItems.length; 96 | } 97 | }, { 98 | key: 'getUpdatedCount', 99 | value: function getUpdatedCount() { 100 | return this._updatedCount; 101 | } 102 | }, { 103 | key: 'getAppendedCount', 104 | value: function getAppendedCount() { 105 | return this._appendedCount; 106 | } 107 | }, { 108 | key: 'getErasedCount', 109 | value: function getErasedCount() { 110 | return this._erasedCount; 111 | } 112 | }, { 113 | key: 'getDecimalDigits', 114 | value: function getDecimalDigits() { 115 | return this._decimalDigits; 116 | } 117 | }, { 118 | key: 'calcDecimalDigits', 119 | value: function calcDecimalDigits(v) { 120 | var str = "" + v; 121 | var i = str.indexOf('.'); 122 | if (i < 0) { 123 | return 0; 124 | } 125 | return str.length - 1 - i; 126 | } 127 | }, { 128 | key: 'getLastDate', 129 | value: function getLastDate() { 130 | var count = this.getDataCount(); 131 | if (count < 1) { 132 | return -1; 133 | } 134 | return this.getDataAt(count - 1).date; 135 | } 136 | }, { 137 | key: 'getDataAt', 138 | value: function getDataAt(index) { 139 | return this._dataItems[index]; 140 | } 141 | }, { 142 | key: 'update', 143 | value: function update(data) { 144 | this._updatedCount = 0; 145 | this._appendedCount = 0; 146 | this._erasedCount = 0; 147 | var len = this._dataItems.length; 148 | if (len > 0) { 149 | var lastIndex = len - 1; 150 | var lastItem = this._dataItems[lastIndex]; 151 | var _e = void 0, 152 | _i = void 0, 153 | _cnt = data.length; 154 | for (_i = 0; _i < _cnt; _i++) { 155 | _e = data[_i]; 156 | if (_e[0] === lastItem.date) { 157 | if (lastItem.open === _e[1] && lastItem.high === _e[2] && lastItem.low === _e[3] && lastItem.close === _e[4] && lastItem.volume === _e[5]) { 158 | this.setUpdateMode(DataSource.UpdateMode.DoNothing); 159 | } else { 160 | this.setUpdateMode(DataSource.UpdateMode.Update); 161 | this._dataItems[lastIndex] = { 162 | date: _e[0], 163 | open: _e[1], 164 | high: _e[2], 165 | low: _e[3], 166 | close: _e[4], 167 | volume: _e[5] 168 | }; 169 | this._updatedCount++; 170 | } 171 | _i++; 172 | if (_i < _cnt) { 173 | this.setUpdateMode(DataSource.UpdateMode.Append); 174 | for (; _i < _cnt; _i++, this._appendedCount++) { 175 | _e = data[_i]; 176 | this._dataItems.push({ 177 | date: _e[0], 178 | open: _e[1], 179 | high: _e[2], 180 | low: _e[3], 181 | close: _e[4], 182 | volume: _e[5] 183 | }); 184 | } 185 | } 186 | return true; 187 | } 188 | } 189 | if (_cnt < _kline2.default.instance.limit) { 190 | this.setUpdateMode(DataSource.UpdateMode.DoNothing); 191 | return false; 192 | } 193 | } 194 | this.setUpdateMode(DataSource.UpdateMode.Refresh); 195 | this._dataItems = []; 196 | var d = void 0, 197 | n = void 0, 198 | e = void 0, 199 | i = void 0, 200 | cnt = data.length; 201 | for (i = 0; i < cnt; i++) { 202 | e = data[i]; 203 | for (n = 1; n <= 4; n++) { 204 | d = this.calcDecimalDigits(e[n]); 205 | if (this._decimalDigits < d) this._decimalDigits = d; 206 | } 207 | this._dataItems.push({ 208 | date: e[0], 209 | open: e[1], 210 | high: e[2], 211 | low: e[3], 212 | close: e[4], 213 | volume: e[5] 214 | }); 215 | } 216 | return true; 217 | } 218 | }, { 219 | key: 'select', 220 | value: function select(id) { 221 | this.toolManager.selecedObject = id; 222 | } 223 | }, { 224 | key: 'unselect', 225 | value: function unselect() { 226 | this.toolManager.selecedObject = -1; 227 | } 228 | }, { 229 | key: 'addToolObject', 230 | value: function addToolObject(toolObject) { 231 | this.toolManager.addToolObject(toolObject); 232 | } 233 | }, { 234 | key: 'delToolObject', 235 | value: function delToolObject() { 236 | this.toolManager.delCurrentObject(); 237 | } 238 | }, { 239 | key: 'getToolObject', 240 | value: function getToolObject(index) { 241 | return this.toolManager.getToolObject(index); 242 | } 243 | }, { 244 | key: 'getToolObjectCount', 245 | value: function getToolObjectCount() { 246 | return this.toolManager.toolObjects.length; 247 | } 248 | }, { 249 | key: 'getCurrentToolObject', 250 | value: function getCurrentToolObject() { 251 | return this.toolManager.getCurrentObject(); 252 | } 253 | }, { 254 | key: 'getSelectToolObjcet', 255 | value: function getSelectToolObjcet() { 256 | return this.toolManager.getSelectedObject(); 257 | } 258 | }, { 259 | key: 'delSelectToolObject', 260 | value: function delSelectToolObject() { 261 | this.toolManager.delSelectedObject(); 262 | } 263 | }]); 264 | 265 | return MainDataSource; 266 | }(DataSource); -------------------------------------------------------------------------------- /npm_dist/js/mevent.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10 | 11 | var MEvent = exports.MEvent = function () { 12 | function MEvent() { 13 | _classCallCheck(this, MEvent); 14 | 15 | this._handlers = []; 16 | } 17 | 18 | _createClass(MEvent, [{ 19 | key: "addHandler", 20 | value: function addHandler(o, f) { 21 | if (this.indexOf(o, f) < 0) this._handlers.push({ obj: o, func: f }); 22 | } 23 | }, { 24 | key: "removeHandler", 25 | value: function removeHandler(o, f) { 26 | var i = this.indexOf(o, f); 27 | if (i >= 0) this._handlers.splice(i, 1); 28 | } 29 | }, { 30 | key: "raise", 31 | value: function raise(s, g) { 32 | var a = this._handlers; 33 | var e = void 0, 34 | i = void 0, 35 | c = a.length; 36 | for (i = 0; i < c; i++) { 37 | e = a[i]; 38 | e.func(s, g); 39 | } 40 | } 41 | }, { 42 | key: "indexOf", 43 | value: function indexOf(o, f) { 44 | var a = this._handlers; 45 | var e = void 0, 46 | i = void 0, 47 | c = a.length; 48 | for (i = 0; i < c; i++) { 49 | e = a[i]; 50 | if (o === e.obj && f === e.func) return i; 51 | } 52 | return -1; 53 | } 54 | }]); 55 | 56 | return MEvent; 57 | }(); -------------------------------------------------------------------------------- /npm_dist/js/named_object.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.NamedObject = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _cname = require('./cname'); 11 | 12 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 13 | 14 | var NamedObject = exports.NamedObject = function () { 15 | function NamedObject(name) { 16 | _classCallCheck(this, NamedObject); 17 | 18 | this._name = name; 19 | this._nameObj = new _cname.CName(name); 20 | } 21 | 22 | _createClass(NamedObject, [{ 23 | key: 'getFrameName', 24 | value: function getFrameName() { 25 | return this._nameObj.getName(0); 26 | } 27 | }, { 28 | key: 'getDataSourceName', 29 | value: function getDataSourceName() { 30 | return this._nameObj.getName(1); 31 | } 32 | }, { 33 | key: 'getAreaName', 34 | value: function getAreaName() { 35 | return this._nameObj.getName(2); 36 | } 37 | }, { 38 | key: 'getName', 39 | value: function getName() { 40 | return this._nameObj.getName(-1); 41 | } 42 | }, { 43 | key: 'getNameObject', 44 | value: function getNameObject() { 45 | return this._nameObj; 46 | } 47 | }, { 48 | key: 'getRectCrossPt', 49 | value: function getRectCrossPt(rect, startPt, endPt) { 50 | var crossPt = void 0; 51 | var firstPt = { x: -1, y: -1 }; 52 | var secondPt = { x: -1, y: -1 }; 53 | var xdiff = endPt.x - startPt.x; 54 | var ydiff = endPt.y - startPt.y; 55 | if (Math.abs(xdiff) < 2) { 56 | firstPt = { x: startPt.x, y: rect.top }; 57 | secondPt = { x: endPt.x, y: rect.bottom }; 58 | crossPt = [firstPt, secondPt]; 59 | return crossPt; 60 | } 61 | var k = ydiff / xdiff; 62 | secondPt.x = rect.right; 63 | secondPt.y = startPt.y + (rect.right - startPt.x) * k; 64 | firstPt.x = rect.left; 65 | firstPt.y = startPt.y + (rect.left - startPt.x) * k; 66 | crossPt = [firstPt, secondPt]; 67 | return crossPt; 68 | } 69 | }]); 70 | 71 | return NamedObject; 72 | }(); -------------------------------------------------------------------------------- /npm_dist/js/templates.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.TemplateMeasuringHandler = exports.DefaultTemplate = exports.Template = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _chart_manager = require('./chart_manager'); 11 | 12 | var _chart_settings = require('./chart_settings'); 13 | 14 | var _data_sources = require('./data_sources'); 15 | 16 | var data_sources = _interopRequireWildcard(_data_sources); 17 | 18 | var _data_providers = require('./data_providers'); 19 | 20 | var data_providers = _interopRequireWildcard(_data_providers); 21 | 22 | var _areas = require('./areas'); 23 | 24 | var areas = _interopRequireWildcard(_areas); 25 | 26 | var _plotters = require('./plotters'); 27 | 28 | var plotters = _interopRequireWildcard(_plotters); 29 | 30 | var _timeline = require('./timeline'); 31 | 32 | var _cname = require('./cname'); 33 | 34 | var _layouts = require('./layouts'); 35 | 36 | var layouts = _interopRequireWildcard(_layouts); 37 | 38 | var _themes = require('./themes'); 39 | 40 | var themes = _interopRequireWildcard(_themes); 41 | 42 | var _ranges = require('./ranges'); 43 | 44 | var ranges = _interopRequireWildcard(_ranges); 45 | 46 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } 47 | 48 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 49 | 50 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 51 | 52 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 53 | 54 | var Template = exports.Template = function () { 55 | function Template() { 56 | _classCallCheck(this, Template); 57 | } 58 | 59 | _createClass(Template, null, [{ 60 | key: 'createCandlestickDataSource', 61 | value: function createCandlestickDataSource(dsAlias) { 62 | return new data_sources.MainDataSource(dsAlias); 63 | } 64 | }, { 65 | key: 'createDataSource', 66 | value: function createDataSource(dsName, dsAlias, createFunc) { 67 | var mgr = _chart_manager.ChartManager.instance; 68 | if (mgr.getCachedDataSource(dsAlias) === null) mgr.setCachedDataSource(dsAlias, createFunc(dsAlias)); 69 | mgr.setCurrentDataSource(dsName, dsAlias); 70 | mgr.updateData(dsName, null); 71 | } 72 | }, { 73 | key: 'createTableComps', 74 | value: function createTableComps(dsName) { 75 | this.createMainChartComps(dsName); 76 | this.createTimelineComps(dsName); 77 | } 78 | }, { 79 | key: 'createMainChartComps', 80 | value: function createMainChartComps(dsName) { 81 | var mgr = _chart_manager.ChartManager.instance; 82 | var tableLayout = mgr.getArea(dsName + ".charts"); 83 | var areaName = dsName + ".main"; 84 | var rangeAreaName = areaName + "Range"; 85 | var area = new areas.MainArea(areaName); 86 | mgr.setArea(areaName, area); 87 | tableLayout.addArea(area); 88 | var rangeArea = new areas.MainRangeArea(rangeAreaName); 89 | mgr.setArea(rangeAreaName, rangeArea); 90 | tableLayout.addArea(rangeArea); 91 | var dp = new data_providers.MainDataProvider(areaName + ".main"); 92 | mgr.setDataProvider(dp.getName(), dp); 93 | mgr.setMainIndicator(dsName, "MA"); 94 | var range = new ranges.MainRange(areaName); 95 | mgr.setRange(range.getName(), range); 96 | range.setPaddingTop(28); 97 | range.setPaddingBottom(12); 98 | var plotter = new plotters.MainAreaBackgroundPlotter(areaName + ".background"); 99 | mgr.setPlotter(plotter.getName(), plotter); 100 | plotter = new plotters.CGridPlotter(areaName + ".grid"); 101 | mgr.setPlotter(plotter.getName(), plotter); 102 | plotter = new plotters.CandlestickPlotter(areaName + ".main"); 103 | mgr.setPlotter(plotter.getName(), plotter); 104 | plotter = new plotters.MinMaxPlotter(areaName + ".decoration"); 105 | mgr.setPlotter(plotter.getName(), plotter); 106 | plotter = new plotters.MainInfoPlotter(areaName + ".info"); 107 | mgr.setPlotter(plotter.getName(), plotter); 108 | plotter = new plotters.SelectionPlotter(areaName + ".selection"); 109 | mgr.setPlotter(plotter.getName(), plotter); 110 | plotter = new plotters.CDynamicLinePlotter(areaName + ".tool"); 111 | mgr.setPlotter(plotter.getName(), plotter); 112 | plotter = new plotters.RangeAreaBackgroundPlotter(areaName + "Range.background"); 113 | mgr.setPlotter(plotter.getName(), plotter); 114 | plotter = new plotters.COrderGraphPlotter(areaName + "Range.grid"); 115 | mgr.setPlotter(plotter.getName(), plotter); 116 | plotter = new plotters.RangePlotter(areaName + "Range.main"); 117 | mgr.setPlotter(plotter.getName(), plotter); 118 | plotter = new plotters.RangeSelectionPlotter(areaName + "Range.selection"); 119 | mgr.setPlotter(plotter.getName(), plotter); 120 | plotter = new plotters.LastClosePlotter(areaName + "Range.decoration"); 121 | mgr.setPlotter(plotter.getName(), plotter); 122 | } 123 | }, { 124 | key: 'createIndicatorChartComps', 125 | value: function createIndicatorChartComps(dsName, indicName) { 126 | var mgr = _chart_manager.ChartManager.instance; 127 | var tableLayout = mgr.getArea(dsName + ".charts"); 128 | var areaName = dsName + ".indic" + tableLayout.getNextRowId(); 129 | var rangeAreaName = areaName + "Range"; 130 | var area = new areas.IndicatorArea(areaName); 131 | mgr.setArea(areaName, area); 132 | tableLayout.addArea(area); 133 | var rowIndex = tableLayout.getAreaCount() >> 1; 134 | var heights = _chart_settings.ChartSettings.get().charts.areaHeight; 135 | if (heights.length > rowIndex) { 136 | var a = void 0, 137 | i = void 0; 138 | for (i = 0; i < rowIndex; i++) { 139 | a = tableLayout.getAreaAt(i << 1); 140 | a.setTop(0); 141 | a.setBottom(heights[i]); 142 | } 143 | area.setTop(0); 144 | area.setBottom(heights[rowIndex]); 145 | } 146 | var rangeArea = new areas.IndicatorRangeArea(rangeAreaName); 147 | mgr.setArea(rangeAreaName, rangeArea); 148 | tableLayout.addArea(rangeArea); 149 | var dp = new data_providers.IndicatorDataProvider(areaName + ".secondary"); 150 | mgr.setDataProvider(dp.getName(), dp); 151 | if (mgr.setIndicator(areaName, indicName) === false) { 152 | mgr.removeIndicator(areaName); 153 | return; 154 | } 155 | var plotter = new plotters.MainAreaBackgroundPlotter(areaName + ".background"); 156 | mgr.setPlotter(plotter.getName(), plotter); 157 | plotter = new plotters.CGridPlotter(areaName + ".grid"); 158 | mgr.setPlotter(plotter.getName(), plotter); 159 | plotter = new plotters.IndicatorPlotter(areaName + ".secondary"); 160 | mgr.setPlotter(plotter.getName(), plotter); 161 | plotter = new plotters.IndicatorInfoPlotter(areaName + ".info"); 162 | mgr.setPlotter(plotter.getName(), plotter); 163 | plotter = new plotters.SelectionPlotter(areaName + ".selection"); 164 | mgr.setPlotter(plotter.getName(), plotter); 165 | plotter = new plotters.RangeAreaBackgroundPlotter(areaName + "Range.background"); 166 | mgr.setPlotter(plotter.getName(), plotter); 167 | plotter = new plotters.RangePlotter(areaName + "Range.main"); 168 | mgr.setPlotter(plotter.getName(), plotter); 169 | plotter = new plotters.RangeSelectionPlotter(areaName + "Range.selection"); 170 | mgr.setPlotter(plotter.getName(), plotter); 171 | } 172 | }, { 173 | key: 'createTimelineComps', 174 | value: function createTimelineComps(dsName) { 175 | var mgr = _chart_manager.ChartManager.instance; 176 | var plotter = void 0; 177 | var timeline = new _timeline.Timeline(dsName); 178 | mgr.setTimeline(timeline.getName(), timeline); 179 | plotter = new plotters.TimelineAreaBackgroundPlotter(dsName + ".timeline.background"); 180 | mgr.setPlotter(plotter.getName(), plotter); 181 | plotter = new plotters.TimelinePlotter(dsName + ".timeline.main"); 182 | mgr.setPlotter(plotter.getName(), plotter); 183 | plotter = new plotters.TimelineSelectionPlotter(dsName + ".timeline.selection"); 184 | mgr.setPlotter(plotter.getName(), plotter); 185 | } 186 | }, { 187 | key: 'createLiveOrderComps', 188 | value: function createLiveOrderComps(dsName) { 189 | var mgr = _chart_manager.ChartManager.instance; 190 | var plotter = void 0; 191 | plotter = new plotters.BackgroundPlotter(dsName + ".main.background"); 192 | mgr.setPlotter(plotter.getName(), plotter); 193 | plotter = new plotters.CLiveOrderPlotter(dsName + ".main.main"); 194 | mgr.setPlotter(plotter.getName(), plotter); 195 | } 196 | }, { 197 | key: 'createLiveTradeComps', 198 | value: function createLiveTradeComps(dsName) { 199 | var mgr = _chart_manager.ChartManager.instance; 200 | var plotter = void 0; 201 | plotter = new plotters.BackgroundPlotter(dsName + ".main.background"); 202 | mgr.setPlotter(plotter.getName(), plotter); 203 | plotter = new plotters.CLiveTradePlotter(dsName + ".main.main"); 204 | mgr.setPlotter(plotter.getName(), plotter); 205 | } 206 | }]); 207 | 208 | return Template; 209 | }(); 210 | 211 | var DefaultTemplate = exports.DefaultTemplate = function (_Template) { 212 | _inherits(DefaultTemplate, _Template); 213 | 214 | function DefaultTemplate() { 215 | _classCallCheck(this, DefaultTemplate); 216 | 217 | return _possibleConstructorReturn(this, (DefaultTemplate.__proto__ || Object.getPrototypeOf(DefaultTemplate)).apply(this, arguments)); 218 | } 219 | 220 | _createClass(DefaultTemplate, null, [{ 221 | key: 'loadTemplate', 222 | value: function loadTemplate(dsName, dsAlias) { 223 | var mgr = _chart_manager.ChartManager.instance; 224 | var settings = _chart_settings.ChartSettings.get(); 225 | var frameName = new _cname.CName(dsName).getCompAt(0); 226 | mgr.unloadTemplate(frameName); 227 | this.createDataSource(dsName, dsAlias, this.createCandlestickDataSource); 228 | var frame = new layouts.DockableLayout(frameName); 229 | mgr.setFrame(frame.getName(), frame); 230 | mgr.setArea(frame.getName(), frame); 231 | frame.setGridColor(themes.Theme.Color.Grid1); 232 | var area = new areas.TimelineArea(dsName + ".timeline"); 233 | mgr.setArea(area.getName(), area); 234 | frame.addArea(area); 235 | area.setDockStyle(areas.ChartArea.DockStyle.Bottom); 236 | area.Measuring.addHandler(area, TemplateMeasuringHandler.onMeasuring); 237 | var tableLayout = new layouts.TableLayout(dsName + ".charts"); 238 | mgr.setArea(tableLayout.getName(), tableLayout); 239 | tableLayout.setDockStyle(areas.ChartArea.DockStyle.Fill); 240 | frame.addArea(tableLayout); 241 | this.createTableComps(dsName); 242 | mgr.setThemeName(frameName, settings.theme); 243 | return mgr; 244 | } 245 | }]); 246 | 247 | return DefaultTemplate; 248 | }(Template); 249 | 250 | var TemplateMeasuringHandler = exports.TemplateMeasuringHandler = function () { 251 | function TemplateMeasuringHandler() { 252 | _classCallCheck(this, TemplateMeasuringHandler); 253 | } 254 | 255 | _createClass(TemplateMeasuringHandler, null, [{ 256 | key: 'onMeasuring', 257 | value: function onMeasuring(sender, args) { 258 | var width = args.Width; 259 | var height = args.Height; 260 | var areaName = sender.getNameObject().getCompAt(2); 261 | if (areaName === "timeline") { 262 | sender.setMeasuredDimension(width, 22); 263 | } 264 | } 265 | }]); 266 | 267 | return TemplateMeasuringHandler; 268 | }(); -------------------------------------------------------------------------------- /npm_dist/js/themes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.LightTheme = exports.DarkTheme = exports.Theme = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _kline = require("./kline"); 11 | 12 | var _kline2 = _interopRequireDefault(_kline); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15 | 16 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 17 | 18 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 19 | 20 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 21 | 22 | var Theme = exports.Theme = function () { 23 | function Theme() { 24 | _classCallCheck(this, Theme); 25 | 26 | this._colors = []; 27 | this._fonts = []; 28 | } 29 | 30 | _createClass(Theme, [{ 31 | key: "getColor", 32 | value: function getColor(which) { 33 | return this._colors[which]; 34 | } 35 | }, { 36 | key: "getFont", 37 | value: function getFont(which) { 38 | return this._fonts[which]; 39 | } 40 | }]); 41 | 42 | return Theme; 43 | }(); 44 | 45 | Theme.theme_color_id = 0; 46 | Theme.theme_font_id = 0; 47 | Theme.Color = { 48 | Positive: Theme.theme_color_id++, 49 | Negative: Theme.theme_color_id++, 50 | PositiveDark: Theme.theme_color_id++, 51 | NegativeDark: Theme.theme_color_id++, 52 | Unchanged: Theme.theme_color_id++, 53 | Background: Theme.theme_color_id++, 54 | Cursor: Theme.theme_color_id++, 55 | RangeMark: Theme.theme_color_id++, 56 | Indicator0: Theme.theme_color_id++, 57 | Indicator1: Theme.theme_color_id++, 58 | Indicator2: Theme.theme_color_id++, 59 | Indicator3: Theme.theme_color_id++, 60 | Indicator4: Theme.theme_color_id++, 61 | Indicator5: Theme.theme_color_id++, 62 | Grid0: Theme.theme_color_id++, 63 | Grid1: Theme.theme_color_id++, 64 | Grid2: Theme.theme_color_id++, 65 | Grid3: Theme.theme_color_id++, 66 | Grid4: Theme.theme_color_id++, 67 | TextPositive: Theme.theme_color_id++, 68 | TextNegative: Theme.theme_color_id++, 69 | Text0: Theme.theme_color_id++, 70 | Text1: Theme.theme_color_id++, 71 | Text2: Theme.theme_color_id++, 72 | Text3: Theme.theme_color_id++, 73 | Text4: Theme.theme_color_id++, 74 | LineColorNormal: Theme.theme_color_id++, 75 | LineColorSelected: Theme.theme_color_id++, 76 | CircleColorFill: Theme.theme_color_id++, 77 | CircleColorStroke: Theme.theme_color_id++ 78 | }; 79 | Theme.Font = { 80 | Default: Theme.theme_font_id++ 81 | }; 82 | 83 | var DarkTheme = exports.DarkTheme = function (_Theme) { 84 | _inherits(DarkTheme, _Theme); 85 | 86 | function DarkTheme() { 87 | _classCallCheck(this, DarkTheme); 88 | 89 | var _this = _possibleConstructorReturn(this, (DarkTheme.__proto__ || Object.getPrototypeOf(DarkTheme)).call(this)); 90 | 91 | _this._colors = []; 92 | 93 | _this._colors[Theme.Color.Positive] = "#19b34c"; 94 | _this._colors[Theme.Color.Negative] = "#990e0e"; 95 | _this._colors[Theme.Color.PositiveDark] = "#004718"; 96 | _this._colors[Theme.Color.NegativeDark] = "#3b0e08"; 97 | 98 | _this._colors[Theme.Color.Unchanged] = "#fff"; 99 | _this._colors[Theme.Color.Background] = "#161616"; 100 | _this._colors[Theme.Color.Cursor] = "#aaa"; 101 | _this._colors[Theme.Color.RangeMark] = "#f9ee30"; 102 | _this._colors[Theme.Color.Indicator0] = "#ddd"; 103 | _this._colors[Theme.Color.Indicator1] = "#f9ee30"; 104 | _this._colors[Theme.Color.Indicator2] = "#f600ff"; 105 | _this._colors[Theme.Color.Indicator3] = "#6bf"; 106 | _this._colors[Theme.Color.Indicator4] = "#a5cf81"; 107 | _this._colors[Theme.Color.Indicator5] = "#e18b89"; 108 | _this._colors[Theme.Color.Grid0] = "#555"; 109 | _this._colors[Theme.Color.Grid1] = "#555"; 110 | _this._colors[Theme.Color.Grid3] = "#888"; 111 | _this._colors[Theme.Color.Grid4] = "#aaa"; 112 | _this._colors[Theme.Color.TextPositive] = "#1bd357"; 113 | _this._colors[Theme.Color.TextNegative] = "#ff6f5e"; 114 | _this._colors[Theme.Color.Text0] = "#444"; 115 | _this._colors[Theme.Color.Text1] = "#666"; 116 | _this._colors[Theme.Color.Text2] = "#888"; 117 | _this._colors[Theme.Color.Text3] = "#aaa"; 118 | _this._colors[Theme.Color.Text4] = "#ccc"; 119 | _this._colors[Theme.Color.LineColorNormal] = "#a6a6a6"; 120 | _this._colors[Theme.Color.LineColorSelected] = "#ffffff"; 121 | _this._colors[Theme.Color.CircleColorFill] = "#161616"; 122 | _this._colors[Theme.Color.CircleColorStroke] = "#ffffff"; 123 | _this._fonts = []; 124 | _this._fonts[Theme.Font.Default] = "12px Tahoma"; 125 | return _this; 126 | } 127 | 128 | return DarkTheme; 129 | }(Theme); 130 | 131 | var LightTheme = exports.LightTheme = function (_Theme2) { 132 | _inherits(LightTheme, _Theme2); 133 | 134 | function LightTheme() { 135 | _classCallCheck(this, LightTheme); 136 | 137 | var _this2 = _possibleConstructorReturn(this, (LightTheme.__proto__ || Object.getPrototypeOf(LightTheme)).call(this)); 138 | 139 | _this2._colors = []; 140 | 141 | _this2._colors[Theme.Color.Positive] = "#53b37b"; 142 | _this2._colors[Theme.Color.Negative] = "#db5542"; 143 | _this2._colors[Theme.Color.PositiveDark] = "#66d293"; 144 | _this2._colors[Theme.Color.NegativeDark] = "#ffadaa"; 145 | 146 | _this2._colors[Theme.Color.Unchanged] = "#fff"; 147 | _this2._colors[Theme.Color.Background] = "#f6f6f6"; 148 | _this2._colors[Theme.Color.Cursor] = "#aaa"; 149 | _this2._colors[Theme.Color.RangeMark] = "#f27935"; 150 | _this2._colors[Theme.Color.Indicator0] = "#d27972"; 151 | _this2._colors[Theme.Color.Indicator1] = "#ffb400"; 152 | _this2._colors[Theme.Color.Indicator2] = "#e849b9"; 153 | _this2._colors[Theme.Color.Indicator3] = "#1478c8"; 154 | _this2._colors[Theme.Color.Grid0] = "#aaa"; 155 | _this2._colors[Theme.Color.Grid1] = "#aaa"; 156 | _this2._colors[Theme.Color.Grid3] = "#bbb"; 157 | _this2._colors[Theme.Color.Grid4] = "#aaa"; 158 | _this2._colors[Theme.Color.TextPositive] = "#53b37b"; 159 | _this2._colors[Theme.Color.TextNegative] = "#db5542"; 160 | _this2._colors[Theme.Color.Text0] = "#ccc"; 161 | _this2._colors[Theme.Color.Text1] = "#aaa"; 162 | _this2._colors[Theme.Color.Text2] = "#888"; 163 | _this2._colors[Theme.Color.Text3] = "#666"; 164 | _this2._colors[Theme.Color.Text4] = "#444"; 165 | _this2._colors[Theme.Color.LineColorNormal] = "#8c8c8c"; 166 | _this2._colors[Theme.Color.LineColorSelected] = "#393c40"; 167 | _this2._colors[Theme.Color.CircleColorFill] = "#f6f6f6"; 168 | _this2._colors[Theme.Color.CircleColorStroke] = "#393c40"; 169 | _this2._fonts = []; 170 | _this2._fonts[Theme.Font.Default] = "12px Tahoma"; 171 | return _this2; 172 | } 173 | 174 | return LightTheme; 175 | }(Theme); -------------------------------------------------------------------------------- /npm_dist/js/timeline.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.Timeline = undefined; 7 | 8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 9 | 10 | var _named_object = require('./named_object'); 11 | 12 | var _chart_manager = require('./chart_manager'); 13 | 14 | var _data_sources = require('./data_sources'); 15 | 16 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 17 | 18 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 19 | 20 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 21 | 22 | var Timeline = exports.Timeline = function (_NamedObject) { 23 | _inherits(Timeline, _NamedObject); 24 | 25 | function Timeline(name) { 26 | _classCallCheck(this, Timeline); 27 | 28 | var _this = _possibleConstructorReturn(this, (Timeline.__proto__ || Object.getPrototypeOf(Timeline)).call(this, name)); 29 | 30 | _this._updated = false; 31 | _this._innerLeft = 0; 32 | _this._innerWidth = 0; 33 | _this._firstColumnLeft = 0; 34 | _this._scale = 3; 35 | _this._lastScale = -1; 36 | _this._maxItemCount = 0; 37 | _this._maxIndex = 0; 38 | _this._firstIndex = -1; 39 | _this._selectedIndex = -1; 40 | _this._savedFirstIndex = -1; 41 | return _this; 42 | } 43 | 44 | _createClass(Timeline, [{ 45 | key: 'isLatestShown', 46 | value: function isLatestShown() { 47 | return this.getLastIndex() === this._maxIndex; 48 | } 49 | }, { 50 | key: 'isUpdated', 51 | value: function isUpdated() { 52 | return this._updated; 53 | } 54 | }, { 55 | key: 'setUpdated', 56 | value: function setUpdated(v) { 57 | this._updated = v; 58 | } 59 | }, { 60 | key: 'getItemWidth', 61 | value: function getItemWidth() { 62 | return Timeline.itemWidth[this._scale]; 63 | } 64 | }, { 65 | key: 'getSpaceWidth', 66 | value: function getSpaceWidth() { 67 | return Timeline.spaceWidth[this._scale]; 68 | } 69 | }, { 70 | key: 'getColumnWidth', 71 | value: function getColumnWidth() { 72 | return this.getSpaceWidth() + this.getItemWidth(); 73 | } 74 | }, { 75 | key: 'getInnerWidth', 76 | value: function getInnerWidth() { 77 | return this._innerWidth; 78 | } 79 | }, { 80 | key: 'getItemLeftOffset', 81 | value: function getItemLeftOffset() { 82 | return this.getSpaceWidth(); 83 | } 84 | }, { 85 | key: 'getItemCenterOffset', 86 | value: function getItemCenterOffset() { 87 | return this.getSpaceWidth() + (this.getItemWidth() >> 1); 88 | } 89 | }, { 90 | key: 'getFirstColumnLeft', 91 | value: function getFirstColumnLeft() { 92 | return this._firstColumnLeft; 93 | } 94 | }, { 95 | key: 'getMaxItemCount', 96 | value: function getMaxItemCount() { 97 | return this._maxItemCount; 98 | } 99 | }, { 100 | key: 'getFirstIndex', 101 | value: function getFirstIndex() { 102 | return this._firstIndex; 103 | } 104 | }, { 105 | key: 'getLastIndex', 106 | value: function getLastIndex() { 107 | return Math.min(this._firstIndex + this._maxItemCount, this._maxIndex); 108 | } 109 | }, { 110 | key: 'getSelectedIndex', 111 | value: function getSelectedIndex() { 112 | return this._selectedIndex; 113 | } 114 | }, { 115 | key: 'getMaxIndex', 116 | value: function getMaxIndex() { 117 | return this._maxIndex; 118 | } 119 | }, { 120 | key: 'calcColumnCount', 121 | value: function calcColumnCount(w) { 122 | return Math.floor(w / this.getColumnWidth()) << 0; 123 | } 124 | }, { 125 | key: 'calcFirstColumnLeft', 126 | value: function calcFirstColumnLeft(maxItemCount) { 127 | return this._innerLeft + this._innerWidth - this.getColumnWidth() * maxItemCount; 128 | } 129 | }, { 130 | key: 'calcFirstIndexAlignRight', 131 | value: function calcFirstIndexAlignRight(oldFirstIndex, oldMaxItemCount, newMaxItemCount) { 132 | return Math.max(0, oldFirstIndex + Math.max(oldMaxItemCount, 1) - Math.max(newMaxItemCount, 1)); 133 | } 134 | }, { 135 | key: 'calcFirstIndex', 136 | value: function calcFirstIndex(newMaxItemCount) { 137 | return this.validateFirstIndex(this.calcFirstIndexAlignRight(this._firstIndex, this._maxItemCount, newMaxItemCount), newMaxItemCount); 138 | } 139 | }, { 140 | key: 'updateMaxItemCount', 141 | value: function updateMaxItemCount() { 142 | var newMaxItemCount = this.calcColumnCount(this._innerWidth); 143 | var newFirstIndex = void 0; 144 | if (this._maxItemCount < 1) { 145 | newFirstIndex = this.calcFirstIndex(newMaxItemCount); 146 | } else if (this._lastScale === this._scale) { 147 | newFirstIndex = this.validateFirstIndex(this._firstIndex - (newMaxItemCount - this._maxItemCount)); 148 | } else { 149 | var focusedIndex = this._selectedIndex >= 0 ? this._selectedIndex : this.getLastIndex() - 1; 150 | newFirstIndex = this.validateFirstIndex(focusedIndex - Math.round((focusedIndex - this._firstIndex) * newMaxItemCount / this._maxItemCount)); 151 | } 152 | this._lastScale = this._scale; 153 | if (this._firstIndex !== newFirstIndex) { 154 | if (this._selectedIndex === this._firstIndex) this._selectedIndex = newFirstIndex; 155 | this._firstIndex = newFirstIndex; 156 | this._updated = true; 157 | } 158 | if (this._maxItemCount !== newMaxItemCount) { 159 | this._maxItemCount = newMaxItemCount; 160 | this._updated = true; 161 | } 162 | this._firstColumnLeft = this.calcFirstColumnLeft(newMaxItemCount); 163 | } 164 | }, { 165 | key: 'validateFirstIndex', 166 | value: function validateFirstIndex(firstIndex, maxItemCount) { 167 | if (this._maxIndex < 1) { 168 | return -1; 169 | } 170 | if (firstIndex < 0) { 171 | return 0; 172 | } 173 | var lastFirst = Math.max(0, this._maxIndex - 1 /*maxItemCount*/); 174 | if (firstIndex > lastFirst) { 175 | return lastFirst; 176 | } 177 | return firstIndex; 178 | } 179 | }, { 180 | key: 'validateSelectedIndex', 181 | value: function validateSelectedIndex() { 182 | if (this._selectedIndex < this._firstIndex) this._selectedIndex = -1;else if (this._selectedIndex >= this.getLastIndex()) this._selectedIndex = -1; 183 | } 184 | }, { 185 | key: 'onLayout', 186 | value: function onLayout() { 187 | var mgr = _chart_manager.ChartManager.instance; 188 | var area = mgr.getArea(this.getDataSourceName() + ".main"); 189 | if (area !== null) { 190 | this._innerLeft = area.getLeft() + Timeline.PADDING_LEFT; 191 | var w = Math.max(0, area.getWidth() - (Timeline.PADDING_LEFT + Timeline.PADDING_RIGHT)); 192 | if (this._innerWidth !== w) { 193 | this._innerWidth = w; 194 | this.updateMaxItemCount(); 195 | } 196 | } 197 | } 198 | }, { 199 | key: 'toIndex', 200 | value: function toIndex(x) { 201 | return this._firstIndex + this.calcColumnCount(x - this._firstColumnLeft); 202 | } 203 | }, { 204 | key: 'toColumnLeft', 205 | value: function toColumnLeft(index) { 206 | return this._firstColumnLeft + this.getColumnWidth() * (index - this._firstIndex); 207 | } 208 | }, { 209 | key: 'toItemLeft', 210 | value: function toItemLeft(index) { 211 | return this.toColumnLeft(index) + this.getItemLeftOffset(); 212 | } 213 | }, { 214 | key: 'toItemCenter', 215 | value: function toItemCenter(index) { 216 | return this.toColumnLeft(index) + this.getItemCenterOffset(); 217 | } 218 | }, { 219 | key: 'selectAt', 220 | value: function selectAt(x) { 221 | this._selectedIndex = this.toIndex(x); 222 | this.validateSelectedIndex(); 223 | return this._selectedIndex >= 0; 224 | } 225 | }, { 226 | key: 'unselect', 227 | value: function unselect() { 228 | this._selectedIndex = -1; 229 | } 230 | }, { 231 | key: 'update', 232 | value: function update() { 233 | var mgr = _chart_manager.ChartManager.instance; 234 | var ds = mgr.getDataSource(this.getDataSourceName()); 235 | var oldMaxIndex = this._maxIndex; 236 | this._maxIndex = ds.getDataCount(); 237 | switch (ds.getUpdateMode()) { 238 | case _data_sources.DataSource.UpdateMode.Refresh: 239 | if (this._maxIndex < 1) this._firstIndex = -1;else this._firstIndex = Math.max(this._maxIndex - this._maxItemCount, 0); 240 | this._selectedIndex = -1; 241 | this._updated = true; 242 | break; 243 | case _data_sources.DataSource.UpdateMode.Append: 244 | var lastIndex = this.getLastIndex(); 245 | var erasedCount = ds.getErasedCount(); 246 | if (lastIndex < oldMaxIndex) { 247 | if (erasedCount > 0) { 248 | this._firstIndex = Math.max(this._firstIndex - erasedCount, 0); 249 | if (this._selectedIndex >= 0) { 250 | this._selectedIndex -= erasedCount; 251 | this.validateSelectedIndex(); 252 | } 253 | this._updated = true; 254 | } 255 | } else if (lastIndex === oldMaxIndex) { 256 | this._firstIndex += this._maxIndex - oldMaxIndex; 257 | if (this._selectedIndex >= 0) { 258 | this._selectedIndex -= erasedCount; 259 | this.validateSelectedIndex(); 260 | } 261 | this._updated = true; 262 | } 263 | break; 264 | } 265 | } 266 | }, { 267 | key: 'move', 268 | value: function move(x) { 269 | if (this.isLatestShown()) { 270 | _chart_manager.ChartManager.instance.getArea(this.getDataSourceName() + ".mainRange").setChanged(true); 271 | } 272 | this._firstIndex = this.validateFirstIndex(this._savedFirstIndex - this.calcColumnCount(x), this._maxItemCount); 273 | this._updated = true; 274 | if (this._selectedIndex >= 0) this.validateSelectedIndex(); 275 | } 276 | }, { 277 | key: 'startMove', 278 | value: function startMove() { 279 | this._savedFirstIndex = this._firstIndex; 280 | } 281 | }, { 282 | key: 'scale', 283 | value: function scale(s) { 284 | this._scale += s; 285 | if (this._scale < 0) { 286 | this._scale = 0; 287 | } else if (this._scale >= Timeline.itemWidth.length) { 288 | this._scale = Timeline.itemWidth.length - 1; 289 | } 290 | this.updateMaxItemCount(); 291 | if (this._selectedIndex >= 0) { 292 | this.validateSelectedIndex(); 293 | } 294 | } 295 | }]); 296 | 297 | return Timeline; 298 | }(_named_object.NamedObject); 299 | 300 | Timeline.itemWidth = [1, 3, 3, 5, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]; 301 | Timeline.spaceWidth = [1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 7, 7, 7]; 302 | Timeline.PADDING_LEFT = 4; 303 | Timeline.PADDING_RIGHT = 8; -------------------------------------------------------------------------------- /npm_dist/js/util.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 10 | 11 | var Util = exports.Util = function () { 12 | function Util() { 13 | _classCallCheck(this, Util); 14 | } 15 | 16 | _createClass(Util, null, [{ 17 | key: 'fromFloat', 18 | value: function fromFloat(v, fractionDigits) { 19 | var text = v.toFixed(fractionDigits); 20 | for (var i = text.length - 1; i >= 0; i--) { 21 | if (text[i] === '.') return text.substring(0, i); 22 | if (text[i] !== '0') return text.substring(0, i + 1); 23 | } 24 | } 25 | }, { 26 | key: 'formatTime', 27 | value: function formatTime(v) { 28 | return v < 10 ? "0" + v.toString() : v.toString(); 29 | } 30 | }, { 31 | key: 'isInstance', 32 | value: function isInstance(obj, clazz) { 33 | if (obj === null || obj === undefined) { 34 | return false; 35 | } 36 | return obj instanceof clazz; 37 | } 38 | }]); 39 | 40 | return Util; 41 | }(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-kline", 3 | "version": "1.2.3", 4 | "description": "", 5 | "main": "npm_dist/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "webpack-dev-server --inline --progress --mode development", 9 | "build-npm": "babel src -d npm_dist --copy-files", 10 | "build-demo": "webpack --mode production", 11 | "deploy-demo": "gh-pages -d demo_dist", 12 | "publish-demo": "npm run build-demo && npm run deploy-demo" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "jquery": "^3.3.1", 19 | "jquery-mousewheel": "^3.1.13", 20 | "react": "^16.4.1", 21 | "react-dom": "^16.4.1" 22 | }, 23 | "devDependencies": { 24 | "babel-cli": "^6.26.0", 25 | "babel-core": "^6.26.3", 26 | "babel-loader": "^7.1.4", 27 | "babel-plugin-transform-class-properties": "^6.24.1", 28 | "babel-preset-env": "^1.7.0", 29 | "babel-preset-react": "^6.24.1", 30 | "compression-webpack-plugin": "^1.1.11", 31 | "css-loader": "^0.28.11", 32 | "gh-pages": "^1.2.0", 33 | "html-loader": "^0.5.1", 34 | "html-webpack-plugin": "^3.2.0", 35 | "style-loader": "^0.21.0", 36 | "uglifyjs-webpack-plugin": "^1.1.6", 37 | "url-loader": "^0.6.2", 38 | "webpack": "^4.12.0", 39 | "webpack-bundle-analyzer": "^2.13.1", 40 | "webpack-cli": "^3.0.8", 41 | "webpack-dev-server": "^3.1.4", 42 | "webpack-node-externals": "^1.7.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/img/clear_333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/clear_333.png -------------------------------------------------------------------------------- /src/img/clear_ccc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/clear_ccc.png -------------------------------------------------------------------------------- /src/img/dropdown_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/dropdown_b.png -------------------------------------------------------------------------------- /src/img/dropdown_w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/dropdown_w.png -------------------------------------------------------------------------------- /src/img/dropup_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/dropup_b.png -------------------------------------------------------------------------------- /src/img/dropup_w.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/dropup_w.png -------------------------------------------------------------------------------- /src/img/size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/size.png -------------------------------------------------------------------------------- /src/img/size_d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/size_d.png -------------------------------------------------------------------------------- /src/img/size_l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/size_l.png -------------------------------------------------------------------------------- /src/img/tool_d_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/tool_d_normal.png -------------------------------------------------------------------------------- /src/img/tool_d_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/tool_d_push.png -------------------------------------------------------------------------------- /src/img/tool_l_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/tool_l_normal.png -------------------------------------------------------------------------------- /src/img/tool_l_push.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangcj-github/react-kline/90f3fe68fcc9d0715331e89986f3c730b2026ced/src/img/tool_l_push.png -------------------------------------------------------------------------------- /src/js/areas.js: -------------------------------------------------------------------------------- 1 | import {NamedObject} from './named_object' 2 | import {ChartManager} from './chart_manager' 3 | import {MEvent} from './mevent' 4 | 5 | export class ChartArea extends NamedObject { 6 | 7 | constructor(name) { 8 | super(name); 9 | this._left = 0; 10 | this._top = 0; 11 | this._right = 0; 12 | this._bottom = 0; 13 | this._changed = false; 14 | this._highlighted = false; 15 | this._pressed = false; 16 | this._selected = false; 17 | this.Measuring = new MEvent(); 18 | } 19 | 20 | getDockStyle() { 21 | return this._dockStyle; 22 | } 23 | 24 | setDockStyle(dockStyle) { 25 | this._dockStyle = dockStyle; 26 | } 27 | 28 | getLeft() { 29 | return this._left; 30 | } 31 | 32 | 33 | getTop() { 34 | return this._top; 35 | } 36 | 37 | 38 | setTop(v) { 39 | if (this._top !== v) { 40 | this._top = v; 41 | this._changed = true; 42 | } 43 | } 44 | 45 | 46 | getRight() { 47 | return this._right; 48 | } 49 | 50 | 51 | getBottom() { 52 | return this._bottom; 53 | } 54 | 55 | setBottom(v) { 56 | if (this._bottom !== v) { 57 | this._bottom = v; 58 | this._changed = true; 59 | } 60 | } 61 | 62 | getCenter() { 63 | return (this._left + this._right) >> 1; 64 | } 65 | 66 | getMiddle() { 67 | return (this._top + this._bottom) >> 1; 68 | } 69 | 70 | getWidth() { 71 | return this._right - this._left; 72 | } 73 | 74 | getHeight() { 75 | return this._bottom - this._top; 76 | } 77 | 78 | getRect() { 79 | return { 80 | X: this._left, 81 | Y: this._top, 82 | Width: this._right - this._left, 83 | Height: this._bottom - this._top 84 | }; 85 | } 86 | 87 | contains(x, y) { 88 | if (x >= this._left && x < this._right) 89 | if (y >= this._top && y < this._bottom) 90 | return [this]; 91 | return null; 92 | } 93 | 94 | getMeasuredWidth() { 95 | return this._measuredWidth; 96 | } 97 | 98 | getMeasuredHeight() { 99 | return this._measuredHeight; 100 | } 101 | 102 | setMeasuredDimension(width, height) { 103 | this._measuredWidth = width; 104 | this._measuredHeight = height; 105 | } 106 | 107 | measure(context, width, height) { 108 | this._measuredWidth = 0; 109 | this._measuredHeight = 0; 110 | this.Measuring.raise(this, {Width: width, Height: height}); 111 | if (this._measuredWidth === 0 && this._measuredHeight === 0) 112 | this.setMeasuredDimension(width, height); 113 | } 114 | 115 | layout(left, top, right, bottom, forceChange) { 116 | left <<= 0; 117 | if (this._left !== left) { 118 | this._left = left; 119 | this._changed = true; 120 | } 121 | top <<= 0; 122 | if (this._top !== top) { 123 | this._top = top; 124 | this._changed = true; 125 | } 126 | right <<= 0; 127 | if (this._right !== right) { 128 | this._right = right; 129 | this._changed = true; 130 | } 131 | bottom <<= 0; 132 | if (this._bottom !== bottom) { 133 | this._bottom = bottom; 134 | this._changed = true; 135 | } 136 | if (forceChange) 137 | this._changed = true; 138 | } 139 | 140 | isChanged() { 141 | return this._changed; 142 | } 143 | 144 | setChanged(v) { 145 | this._changed = v; 146 | } 147 | 148 | isHighlighted() { 149 | return this._highlighted; 150 | } 151 | 152 | getHighlightedArea() { 153 | return this._highlighted ? this : null; 154 | } 155 | 156 | 157 | highlight(area) { 158 | this._highlighted = (this === area); 159 | return this._highlighted ? this : null; 160 | } 161 | 162 | isPressed() { 163 | return this._pressed; 164 | } 165 | 166 | 167 | setPressed(v) { 168 | this._pressed = v; 169 | } 170 | 171 | isSelected() { 172 | return this._selected; 173 | } 174 | 175 | getSelectedArea() { 176 | return this._selected ? this : null; 177 | } 178 | 179 | select(area) { 180 | this._selected = (this === area); 181 | return this._selected ? this : null; 182 | } 183 | 184 | onMouseMove(x, y) { 185 | return null; 186 | } 187 | 188 | onMouseLeave(x, y) { 189 | } 190 | 191 | onMouseDown(x, y) { 192 | return null; 193 | } 194 | 195 | onMouseUp(x, y) { 196 | return null; 197 | } 198 | 199 | } 200 | ChartArea.DockStyle = { 201 | Left: 0, 202 | Top: 1, 203 | Right: 2, 204 | Bottom: 3, 205 | Fill: 4 206 | }; 207 | 208 | export class MainArea extends ChartArea { 209 | 210 | constructor(name) { 211 | super(name); 212 | this._dragStarted = false; 213 | this._oldX = 0; 214 | this._oldY = 0; 215 | this._passMoveEventToToolManager = true; 216 | } 217 | 218 | onMouseMove(x, y) { 219 | let mgr = ChartManager.instance; 220 | if (mgr._capturingMouseArea === this) 221 | if (this._dragStarted === false) 222 | if (Math.abs(this._oldX - x) > 1 || Math.abs(this._oldY - y) > 1) 223 | this._dragStarted = true; 224 | if (this._dragStarted) { 225 | mgr.hideCursor(); 226 | if (mgr.onToolMouseDrag(this.getFrameName(), x, y)) 227 | return this; 228 | mgr.getTimeline(this.getDataSourceName()).move(x - this._oldX); 229 | return this; 230 | } 231 | if (this._passMoveEventToToolManager && mgr.onToolMouseMove(this.getFrameName(), x, y)) { 232 | mgr.hideCursor(); 233 | return this; 234 | } 235 | switch (mgr._drawingTool) { 236 | case ChartManager.DrawingTool.Cursor: 237 | mgr.showCursor(); 238 | break; 239 | case ChartManager.DrawingTool.CrossCursor: 240 | if (mgr.showCrossCursor(this, x, y)) 241 | mgr.hideCursor(); 242 | else 243 | mgr.showCursor(); 244 | break; 245 | default: 246 | mgr.hideCursor(); 247 | break; 248 | } 249 | return this; 250 | } 251 | 252 | onMouseLeave(x, y) { 253 | this._dragStarted = false; 254 | this._passMoveEventToToolManager = true; 255 | } 256 | 257 | onMouseDown(x, y) { 258 | let mgr = ChartManager.instance; 259 | mgr.getTimeline(this.getDataSourceName()).startMove(); 260 | this._oldX = x; 261 | this._oldY = y; 262 | this._dragStarted = false; 263 | if (mgr.onToolMouseDown(this.getFrameName(), x, y)) 264 | this._passMoveEventToToolManager = false; 265 | return this; 266 | } 267 | 268 | onMouseUp(x, y) { 269 | let mgr = ChartManager.instance; 270 | let ret = null; 271 | if (this._dragStarted) { 272 | this._dragStarted = false; 273 | ret = this; 274 | } 275 | if (mgr.onToolMouseUp(this.getFrameName(), x, y)) 276 | ret = this; 277 | this._passMoveEventToToolManager = true; 278 | return ret; 279 | } 280 | } 281 | 282 | export class IndicatorArea extends ChartArea { 283 | 284 | constructor(name) { 285 | super(name); 286 | this._dragStarted = false; 287 | this._oldX = 0; 288 | this._oldY = 0; 289 | } 290 | 291 | onMouseMove(x, y) { 292 | let mgr = ChartManager.instance; 293 | if (mgr._capturingMouseArea === this) { 294 | if (this._dragStarted === false) { 295 | if (this._oldX !== x || this._oldY !== y) { 296 | this._dragStarted = true; 297 | } 298 | } 299 | } 300 | if (this._dragStarted) { 301 | mgr.hideCursor(); 302 | mgr.getTimeline(this.getDataSourceName()).move(x - this._oldX); 303 | return this; 304 | } 305 | switch (mgr._drawingTool) { 306 | case ChartManager.DrawingTool.CrossCursor: 307 | if (mgr.showCrossCursor(this, x, y)) 308 | mgr.hideCursor(); 309 | else 310 | mgr.showCursor(); 311 | break; 312 | default: 313 | mgr.showCursor(); 314 | break; 315 | } 316 | return this; 317 | } 318 | 319 | onMouseLeave(x, y) { 320 | this._dragStarted = false; 321 | } 322 | 323 | 324 | onMouseDown(x, y) { 325 | let mgr = ChartManager.instance; 326 | mgr.getTimeline(this.getDataSourceName()).startMove(); 327 | this._oldX = x; 328 | this._oldY = y; 329 | this._dragStarted = false; 330 | return this; 331 | } 332 | 333 | onMouseUp(x, y) { 334 | if (this._dragStarted) { 335 | this._dragStarted = false; 336 | return this; 337 | } 338 | return null; 339 | } 340 | 341 | } 342 | 343 | export class MainRangeArea extends ChartArea { 344 | 345 | constructor(name) { 346 | super(name); 347 | } 348 | 349 | onMouseMove(x, y) { 350 | ChartManager.instance.showCursor(); 351 | return this; 352 | } 353 | 354 | } 355 | 356 | export class IndicatorRangeArea extends ChartArea { 357 | 358 | constructor(name) { 359 | super(name); 360 | } 361 | 362 | onMouseMove(x, y) { 363 | ChartManager.instance.showCursor(); 364 | return this; 365 | } 366 | 367 | } 368 | 369 | export class TimelineArea extends ChartArea { 370 | 371 | constructor(name) { 372 | super(name); 373 | } 374 | 375 | onMouseMove(x, y) { 376 | ChartManager.instance.showCursor(); 377 | return this; 378 | } 379 | 380 | } 381 | 382 | export class ChartAreaGroup extends ChartArea { 383 | 384 | constructor(name) { 385 | super(name); 386 | this._areas = []; 387 | this._highlightedArea = null; 388 | this._selectedArea = null; 389 | } 390 | 391 | contains(x, y) { 392 | let areas; 393 | let a, i, cnt = this._areas.length; 394 | for (i = 0; i < cnt; i++) { 395 | a = this._areas[i]; 396 | areas = a.contains(x, y); 397 | if (areas !== null) { 398 | areas.push(this); 399 | return areas; 400 | } 401 | } 402 | return super.contains(x, y); 403 | } 404 | 405 | getAreaCount() { 406 | return this._areas.length; 407 | } 408 | 409 | getAreaAt(index) { 410 | if (index < 0 || index >= this._areas.length) { 411 | return null; 412 | } 413 | return this._areas[index]; 414 | } 415 | 416 | 417 | addArea(area) { 418 | this._areas.push(area); 419 | } 420 | 421 | removeArea(area) { 422 | let i, cnt = this._areas.length; 423 | for (i = 0; i < cnt; i++) { 424 | if (area === this._areas[i]) { 425 | this._areas.splice(i); 426 | this.setChanged(true); 427 | break; 428 | } 429 | } 430 | } 431 | 432 | getGridColor() { 433 | return this._gridColor; 434 | } 435 | 436 | setGridColor(c) { 437 | this._gridColor = c; 438 | } 439 | 440 | getHighlightedArea() { 441 | if (this._highlightedArea !== null) { 442 | return this._highlightedArea.getHighlightedArea(); 443 | } 444 | return null; 445 | } 446 | 447 | highlight(area) { 448 | this._highlightedArea = null; 449 | let e, i, cnt = this._areas.length; 450 | for (i = 0; i < cnt; i++) { 451 | e = this._areas[i].highlight(area); 452 | if (e !== null) { 453 | this._highlightedArea = e; 454 | return this; 455 | } 456 | } 457 | return null; 458 | } 459 | 460 | getSelectedArea() { 461 | if (this._selectedArea !== null) { 462 | return this._selectedArea.getSelectedArea(); 463 | } 464 | return null; 465 | } 466 | 467 | select(area) { 468 | this._selectedArea = null; 469 | let e, i, cnt = this._areas.length; 470 | for (i = 0; i < cnt; i++) { 471 | e = this._areas[i].select(area); 472 | if (e !== null) { 473 | this._selectedArea = e; 474 | return this; 475 | } 476 | } 477 | return null; 478 | } 479 | 480 | onMouseLeave(x, y) { 481 | let i, cnt = this._areas.length; 482 | for (i = 0; i < cnt; i++) 483 | this._areas[i].onMouseLeave(x, y); 484 | } 485 | 486 | onMouseUp(x, y) { 487 | let a, i, cnt = this._areas.length; 488 | for (i = 0; i < cnt; i++) { 489 | a = this._areas[i].onMouseUp(x, y); 490 | if (a !== null) 491 | return a; 492 | } 493 | return null; 494 | } 495 | 496 | } 497 | 498 | -------------------------------------------------------------------------------- /src/js/chart.js: -------------------------------------------------------------------------------- 1 | import {ChartManager} from './chart_manager' 2 | import {Control} from './control' 3 | import Kline from './kline' 4 | import {Template} from './templates' 5 | import $ from 'jquery' 6 | 7 | export class Chart { 8 | constructor() { 9 | this._data = null; 10 | this._charStyle = "CandleStick"; 11 | this._depthData = { 12 | array: null, 13 | asks_count: 0, 14 | bids_count: 0, 15 | asks_si: 0, 16 | asks_ei: 0, 17 | bids_si: 0, 18 | bids_ei: 0 19 | }; 20 | this.strIsLine = false; 21 | this._range = Kline.instance.range; 22 | this._symbol = Kline.instance.symbol; 23 | } 24 | 25 | setTitle() { 26 | let lang = ChartManager.instance.getLanguage(); 27 | let title = Kline.instance.symbolName; 28 | title += ' '; 29 | title += this.strIsLine ? Chart.strPeriod[lang]['line'] : Chart.strPeriod[lang][this._range]; 30 | title += (this._contract_unit + '/' + this._money_type).toUpperCase(); 31 | ChartManager.instance.setTitle('frame0.k0', title); 32 | } 33 | 34 | 35 | setSymbol(symbol) { 36 | this._symbol = symbol; 37 | this.updateDataAndDisplay(); 38 | } 39 | 40 | updateDataAndDisplay() { 41 | Kline.instance.symbol = this._symbol; 42 | Kline.instance.range = this._range; 43 | ChartManager.instance.setCurrentDataSource('frame0.k0', this._symbol + '.' + this._range); 44 | ChartManager.instance.setNormalMode(); 45 | let f = Kline.instance.chartMgr.getDataSource("frame0.k0").getLastDate(); 46 | if (f === -1) { 47 | Kline.instance.requestParam = Control.setHttpRequestParam(Kline.instance.symbol, Kline.instance.range, Kline.instance.limit, null); 48 | Control.requestData(true); 49 | } else { 50 | Kline.instance.requestParam = Control.setHttpRequestParam(Kline.instance.symbol, Kline.instance.range, null, f.toString()); 51 | Control.requestData(); 52 | } 53 | ChartManager.instance.redraw('All', false); 54 | } 55 | 56 | 57 | setCurrentContractUnit(contractUnit) { 58 | this._contract_unit = contractUnit; 59 | this.updateDataAndDisplay(); 60 | } 61 | 62 | setCurrentMoneyType(moneyType) { 63 | this._money_type = moneyType; 64 | this.updateDataAndDisplay(); 65 | } 66 | 67 | setCurrentPeriod(period) { 68 | this._range = Kline.instance.periodMap[period]; 69 | if (Kline.instance.type === "stomp" && Kline.instance.stompClient.ws.readyState === 1) { 70 | Kline.instance.subscribed.unsubscribe(); 71 | Kline.instance.subscribed = Kline.instance.stompClient.subscribe(Kline.instance.subscribePath + '/' + Kline.instance.symbol + '/' + this._range, Control.subscribeCallback); 72 | } 73 | this.updateDataAndDisplay(); 74 | Kline.instance.onRangeChangeFunc(this._range); 75 | } 76 | 77 | updateDataSource(data) { 78 | this._data = data; 79 | ChartManager.instance.updateData("frame0.k0", this._data); 80 | } 81 | 82 | updateDepth(array) { 83 | if (array == null) { 84 | this._depthData.array = []; 85 | ChartManager.instance.redraw('All', false); 86 | return; 87 | } 88 | if (!array.asks || !array.bids || array.asks === '' || array.bids === '') 89 | return; 90 | let _data = this._depthData; 91 | _data.array = []; 92 | for (let i = 0; i < array.asks.length; i++) { 93 | let data = {}; 94 | data.rate = array.asks[i][0]; 95 | data.amount = array.asks[i][1]; 96 | _data.array.push(data); 97 | } 98 | for (let i = 0; i < array.bids.length; i++) { 99 | let data = {}; 100 | data.rate = array.bids[i][0]; 101 | data.amount = array.bids[i][1]; 102 | _data.array.push(data); 103 | } 104 | _data.asks_count = array.asks.length; 105 | _data.bids_count = array.bids.length; 106 | _data.asks_si = _data.asks_count - 1; 107 | _data.asks_ei = 0; 108 | _data.bids_si = _data.asks_count - 1; 109 | _data.bids_ei = _data.asks_count + _data.bids_count - 2; 110 | for (let i = _data.asks_si; i >= _data.asks_ei; i--) { 111 | if (i === _data.asks_si && _data.array[i] !== undefined) { 112 | _data.array[i].amounts = _data.array[i].amount; 113 | } else if(_data.array[i + 1] !== undefined) { 114 | _data.array[i].amounts = _data.array[i + 1].amounts + _data.array[i].amount; 115 | } 116 | } 117 | for (let i = _data.bids_si; i <= _data.bids_ei; i++) { 118 | if (i === _data.bids_si && _data.array[i] !== undefined) { 119 | _data.array[i].amounts = _data.array[i].amount; 120 | } else if (_data.array[i - 1] !== undefined) { 121 | _data.array[i].amounts = _data.array[i - 1].amounts + _data.array[i].amount; 122 | } 123 | } 124 | ChartManager.instance.redraw('All', false); 125 | } 126 | 127 | setMainIndicator(indicName) { 128 | this._mainIndicator = indicName; 129 | if (indicName === 'NONE') { 130 | ChartManager.instance.removeMainIndicator('frame0.k0'); 131 | } else { 132 | ChartManager.instance.setMainIndicator('frame0.k0', indicName); 133 | } 134 | ChartManager.instance.redraw('All', true); 135 | } 136 | 137 | setIndicator(index, indicName) { 138 | if (indicName === 'NONE') { 139 | /* 140 | let index = 2; 141 | if (Template.displayVolume === false) 142 | index = 1; 143 | */ 144 | let index=1; 145 | let areaName = ChartManager.instance.getIndicatorAreaName('frame0.k0', index); 146 | if (areaName !== '') 147 | ChartManager.instance.removeIndicator(areaName); 148 | } else { 149 | /* 150 | let index = 2; 151 | if (Template.displayVolume === false) 152 | index = 1; 153 | */ 154 | let index=1; 155 | let areaName = ChartManager.instance.getIndicatorAreaName('frame0.k0', index); 156 | if (areaName === '') { 157 | Template.createIndicatorChartComps('frame0.k0', indicName); 158 | } else { 159 | ChartManager.instance.setIndicator(areaName, indicName); 160 | } 161 | } 162 | ChartManager.instance.redraw('All', true); 163 | } 164 | 165 | addIndicator(indicName) { 166 | ChartManager.instance.addIndicator(indicName); 167 | ChartManager.instance.redraw('All', true); 168 | } 169 | 170 | removeIndicator(indicName) { 171 | let areaName = ChartManager.instance.getIndicatorAreaName(2); 172 | ChartManager.instance.removeIndicator(areaName); 173 | ChartManager.instance.redraw('All', true); 174 | }; 175 | 176 | } 177 | Chart.strPeriod = { 178 | 'zh-cn': { 179 | 'line': '(分时)', 180 | '1min': '(1分钟)', 181 | '5min': '(5分钟)', 182 | '15min': '(15分钟)', 183 | '30min': '(30分钟)', 184 | '1hour': '(1小时)', 185 | '1day': '(日线)', 186 | '1week': '(周线)', 187 | '3min': '(3分钟)', 188 | '2hour': '(2小时)', 189 | '4hour': '(4小时)', 190 | '6hour': '(6小时)', 191 | '12hour': '(12小时)', 192 | '3day': '(3天)' 193 | }, 194 | 'en-us': { 195 | 'line': '(Line)', 196 | '1min': '(1m)', 197 | '5min': '(5m)', 198 | '15min': '(15m)', 199 | '30min': '(30m)', 200 | '1hour': '(1h)', 201 | '1day': '(1d)', 202 | '1week': '(1w)', 203 | '3min': '(3m)', 204 | '2hour': '(2h)', 205 | '4hour': '(4h)', 206 | '6hour': '(6h)', 207 | '12hour': '(12h)', 208 | '3day': '(3d)' 209 | }, 210 | 'zh-tw': { 211 | 'line': '(分時)', 212 | '1min': '(1分鐘)', 213 | '5min': '(5分鐘)', 214 | '15min': '(15分鐘)', 215 | '30min': '(30分鐘)', 216 | '1hour': '(1小時)', 217 | '1day': '(日線)', 218 | '1week': '(周線)', 219 | '3min': '(3分鐘)', 220 | '2hour': '(2小時)', 221 | '4hour': '(4小時)', 222 | '6hour': '(6小時)', 223 | '12hour': '(12小時)', 224 | '3day': '(3天)' 225 | } 226 | }; -------------------------------------------------------------------------------- /src/js/chart_settings.js: -------------------------------------------------------------------------------- 1 | import {ChartManager} from './chart_manager' 2 | 3 | export class ChartSettings { 4 | 5 | static checkVersion() { 6 | if (ChartSettings._data.ver < 2) { 7 | ChartSettings._data.ver = 2; 8 | let charts = ChartSettings._data.charts; 9 | charts.period_weight = {}; 10 | charts.period_weight['line'] = 8; 11 | charts.period_weight['1min'] = 7; 12 | charts.period_weight['5min'] = 6; 13 | charts.period_weight['15min'] = 5; 14 | charts.period_weight['30min'] = 4; 15 | charts.period_weight['1hour'] = 3; 16 | charts.period_weight['1day'] = 2; 17 | charts.period_weight['1week'] = 1; 18 | charts.period_weight['3min'] = 0; 19 | charts.period_weight['2hour'] = 0; 20 | charts.period_weight['4hour'] = 0; 21 | charts.period_weight['6hour'] = 0; 22 | charts.period_weight['12hour'] = 0; 23 | charts.period_weight['3day'] = 0; 24 | } 25 | if (ChartSettings._data.ver < 3) { 26 | ChartSettings._data.ver = 3; 27 | let charts = ChartSettings._data.charts; 28 | charts.areaHeight = []; 29 | } 30 | } 31 | 32 | static get () { 33 | if (ChartSettings._data === undefined) { 34 | ChartSettings.init(); 35 | ChartSettings.load(); 36 | ChartSettings.checkVersion(); 37 | } 38 | return ChartSettings._data; 39 | }; 40 | 41 | static init() { 42 | let _indic_param = {}; 43 | let _name = ['MA', 'EMA', 'VOLUME', 'MACD', 'KDJ', 'StochRSI', 'RSI', 'DMI', 'OBV', 'BOLL', 'DMA', 'TRIX', 'BRAR', 'VR', 'EMV', 'WR', 'ROC', 'MTM', 'PSY']; 44 | for (let i = 0; i < _name.length; i++) { 45 | let _value = ChartManager.instance.createIndicatorAndRange('', _name[i], true); 46 | if (_value === null) continue; 47 | _indic_param[_name[i]] = []; 48 | let param = _value.indic.getParameters(); 49 | for (let j = 0; j < param.length; j++) { 50 | _indic_param[_name[i]].push(param[j]); 51 | } 52 | } 53 | let _chart_style = 'CandleStick'; 54 | let _m_indic = 'MA'; 55 | let _indic = ['VOLUME', 'VOLUME']; 56 | let _range = '15m'; 57 | let _frame = {}; 58 | _frame.chartStyle = _chart_style; 59 | _frame.mIndic = _m_indic; 60 | _frame.indics = _indic; 61 | _frame.indicsStatus = 'open'; 62 | _frame.period = _range; 63 | _frame.depthStatus = 'close'; 64 | ChartSettings._data = { 65 | ver: 1, 66 | charts: _frame, 67 | indics: _indic_param, 68 | theme: "Dark" 69 | }; 70 | ChartSettings.checkVersion(); 71 | } 72 | 73 | static load() { 74 | if (document.cookie.length <= 0) 75 | return; 76 | let start = document.cookie.indexOf("chartSettings="); 77 | if (start < 0) 78 | return; 79 | start += "chartSettings=".length; 80 | let end = document.cookie.indexOf(";", start); 81 | if (end < 0) 82 | end = document.cookie.length; 83 | let json = unescape(document.cookie.substring(start, end)); 84 | ChartSettings._data = JSON.parse(json); 85 | } 86 | 87 | static save() { 88 | let exdate = new Date(); 89 | exdate.setDate(exdate.getDate() + 2); 90 | document.cookie = "chartSettings=" + escape(JSON.stringify(ChartSettings._data)) + 91 | ";expires=" + exdate.toGMTString(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/js/cname.js: -------------------------------------------------------------------------------- 1 | export class CName { 2 | 3 | constructor(name) { 4 | this._names = []; 5 | this._comps = []; 6 | if (name instanceof CName) { 7 | this._names = name._names; 8 | this._comps = name._comps; 9 | } else { 10 | let comps = name.split("."); 11 | let dotNum = comps.length - 1; 12 | if (dotNum > 0) { 13 | this._comps = comps; 14 | this._names.push(comps[0]); 15 | for (let i = 1; i <= dotNum; i++) { 16 | this._names.push(this._names[i - 1] + "." + comps[i]); 17 | } 18 | } else { 19 | this._comps.push(name); 20 | this._names.push(name); 21 | } 22 | } 23 | } 24 | 25 | getCompAt(index) { 26 | if (index >= 0 && index < this._comps.length) 27 | return this._comps[index]; 28 | return ""; 29 | } 30 | 31 | getName(index) { 32 | if (index < 0) { 33 | if (this._names.length > 0) 34 | return this._names[this._names.length - 1]; 35 | } else if (index < this._names.length) { 36 | return this._names[index]; 37 | } 38 | return ""; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/js/cpoint.js: -------------------------------------------------------------------------------- 1 | import {ChartManager} from './chart_manager' 2 | import {NamedObject} from './named_object' 3 | import * as data_sources from './data_sources' 4 | import {Util} from './util' 5 | 6 | export class CPoint extends NamedObject { 7 | 8 | constructor(name) { 9 | super(name); 10 | this.pos = {index: -1, value: -1}; 11 | 12 | this.state = CPoint.state.Hide; 13 | } 14 | 15 | getChartObjects() { 16 | let ppMgr = ChartManager.instance; 17 | let ppCDS = ppMgr.getDataSource("frame0.k0"); 18 | if (ppCDS === null || !Util.isInstance(ppCDS, data_sources.MainDataSource)) 19 | return null; 20 | let ppTimeline = ppMgr.getTimeline("frame0.k0"); 21 | if (ppTimeline === null) 22 | return null; 23 | let ppRange = ppMgr.getRange("frame0.k0.main"); 24 | if (ppRange === null) 25 | return null; 26 | return {pMgr: ppMgr, pCDS: ppCDS, pTimeline: ppTimeline, pRange: ppRange}; 27 | } 28 | 29 | setPosXY(x, y) { 30 | let pObj = this.getChartObjects(); 31 | let i = pObj.pTimeline.toIndex(x); 32 | let v = pObj.pRange.toValue(y); 33 | let result = this.snapValue(i, v); 34 | if (result !== null) 35 | v = result; 36 | this.setPosIV(i, v); 37 | } 38 | 39 | setPosXYNoSnap(x, y) { 40 | let pObj = this.getChartObjects(); 41 | let i = pObj.pTimeline.toIndex(x); 42 | let v = pObj.pRange.toValue(y); 43 | this.setPosIV(i, v); 44 | } 45 | 46 | setPosIV(i, v) { 47 | this.pos = {index: i, value: v}; 48 | } 49 | 50 | getPosXY() { 51 | let pObj = this.getChartObjects(); 52 | let _x = pObj.pTimeline.toItemCenter(this.pos.index); 53 | let _y = pObj.pRange.toY(this.pos.value); 54 | return {x: _x, y: _y}; 55 | } 56 | 57 | getPosIV() { 58 | return {i: this.pos.index, v: this.pos.value}; 59 | } 60 | 61 | setState(s) { 62 | this.state = s; 63 | } 64 | 65 | getState() { 66 | return this.state; 67 | } 68 | 69 | isSelected(x, y) { 70 | let xy = this.getPosXY(); 71 | if (x < xy.x - 4 || x > xy.x + 4 || y < xy.y - 4 || y > xy.y + 4) 72 | return false; 73 | this.setState(CPoint.state.Highlight); 74 | return true; 75 | } 76 | 77 | snapValue(i, v) { 78 | let pObj = this.getChartObjects(); 79 | let result = null; 80 | let first = Math.floor(pObj.pTimeline.getFirstIndex()); 81 | let last = Math.floor(pObj.pTimeline.getLastIndex()); 82 | if (i < first || i > last) 83 | return result; 84 | let y = pObj.pRange.toY(v); 85 | let pData = pObj.pCDS.getDataAt(i); 86 | if (pData === null || pData === undefined) 87 | return result; 88 | let pDataPre = null; 89 | if (i > 0) 90 | pDataPre = pObj.pCDS.getDataAt(i - 1); 91 | else 92 | pDataPre = pObj.pCDS.getDataAt(i); 93 | let candleStickStyle = pObj.pMgr.getChartStyle(pObj.pCDS.getFrameName()); 94 | let open = pObj.pRange.toY(pData.open); 95 | let high = pObj.pRange.toY(pData.high); 96 | let low = pObj.pRange.toY(pData.low); 97 | let close = pObj.pRange.toY(pData.close); 98 | if (candleStickStyle === "CandleStickHLC") { 99 | open = pObj.pRange.toY(pDataPre.close); 100 | } 101 | let dif_open = Math.abs(open - y); 102 | let dif_high = Math.abs(high - y); 103 | let dif_low = Math.abs(low - y); 104 | let dif_close = Math.abs(close - y); 105 | if (dif_open <= dif_high && dif_open <= dif_low && dif_open <= dif_close) { 106 | if (dif_open < 6) 107 | result = pData.open; 108 | } 109 | if (dif_high <= dif_open && dif_high <= dif_low && dif_high <= dif_close) { 110 | if (dif_high < 6) 111 | result = pData.high; 112 | } 113 | if (dif_low <= dif_open && dif_low <= dif_high && dif_low <= dif_close) { 114 | if (dif_low < 6) 115 | result = pData.low; 116 | } 117 | if (dif_close <= dif_open && dif_close <= dif_high && dif_close <= dif_low) { 118 | if (dif_close < 6) 119 | result = pData.close; 120 | } 121 | return result; 122 | } 123 | 124 | } 125 | 126 | CPoint.state = { 127 | Hide: 0, 128 | Show: 1, 129 | Highlight: 2 130 | }; -------------------------------------------------------------------------------- /src/js/ctool_manager.js: -------------------------------------------------------------------------------- 1 | import {NamedObject} from './named_object' 2 | import {CPoint} from './cpoint' 3 | import * as ctools from './ctools' 4 | 5 | export class CToolManager extends NamedObject { 6 | 7 | constructor(name) { 8 | super(name); 9 | this.selectedObject = -1; 10 | this.toolObjects = []; 11 | } 12 | 13 | getToolObjectCount() { 14 | return this.toolObjects.length; 15 | } 16 | 17 | addToolObject(o) { 18 | this.toolObjects.push(o); 19 | } 20 | 21 | getToolObject(i) { 22 | if (i < this.toolObjects.length && i >= 0) { 23 | return this.toolObjects[i]; 24 | } 25 | return null; 26 | } 27 | 28 | getCurrentObject() { 29 | return this.getToolObject(this.getToolObjectCount() - 1); 30 | } 31 | 32 | getSelectedObject() { 33 | return this.getToolObject(this.selectedObject); 34 | } 35 | 36 | delCurrentObject() { 37 | this.toolObjects.splice(this.getToolObjectCount() - 1, 1); 38 | } 39 | 40 | delSelectedObject() { 41 | this.toolObjects.splice(this.selectedObject, 1); 42 | this.selectedObject = -1; 43 | } 44 | 45 | acceptMouseMoveEvent(x, y) { 46 | if (this.selectedObject === -1) { 47 | let curr = this.toolObjects[this.getToolObjectCount() - 1]; 48 | if (curr !== null && curr !== undefined && curr.getState() !== ctools.CToolObject.state.AfterDraw) 49 | return curr.acceptMouseMoveEvent(x, y); 50 | } else { 51 | let sel = this.toolObjects[this.selectedObject]; 52 | if (sel.getState() === ctools.CToolObject.state.Draw) { 53 | return sel.acceptMouseMoveEvent(x, y); 54 | } 55 | sel.unselect(); 56 | this.selectedObject = -1; 57 | } 58 | for (let index in this.toolObjects) { 59 | if (this.toolObjects[index].isSelected(x, y)) { 60 | this.selectedObject = index; 61 | return false; 62 | } 63 | } 64 | return false; 65 | } 66 | 67 | acceptMouseDownEvent(x, y) { 68 | this.mouseDownMove = false; 69 | if (this.selectedObject === -1) { 70 | let curr = this.toolObjects[this.getToolObjectCount() - 1]; 71 | if (curr !== null && curr !== undefined && curr.getState() !== ctools.CToolObject.state.AfterDraw) 72 | return curr.acceptMouseDownEvent(x, y); 73 | } else { 74 | let sel = this.toolObjects[this.selectedObject]; 75 | if (sel.getState() !== ctools.CToolObject.state.BeforeDraw) 76 | return sel.acceptMouseDownEvent(x, y); 77 | } 78 | return false; 79 | } 80 | 81 | acceptMouseDownMoveEvent(x, y) { 82 | this.mouseDownMove = true; 83 | if (this.selectedObject === -1) { 84 | let curr = this.toolObjects[this.getToolObjectCount() - 1]; 85 | if (curr !== null && curr !== undefined && curr.getState() === ctools.CToolObject.state.Draw) 86 | return curr.acceptMouseDownMoveEvent(x, y); 87 | return false; 88 | } else { 89 | let sel = this.toolObjects[this.selectedObject]; 90 | if (sel.getState() !== ctools.CToolObject.state.BeforeDraw) { 91 | if (sel.acceptMouseDownMoveEvent(x, y) === true) { 92 | let point = this.toolObjects[this.selectedObject].points; 93 | for (let i = 0; i < point.length; i++) { 94 | if (point[i].state === CPoint.state.Highlight || point[i].state === CPoint.state.Show) { 95 | return true; 96 | } 97 | } 98 | } 99 | return true; 100 | } 101 | } 102 | } 103 | 104 | acceptMouseUpEvent(x, y) { 105 | if (this.mouseDownMove === true) { 106 | if (this.selectedObject === -1) { 107 | let curr = this.toolObjects[this.getToolObjectCount() - 1]; 108 | if (curr !== null && curr !== undefined && curr.getState() === ctools.CToolObject.state.Draw) 109 | return curr.acceptMouseUpEvent(x, y); 110 | return true; 111 | } else { 112 | let sel = this.toolObjects[this.selectedObject]; 113 | if (sel.getState() !== ctools.CToolObject.state.BeforeDraw) 114 | return sel.acceptMouseUpEvent(x, y); 115 | } 116 | } 117 | if (this.selectedObject !== -1) { 118 | return true; 119 | } 120 | let curr = this.toolObjects[this.getToolObjectCount() - 1]; 121 | if (curr !== null && curr !== undefined) { 122 | if (curr.getState() === ctools.CToolObject.state.Draw) 123 | return true; 124 | if (!curr.isValidMouseXY(x, y)) { 125 | return false; 126 | } 127 | if (curr.isSelected(x, y)) { 128 | return true; 129 | } 130 | } 131 | return false; 132 | } 133 | 134 | } 135 | 136 | -------------------------------------------------------------------------------- /src/js/data_providers.js: -------------------------------------------------------------------------------- 1 | import {NamedObject} from './named_object' 2 | import {ChartManager} from './chart_manager' 3 | import {Util} from './util' 4 | import * as data_sources from './data_sources' 5 | 6 | 7 | export class DataProvider extends NamedObject { 8 | 9 | constructor(name) { 10 | super(name); 11 | this._minValue = 0; 12 | this._maxValue = 0; 13 | this._minValueIndex = -1; 14 | this._maxValueIndex = -1; 15 | } 16 | 17 | getMinValue() { 18 | return this._minValue; 19 | } 20 | 21 | getMaxValue() { 22 | return this._maxValue; 23 | } 24 | 25 | getMinValueIndex() { 26 | return this._minValueIndex; 27 | } 28 | 29 | getMaxValueIndex() { 30 | return this._maxValueIndex; 31 | } 32 | 33 | getMinMaxAt(index, minmax) { 34 | return true; 35 | } 36 | 37 | calcRange(firstIndexes, lastIndex, minmaxes, indexes) { 38 | let min = Number.MAX_VALUE; 39 | let max = -Number.MAX_VALUE; 40 | let minIndex = -1; 41 | let maxIndex = -1; 42 | let minmax = {}; 43 | let i = lastIndex - 1; 44 | let n = firstIndexes.length - 1; 45 | for (; n >= 0; n--) { 46 | let first = firstIndexes[n]; 47 | if (i < first) { 48 | minmaxes[n] = {"min": min, "max": max}; 49 | } else { 50 | for (; i >= first; i--) { 51 | if (this.getMinMaxAt(i, minmax) === false) { 52 | continue; 53 | } 54 | if (min > minmax.min) { 55 | min = minmax.min; 56 | minIndex = i; 57 | } 58 | if (max < minmax.max) { 59 | max = minmax.max; 60 | maxIndex = i; 61 | } 62 | } 63 | minmaxes[n] = {"min": min, "max": max}; 64 | } 65 | if (indexes !== null && indexes !== undefined) { 66 | indexes[n] = {"minIndex": minIndex, "maxIndex": maxIndex}; 67 | } 68 | } 69 | } 70 | 71 | updateRange() { 72 | let mgr = ChartManager.instance; 73 | let timeline = mgr.getTimeline(this.getDataSourceName()); 74 | let firstIndexes = [timeline.getFirstIndex()]; 75 | let minmaxes = [{}]; 76 | let indexes = [{}]; 77 | this.calcRange(firstIndexes, timeline.getLastIndex(), minmaxes, indexes); 78 | this._minValue = minmaxes[0].min; 79 | this._maxValue = minmaxes[0].max; 80 | this._minValueIndex = indexes[0].minIndex; 81 | this._maxValueIndex = indexes[0].maxIndex; 82 | } 83 | 84 | } 85 | 86 | 87 | export class MainDataProvider extends DataProvider { 88 | 89 | constructor(name) { 90 | super(name); 91 | this._candlestickDS = null; 92 | } 93 | 94 | updateData() { 95 | let mgr = ChartManager.instance; 96 | let ds = mgr.getDataSource(this.getDataSourceName()); 97 | if (!Util.isInstance(ds, data_sources.MainDataSource)) { 98 | return; 99 | } 100 | this._candlestickDS = ds; 101 | } 102 | 103 | getMinMaxAt(index, minmax) { 104 | let data = this._candlestickDS.getDataAt(index); 105 | minmax.min = data.low; 106 | minmax.max = data.high; 107 | return true; 108 | } 109 | 110 | } 111 | 112 | 113 | export class IndicatorDataProvider extends DataProvider { 114 | 115 | getIndicator() { 116 | return this._indicator; 117 | } 118 | 119 | setIndicator(v) { 120 | this._indicator = v; 121 | this.refresh(); 122 | } 123 | 124 | refresh() { 125 | let mgr = ChartManager.instance; 126 | let ds = mgr.getDataSource(this.getDataSourceName()); 127 | if (ds.getDataCount() < 1) { 128 | return; 129 | } 130 | let indic = this._indicator; 131 | let i, last = ds.getDataCount(); 132 | indic.clear(); 133 | indic.reserve(last); 134 | for (i = 0; i < last; i++) { 135 | indic.execute(ds, i); 136 | } 137 | } 138 | 139 | updateData() { 140 | let mgr = ChartManager.instance; 141 | let ds = mgr.getDataSource(this.getDataSourceName()); 142 | if (ds.getDataCount() < 1) { 143 | return; 144 | } 145 | let indic = this._indicator; 146 | let mode = ds.getUpdateMode(); 147 | switch (mode) { 148 | case data_sources.DataSource.UpdateMode.Refresh: { 149 | this.refresh(); 150 | break; 151 | } 152 | case data_sources.DataSource.UpdateMode.Append: { 153 | indic.reserve(ds.getAppendedCount()); 154 | break; 155 | } 156 | case data_sources.DataSource.UpdateMode.Update: { 157 | let i, last = ds.getDataCount(); 158 | let cnt = ds.getUpdatedCount() + ds.getAppendedCount(); 159 | for (i = last - cnt; i < last; i++) { 160 | indic.execute(ds, i); 161 | } 162 | break; 163 | } 164 | } 165 | } 166 | 167 | getMinMaxAt(index, minmax) { 168 | minmax.min = Number.MAX_VALUE; 169 | minmax.max = -Number.MAX_VALUE; 170 | let result, valid = false; 171 | let i, cnt = this._indicator.getOutputCount(); 172 | for (i = 0; i < cnt; i++) { 173 | result = this._indicator.getOutputAt(i).execute(index); 174 | if (isNaN(result) === false) { 175 | valid = true; 176 | if (minmax.min > result) { 177 | minmax.min = result; 178 | } 179 | if (minmax.max < result) { 180 | minmax.max = result; 181 | } 182 | } 183 | } 184 | return valid; 185 | } 186 | 187 | } 188 | 189 | -------------------------------------------------------------------------------- /src/js/data_sources.js: -------------------------------------------------------------------------------- 1 | import {NamedObject} from './named_object' 2 | import {CToolManager} from './ctool_manager' 3 | import Kline from './kline' 4 | 5 | 6 | 7 | export class DataSource extends NamedObject { 8 | 9 | constructor(name) { 10 | super(name); 11 | } 12 | 13 | getUpdateMode() { 14 | return this._updateMode; 15 | } 16 | 17 | setUpdateMode(mode) { 18 | this._updateMode = mode; 19 | } 20 | 21 | getCacheSize() { 22 | return 0; 23 | } 24 | 25 | getDataCount() { 26 | return 0; 27 | } 28 | 29 | getDataAt(index) { 30 | return this._dataItems[index]; 31 | } 32 | 33 | } 34 | DataSource.UpdateMode = { 35 | DoNothing: 0, 36 | Refresh: 1, 37 | Update: 2, 38 | Append: 3 39 | }; 40 | 41 | 42 | export class MainDataSource extends DataSource { 43 | 44 | constructor(name) { 45 | super(name); 46 | this._erasedCount = 0; 47 | this._dataItems = []; 48 | this._decimalDigits = 0; 49 | this.toolManager = new CToolManager(name); 50 | } 51 | 52 | getCacheSize() { 53 | return this._dataItems.length; 54 | } 55 | 56 | getDataCount() { 57 | return this._dataItems.length; 58 | } 59 | 60 | getUpdatedCount() { 61 | return this._updatedCount; 62 | } 63 | 64 | getAppendedCount() { 65 | return this._appendedCount; 66 | } 67 | 68 | getErasedCount() { 69 | return this._erasedCount; 70 | } 71 | 72 | getDecimalDigits() { 73 | return this._decimalDigits; 74 | } 75 | 76 | calcDecimalDigits(v) { 77 | let str = "" + v; 78 | let i = str.indexOf('.'); 79 | if (i < 0) { 80 | return 0; 81 | } 82 | return (str.length - 1) - i; 83 | } 84 | 85 | getLastDate() { 86 | let count = this.getDataCount(); 87 | if (count < 1) { 88 | return -1; 89 | } 90 | return this.getDataAt(count - 1).date; 91 | } 92 | 93 | getDataAt(index) { 94 | return this._dataItems[index]; 95 | } 96 | 97 | update(data) { 98 | this._updatedCount = 0; 99 | this._appendedCount = 0; 100 | this._erasedCount = 0; 101 | let len = this._dataItems.length; 102 | if (len > 0) { 103 | let lastIndex = len - 1; 104 | let lastItem = this._dataItems[lastIndex]; 105 | let e, i, cnt = data.length; 106 | for (i = 0; i < cnt; i++) { 107 | e = data[i]; 108 | if (e[0] === lastItem.date) { 109 | if (lastItem.open === e[1] && 110 | lastItem.high === e[2] && 111 | lastItem.low === e[3] && 112 | lastItem.close === e[4] && 113 | lastItem.volume === e[5]) { 114 | this.setUpdateMode(DataSource.UpdateMode.DoNothing); 115 | } else { 116 | this.setUpdateMode(DataSource.UpdateMode.Update); 117 | this._dataItems[lastIndex] = { 118 | date: e[0], 119 | open: e[1], 120 | high: e[2], 121 | low: e[3], 122 | close: e[4], 123 | volume: e[5] 124 | }; 125 | this._updatedCount++; 126 | } 127 | i++; 128 | if (i < cnt) { 129 | this.setUpdateMode(DataSource.UpdateMode.Append); 130 | for (; i < cnt; i++, this._appendedCount++) { 131 | e = data[i]; 132 | this._dataItems.push({ 133 | date: e[0], 134 | open: e[1], 135 | high: e[2], 136 | low: e[3], 137 | close: e[4], 138 | volume: e[5] 139 | }); 140 | } 141 | } 142 | return true; 143 | } 144 | } 145 | if (cnt < Kline.instance.limit) { 146 | this.setUpdateMode(DataSource.UpdateMode.DoNothing); 147 | return false; 148 | } 149 | } 150 | this.setUpdateMode(DataSource.UpdateMode.Refresh); 151 | this._dataItems = []; 152 | let d, n, e, i, cnt = data.length; 153 | for (i = 0; i < cnt; i++) { 154 | e = data[i]; 155 | for (n = 1; n <= 4; n++) { 156 | d = this.calcDecimalDigits(e[n]); 157 | if (this._decimalDigits < d) 158 | this._decimalDigits = d; 159 | } 160 | this._dataItems.push({ 161 | date: e[0], 162 | open: e[1], 163 | high: e[2], 164 | low: e[3], 165 | close: e[4], 166 | volume: e[5] 167 | }); 168 | } 169 | return true; 170 | } 171 | 172 | select(id) { 173 | this.toolManager.selecedObject = id; 174 | } 175 | 176 | unselect() { 177 | this.toolManager.selecedObject = -1; 178 | } 179 | 180 | addToolObject(toolObject) { 181 | this.toolManager.addToolObject(toolObject); 182 | } 183 | 184 | delToolObject() { 185 | this.toolManager.delCurrentObject(); 186 | } 187 | 188 | getToolObject(index) { 189 | return this.toolManager.getToolObject(index); 190 | } 191 | 192 | getToolObjectCount() { 193 | return this.toolManager.toolObjects.length; 194 | } 195 | 196 | getCurrentToolObject() { 197 | return this.toolManager.getCurrentObject(); 198 | } 199 | 200 | getSelectToolObjcet() { 201 | return this.toolManager.getSelectedObject(); 202 | } 203 | 204 | delSelectToolObject() { 205 | this.toolManager.delSelectedObject(); 206 | } 207 | 208 | } 209 | 210 | -------------------------------------------------------------------------------- /src/js/layouts.js: -------------------------------------------------------------------------------- 1 | import * as areas from './areas' 2 | import {ChartManager} from './chart_manager' 3 | import * as themes from './themes' 4 | import {ChartSettings} from './chart_settings' 5 | import Kline from "./kline"; 6 | 7 | export class TableLayout extends areas.ChartAreaGroup { 8 | 9 | constructor(name) { 10 | super(name); 11 | this._nextRowId = 0; 12 | this._focusedRowIndex = -1; 13 | } 14 | 15 | getNextRowId() { 16 | return this._nextRowId++; 17 | } 18 | 19 | measure(context, width, height) { 20 | this.setMeasuredDimension(width, height); 21 | let rowH, prevH = 0, 22 | totalH = 0; 23 | let h, rows; 24 | let rh = []; 25 | let i, cnt = this._areas.length; 26 | for (i = 0; i < cnt; i += 2) { 27 | rowH = this._areas[i].getHeight(); 28 | if (rowH === 0) { 29 | if (i === 0) { 30 | rows = (cnt + 1) >> 1; 31 | let n = (rows * 2) + 5; 32 | let nh = ((height / n) * 2) << 0; 33 | h = height; 34 | for (i = rows - 1; i > 0; i--) { 35 | rh.unshift(nh); 36 | h -= nh; 37 | } 38 | rh.unshift(h); 39 | break; 40 | } else if (i === 2) { 41 | rowH = prevH / 3; 42 | } else { 43 | rowH = prevH; 44 | } 45 | } 46 | totalH += rowH; 47 | prevH = rowH; 48 | rh.push(rowH); 49 | } 50 | if (totalH > 0) { 51 | let rate = height / totalH; 52 | rows = (cnt + 1) >> 1; 53 | h = height; 54 | for (i = rows - 1; i > 0; i--) { 55 | rh[i] *= rate; 56 | h -= rh[i]; 57 | } 58 | rh[0] = h; 59 | } 60 | let nw = 8; 61 | // chart depths sidebar (深度图侧边栏宽度) 62 | let tmp = ChartSettings.get(); 63 | let minRW = tmp.charts.depthStatus==="open" ? Kline.instance.depthWidth : 50; 64 | let maxRW = Math.min(240, width >> 1); 65 | let rw = minRW; 66 | let mgr = ChartManager.instance; 67 | let timeline = mgr.getTimeline(this.getDataSourceName()); 68 | if (timeline.getFirstIndex() >= 0) { 69 | let firstIndexes = []; 70 | for (rw = minRW; rw < maxRW; rw += nw) { 71 | firstIndexes.push(timeline.calcFirstIndex(timeline.calcColumnCount(width - rw))); 72 | } 73 | let lastIndex = timeline.getLastIndex(); 74 | let dpNames = [".main", ".secondary"]; 75 | let minmaxes = new Array(firstIndexes.length); 76 | let iArea, iIndex; 77 | for (iArea = 0, iIndex = 0, rw = minRW; iArea < this._areas.length && iIndex < firstIndexes.length; iArea += 2) { 78 | let area = this._areas[iArea]; 79 | let plotter = mgr.getPlotter(area.getName() + "Range.main"); 80 | for (let iDp in dpNames) { 81 | let dp = mgr.getDataProvider(area.getName() + dpNames[iDp]); 82 | if (dp === undefined) { 83 | continue; 84 | } 85 | dp.calcRange(firstIndexes, lastIndex, minmaxes, null); 86 | while (iIndex < firstIndexes.length) { 87 | let minW = plotter.getRequiredWidth(context, minmaxes[iIndex].min); 88 | let maxW = plotter.getRequiredWidth(context, minmaxes[iIndex].max); 89 | if (Math.max(minW, maxW) < rw) { 90 | break; 91 | } 92 | iIndex++; 93 | rw += nw; 94 | } 95 | } 96 | } 97 | } 98 | for (i = 1; i < this._areas.length; i += 2) { 99 | this._areas[i].measure(context, rw, rh[i >> 1]); 100 | } 101 | let lw = width - rw; 102 | for (i = 0; i < this._areas.length; i += 2) { 103 | this._areas[i].measure(context, lw, rh[i >> 1]); 104 | } 105 | } 106 | 107 | layout(left, top, right, bottom, forceChange) { 108 | super.layout(left, top, right, bottom, forceChange); 109 | if (this._areas.length < 1) 110 | return; 111 | let area; 112 | let center = left + this._areas[0].getMeasuredWidth(); 113 | let t = top, 114 | b; 115 | if (!forceChange) 116 | forceChange = this.isChanged(); 117 | let i, cnt = this._areas.length; 118 | for (i = 0; i < cnt; i++) { 119 | area = this._areas[i]; 120 | b = t + area.getMeasuredHeight(); 121 | area.layout(left, t, center, b, forceChange); 122 | i++; 123 | area = this._areas[i]; 124 | area.layout(center, t, this.getRight(), b, forceChange); 125 | t = b; 126 | } 127 | this.setChanged(false); 128 | } 129 | 130 | drawGrid(context) { 131 | if (this._areas.length < 1) { 132 | return; 133 | } 134 | let mgr = ChartManager.instance; 135 | let theme = mgr.getTheme(this.getFrameName()); 136 | context.fillStyle = theme.getColor(themes.Theme.Color.Grid1); 137 | context.fillRect(this._areas[0].getRight(), this.getTop(), 1, this.getHeight()); 138 | let i, cnt = this._areas.length - 2; 139 | for (i = 0; i < cnt; i += 2) 140 | context.fillRect(this.getLeft(), this._areas[i].getBottom(), this.getWidth(), 1); 141 | if (!mgr.getCaptureMouseWheelDirectly()) { 142 | for (i = 0, cnt += 2; i < cnt; i += 2) { 143 | if (this._areas[i].isSelected()) { 144 | context.strokeStyle = theme.getColor(themes.Theme.Color.Indicator1); 145 | context.strokeRect( 146 | this.getLeft() + 0.5, this.getTop() + 0.5, 147 | this.getWidth() - 1, this.getHeight() - 1); 148 | break; 149 | } 150 | } 151 | } 152 | } 153 | 154 | highlight(area) { 155 | this._highlightedArea = null; 156 | let e, i, cnt = this._areas.length; 157 | for (i = 0; i < cnt; i++) { 158 | e = this._areas[i]; 159 | if (e === area) { 160 | i &= ~1; 161 | e = this._areas[i]; 162 | e.highlight(e); 163 | this._highlightedArea = e; 164 | i++; 165 | e = this._areas[i]; 166 | e.highlight(null); 167 | e.highlight(e); 168 | } else { 169 | e.highlight(null); 170 | } 171 | } 172 | return this._highlightedArea !== null ? this : null; 173 | } 174 | 175 | select(area) { 176 | this._selectedArea = null; 177 | let e, i, cnt = this._areas.length; 178 | for (i = 0; i < cnt; i++) { 179 | e = this._areas[i]; 180 | if (e === area) { 181 | i &= ~1; 182 | e = this._areas[i]; 183 | e.select(e); 184 | this._selectedArea = e; 185 | i++; 186 | e = this._areas[i]; 187 | e.select(e); 188 | } else { 189 | e.select(null); 190 | } 191 | } 192 | return this._selectedArea !== null ? this : null; 193 | } 194 | 195 | onMouseMove(x, y) { 196 | if (this._focusedRowIndex >= 0) { 197 | let upper = this._areas[this._focusedRowIndex]; 198 | let lower = this._areas[this._focusedRowIndex + 2]; 199 | let d = y - this._oldY; 200 | if (d === 0) 201 | return this; 202 | let upperBottom = this._oldUpperBottom + d; 203 | let lowerTop = this._oldLowerTop + d; 204 | if (upperBottom - upper.getTop() >= 60 && lower.getBottom() - lowerTop >= 60) { 205 | upper.setBottom(upperBottom); 206 | lower.setTop(lowerTop); 207 | } 208 | return this; 209 | } 210 | let i, cnt = this._areas.length - 2; 211 | for (i = 0; i < cnt; i += 2) { 212 | let b = this._areas[i].getBottom(); 213 | if (y >= b - 4 && y < b + 4) { 214 | ChartManager.instance.showCursor('n-resize'); 215 | return this; 216 | } 217 | } 218 | return null; 219 | } 220 | 221 | onMouseLeave(x, y) { 222 | this._focusedRowIndex = -1; 223 | } 224 | 225 | onMouseDown(x, y) { 226 | let i, cnt = this._areas.length - 2; 227 | for (i = 0; i < cnt; i += 2) { 228 | let b = this._areas[i].getBottom(); 229 | if (y >= b - 4 && y < b + 4) { 230 | this._focusedRowIndex = i; 231 | this._oldY = y; 232 | this._oldUpperBottom = b; 233 | this._oldLowerTop = this._areas[i + 2].getTop(); 234 | return this; 235 | } 236 | } 237 | return null; 238 | } 239 | 240 | onMouseUp(x, y) { 241 | if (this._focusedRowIndex >= 0) { 242 | this._focusedRowIndex = -1; 243 | let i, cnt = this._areas.length; 244 | let height = []; 245 | for (i = 0; i < cnt; i += 2) { 246 | height.push(this._areas[i].getHeight()); 247 | } 248 | ChartSettings.get().charts.areaHeight = height; 249 | ChartSettings.save(); 250 | } 251 | return this; 252 | } 253 | 254 | } 255 | 256 | export class DockableLayout extends areas.ChartAreaGroup { 257 | 258 | constructor(name) { 259 | super(name); 260 | } 261 | 262 | measure(context, width, height) { 263 | super.measure(context, width, height); 264 | width = this.getMeasuredWidth(); 265 | height = this.getMeasuredHeight(); 266 | for (let i in this._areas) { 267 | let area = this._areas[i]; 268 | area.measure(context, width, height); 269 | switch (area.getDockStyle()) { 270 | case areas.ChartArea.DockStyle.left: 271 | case areas.ChartArea.DockStyle.Right: 272 | width -= area.getMeasuredWidth(); 273 | break; 274 | case areas.ChartArea.DockStyle.Top: 275 | case areas.ChartArea.DockStyle.Bottom: 276 | height -= area.getMeasuredHeight(); 277 | break; 278 | case areas.ChartArea.DockStyle.Fill: 279 | width = 0; 280 | height = 0; 281 | break; 282 | } 283 | } 284 | } 285 | 286 | layout(left, top, right, bottom, forceChange) { 287 | super.layout(left, top, right, bottom, forceChange); 288 | left = this.getLeft(); 289 | top = this.getTop(); 290 | right = this.getRight(); 291 | bottom = this.getBottom(); 292 | let w, h; 293 | if (!forceChange) { 294 | forceChange = this.isChanged(); 295 | } 296 | for (let i in this._areas) { 297 | let area = this._areas[i]; 298 | switch (area.getDockStyle()) { 299 | case areas.ChartArea.DockStyle.left: 300 | w = area.getMeasuredWidth(); 301 | area.layout(left, top, left + w, bottom, forceChange); 302 | left += w; 303 | break; 304 | case areas.ChartArea.DockStyle.Top: 305 | h = area.getMeasuredHeight(); 306 | area.layout(left, top, right, top + h, forceChange); 307 | top += h; 308 | break; 309 | case areas.ChartArea.DockStyle.Right: 310 | w = area.getMeasuredWidth(); 311 | area.layout(right - w, top, right, bottom, forceChange); 312 | right -= w; 313 | break; 314 | case areas.ChartArea.DockStyle.Bottom: 315 | h = area.getMeasuredHeight(); 316 | area.layout(left, bottom - h, right, bottom, forceChange); 317 | bottom -= h; 318 | break; 319 | case areas.ChartArea.DockStyle.Fill: 320 | area.layout(left, top, right, bottom, forceChange); 321 | left = right; 322 | top = bottom; 323 | break; 324 | } 325 | } 326 | this.setChanged(false); 327 | } 328 | 329 | drawGrid(context) { 330 | let mgr = ChartManager.instance; 331 | let theme = mgr.getTheme(this.getFrameName()); 332 | let left = this.getLeft(); 333 | let top = this.getTop(); 334 | let right = this.getRight(); 335 | let bottom = this.getBottom(); 336 | context.fillStyle = theme.getColor(this._gridColor); 337 | for (let i in this._areas) { 338 | let area = this._areas[i]; 339 | switch (area.getDockStyle()) { 340 | case areas.ChartArea.DockStyle.Left: 341 | context.fillRect(area.getRight(), top, 1, bottom - top); 342 | left += area.getWidth(); 343 | break; 344 | case areas.ChartArea.DockStyle.Top: 345 | context.fillRect(left, area.getBottom(), right - left, 1); 346 | top += area.getHeight(); 347 | break; 348 | case areas.ChartArea.DockStyle.Right: 349 | context.fillRect(area.getLeft(), top, 1, bottom - top); 350 | right -= area.getWidth(); 351 | break; 352 | case areas.ChartArea.DockStyle.Bottom: 353 | context.fillRect(left, area.getTop(), right - left, 1); 354 | bottom -= area.getHeight(); 355 | break; 356 | } 357 | } 358 | } 359 | 360 | } 361 | -------------------------------------------------------------------------------- /src/js/mevent.js: -------------------------------------------------------------------------------- 1 | export class MEvent { 2 | 3 | constructor() { 4 | this._handlers = []; 5 | } 6 | 7 | addHandler(o, f) { 8 | if (this.indexOf(o, f) < 0) 9 | this._handlers.push({obj: o, func: f}); 10 | } 11 | 12 | removeHandler(o, f) { 13 | let i = this.indexOf(o, f); 14 | if (i >= 0) 15 | this._handlers.splice(i, 1); 16 | } 17 | 18 | raise(s, g) { 19 | let a = this._handlers; 20 | let e, i, c = a.length; 21 | for (i = 0; i < c; i++) { 22 | e = a[i]; 23 | e.func(s, g); 24 | } 25 | } 26 | 27 | indexOf(o, f) { 28 | let a = this._handlers; 29 | let e, i, c = a.length; 30 | for (i = 0; i < c; i++) { 31 | e = a[i]; 32 | if (o === e.obj && f === e.func) 33 | return i; 34 | } 35 | return -1; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/js/named_object.js: -------------------------------------------------------------------------------- 1 | import {CName} from './cname' 2 | 3 | export class NamedObject { 4 | 5 | constructor(name) { 6 | this._name = name; 7 | this._nameObj = new CName(name); 8 | } 9 | 10 | getFrameName() { 11 | return this._nameObj.getName(0); 12 | } 13 | 14 | getDataSourceName() { 15 | return this._nameObj.getName(1); 16 | } 17 | 18 | getAreaName() { 19 | return this._nameObj.getName(2); 20 | } 21 | 22 | getName() { 23 | return this._nameObj.getName(-1); 24 | } 25 | 26 | getNameObject() { 27 | return this._nameObj; 28 | } 29 | 30 | getRectCrossPt(rect, startPt, endPt) { 31 | let crossPt; 32 | let firstPt = {x: -1, y: -1}; 33 | let secondPt = {x: -1, y: -1}; 34 | let xdiff = endPt.x - startPt.x; 35 | let ydiff = endPt.y - startPt.y; 36 | if (Math.abs(xdiff) < 2) { 37 | firstPt = {x: startPt.x, y: rect.top}; 38 | secondPt = {x: endPt.x, y: rect.bottom}; 39 | crossPt = [firstPt, secondPt]; 40 | return crossPt; 41 | } 42 | let k = ydiff / xdiff; 43 | secondPt.x = rect.right; 44 | secondPt.y = startPt.y + (rect.right - startPt.x) * k; 45 | firstPt.x = rect.left; 46 | firstPt.y = startPt.y + (rect.left - startPt.x) * k; 47 | crossPt = [firstPt, secondPt]; 48 | return crossPt; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/js/ranges.js: -------------------------------------------------------------------------------- 1 | import {NamedObject} from './named_object' 2 | import {ChartManager} from './chart_manager' 3 | 4 | export class Range extends NamedObject { 5 | 6 | constructor(name) { 7 | super(name); 8 | this._updated = true; 9 | this._minValue = Number.MAX_VALUE; 10 | this._maxValue = -Number.MAX_VALUE; 11 | this._outerMinValue = Number.MAX_VALUE; 12 | this._outerMaxValue = -Number.MAX_VALUE; 13 | this._ratio = 0; 14 | this._top = 0; 15 | this._bottom = 0; 16 | this._paddingTop = 0; 17 | this._paddingBottom = 0; 18 | this._minInterval = 36; 19 | this._selectedPosition = -1; 20 | this._selectedValue = -Number.MAX_VALUE; 21 | this._gradations = []; 22 | } 23 | 24 | isUpdated() { 25 | return this._updated; 26 | } 27 | 28 | setUpdated(v) { 29 | this._updated = v; 30 | } 31 | 32 | getMinValue() { 33 | return this._minValue; 34 | } 35 | 36 | getMaxValue() { 37 | return this._maxValue; 38 | } 39 | 40 | getRange() { 41 | return this._maxValue - this._minValue; 42 | } 43 | 44 | getOuterMinValue() { 45 | return this._outerMinValue; 46 | } 47 | 48 | getOuterMaxValue() { 49 | return this._outerMaxValue; 50 | } 51 | 52 | getOuterRange() { 53 | return this._outerMaxValue - this._outerMinValue; 54 | } 55 | 56 | getHeight() { 57 | return Math.max(0, this._bottom - this._top); 58 | } 59 | 60 | getGradations() { 61 | return this._gradations; 62 | } 63 | 64 | getMinInterval() { 65 | return this._minInterval; 66 | } 67 | 68 | setMinInterval(v) { 69 | this._minInterval = v; 70 | } 71 | 72 | getSelectedPosition() { 73 | if (this._selectedPosition >= 0) { 74 | return this._selectedPosition; 75 | } 76 | if (this._selectedValue > -Number.MAX_VALUE) { 77 | return this.toY(this._selectedValue); 78 | } 79 | return -1; 80 | } 81 | 82 | getSelectedValue() { 83 | if (this._selectedValue > -Number.MAX_VALUE) { 84 | return this._selectedValue; 85 | } 86 | let mgr = ChartManager.instance; 87 | let area = mgr.getArea(this.getAreaName()); 88 | if (area === null) { 89 | return -Number.MAX_VALUE; 90 | } 91 | if (this._selectedPosition < area.getTop() + 12 || this._selectedPosition >= area.getBottom() - 4) { 92 | return -Number.MAX_VALUE; 93 | } 94 | return this.toValue(this._selectedPosition); 95 | } 96 | 97 | setPaddingTop(p) { 98 | this._paddingTop = p; 99 | } 100 | 101 | setPaddingBottom(p) { 102 | this._paddingBottom = p; 103 | } 104 | 105 | toValue(y) { 106 | return this._maxValue - (y - this._top) / this._ratio; 107 | } 108 | 109 | toY(value) { 110 | if (this._ratio > 0) { 111 | return this._top + Math.floor((this._maxValue - value) * this._ratio + 0.5); 112 | } 113 | return this._top; 114 | } 115 | 116 | toHeight(value) { 117 | if (value == Infinity || this._ratio == 0) { 118 | return 1.5; 119 | } 120 | return Math.floor(value * this._ratio + 1.5); 121 | } 122 | 123 | update() { 124 | let min = Number.MAX_VALUE; 125 | let max = -Number.MAX_VALUE; 126 | let mgr = ChartManager.instance; 127 | let dp, dpNames = [".main", ".secondary"]; 128 | for (let i = 0; i < dpNames.length; i++) { 129 | dp = mgr.getDataProvider(this.getName() + dpNames[i]); 130 | if (dp !== null && dp !== undefined) { 131 | min = Math.min(min, dp.getMinValue()); 132 | max = Math.max(max, dp.getMaxValue()); 133 | } 134 | } 135 | let r = {"min": min, "max": max}; 136 | this.preSetRange(r); 137 | this.setRange(r.min, r.max); 138 | } 139 | 140 | select(v) { 141 | this._selectedValue = v; 142 | this._selectedPosition = -1; 143 | } 144 | 145 | selectAt(y) { 146 | this._selectedPosition = y; 147 | this._selectedValue = -Number.MAX_VALUE; 148 | } 149 | 150 | unselect() { 151 | this._selectedPosition = -1; 152 | this._selectedValue = -Number.MAX_VALUE; 153 | } 154 | 155 | preSetRange(r) { 156 | if (r.min === r.max) { 157 | r.min = -1.0; 158 | r.max = 1.0; 159 | } 160 | } 161 | 162 | setRange(minValue, maxValue) { 163 | let mgr = ChartManager.instance; 164 | let area = mgr.getArea(this.getAreaName()); 165 | if (this._minValue === minValue && this._maxValue === maxValue && !area.isChanged()) { 166 | return; 167 | } 168 | this._updated = true; 169 | this._minValue = minValue; 170 | this._maxValue = maxValue; 171 | this._gradations = []; 172 | let top = area.getTop() + this._paddingTop; 173 | let bottom = area.getBottom() - (this._paddingBottom + 1); 174 | if (top >= bottom) { 175 | this._minValue = this._maxValue; 176 | return; 177 | } 178 | this._top = top; 179 | this._bottom = bottom; 180 | if (this._maxValue > this._minValue) 181 | this._ratio = (bottom - top) / (this._maxValue - this._minValue); 182 | else { 183 | this._ratio = 1; 184 | } 185 | this._outerMinValue = this.toValue(area.getBottom()); 186 | this._outerMaxValue = this.toValue(area.getTop()); 187 | this.updateGradations(); 188 | } 189 | 190 | calcInterval() { 191 | let H = this.getHeight(); 192 | let h = this.getMinInterval(); 193 | if ((H / h) <= 1) { 194 | h = H >> 1; 195 | } 196 | let d = this.getRange(); 197 | let i = 0; 198 | while (i > -2 && Math.floor(d) < d) { 199 | d *= 10.0; 200 | i--; 201 | } 202 | let m, c; 203 | for (; ; i++) { 204 | c = Math.pow(10.0, i); 205 | m = c; 206 | if (this.toHeight(m) > h) 207 | break; 208 | m = 2.0 * c; 209 | if (this.toHeight(m) > h) 210 | break; 211 | m = 5.0 * c; 212 | if (this.toHeight(m) > h) 213 | break; 214 | } 215 | return m; 216 | } 217 | 218 | updateGradations() { 219 | this._gradations = []; 220 | let interval = this.calcInterval(); 221 | if (interval <= 0.0) { 222 | return; 223 | } 224 | let v = Math.floor(this.getMaxValue() / interval) * interval; 225 | do { 226 | this._gradations.push(v); 227 | v -= interval; 228 | } while (v > this.getMinValue()); 229 | } 230 | 231 | } 232 | 233 | 234 | export class PositiveRange extends Range { 235 | 236 | constructor(name) { 237 | super(name); 238 | } 239 | 240 | preSetRange(r) { 241 | if (r.min < 0) r.min = 0; 242 | if (r.max < 0) r.max = 0; 243 | } 244 | 245 | } 246 | 247 | 248 | export class ZeroBasedPositiveRange extends Range { 249 | 250 | constructor(name) { 251 | super(name); 252 | } 253 | 254 | preSetRange(r) { 255 | r.min = 0; 256 | if (r.max < 0) r.max = 0; 257 | } 258 | 259 | } 260 | 261 | 262 | export class MainRange extends Range { 263 | 264 | constructor(name) { 265 | super(name); 266 | } 267 | 268 | preSetRange(r) { 269 | let mgr = ChartManager.instance; 270 | 271 | let timeline = mgr.getTimeline(this.getDataSourceName()); 272 | let dIndex = timeline.getMaxIndex() - timeline.getLastIndex(); 273 | if (dIndex < 25) { 274 | let ds = mgr.getDataSource(this.getDataSourceName()); 275 | 276 | let data = ds.getDataAt(ds.getDataCount() - 1); 277 | let d = ((r.max - r.min) / 4) * (1 - (dIndex / 25)); 278 | 279 | r.min = Math.min(r.min, Math.max(data.low - d, 0)); 280 | r.max = Math.max(r.max, data.high + d); 281 | } 282 | 283 | if (r.min > 0) { 284 | let a = r.max / r.min; 285 | 286 | if (a < 1.016) { 287 | let m = (r.max + r.min) / 2.0; 288 | let c = (a - 1.0) * 1.5; 289 | r.max = m * (1.0 + c); 290 | r.min = m * (1.0 - c); 291 | } else if (a < 1.048) { 292 | let m = (r.max + r.min) / 2.0; 293 | r.max = m * 1.024; 294 | r.min = m * 0.976; 295 | } 296 | } 297 | if (r.min < 0) r.min = 0; 298 | if (r.max < 0) r.max = 0; 299 | } 300 | 301 | } 302 | 303 | 304 | export class ZeroCenteredRange extends Range { 305 | 306 | constructor(name) { 307 | super(name); 308 | } 309 | 310 | calcInterval(area) { 311 | let h = this.getMinInterval(); 312 | if (area.getHeight() / h < 2) { 313 | return 0.0; 314 | } 315 | let r = this.getRange(); 316 | let i; 317 | for (i = 3; ; i += 2) { 318 | if (this.toHeight(r / i) <= h) 319 | break; 320 | } 321 | i -= 2; 322 | return r / i; 323 | } 324 | 325 | updateGradations() { 326 | this._gradations = []; 327 | let mgr = ChartManager.instance; 328 | let area = mgr.getArea(this.getAreaName()); 329 | let interval = this.calcInterval(area); 330 | if (interval <= 0.0) { 331 | return; 332 | } 333 | let v = interval / 2.0; 334 | do { 335 | this._gradations.push(v); 336 | this._gradations.push(-v); 337 | v += interval; 338 | } while (v <= this.getMaxValue()); 339 | } 340 | 341 | preSetRange(r) { 342 | let abs = Math.max(Math.abs(r.min), Math.abs(r.max)); 343 | r.min = -abs; 344 | r.max = abs; 345 | } 346 | 347 | } 348 | 349 | 350 | export class PercentageRange extends Range { 351 | 352 | constructor(name) { 353 | super(name); 354 | } 355 | 356 | updateGradations() { 357 | this._gradations = []; 358 | let mgr = ChartManager.instance; 359 | let area = mgr.getArea(this.getAreaName()); 360 | let interval = 10.0; 361 | let h = Math.floor(this.toHeight(interval)); 362 | if ((h << 2) > area.getHeight()) 363 | return; 364 | let v = Math.ceil(this.getMinValue() / interval) * interval; 365 | if (v === 0.0) 366 | v = 0; 367 | if ((h << 2) < 24) { 368 | if ((h << 1) < 8) 369 | return; 370 | do { 371 | if (v === 20.0 || v === 80.0) 372 | this._gradations.push(v); 373 | v += interval; 374 | } while (v < this.getMaxValue()); 375 | } else { 376 | do { 377 | if (h < 8) { 378 | if (v === 20.0 || v === 50.0 || v === 80.0) 379 | this._gradations.push(v); 380 | } else { 381 | if (v === 0.0 || v === 20.0 || v === 50.0 || v === 80.0 || v === 100.0) 382 | this._gradations.push(v); 383 | } 384 | v += interval; 385 | } while (v < this.getMaxValue()); 386 | } 387 | } 388 | 389 | } 390 | 391 | -------------------------------------------------------------------------------- /src/js/templates.js: -------------------------------------------------------------------------------- 1 | import {ChartManager} from './chart_manager' 2 | import {ChartSettings} from './chart_settings' 3 | import * as data_sources from './data_sources' 4 | import * as data_providers from './data_providers' 5 | import * as areas from './areas' 6 | import * as plotters from './plotters' 7 | import {Timeline} from './timeline' 8 | import {CName} from './cname' 9 | import * as layouts from './layouts' 10 | import * as themes from './themes' 11 | import * as ranges from './ranges' 12 | 13 | export class Template { 14 | 15 | static createCandlestickDataSource(dsAlias) { 16 | return new data_sources.MainDataSource(dsAlias); 17 | } 18 | 19 | static createDataSource(dsName, dsAlias, createFunc) { 20 | let mgr = ChartManager.instance; 21 | if (mgr.getCachedDataSource(dsAlias) === null) 22 | mgr.setCachedDataSource(dsAlias, createFunc(dsAlias)); 23 | mgr.setCurrentDataSource(dsName, dsAlias); 24 | mgr.updateData(dsName, null); 25 | } 26 | 27 | static createTableComps(dsName) { 28 | this.createMainChartComps(dsName); 29 | this.createTimelineComps(dsName); 30 | } 31 | 32 | static createMainChartComps(dsName) { 33 | let mgr = ChartManager.instance; 34 | let tableLayout = mgr.getArea(dsName + ".charts"); 35 | let areaName = dsName + ".main"; 36 | let rangeAreaName = areaName + "Range"; 37 | let area = new areas.MainArea(areaName); 38 | mgr.setArea(areaName, area); 39 | tableLayout.addArea(area); 40 | let rangeArea = new areas.MainRangeArea(rangeAreaName); 41 | mgr.setArea(rangeAreaName, rangeArea); 42 | tableLayout.addArea(rangeArea); 43 | let dp = new data_providers.MainDataProvider(areaName + ".main"); 44 | mgr.setDataProvider(dp.getName(), dp); 45 | mgr.setMainIndicator(dsName, "MA"); 46 | let range = new ranges.MainRange(areaName); 47 | mgr.setRange(range.getName(), range); 48 | range.setPaddingTop(28); 49 | range.setPaddingBottom(12); 50 | let plotter = new plotters.MainAreaBackgroundPlotter(areaName + ".background"); 51 | mgr.setPlotter(plotter.getName(), plotter); 52 | plotter = new plotters.CGridPlotter(areaName + ".grid"); 53 | mgr.setPlotter(plotter.getName(), plotter); 54 | plotter = new plotters.CandlestickPlotter(areaName + ".main"); 55 | mgr.setPlotter(plotter.getName(), plotter); 56 | plotter = new plotters.MinMaxPlotter(areaName + ".decoration"); 57 | mgr.setPlotter(plotter.getName(), plotter); 58 | plotter = new plotters.MainInfoPlotter(areaName + ".info"); 59 | mgr.setPlotter(plotter.getName(), plotter); 60 | plotter = new plotters.SelectionPlotter(areaName + ".selection"); 61 | mgr.setPlotter(plotter.getName(), plotter); 62 | plotter = new plotters.CDynamicLinePlotter(areaName + ".tool"); 63 | mgr.setPlotter(plotter.getName(), plotter); 64 | plotter = new plotters.RangeAreaBackgroundPlotter(areaName + "Range.background"); 65 | mgr.setPlotter(plotter.getName(), plotter); 66 | plotter = new plotters.COrderGraphPlotter(areaName + "Range.grid"); 67 | mgr.setPlotter(plotter.getName(), plotter); 68 | plotter = new plotters.RangePlotter(areaName + "Range.main"); 69 | mgr.setPlotter(plotter.getName(), plotter); 70 | plotter = new plotters.RangeSelectionPlotter(areaName + "Range.selection"); 71 | mgr.setPlotter(plotter.getName(), plotter); 72 | plotter = new plotters.LastClosePlotter(areaName + "Range.decoration"); 73 | mgr.setPlotter(plotter.getName(), plotter); 74 | } 75 | 76 | static createIndicatorChartComps(dsName, indicName) { 77 | let mgr = ChartManager.instance; 78 | let tableLayout = mgr.getArea(dsName + ".charts"); 79 | let areaName = dsName + ".indic" + tableLayout.getNextRowId(); 80 | let rangeAreaName = areaName + "Range"; 81 | let area = new areas.IndicatorArea(areaName); 82 | mgr.setArea(areaName, area); 83 | tableLayout.addArea(area); 84 | let rowIndex = tableLayout.getAreaCount() >> 1; 85 | let heights = ChartSettings.get().charts.areaHeight; 86 | if (heights.length > rowIndex) { 87 | let a, i; 88 | for (i = 0; i < rowIndex; i++) { 89 | a = tableLayout.getAreaAt(i << 1); 90 | a.setTop(0); 91 | a.setBottom(heights[i]); 92 | } 93 | area.setTop(0); 94 | area.setBottom(heights[rowIndex]); 95 | } 96 | let rangeArea = new areas.IndicatorRangeArea(rangeAreaName); 97 | mgr.setArea(rangeAreaName, rangeArea); 98 | tableLayout.addArea(rangeArea); 99 | let dp = new data_providers.IndicatorDataProvider(areaName + ".secondary"); 100 | mgr.setDataProvider(dp.getName(), dp); 101 | if (mgr.setIndicator(areaName, indicName) === false) { 102 | mgr.removeIndicator(areaName); 103 | return; 104 | } 105 | let plotter = new plotters.MainAreaBackgroundPlotter(areaName + ".background"); 106 | mgr.setPlotter(plotter.getName(), plotter); 107 | plotter = new plotters.CGridPlotter(areaName + ".grid"); 108 | mgr.setPlotter(plotter.getName(), plotter); 109 | plotter = new plotters.IndicatorPlotter(areaName + ".secondary"); 110 | mgr.setPlotter(plotter.getName(), plotter); 111 | plotter = new plotters.IndicatorInfoPlotter(areaName + ".info"); 112 | mgr.setPlotter(plotter.getName(), plotter); 113 | plotter = new plotters.SelectionPlotter(areaName + ".selection"); 114 | mgr.setPlotter(plotter.getName(), plotter); 115 | plotter = new plotters.RangeAreaBackgroundPlotter(areaName + "Range.background"); 116 | mgr.setPlotter(plotter.getName(), plotter); 117 | plotter = new plotters.RangePlotter(areaName + "Range.main"); 118 | mgr.setPlotter(plotter.getName(), plotter); 119 | plotter = new plotters.RangeSelectionPlotter(areaName + "Range.selection"); 120 | mgr.setPlotter(plotter.getName(), plotter); 121 | } 122 | 123 | static createTimelineComps(dsName) { 124 | let mgr = ChartManager.instance; 125 | let plotter; 126 | let timeline = new Timeline(dsName); 127 | mgr.setTimeline(timeline.getName(), timeline); 128 | plotter = new plotters.TimelineAreaBackgroundPlotter(dsName + ".timeline.background"); 129 | mgr.setPlotter(plotter.getName(), plotter); 130 | plotter = new plotters.TimelinePlotter(dsName + ".timeline.main"); 131 | mgr.setPlotter(plotter.getName(), plotter); 132 | plotter = new plotters.TimelineSelectionPlotter(dsName + ".timeline.selection"); 133 | mgr.setPlotter(plotter.getName(), plotter); 134 | } 135 | 136 | static createLiveOrderComps(dsName) { 137 | let mgr = ChartManager.instance; 138 | let plotter; 139 | plotter = new plotters.BackgroundPlotter(dsName + ".main.background"); 140 | mgr.setPlotter(plotter.getName(), plotter); 141 | plotter = new plotters.CLiveOrderPlotter(dsName + ".main.main"); 142 | mgr.setPlotter(plotter.getName(), plotter); 143 | } 144 | 145 | static createLiveTradeComps(dsName) { 146 | let mgr = ChartManager.instance; 147 | let plotter; 148 | plotter = new plotters.BackgroundPlotter(dsName + ".main.background"); 149 | mgr.setPlotter(plotter.getName(), plotter); 150 | plotter = new plotters.CLiveTradePlotter(dsName + ".main.main"); 151 | mgr.setPlotter(plotter.getName(), plotter); 152 | } 153 | 154 | } 155 | 156 | export class DefaultTemplate extends Template { 157 | 158 | static loadTemplate(dsName, dsAlias) { 159 | let mgr = ChartManager.instance; 160 | let settings = ChartSettings.get(); 161 | let frameName = (new CName(dsName)).getCompAt(0); 162 | mgr.unloadTemplate(frameName); 163 | this.createDataSource(dsName, dsAlias, this.createCandlestickDataSource); 164 | let frame = new layouts.DockableLayout(frameName); 165 | mgr.setFrame(frame.getName(), frame); 166 | mgr.setArea(frame.getName(), frame); 167 | frame.setGridColor(themes.Theme.Color.Grid1); 168 | let area = new areas.TimelineArea(dsName + ".timeline"); 169 | mgr.setArea(area.getName(), area); 170 | frame.addArea(area); 171 | area.setDockStyle(areas.ChartArea.DockStyle.Bottom); 172 | area.Measuring.addHandler(area, TemplateMeasuringHandler.onMeasuring); 173 | let tableLayout = new layouts.TableLayout(dsName + ".charts"); 174 | mgr.setArea(tableLayout.getName(), tableLayout); 175 | tableLayout.setDockStyle(areas.ChartArea.DockStyle.Fill); 176 | frame.addArea(tableLayout); 177 | this.createTableComps(dsName); 178 | mgr.setThemeName(frameName, settings.theme); 179 | return mgr; 180 | } 181 | 182 | } 183 | 184 | export class TemplateMeasuringHandler { 185 | 186 | static onMeasuring(sender, args) { 187 | let width = args.Width; 188 | let height = args.Height; 189 | let areaName = sender.getNameObject().getCompAt(2); 190 | if (areaName === "timeline") { 191 | sender.setMeasuredDimension(width, 22); 192 | } 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /src/js/themes.js: -------------------------------------------------------------------------------- 1 | import Kline from './kline' 2 | 3 | export class Theme { 4 | constructor(){ 5 | this._colors=[]; 6 | this._fonts=[]; 7 | } 8 | getColor(which) { 9 | return this._colors[which]; 10 | } 11 | getFont(which) { 12 | return this._fonts[which]; 13 | } 14 | } 15 | Theme.theme_color_id = 0; 16 | Theme.theme_font_id = 0; 17 | Theme.Color = { 18 | Positive: Theme.theme_color_id++, 19 | Negative: Theme.theme_color_id++, 20 | PositiveDark: Theme.theme_color_id++, 21 | NegativeDark: Theme.theme_color_id++, 22 | Unchanged: Theme.theme_color_id++, 23 | Background: Theme.theme_color_id++, 24 | Cursor: Theme.theme_color_id++, 25 | RangeMark: Theme.theme_color_id++, 26 | Indicator0: Theme.theme_color_id++, 27 | Indicator1: Theme.theme_color_id++, 28 | Indicator2: Theme.theme_color_id++, 29 | Indicator3: Theme.theme_color_id++, 30 | Indicator4: Theme.theme_color_id++, 31 | Indicator5: Theme.theme_color_id++, 32 | Grid0: Theme.theme_color_id++, 33 | Grid1: Theme.theme_color_id++, 34 | Grid2: Theme.theme_color_id++, 35 | Grid3: Theme.theme_color_id++, 36 | Grid4: Theme.theme_color_id++, 37 | TextPositive: Theme.theme_color_id++, 38 | TextNegative: Theme.theme_color_id++, 39 | Text0: Theme.theme_color_id++, 40 | Text1: Theme.theme_color_id++, 41 | Text2: Theme.theme_color_id++, 42 | Text3: Theme.theme_color_id++, 43 | Text4: Theme.theme_color_id++, 44 | LineColorNormal: Theme.theme_color_id++, 45 | LineColorSelected: Theme.theme_color_id++, 46 | CircleColorFill: Theme.theme_color_id++, 47 | CircleColorStroke: Theme.theme_color_id++ 48 | }; 49 | Theme.Font = { 50 | Default: Theme.theme_font_id++ 51 | }; 52 | 53 | export class DarkTheme extends Theme { 54 | 55 | constructor() { 56 | super(); 57 | this._colors = []; 58 | 59 | this._colors[Theme.Color.Positive] = "#19b34c"; 60 | this._colors[Theme.Color.Negative] = "#990e0e"; 61 | this._colors[Theme.Color.PositiveDark] = "#004718"; 62 | this._colors[Theme.Color.NegativeDark] = "#3b0e08"; 63 | 64 | this._colors[Theme.Color.Unchanged] = "#fff"; 65 | this._colors[Theme.Color.Background] = "#161616"; 66 | this._colors[Theme.Color.Cursor] = "#aaa"; 67 | this._colors[Theme.Color.RangeMark] = "#f9ee30"; 68 | this._colors[Theme.Color.Indicator0] = "#ddd"; 69 | this._colors[Theme.Color.Indicator1] = "#f9ee30"; 70 | this._colors[Theme.Color.Indicator2] = "#f600ff"; 71 | this._colors[Theme.Color.Indicator3] = "#6bf"; 72 | this._colors[Theme.Color.Indicator4] = "#a5cf81"; 73 | this._colors[Theme.Color.Indicator5] = "#e18b89"; 74 | this._colors[Theme.Color.Grid0] = "#555"; 75 | this._colors[Theme.Color.Grid1] = "#555"; 76 | this._colors[Theme.Color.Grid3] = "#888"; 77 | this._colors[Theme.Color.Grid4] = "#aaa"; 78 | this._colors[Theme.Color.TextPositive] = "#1bd357"; 79 | this._colors[Theme.Color.TextNegative] = "#ff6f5e"; 80 | this._colors[Theme.Color.Text0] = "#444"; 81 | this._colors[Theme.Color.Text1] = "#666"; 82 | this._colors[Theme.Color.Text2] = "#888"; 83 | this._colors[Theme.Color.Text3] = "#aaa"; 84 | this._colors[Theme.Color.Text4] = "#ccc"; 85 | this._colors[Theme.Color.LineColorNormal] = "#a6a6a6"; 86 | this._colors[Theme.Color.LineColorSelected] = "#ffffff"; 87 | this._colors[Theme.Color.CircleColorFill] = "#161616"; 88 | this._colors[Theme.Color.CircleColorStroke] = "#ffffff"; 89 | this._fonts = []; 90 | this._fonts[Theme.Font.Default] = "12px Tahoma"; 91 | } 92 | 93 | } 94 | 95 | 96 | export class LightTheme extends Theme { 97 | 98 | constructor() { 99 | super(); 100 | this._colors = []; 101 | 102 | this._colors[Theme.Color.Positive] = "#53b37b"; 103 | this._colors[Theme.Color.Negative] = "#db5542"; 104 | this._colors[Theme.Color.PositiveDark] = "#66d293"; 105 | this._colors[Theme.Color.NegativeDark] = "#ffadaa"; 106 | 107 | this._colors[Theme.Color.Unchanged] = "#fff"; 108 | this._colors[Theme.Color.Background] = "#f6f6f6"; 109 | this._colors[Theme.Color.Cursor] = "#aaa"; 110 | this._colors[Theme.Color.RangeMark] = "#f27935"; 111 | this._colors[Theme.Color.Indicator0] = "#d27972"; 112 | this._colors[Theme.Color.Indicator1] = "#ffb400"; 113 | this._colors[Theme.Color.Indicator2] = "#e849b9"; 114 | this._colors[Theme.Color.Indicator3] = "#1478c8"; 115 | this._colors[Theme.Color.Grid0] = "#aaa"; 116 | this._colors[Theme.Color.Grid1] = "#aaa"; 117 | this._colors[Theme.Color.Grid3] = "#bbb"; 118 | this._colors[Theme.Color.Grid4] = "#aaa"; 119 | this._colors[Theme.Color.TextPositive] = "#53b37b"; 120 | this._colors[Theme.Color.TextNegative] = "#db5542"; 121 | this._colors[Theme.Color.Text0] = "#ccc"; 122 | this._colors[Theme.Color.Text1] = "#aaa"; 123 | this._colors[Theme.Color.Text2] = "#888"; 124 | this._colors[Theme.Color.Text3] = "#666"; 125 | this._colors[Theme.Color.Text4] = "#444"; 126 | this._colors[Theme.Color.LineColorNormal] = "#8c8c8c"; 127 | this._colors[Theme.Color.LineColorSelected] = "#393c40"; 128 | this._colors[Theme.Color.CircleColorFill] = "#f6f6f6"; 129 | this._colors[Theme.Color.CircleColorStroke] = "#393c40"; 130 | this._fonts = []; 131 | this._fonts[Theme.Font.Default] = "12px Tahoma"; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/js/timeline.js: -------------------------------------------------------------------------------- 1 | import {NamedObject} from './named_object' 2 | import {ChartManager} from './chart_manager' 3 | import {DataSource} from './data_sources' 4 | 5 | export class Timeline extends NamedObject { 6 | 7 | constructor(name) { 8 | super(name); 9 | this._updated = false; 10 | this._innerLeft = 0; 11 | this._innerWidth = 0; 12 | this._firstColumnLeft = 0; 13 | this._scale = 3; 14 | this._lastScale = -1; 15 | this._maxItemCount = 0; 16 | this._maxIndex = 0; 17 | this._firstIndex = -1; 18 | this._selectedIndex = -1; 19 | this._savedFirstIndex = -1; 20 | } 21 | 22 | 23 | isLatestShown() { 24 | return this.getLastIndex() === this._maxIndex; 25 | } 26 | 27 | isUpdated() { 28 | return this._updated; 29 | } 30 | 31 | setUpdated(v) { 32 | this._updated = v; 33 | } 34 | 35 | getItemWidth() { 36 | return Timeline.itemWidth[this._scale]; 37 | } 38 | 39 | getSpaceWidth() { 40 | return Timeline.spaceWidth[this._scale]; 41 | } 42 | 43 | getColumnWidth() { 44 | return this.getSpaceWidth() + this.getItemWidth(); 45 | } 46 | 47 | getInnerWidth() { 48 | return this._innerWidth; 49 | } 50 | 51 | getItemLeftOffset() { 52 | return this.getSpaceWidth(); 53 | } 54 | 55 | getItemCenterOffset() { 56 | return this.getSpaceWidth() + (this.getItemWidth() >> 1); 57 | } 58 | 59 | getFirstColumnLeft() { 60 | return this._firstColumnLeft; 61 | } 62 | 63 | getMaxItemCount() { 64 | return this._maxItemCount; 65 | } 66 | 67 | getFirstIndex() { 68 | return this._firstIndex; 69 | } 70 | 71 | getLastIndex() { 72 | return Math.min(this._firstIndex + this._maxItemCount, this._maxIndex); 73 | } 74 | 75 | getSelectedIndex() { 76 | return this._selectedIndex; 77 | } 78 | 79 | getMaxIndex() { 80 | return this._maxIndex; 81 | } 82 | 83 | calcColumnCount(w) { 84 | return Math.floor(w / this.getColumnWidth()) << 0; 85 | } 86 | 87 | calcFirstColumnLeft(maxItemCount) { 88 | return this._innerLeft + this._innerWidth - (this.getColumnWidth() * maxItemCount); 89 | } 90 | 91 | calcFirstIndexAlignRight(oldFirstIndex, oldMaxItemCount, newMaxItemCount) { 92 | return Math.max(0, oldFirstIndex + Math.max(oldMaxItemCount, 1) - Math.max(newMaxItemCount, 1)); 93 | } 94 | 95 | calcFirstIndex(newMaxItemCount) { 96 | return this.validateFirstIndex( 97 | this.calcFirstIndexAlignRight(this._firstIndex, this._maxItemCount, 98 | newMaxItemCount), newMaxItemCount); 99 | } 100 | 101 | updateMaxItemCount() { 102 | let newMaxItemCount = this.calcColumnCount(this._innerWidth); 103 | let newFirstIndex; 104 | if (this._maxItemCount < 1) { 105 | newFirstIndex = this.calcFirstIndex(newMaxItemCount); 106 | } else if (this._lastScale === this._scale) { 107 | newFirstIndex = this.validateFirstIndex(this._firstIndex - (newMaxItemCount - this._maxItemCount)); 108 | } else { 109 | let focusedIndex = (this._selectedIndex >= 0) ? this._selectedIndex : this.getLastIndex() - 1; 110 | newFirstIndex = this.validateFirstIndex(focusedIndex - 111 | Math.round((focusedIndex - this._firstIndex) * newMaxItemCount / this._maxItemCount)); 112 | } 113 | this._lastScale = this._scale; 114 | if (this._firstIndex !== newFirstIndex) { 115 | if (this._selectedIndex === this._firstIndex) 116 | this._selectedIndex = newFirstIndex; 117 | this._firstIndex = newFirstIndex; 118 | this._updated = true; 119 | } 120 | if (this._maxItemCount !== newMaxItemCount) { 121 | this._maxItemCount = newMaxItemCount; 122 | this._updated = true; 123 | } 124 | this._firstColumnLeft = this.calcFirstColumnLeft(newMaxItemCount); 125 | } 126 | 127 | validateFirstIndex(firstIndex, maxItemCount) { 128 | if (this._maxIndex < 1) { 129 | return -1; 130 | } 131 | if (firstIndex < 0) { 132 | return 0; 133 | } 134 | let lastFirst = Math.max(0, this._maxIndex - 1 /*maxItemCount*/); 135 | if (firstIndex > lastFirst) { 136 | return lastFirst; 137 | } 138 | return firstIndex; 139 | } 140 | 141 | validateSelectedIndex() { 142 | if (this._selectedIndex < this._firstIndex) 143 | this._selectedIndex = -1; 144 | else if (this._selectedIndex >= this.getLastIndex()) 145 | this._selectedIndex = -1; 146 | } 147 | 148 | onLayout() { 149 | let mgr = ChartManager.instance; 150 | let area = mgr.getArea(this.getDataSourceName() + ".main"); 151 | if (area !== null) { 152 | this._innerLeft = area.getLeft() + Timeline.PADDING_LEFT; 153 | let w = Math.max(0, area.getWidth() - (Timeline.PADDING_LEFT + Timeline.PADDING_RIGHT)); 154 | if (this._innerWidth !== w) { 155 | this._innerWidth = w; 156 | this.updateMaxItemCount(); 157 | } 158 | } 159 | } 160 | 161 | toIndex(x) { 162 | return this._firstIndex + this.calcColumnCount(x - this._firstColumnLeft); 163 | } 164 | 165 | toColumnLeft(index) { 166 | return this._firstColumnLeft + (this.getColumnWidth() * (index - this._firstIndex)); 167 | } 168 | 169 | toItemLeft(index) { 170 | return this.toColumnLeft(index) + this.getItemLeftOffset(); 171 | } 172 | 173 | toItemCenter(index) { 174 | return this.toColumnLeft(index) + this.getItemCenterOffset(); 175 | } 176 | 177 | selectAt(x) { 178 | this._selectedIndex = this.toIndex(x); 179 | this.validateSelectedIndex(); 180 | return (this._selectedIndex >= 0); 181 | } 182 | 183 | unselect() { 184 | this._selectedIndex = -1; 185 | } 186 | 187 | update() { 188 | let mgr = ChartManager.instance; 189 | let ds = mgr.getDataSource(this.getDataSourceName()); 190 | let oldMaxIndex = this._maxIndex; 191 | this._maxIndex = ds.getDataCount(); 192 | switch (ds.getUpdateMode()) { 193 | case DataSource.UpdateMode.Refresh: 194 | if (this._maxIndex < 1) 195 | this._firstIndex = -1; 196 | else 197 | this._firstIndex = Math.max(this._maxIndex - this._maxItemCount, 0); 198 | this._selectedIndex = -1; 199 | this._updated = true; 200 | break; 201 | case DataSource.UpdateMode.Append: 202 | let lastIndex = this.getLastIndex(); 203 | let erasedCount = ds.getErasedCount(); 204 | if (lastIndex < oldMaxIndex) { 205 | if (erasedCount > 0) { 206 | this._firstIndex = Math.max(this._firstIndex - erasedCount, 0); 207 | if (this._selectedIndex >= 0) { 208 | this._selectedIndex -= erasedCount; 209 | this.validateSelectedIndex(); 210 | } 211 | this._updated = true; 212 | } 213 | } else if (lastIndex === oldMaxIndex) { 214 | this._firstIndex += (this._maxIndex - oldMaxIndex); 215 | if (this._selectedIndex >= 0) { 216 | this._selectedIndex -= erasedCount; 217 | this.validateSelectedIndex(); 218 | } 219 | this._updated = true; 220 | } 221 | break; 222 | } 223 | } 224 | 225 | move(x) { 226 | if (this.isLatestShown()) { 227 | ChartManager.instance.getArea(this.getDataSourceName() + ".mainRange").setChanged(true); 228 | } 229 | this._firstIndex = this.validateFirstIndex( 230 | this._savedFirstIndex - this.calcColumnCount(x), this._maxItemCount); 231 | this._updated = true; 232 | if (this._selectedIndex >= 0) 233 | this.validateSelectedIndex(); 234 | } 235 | 236 | startMove() { 237 | this._savedFirstIndex = this._firstIndex; 238 | } 239 | 240 | scale(s) { 241 | this._scale += s; 242 | if (this._scale < 0) { 243 | this._scale = 0; 244 | } else if (this._scale >= Timeline.itemWidth.length) { 245 | this._scale = Timeline.itemWidth.length - 1; 246 | } 247 | this.updateMaxItemCount(); 248 | if (this._selectedIndex >= 0) { 249 | this.validateSelectedIndex(); 250 | } 251 | } 252 | 253 | } 254 | Timeline.itemWidth = [1, 3, 3, 5, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]; 255 | Timeline.spaceWidth = [1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 7, 7, 7]; 256 | Timeline.PADDING_LEFT = 4; 257 | Timeline.PADDING_RIGHT = 8; 258 | -------------------------------------------------------------------------------- /src/js/util.js: -------------------------------------------------------------------------------- 1 | export class Util { 2 | 3 | static fromFloat(v, fractionDigits) { 4 | let text = v.toFixed(fractionDigits); 5 | for (let i = text.length - 1; i >= 0; i--) { 6 | if (text[i] === '.') 7 | return text.substring(0, i); 8 | if (text[i] !== '0') 9 | return text.substring(0, i + 1); 10 | } 11 | }; 12 | 13 | static formatTime(v) { 14 | return (v < 10) ? "0" + v.toString() : v.toString(); 15 | } 16 | 17 | static isInstance(obj, clazz) { 18 | if (obj === null || obj === undefined) { 19 | return false; 20 | } 21 | return obj instanceof clazz; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 3 | const htmlWebpackPlugin = new HtmlWebpackPlugin({ 4 | template: path.join(__dirname, "example/src/index.html"), 5 | filename: "./index.html" 6 | }); 7 | module.exports = [ 8 | { 9 | entry: path.join(__dirname, "example/src/index.jsx"), 10 | output: { 11 | path: path.join(__dirname, "demo_dist"), 12 | filename: "bundle.js" 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.(js|jsx)$/, 18 | use: "babel-loader", 19 | exclude: /node_modules/ 20 | }, 21 | { 22 | test: /\.css$/, 23 | use: ["style-loader", "css-loader"] 24 | }, 25 | { 26 | test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/, 27 | loader: 'url-loader', 28 | options: { 29 | limit: 10000 30 | } 31 | }, 32 | { 33 | test: /\.(html)$/, 34 | use: { 35 | loader: 'html-loader', 36 | options: { 37 | attrs: [':data-src'] 38 | } 39 | } 40 | } 41 | ] 42 | }, 43 | plugins: [htmlWebpackPlugin], 44 | resolve: { 45 | extensions: [".js", ".jsx"] 46 | }, 47 | devServer: { 48 | port: 3001 49 | } 50 | }, 51 | ]; 52 | --------------------------------------------------------------------------------