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

718 lines
16 KiB

  1. <template>
  2. <!-- #ifdef H5 -->
  3. <div class='kline' v-bind:id='KLineID' v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}" ref='kline'></div>
  4. <!-- #endif -->
  5. <!-- #ifdef MP-WEIXIN -->
  6. <canvas class="kline" v-bind:id='KLineID' type="2d"
  7. v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}"
  8. @touchstart="KLineTouchStart" @touchmove='KLineTouchMove' @touchend='KLineTouchEnd' />
  9. <!-- #endif -->
  10. <!-- #ifndef H5 || MP-WEIXIN -->
  11. <canvas v-bind:id='KLineID' v-bind:canvas-id='KLineID' class='kline2' v-bind:style="{width: ChartWidth+'px', height: ChartHeight+'px'}"
  12. @touchstart="KLineTouchStart" @touchmove='KLineTouchMove' @touchend='KLineTouchEnd' ></canvas>
  13. <!-- #endif -->
  14. </template>
  15. <script>
  16. /*
  17. copyright (c) 2018 jones
  18. http://www.apache.org/licenses/LICENSE-2.0
  19. 开源项目 https://github.com/jones2000/HQChart
  20. jones_2000@163.com
  21. HQChart简单的模板类
  22. */
  23. // #ifdef H5
  24. import HQChart from './umychart.uniapp.h5.js'
  25. import './umychart.resource/font/iconfont.css'
  26. // #endif
  27. // #ifndef H5
  28. import {JSCommon} from './umychart.wechat.3.0.js'
  29. import {JSCommonHQStyle} from './umychart.style.wechat.js'
  30. import {JSConsole} from './umychart.console.wechat.js'
  31. //禁用日志
  32. JSConsole.Complier.Log=()=>{ };
  33. JSConsole.Chart.Log=()=>{ };
  34. // #endif
  35. //插件帮助函数
  36. function HQChartHelper() { }
  37. //把Vue3的markRow包装下,支持vue2
  38. HQChartHelper.MarkRaw=function(value)
  39. {
  40. return value;
  41. }
  42. // #ifdef VUE3
  43. HQChartHelper.MarkRaw=function(value)
  44. {
  45. return markRaw(value);
  46. }
  47. // #endif
  48. function DefaultData() { }
  49. DefaultData.GetKLineOption = function ()
  50. {
  51. let data =
  52. {
  53. Type: '历史K线图',
  54. Windows: //窗口指标
  55. [
  56. {Index:"MA",Modify: false, Change: false},
  57. {Index:"VOL",Modify: false, Change: false},
  58. {Index:"AMO",Modify: false, Change: false}
  59. /*
  60. {
  61. Index:'多线段指标',Modify: false, Change: false,
  62. API:
  63. {
  64. Name:'多线段指标',
  65. Script:null,
  66. Args:null,
  67. Url:'http://127.0.0.1:18080/api/jsindex'
  68. }
  69. }
  70. */
  71. ],
  72. IsAutoUpdate:true,
  73. IsCorssOnlyDrawKLine:true,
  74. CorssCursorTouchEnd:true,
  75. IsClickShowCorssCursor:true,
  76. CorssCursorInfo:{ Left:2, Right:2, Bottom:1, IsShowCorss:true}, //十字光标刻度设置
  77. //IsFullDraw:true,
  78. Border: //边框
  79. {
  80. Left: 1,
  81. Right: 1, //右边间距
  82. Top: 25,
  83. Bottom: 25,
  84. },
  85. KLine:
  86. {
  87. DragMode:1,
  88. Right:1, //复权 0 不复权 1 前复权 2 后复权
  89. Period:0, //周期: 0 日线 1 周线 2 月线 3 年线
  90. PageSize:6,
  91. IsShowTooltip:false,
  92. DrawType:0,
  93. DataWidth:10
  94. },
  95. KLineTitle: //K线标题栏设置
  96. {
  97. DateTimeSpace:1,
  98. PeriodSpace:1,
  99. NameSpace:1,
  100. },
  101. ExtendChart:
  102. [
  103. {Name:'KLineTooltip' }, //开启手机端tooltip
  104. ],
  105. Frame: //子框架设置
  106. [
  107. {SplitCount:3,Custom: [{ Type: 0, Position: 'right'}]},
  108. {SplitCount:2},
  109. {SplitCount:3},
  110. ],
  111. };
  112. return data;
  113. }
  114. DefaultData.GetMinuteOption=function()
  115. {
  116. var option=
  117. {
  118. Type:'分钟走势图', //创建图形类型
  119. Windows: //窗口指标
  120. [
  121. ],
  122. IsAutoUpdate:true, //是自动更新数据
  123. DayCount:1, //1 最新交易日数据 >1 多日走势图
  124. IsShowRightMenu:false, //是否显示右键菜单
  125. CorssCursorTouchEnd:true,
  126. IsClickShowCorssCursor:true,
  127. //IsFullDraw:true,
  128. MinuteLine:
  129. {
  130. //IsDrawAreaPrice:false, //是否画价格面积图
  131. },
  132. Border: //边框
  133. {
  134. Left:1, //左边间距
  135. Right:1, //右边间距
  136. Top:20,
  137. Bottom:20
  138. },
  139. Frame: //子框架设置
  140. [
  141. {SplitCount:3},
  142. {SplitCount:2},
  143. {SplitCount:3},
  144. ],
  145. ExtendChart: //扩展图形
  146. [
  147. {Name:'MinuteTooltip' } //手机端tooltip
  148. ],
  149. };
  150. return option;
  151. }
  152. DefaultData.CreateGuid=function()
  153. {
  154. function S4()
  155. {
  156. return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
  157. }
  158. return "guid" + (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
  159. }
  160. var g_JSChart=new Map();
  161. export default
  162. {
  163. name:"HQChartControl",
  164. props:
  165. [
  166. 'DefaultSymbol',
  167. 'DefaultChart'
  168. ],
  169. data()
  170. {
  171. let data=
  172. {
  173. Symbol:'600000.sh',
  174. ChartWidth:550,
  175. ChartHeight:1000,
  176. KLineID:"HQChart_"+DefaultData.CreateGuid(),
  177. KLine:
  178. {
  179. Option:DefaultData.GetKLineOption(),
  180. },
  181. Minute:
  182. {
  183. Option:DefaultData.GetMinuteOption(),
  184. },
  185. ChartType:"Minute",
  186. CanvasNode:null,
  187. };
  188. return data;
  189. },
  190. created()
  191. {
  192. if (this.DefaultSymbol) this.Symbol=this.DefaultSymbol; //默认股票
  193. if (this.DefaultChart)
  194. {
  195. //TODO:默认天数,周期在这里加
  196. if (this.DefaultChart.Type=='Minute')
  197. {
  198. this.ChartType="Minute";
  199. }
  200. else
  201. {
  202. this.ChartType="KLine";
  203. }
  204. }
  205. },
  206. methods:
  207. {
  208. SetSize(width, height)
  209. {
  210. this.ChartWidth=width;
  211. this.ChartHeight=height;
  212. },
  213. GetJSChart()
  214. {
  215. if (g_JSChart.has(this.KLineID)) return g_JSChart.get(this.KLineID);
  216. return null;
  217. },
  218. SetJSChart(jsChart)
  219. {
  220. g_JSChart.set(this.KLineID,jsChart)
  221. },
  222. ClearChart()
  223. {
  224. console.log("[ClearChart] clear");
  225. var jsChart=this.GetJSChart();
  226. if (jsChart)
  227. {
  228. jsChart.ChartDestory();
  229. this.SetJSChart(null);
  230. }
  231. // #ifdef H5
  232. var divKLine=document.getElementById(this.KLineID);
  233. while (divKLine.hasChildNodes())
  234. {
  235. divKLine.removeChild(divKLine.lastChild);
  236. } 
  237. // #endif
  238. },
  239. OnSize(option)
  240. {
  241. // #ifdef H5
  242. this.OnSize_h5(option);
  243. // #endif
  244. // #ifndef H5
  245. this.OnSize_app(option);
  246. // #endif
  247. },
  248. OnSize_h5(option)
  249. {
  250. var chartHeight = this.ChartHeight;
  251. var chartWidth = this.ChartWidth;
  252. var kline=this.$refs.kline;
  253. kline.style.width=chartWidth+'px';
  254. kline.style.height=chartHeight+'px';
  255. var jsChart=this.GetJSChart();
  256. if (jsChart) jsChart.OnSize(option);
  257. },
  258. OnSize_app(option)
  259. {
  260. var jsChart=this.GetJSChart();
  261. if (jsChart)
  262. {
  263. jsChart.CanvasElement.Width=this.ChartWidth;
  264. jsChart.CanvasElement.Height=this.ChartHeight;
  265. jsChart.OnSize(option);
  266. }
  267. },
  268. SetHQChartStyle()
  269. {
  270. // #ifdef H5
  271. this.SetHQChartStyle_h5();
  272. // #endif
  273. // #ifndef H5
  274. this.SetHQChartStyle_app();
  275. // #endif
  276. },
  277. SetHQChartStyle_h5()
  278. {
  279. var blackStyle=HQChart.HQChartStyle.GetStyleConfig(HQChart.STYLE_TYPE_ID.BLACK_ID);
  280. HQChart.JSChart.SetStyle(blackStyle);
  281. //this.$refs.kline.style.backgroundColor=blackStyle.BGColor; //div背景色设置黑色
  282. },
  283. SetHQChartStyle_app()
  284. {
  285. var blackStyle=JSCommonHQStyle.GetStyleConfig(JSCommonHQStyle.STYLE_TYPE_ID.BLACK_ID);
  286. JSCommon.JSChart.SetStyle(blackStyle);
  287. },
  288. CreateHQChart()
  289. {
  290. this.SetHQChartStyle();
  291. if (this.ChartType=="Minute")
  292. return this.CreateMinuteChart();
  293. else
  294. return this.CreateKLineChart();
  295. },
  296. CreateKLineChart_h5() //创建K线图
  297. {
  298. this.ClearChart();
  299. var chart=HQChart.JSChart.Init(this.$refs.kline);
  300. this.KLine.Option.Symbol=this.Symbol;
  301. this.KLine.Option.NetworkFilter=this.NetworkFilter;
  302. chart.SetOption(this.KLine.Option);
  303. this.SetJSChart(chart);
  304. return chart;
  305. },
  306. CreateKLineChart_app()
  307. {
  308. this.ClearChart();
  309. var element = new JSCommon.JSCanvasElement();
  310. // #ifdef APP-PLUS
  311. element.IsUniApp=true; //canvas需要指定下 是uniapp的app
  312. // #endif
  313. element.ID = this.KLineID;
  314. element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
  315. element.Width = this.ChartWidth;
  316. var chart = JSCommon.JSChart.Init(element);
  317. this.KLine.Option.NetworkFilter=this.NetworkFilter;
  318. this.KLine.Option.Symbol=this.Symbol;
  319. //this.KLine.Option.IsClickShowCorssCursor=true;
  320. this.KLine.Option.IsFullDraw=true; //每次手势移动全屏重绘
  321. chart.SetOption(this.KLine.Option);
  322. this.SetJSChart(chart);
  323. return chart;
  324. },
  325. CreateKLineChart_WeChat()
  326. {
  327. this.ClearChart();
  328. var id=`#${this.KLineID}`;
  329. wx.createSelectorQuery().in(this)
  330. .select(id)
  331. .fields({
  332. node: true,
  333. size: true,
  334. })
  335. .exec((res)=>
  336. {
  337. console.log("[HQChartControl::CreateKLineChart_WeChat] 2")
  338. this.CanvasNode= HQChartHelper.MarkRaw(res[0]);
  339. var element = new JSCommon.JSCanvasElement();
  340. element.ID = this.KLineID;
  341. element.CanvasNode =this.CanvasNode;
  342. element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
  343. element.Width = this.ChartWidth;
  344. console.log("[HQChartControl::CreateKLineChart_WeChat] 3",this.ChartHeight,this.ChartWidth, res)
  345. var chart = JSCommon.JSChart.Init(element); //把画布绑定到行情模块中
  346. this.KLine.Option.NetworkFilter=this.NetworkFilter;
  347. this.KLine.Option.Symbol=this.Symbol;
  348. //this.KLine.Option.IsClickShowCorssCursor=true;
  349. this.KLine.Option.IsFullDraw=true; //每次手势移动全屏重绘
  350. chart.SetOption(this.KLine.Option);
  351. this.SetJSChart(chart);
  352. });
  353. },
  354. CreateKLineChart()
  355. {
  356. this.ChartType="KLine";
  357. // #ifdef H5
  358. return this.CreateKLineChart_h5();
  359. // #endif
  360. // #ifdef MP-WEIXIN
  361. return this.CreateKLineChart_WeChat();
  362. // #endif
  363. // #ifndef H5 || MP-WEIXIN
  364. return this.CreateKLineChart_app();
  365. // #endif
  366. },
  367. CreateMinuteChart_h5() //创建日线图
  368. {
  369. this.ClearChart();
  370. var chart=HQChart.JSChart.Init(this.$refs.kline);
  371. this.Minute.Option.Symbol=this.Symbol;
  372. this.Minute.Option.NetworkFilter=this.NetworkFilter;
  373. chart.SetOption(this.Minute.Option);
  374. this.SetJSChart(chart);
  375. return chart;
  376. },
  377. CreateMinuteChart_app()
  378. {
  379. this.ClearChart();
  380. var element = new JSCommon.JSCanvasElement();
  381. // #ifdef APP-PLUS
  382. element.IsUniApp=true; //canvas需要指定下 是uniapp的app
  383. // #endif
  384. element.ID = this.KLineID;
  385. element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
  386. element.Width = this.ChartWidth;
  387. var chart = JSCommon.JSChart.Init(element);
  388. this.Minute.Option.NetworkFilter=this.NetworkFilter;
  389. this.Minute.Option.Symbol=this.Symbol;
  390. this.Minute.Option.IsFullDraw=true; //每次手势移动全屏重绘
  391. chart.SetOption(this.Minute.Option);
  392. this.SetJSChart(chart);
  393. return chart;
  394. },
  395. CreateMinuteChart_WeChat()
  396. {
  397. this.ClearChart();
  398. var id=`#${this.KLineID}`;
  399. wx.createSelectorQuery().in(this)
  400. .select(id)
  401. .fields({
  402. node: true,
  403. size: true,
  404. })
  405. .exec((res)=>
  406. {
  407. this.CanvasNode= HQChartHelper.MarkRaw(res[0]);
  408. var element = new JSCommon.JSCanvasElement();
  409. element.ID = this.KLineID;
  410. element.CanvasNode =this.CanvasNode;
  411. element.Height = this.ChartHeight; //高度宽度需要手动绑定!!
  412. element.Width = this.ChartWidth;
  413. console.log("[HQChartControl::CreateMinuteChart_WeChat] 3",this.ChartHeight,this.ChartWidth, res)
  414. var chart = JSCommon.JSChart.Init(element); //把画布绑定到行情模块中
  415. this.Minute.Option.NetworkFilter=this.NetworkFilter;
  416. this.Minute.Option.Symbol=this.Symbol;
  417. this.Minute.Option.IsFullDraw=true; //每次手势移动全屏重绘
  418. chart.SetOption(this.Minute.Option);
  419. this.SetJSChart(chart);
  420. });
  421. },
  422. CreateMinuteChart()
  423. {
  424. this.ChartType="Minute";
  425. // #ifdef H5
  426. return this.CreateMinuteChart_h5();
  427. // #endif
  428. // #ifdef MP-WEIXIN
  429. return this.CreateMinuteChart_WeChat();
  430. // #endif
  431. // #ifndef H5 || MP-WEIXIN
  432. return this.CreateMinuteChart_app();
  433. // #endif
  434. },
  435. IsKLineChart()
  436. {
  437. var jsChart=this.GetJSChart();
  438. if (!jsChart) return false;
  439. var className=jsChart.JSChartContainer.ClassName;
  440. if (className=="KLineChartContainer" || className=="KLineChartHScreenContainer") return true;
  441. return false;
  442. },
  443. IsMinuteChart()
  444. {
  445. var jsChart=this.GetJSChart();
  446. if (!jsChart) return false;
  447. var className=jsChart.JSChartContainer.ClassName;
  448. if (className=="MinuteChartContainer" || className=="MinuteChartHScreenContainer") return true;
  449. return false;
  450. },
  451. //K线周期切换
  452. ChangeKLinePeriod(period)
  453. {
  454. var jsChart=this.GetJSChart();
  455. this.KLine.Option.KLine.Period=period;
  456. if (this.IsKLineChart() && jsChart)
  457. {
  458. jsChart.ChangePeriod(period);
  459. }
  460. else
  461. {
  462. this.CreateKLineChart();
  463. }
  464. },
  465. //走势图多日切换
  466. ChangeMinutePeriod(dayCount)
  467. {
  468. var jsChart=this.GetJSChart();
  469. this.Minute.Option.DayCount=dayCount;
  470. if (this.IsMinuteChart() && jsChart)
  471. {
  472. jsChart.ChangeDayCount(dayCount);
  473. }
  474. else
  475. {
  476. this.CreateMinuteChart(); //类型不对 删了重建
  477. }
  478. },
  479. //切换指标 windowId=窗口索引 name=指标名字
  480. ChangeKLineIndex(windowId,name)
  481. {
  482. var jsChart=this.GetJSChart();
  483. if (this.IsKLineChart() && jsChart) jsChart.ChangeIndex(windowId,name);
  484. },
  485. //切换股票
  486. ChangeSymbol(symbol)
  487. {
  488. this.Symbol=symbol;
  489. var jsChart=this.GetJSChart();
  490. if (jsChart) jsChart.ChangeSymbol(symbol);
  491. },
  492. ChangeRight(right)
  493. {
  494. var jsChart=this.GetJSChart();
  495. if (this.IsKLineChart() && jsChart) jsChart.ChangeRight(right);
  496. },
  497. ChangeKLineDrawType(id)
  498. {
  499. var jsChart=this.GetJSChart();
  500. if (this.IsKLineChart() && jsChart) jsChart.ChangeKLineDrawType(id);
  501. },
  502. ///////////////////////////////////////////////
  503. //手势事件 app/小程序才有
  504. //KLine事件
  505. KLineTouchStart(event)
  506. {
  507. var jsChart=this.GetJSChart();
  508. if (jsChart)
  509. {
  510. var backup=this.ConvertTouchEventData(event);
  511. jsChart.OnTouchStart(event);
  512. this.RestoreTouchEventData(backup, event);
  513. }
  514. },
  515. KLineTouchMove (event)
  516. {
  517. var jsChart=this.GetJSChart();
  518. if (jsChart)
  519. {
  520. var backup=this.ConvertTouchEventData(event);
  521. jsChart.OnTouchMove(event);
  522. this.RestoreTouchEventData(backup, event);
  523. }
  524. },
  525. KLineTouchEnd (event)
  526. {
  527. var jsChart=this.GetJSChart();
  528. if (jsChart)
  529. {
  530. var backup=this.ConvertTouchEventData(event);
  531. jsChart.OnTouchEnd(event);
  532. this.RestoreTouchEventData(backup, event);
  533. }
  534. },
  535. ConvertTouchEventData(event)
  536. {
  537. if (Array.isArray(event.touches)) return null;
  538. var touches=event.touches; //备份下
  539. var aryTouches=[];
  540. for(var i=0;i<10;++i)
  541. {
  542. var key=i.toString();
  543. var item=event.touches[key];
  544. if (!item) break;
  545. aryTouches[i]=item;
  546. }
  547. event.touches=aryTouches;
  548. var changedTouches=event.changedTouches;
  549. var aryChangedTouches=[];
  550. for(var i=0;i<10;++i)
  551. {
  552. var key=i.toString();
  553. var item=event.changedTouches[key];
  554. if (!item) break;
  555. aryChangedTouches[i]=item;
  556. }
  557. event.changedTouches=aryChangedTouches;
  558. //console.log('ConvertTouchEventData' ,event )
  559. return {Touches:touches, ChangedTouches:changedTouches };
  560. },
  561. RestoreTouchEventData(backup, event)
  562. {
  563. if (!backup) return;
  564. event.touches=backup.Touches; //还原原来的touches结构
  565. event.changedTouches=backup.ChangedTouches
  566. //console.log('RestoreTouchEventData' ,event )
  567. },
  568. /////////////////////////////////////////////////////////////////////////////////////////
  569. NetworkFilter(data, callback)
  570. {
  571. console.log(`[HQChartTemplate:NetworkFilter] Name=${data.Name} Explain=${data.Explain}` );
  572. },
  573. },
  574. }
  575. </script>
  576. <style>
  577. </style>