kline.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. var myChart;
  2. // post请求封装
  3. // function post(url,data) {
  4. // let baseUrl='http://192.168.3.135:8080';
  5. // return new Promise((resolve,reject)=>{
  6. // axios({
  7. // headers:{
  8. // "Content-Type": "application/x-www-form-urlencoded",
  9. // },
  10. // method:'post',
  11. // url:baseUrl+url,
  12. // data:Qs.stringify( data || {})
  13. // })
  14. // .then(res=>{
  15. // console.log(res)
  16. // if(res.data.code==1){
  17. // resolve(res.data)
  18. // }else{
  19. // reject()
  20. // alertError('请求超时')
  21. // }
  22. // })
  23. // .catch(err=>{
  24. // alertError('请求超时')
  25. // })
  26. // })
  27. // }
  28. // 弹窗
  29. function alertError(title) {
  30. document.addEventListener('plusready',function() {
  31. console.log('......')
  32. })
  33. try{
  34. plus.nativeUI.toast(title, {
  35. icon:'/static/common/toast-error.png',
  36. style:'inline',
  37. verticalAlign:'top'
  38. });
  39. }catch(e){
  40. //TODO handle the exception
  41. }
  42. }
  43. var app = new Vue({
  44. el:'#app',
  45. data:{
  46. MA5:'',
  47. MA10:'',
  48. MA30:'',
  49. volMA5:'',
  50. volMA10:'',
  51. current:1,
  52. tabs:[
  53. {'label':'1分钟','value':1},
  54. {'label':'15分钟','value':2},
  55. {'label':'30分钟','value':3},
  56. {'label':'1小时','value':4},
  57. {'label':'4小时','value':5},
  58. {'label':'1天','value':6},
  59. ],
  60. category:1,
  61. categoryList:[
  62. {'label':'深度','value':1},
  63. {'label':'成交','value':2},
  64. {'label':'简介','value':3},
  65. ],
  66. txData:{},//交易数据统计
  67. buyList:[],
  68. sellList:[],
  69. dealHis:[],
  70. tokenInfo:{},
  71. page:1,
  72. },
  73. created() {
  74. this.getTxData()
  75. this.getDepth()
  76. },
  77. mounted() {
  78. myChart = echarts.init(document.getElementById('main'));
  79. this.draw()
  80. this.getKline()
  81. },
  82. methods:{
  83. // 返回上一页
  84. back(){
  85. uni.navigateBack()
  86. },
  87. // 获取24小时交易数据统计
  88. getTxData(){
  89. this.txData=txData;
  90. },
  91. // 获取k线数据,生成k线
  92. getKline(){
  93. var dataMA5 = this.calculateMA(5, data);
  94. var dataMA10 = this.calculateMA(10, data);
  95. var dataMA30 = this.calculateMA(30, data);
  96. var volumeMA5 = this.calculateMA(5, volumes);
  97. var volumeMA10 = this.calculateMA(10, volumes);
  98. myChart.setOption({
  99. xAxis: [
  100. {
  101. data: dates
  102. },
  103. {
  104. data: dates
  105. },
  106. ],
  107. series: [
  108. {
  109. name: '日K',
  110. data: data
  111. },
  112. {
  113. name: 'MA5',
  114. data: dataMA5
  115. },
  116. {
  117. name: 'MA10',
  118. data: dataMA10
  119. },
  120. {
  121. name: 'MA30',
  122. data: dataMA30
  123. },
  124. {
  125. name: 'Volume',
  126. data: volumes
  127. },
  128. {
  129. name: 'VolumeMA5',
  130. data: volumeMA5
  131. },
  132. {
  133. name: 'VolumeMA10',
  134. data: volumeMA10
  135. },
  136. ]
  137. })
  138. },
  139. // 列表条数不足补全
  140. addItem(list,type){
  141. // type: 1开头加,2末尾加
  142. list=list || [];
  143. let len=20-list.length;
  144. if(len>0){
  145. for(let i=0;i<len;i++){
  146. if(type==1){
  147. list.unshift({})
  148. }else{
  149. list.push({})
  150. }
  151. }
  152. }
  153. return list;
  154. },
  155. // 获取深度数据
  156. getDepth(){
  157. this.buyList=this.addItem(depthList().buyList || []);
  158. this.sellList=this.addItem(depthList().sellList || []);
  159. },
  160. // 获取成交记录
  161. getDealHis(){
  162. this.dealHis=dealHis();
  163. },
  164. // 获取项目简介信息
  165. getTokenInfo(){
  166. this.tokenInfo=tokenInfo;
  167. },
  168. // 切换tab
  169. switchTab(val){
  170. if(this.current==val) return;
  171. this.current=val;
  172. this.getKline()
  173. },
  174. // 切换类目
  175. switchCategory(val){
  176. if(this.category==val) return;
  177. this.category=val;
  178. if(this.category==1){
  179. this.getDepth()
  180. }else if(this.category==2){
  181. this.getDealHis()
  182. }else{
  183. this.getTokenInfo()
  184. }
  185. },
  186. // 截取数字字符串 保留precision小数
  187. formatterNum(value, precision) {
  188. // console.log(value)
  189. let reg = new RegExp('^\\d+(?:\\.\\d{0,' + precision + '})?')
  190. return value.toString().match(reg)
  191. },
  192. // 计算MA
  193. calculateMA(dayCount, data) {
  194. var result = [];
  195. for (var i = 0, len = data.length; i < len; i++) {
  196. if (i < dayCount) {
  197. result.push('-');
  198. continue;
  199. }
  200. var sum = 0;
  201. for (var j = 0; j < dayCount; j++) {
  202. sum += data[i - j][1];
  203. }
  204. // console.log(sum, dayCount)
  205. result.push((sum / dayCount).toFixed(2));
  206. }
  207. return result;
  208. },
  209. // 绘制(配置项)
  210. draw(){
  211. let that=this;
  212. var upColor = '#03ad91';
  213. var downColor = '#dd345b';
  214. var colorList = ['#c23531', '#2f4554', '#61a0a8', '#d48265', '#91c7ae', '#749f83', '#ca8622', '#bda29a', '#6e7074',
  215. '#546570', '#c4ccd3'
  216. ];
  217. var labelFont = 'bold 12px Sans-serif';
  218. var option = {
  219. backgroundColor: '#0d1723',
  220. title: {
  221. show: false
  222. },
  223. legend: {
  224. show: false
  225. },
  226. visualMap: {
  227. show: false,
  228. seriesIndex: 4,
  229. dimension: 2,
  230. pieces: [{
  231. value: 1,
  232. color: downColor
  233. }, {
  234. value: -1,
  235. color: upColor
  236. }]
  237. },
  238. grid: [{
  239. top: '5%',
  240. left: 20,
  241. right: 20,
  242. height: '70%'
  243. },
  244. {
  245. top: '80%',
  246. left: 20,
  247. right: 20,
  248. height: '16%'
  249. },
  250. ],
  251. axisPointer: { //坐标轴指示器配置项
  252. link: {
  253. xAxisIndex: 'all'
  254. },
  255. label: {
  256. backgroundColor: '#0d1723',
  257. color: '#fff',
  258. borderColor: 'rgb(99, 117, 139)',
  259. borderWidth: 1,
  260. borderRadius: 2,
  261. fontSize: 10
  262. }
  263. },
  264. xAxis: [{
  265. type: 'category', //坐标轴类型。(value:数值轴,适用于连续数据。,category:类目轴,适用于离散的类目数据,time: 时间轴,适用于连续的时序数据,log:对数轴。适用于对数数据)
  266. data: [], //类目数据,在类目轴(type: 'category')中有效。
  267. scale: true,
  268. boundaryGap: false, //坐标轴两边留白策略,类目轴和非类目轴的设置和表现不一样。
  269. axisLine: {
  270. show: false
  271. }, //坐标轴轴线相关设置
  272. axisTick: {
  273. show: false
  274. }, //坐标轴刻度相关设置。
  275. axisLabel: {
  276. show: false,
  277. }, //坐标轴刻度标签的相关设置。
  278. splitLine: {
  279. show: false,
  280. lineStyle: {
  281. color: 'rgba(255,255,255, 0.1)'
  282. }
  283. }, //坐标轴在 grid 区域中的分隔线。
  284. min: 'dataMin', //坐标轴刻度最小值。可以设置成特殊值 'dataMin',此时取数据在该轴上的最小值作为最小刻度。
  285. max: 'dataMax', //坐标轴刻度最大值。可以设置成特殊值 'dataMax',此时取数据在该轴上的最大值作为最大刻度。
  286. axisPointer: {
  287. label: {
  288. margin: 200
  289. }
  290. },
  291. }, {
  292. type: 'category',
  293. gridIndex: 1, //x 轴所在的 grid 的索引,默认位于第一个 grid。
  294. data: [], //类目数据,在类目轴(type: 'category')中有效。
  295. scale: true,
  296. boundaryGap: false, //坐标轴两边留白策略,类目轴和非类目轴的设置和表现不一样。
  297. axisLine: {
  298. show: false,
  299. lineStyle: {
  300. color: 'rgba(255,255,255,1)',
  301. width: 1
  302. }
  303. }, //坐标轴轴线相关设置
  304. axisTick: {
  305. show: false
  306. }, //坐标轴刻度相关设置。
  307. axisLabel: { //坐标轴刻度标签的相关设置。
  308. show: true,
  309. margin: 6,
  310. fontSize: 10,
  311. color: 'rgba(99, 117, 139, 1.0)',
  312. formatter: function(value) {
  313. return echarts.format.formatTime('MM-dd', value);
  314. }
  315. },
  316. splitNumber: 20,
  317. splitLine: {
  318. show: false,
  319. lineStyle: {
  320. color: 'rgba(255,255,255, 0.1)'
  321. }
  322. }, //坐标轴在 grid 区域中的分隔线。
  323. min: 'dataMin', //坐标轴刻度最小值。可以设置成特殊值 'dataMin',此时取数据在该轴上的最小值作为最小刻度。
  324. max: 'dataMax', //坐标轴刻度最大值。可以设置成特殊值 'dataMax',此时取数据在该轴上的最大值作为最大刻度。
  325. // axisPointer: { show: true, type: 'none', label: { show: false }},
  326. }],
  327. yAxis: [{
  328. type: 'value', //坐标轴类型。(value:数值轴,适用于连续数据。,category:类目轴,适用于离散的类目数据,time: 时间轴,适用于连续的时序数据,log:对数轴。适用于对数数据)
  329. position: 'right', //y 轴的位置。'left','right'
  330. scale: true, //是否是脱离 0 值比例。设置成 true 后坐标刻度不会强制包含零刻度。在双数值轴的散点图中比较有用。(在设置 min 和 max 之后该配置项无效。)
  331. axisLine: {
  332. show: true
  333. }, //坐标轴轴线相关设置。
  334. axisTick: {
  335. show: true,
  336. inside:true
  337. }, //坐标轴刻度相关设置。
  338. axisLabel: { //坐标轴刻度标签的相关设置。
  339. show: true,
  340. color: 'rgba(99, 117, 139, 1.0)',
  341. inside: true,
  342. fontSize: 10,
  343. formatter: function(value) {
  344. return Number(value).toFixed(2)
  345. }
  346. },
  347. splitLine: {
  348. show: false,
  349. lineStyle: {
  350. color: 'rgba(255,255,255, 0.1)'
  351. }
  352. }, //坐标轴在 grid 区域中的分隔线。
  353. }, {
  354. type: 'value',
  355. position: 'right',
  356. scale: true,
  357. gridIndex: 1,
  358. axisLine: {
  359. show: false
  360. },
  361. axisTick: {
  362. show: false
  363. },
  364. axisLabel: {
  365. show: false
  366. },
  367. splitLine: {
  368. show: false
  369. }
  370. }],
  371. animation: false, //是否开启动画。
  372. color: colorList,
  373. tooltip: {
  374. show: true, //是否显示提示框组件,包括提示框浮层和 axisPointer。
  375. trigger: 'axis', //触发类型。item,axis,none
  376. formatter(params){
  377. let tooltip = '';
  378. let time = '', open = 0, high = 0, low = 0, close = 0, amount = 0;
  379. for (var i = 0; i < params.length; i++) {
  380. if (params[i].seriesName === '日K') {
  381. time = params[i].name;
  382. open = params[i].data.length > 1 ? Number(that.formatterNum(params[i].data[1], 2)) : 0;
  383. close = params[i].data.length > 1 ? Number(that.formatterNum(params[i].data[2], 2)) : 0;
  384. low = params[i].data.length > 1 ? Number(that.formatterNum(params[i].data[3], 2)) : 0;
  385. high = params[i].data.length > 1 ? Number(that.formatterNum(params[i].data[4], 2)) : 0;
  386. amount = params[i].data.length > 1 ? Number(that.formatterNum(params[i].data[5], 2)) : 0;
  387. // console.log(time,open,close,low,high,amount)
  388. tooltip = '<div class="charts-tooltip">' +
  389. '<div class="charts-tooltip-row"><div class="ctr-label">' + '时间' + '</div><div class="ctr-value">' + time + '</div></div>' +
  390. '<div class="charts-tooltip-row"><div class="ctr-label">' + '开' + '</div><div class="ctr-value">' + open + '</div></div>' +
  391. '<div class="charts-tooltip-row"><div class="ctr-label">' + '高' + '</div><div class="ctr-value">' + high + '</div></div>' +
  392. '<div class="charts-tooltip-row"><div class="ctr-label">' + '低' + '</div><div class="ctr-value">' + low + '</div></div>' +
  393. '<div class="charts-tooltip-row"><div class="ctr-label">' + '收' + '</div><div class="ctr-value">' + close + '</div></div>' +
  394. '<div class="charts-tooltip-row"><div class="ctr-label">' + '数量' + '</div><div class="ctr-value">' +amount + '</div></div></div>';
  395. }
  396. if (params[i].seriesName === 'MA5') {
  397. that.MA5 = params[i].data !== 'NAN' ? Number(that.formatterNum(params[i].data, 2)) : 0
  398. }
  399. if (params[i].seriesName === 'MA10') {
  400. that.MA10 = params[i].data !== 'NAN' ? Number(that.formatterNum(params[i].data, 2)) : 0
  401. }
  402. if (params[i].seriesName === 'MA30') {
  403. that.MA30 = params[i].data !== 'NAN' ? Number(that.formatterNum(params[i].data, 2)) : 0
  404. }
  405. if (params[i].seriesName === 'VolumeMA5') {
  406. that.volMA5 = params[i].data !== 'NAN' ? Number(that.formatterNum(params[i].data, 2)) : 0
  407. }
  408. if (params[i].seriesName === 'VolumeMA10') {
  409. that.volMA10 = params[i].data !== 'NAN' ? Number(that.formatterNum(params[i].data, 2)) : 0
  410. }
  411. }
  412. return tooltip;
  413. },
  414. triggerOn: 'click', //提示框触发的条件 'mousemove','click','mousemove|click','none'
  415. textStyle: {
  416. fontSize: 10
  417. }, //提示框浮层的文本样式
  418. backgroundColor: 'rgba(30,42,66,0.8);', //提示框浮层的背景颜色。
  419. borderColor: '#2f3a56', //提示框浮层的边框颜色。
  420. borderWidth:2,
  421. position: function(pos, params, el, elRect, size) { //提示框浮层的位置,默认不设置时位置会跟随鼠标的位置。
  422. var obj = {
  423. top: 20
  424. };
  425. obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 10;
  426. return obj;
  427. },
  428. axisPointer: { //坐标轴指示器配置项。
  429. label: {
  430. color: 'rgba(255,255,255,.87)',
  431. fontSize: 9,
  432. backgroundColor: '#020204',
  433. borderColor: "#9c9fa4",
  434. shadowBlur: 0,
  435. borderWidth: 0.5,
  436. padding: [4, 2, 3, 2],
  437. },
  438. animation: false,
  439. type: 'cross',
  440. lineStyle: {
  441. color: {
  442. type: 'linear',
  443. x: 0,
  444. y: 0,
  445. x2: 0,
  446. y2: 1,
  447. colorStops: [{
  448. offset: 0,
  449. color: 'rgba(30, 42, 66, 0.1)' // 0% 处的颜色
  450. }, {
  451. offset: 0.7,
  452. color: 'rgba(30, 42, 66,0.9)' // 100% 处的颜色
  453. }, {
  454. offset: 1,
  455. color: 'rgba(30, 42, 66,0.2)' // 100% 处的颜色
  456. }]
  457. },
  458. width: 10,
  459. shadowColor: 'rgba(30, 42, 66,0.7)',
  460. shadowBlur: 0,
  461. shadowOffsetY: 68,
  462. }
  463. }
  464. },
  465. dataZoom: [{ //用于区域缩放
  466. type: 'inside',
  467. xAxisIndex: [0, 1],
  468. realtime: false,
  469. start: 50,
  470. end: 100,
  471. }
  472. ],
  473. series: [
  474. {
  475. type: 'candlestick',
  476. name: '日K',
  477. data: [],
  478. itemStyle: {
  479. color: upColor,
  480. color0: downColor,
  481. borderColor: upColor,
  482. borderColor0: downColor
  483. },
  484. markPoint: {
  485. symbol: 'rect',
  486. symbolSize: [-10, 0.5],
  487. symbolOffset: [5, 0],
  488. itemStyle: {
  489. color: 'rgba(255,255,255,.87)'
  490. },
  491. label: {
  492. color: 'rgba(255,255,255,.87)',
  493. offset: [10, 0],
  494. fontSize: 10,
  495. align: 'left',
  496. formatter: function(params) {
  497. return Number(params.value).toFixed(2)
  498. }
  499. },
  500. data: [{
  501. name: 'max',
  502. type: 'max',
  503. valueDim: 'highest'
  504. },
  505. {
  506. name: 'min',
  507. type: 'min',
  508. valueDim: 'lowest'
  509. }
  510. ]
  511. },
  512. },
  513. {
  514. name: 'MA5',
  515. type: 'line',
  516. data: [],
  517. symbol: 'none',//去除圆点
  518. smooth: true,
  519. lineStyle: { normal: { opacity: 1, width: 1, color: "#eef4ba" } },
  520. z: 5
  521. },
  522. {
  523. name: 'MA10',
  524. type: 'line',
  525. data: [],
  526. symbol: 'none',//去除圆点
  527. smooth: true,
  528. lineStyle: { normal: { opacity: 1, width: 1, color: '#83c1c5' } },
  529. z: 4
  530. },
  531. {
  532. name: 'MA30',
  533. type: 'line',
  534. data: [],
  535. symbol: 'none',//去除圆点
  536. smooth: true,
  537. lineStyle: { normal: { opacity: 1, width: 1, color: '#b39cd8' } },
  538. z: 3
  539. },
  540. {
  541. name: 'Volume',
  542. type: 'bar',
  543. xAxisIndex: 1,
  544. yAxisIndex: 1,
  545. data: []
  546. },
  547. {
  548. name: 'VolumeMA5',
  549. type: 'line',
  550. xAxisIndex: 1,
  551. yAxisIndex: 1,
  552. data: [],
  553. symbol: 'none',//去除圆点
  554. smooth: true,
  555. lineStyle: { normal: { opacity: 1, width: 1, color: "#eef4ba" } },
  556. z: 5
  557. },
  558. {
  559. name: 'VolumeMA10',
  560. type: 'line',
  561. xAxisIndex: 1,
  562. yAxisIndex: 1,
  563. data: [],
  564. symbol: 'none',//去除圆点
  565. smooth: true,
  566. lineStyle: { normal: { opacity: 1, width: 1, color: '#83c1c5' } },
  567. z: 4
  568. },
  569. ]
  570. };
  571. myChart.setOption(option);
  572. // 加载上一页数据
  573. myChart.on('datazoom',function(params){
  574. let num=params.batch[0]['start'];
  575. if(num==0){
  576. console.log('到最左边了')
  577. }
  578. })
  579. window.addEventListener('resize', () => { myChart.resize()})
  580. }
  581. }
  582. })