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.

13463 lines
485 KiB

  1. /*
  2. copyright (c) 2018 jones
  3. http://www.apache.org/licenses/LICENSE-2.0
  4. 开源项目 https://github.com/jones2000/HQChart
  5. jones_2000@163.com
  6. 封装图形控件 (微信小程序版本)
  7. */
  8. //日志
  9. import { JSConsole } from "./umychart.console.wechat.js"
  10. import { JSNetwork } from "./umychart.network.wechart.js"
  11. import { JSCanvasElement } from "./umychart.element.wechart.js";
  12. //行情数据结构体 及涉及到的行情算法(复权,周期等)
  13. import {
  14. ChartData, HistoryData,
  15. SingleData, MinuteData,
  16. CUSTOM_DAY_PERIOD_START,
  17. CUSTOM_DAY_PERIOD_END,
  18. CUSTOM_MINUTE_PERIOD_START,
  19. CUSTOM_MINUTE_PERIOD_END,
  20. CUSTOM_SECOND_PERIOD_START,
  21. CUSTOM_SECOND_PERIOD_END,
  22. Rect,
  23. DataPlus,g_DataPlus,
  24. JSCHART_EVENT_ID,
  25. JSCHART_DATA_FIELD_ID,
  26. PhoneDBClick,
  27. OVERLAY_STATUS_ID,
  28. } from "./umychart.data.wechat.js";
  29. import {
  30. JSKLineInfoMap,
  31. KLINE_INFO_TYPE,
  32. JSMinuteInfoMap,
  33. } from "./umychart.klineinfo.wechat.js";
  34. import
  35. {
  36. JSCommonCoordinateData,
  37. MARKET_SUFFIX_NAME ,
  38. g_FuturesTimeData,
  39. g_NYMEXTimeData,
  40. g_COMEXTimeData,
  41. g_NYBOTTimeData,
  42. g_LMETimeData,
  43. g_CBOTTimeData,
  44. g_TOCOMTimeData,
  45. g_IPETimeData,
  46. GetfloatPrecision,
  47. } from "./umychart.coordinatedata.wechat.js";
  48. import { JSCommonComplier } from "./umychart.complier.wechat.js"; //通达信编译器
  49. import { JSCommonIndexScript, JSIndexScript } from "./umychart.index.data.wechat.js"; //系统指标定义
  50. import { HQIndexFormula } from "./umychart.hqIndexformula.wechat.js"; //通达信编译器
  51. import
  52. {
  53. IChartFramePainting,
  54. AverageWidthFrame,
  55. MinuteFrame,
  56. MinuteHScreenFrame,
  57. ZOOM_SEED,
  58. KLineFrame,
  59. KLineHScreenFrame,
  60. OverlayMinuteFrame,
  61. OverlayMinuteHScreenFrame,
  62. OverlayKLineFrame,
  63. OverlayKLineHScreenFrame,
  64. DepthChartFrame,
  65. } from "./umychart.chartframe.wechat.js"
  66. //图形库
  67. import {
  68. IChartPainting,
  69. ChartSingleText,
  70. ChartKLine,
  71. ChartLine,
  72. ChartSubLine,
  73. ChartPointDot,
  74. ChartStick,
  75. ChartLineStick,
  76. ChartStickLine,
  77. ChartOverlayKLine,
  78. ChartMinuteInfo,
  79. ChartRectangle,
  80. ChartMultiText,
  81. ChartMultiLine,
  82. ChartMultiBar,
  83. ChartPie,
  84. ChartCircle,
  85. ChartChinaMap,
  86. ChartRadar,
  87. ChartCorssCursor,
  88. ChartBuySell,
  89. ChartMACD,
  90. ChartSplashPaint,
  91. ChartBackground,
  92. ChartMinuteVolumBar,
  93. ChartMultiHtmlDom,
  94. ChartLock,
  95. ChartVolStick,
  96. ChartBand,
  97. ChartOverlayMinutePriceLine,
  98. ChartLineMultiData,
  99. ChartStraightLine,
  100. DepthChartCorssCursor,
  101. ChartOrderbookDepth,
  102. ChartMinutePriceLine,
  103. ChartText,
  104. ChartStraightArea,
  105. } from "./umychart.chartpaint.wechat.js";
  106. //扩展画法图形库
  107. import {
  108. IExtendChartPainting,
  109. KLineTooltipPaint,
  110. BarragePaint,
  111. MinuteTooltipPaint,
  112. BackgroundPaint,
  113. g_ExtendChartPaintFactory,
  114. } from "./umychart.extendchart.wechat.js";
  115. import {
  116. IndexInfo,
  117. BaseIndex,
  118. ScriptIndex,
  119. APIScriptIndex,
  120. OverlayScriptIndex,
  121. MarketLongShortIndex,
  122. MarketTimingIndex,
  123. MarketAttentionIndex,
  124. MarketHeatIndex,
  125. CustonIndexHeatIndex,
  126. BenfordIndex,
  127. } from './umychart.index.wechat.js'
  128. import{
  129. g_JSChartResource,
  130. JSCHART_LANGUAGE_ID,
  131. g_JSChartLocalization,
  132. } from './umychart.resource.wechat.js'
  133. import
  134. {
  135. CoordinateInfo,
  136. IFrameSplitOperator,
  137. FrameSplitKLinePriceY,
  138. FrameSplitY,
  139. FrameSplitKLineX,
  140. FrameSplitMinutePriceY,
  141. FrameSplitMinuteX,
  142. FrameSplitXData,
  143. SplitData,
  144. PriceSplitData,
  145. FrameSplitXDepth,
  146. IChangeStringFormat,
  147. HQPriceStringFormat,
  148. HQDateStringFormat,
  149. HQMinuteTimeStringFormat,
  150. g_DivTooltipDataForamt,
  151. } from './umychart.framesplit.wechat.js'
  152. import
  153. {
  154. IChartTitlePainting,
  155. DynamicKLineTitlePainting,
  156. DynamicMinuteTitlePainting,
  157. DynamicChartTitlePainting,
  158. DynamicTitleData,
  159. STRING_FORMAT_TYPE,
  160. } from './umychart.charttitle.wechat.js'
  161. import
  162. {
  163. IChartDrawPicture,
  164. } from "./umychart.ChartDrawPicture.wechart.js"
  165. import { HQCHART_VERSION } from "./umychart.version.wechat.js"
  166. function JSChart(element)
  167. {
  168. this.JSChartContainer; //画图控件
  169. this.CanvasElement = element;
  170. this.AddEventCallback = function (obj) //事件回调 {event:事件id, callback:回调函数}
  171. {
  172. if (this.JSChartContainer && typeof (this.JSChartContainer.AddEventCallback) == 'function')
  173. {
  174. JSConsole.Chart.Log('[JSChart:AddEventCallback] ', obj);
  175. this.JSChartContainer.AddEventCallback(obj);
  176. }
  177. }
  178. //设置语言 'EN', 'CN'
  179. this.SetLanguage=function(language)
  180. {
  181. if(this.JSChartContainer && typeof(this.JSChartContainer.SetLanguage)=='function')
  182. {
  183. JSConsole.Chart.Log('[JSChart:SetLanguage] ', language);
  184. this.JSChartContainer.SetLanguage(language);
  185. }
  186. }
  187. this.OnSize = function (option)
  188. {
  189. if (option)
  190. {
  191. if (IFrameSplitOperator.IsNumber(option.Width)) this.CanvasElement.Width=option.Width;
  192. if (IFrameSplitOperator.IsNumber(option.Height)) this.CanvasElement.Height=option.Height;
  193. }
  194. if (option && option.Redraw==false) return;
  195. if (this.JSChartContainer)
  196. {
  197. if (option && option.Type==1 && this.JSChartContainer.OnSize)
  198. {
  199. this.JSChartContainer.OnSize();
  200. }
  201. else
  202. {
  203. if (this.JSChartContainer.Frame) this.JSChartContainer.Frame.SetSizeChage(true);
  204. this.JSChartContainer.Draw();
  205. }
  206. }
  207. }
  208. this.SetChartBorder=function(chart, option)
  209. {
  210. if (!option.Border) return;
  211. var item=option.Border;
  212. if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
  213. else option.Border.Left=chart.Frame.ChartBorder.Left;
  214. if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
  215. else option.Border.Right=chart.Frame.ChartBorder.Right;
  216. if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
  217. else option.Border.Top=chart.Frame.ChartBorder.Top;
  218. if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
  219. else option.Border.Bottom=chart.Frame.ChartBorder.Bottom;
  220. if (item.AutoLeft)
  221. {
  222. chart.Frame.AutoLeftBorder={ };
  223. if (IFrameSplitOperator.IsNumber(item.AutoLeft.Blank)) chart.Frame.AutoLeftBorder.Blank=item.AutoLeft.Blank;
  224. if (IFrameSplitOperator.IsNumber(item.AutoLeft.MinWidth)) chart.Frame.AutoLeftBorder.MinWidth=item.AutoLeft.MinWidth;
  225. }
  226. if (item.AutoRight)
  227. {
  228. chart.Frame.AutoRightBorder={ };
  229. if (IFrameSplitOperator.IsNumber(item.AutoRight.Blank)) chart.Frame.AutoRightBorder.Blank=item.AutoRight.Blank;
  230. if (IFrameSplitOperator.IsNumber(item.AutoRight.MinWidth)) chart.Frame.AutoRightBorder.MinWidth=item.AutoRight.MinWidth;
  231. }
  232. }
  233. //历史K线图
  234. this.CreateKLineChartContainer = function (option)
  235. {
  236. var chart = null;
  237. if (option.Type === "历史K线图横屏") chart = new KLineChartHScreenContainer(this.CanvasElement);
  238. else chart = new KLineChartContainer(this.CanvasElement);
  239. if (option.NetworkFilter) chart.NetworkFilter = option.NetworkFilter;
  240. if (option.KLine) //k线图的属性设置
  241. {
  242. if (option.KLine.DragMode >= 0) chart.DragMode = option.KLine.DragMode;
  243. if (option.KLine.Right >= 0) chart.Right = option.KLine.Right;
  244. if (option.KLine.Period >= 0) chart.Period = option.KLine.Period;
  245. if (option.KLine.MaxRequestDataCount > 0) chart.MaxRequestDataCount = option.KLine.MaxRequestDataCount;
  246. if (option.KLine.Info && option.KLine.Info.length > 0) chart.SetKLineInfo(option.KLine.Info, false);
  247. if (option.KLine.Policy && option.KLine.Policy.length > 0) chart.SetPolicyInfo(option.KLine.Policy, false);
  248. if (option.KLine.KLineDoubleClick == false) chart.MinuteDialog = this.MinuteDialog = null;
  249. if (option.KLine.MaxRequestMinuteDayCount > 0) chart.MaxRequestMinuteDayCount = option.KLine.MaxRequestMinuteDayCount;
  250. if (option.KLine.DrawType) chart.KLineDrawType = option.KLine.DrawType;
  251. if (option.KLine.RightSpaceCount >= 0) chart.RightSpaceCount = option.KLine.RightSpaceCount;
  252. if (option.KLine.DataWidth>=1) chart.KLineSize={ DataWidth:option.KLine.DataWidth };
  253. if (IFrameSplitOperator.IsNumber(option.KLine.RightFormula)) chart.RightFormula=option.KLine.RightFormula;
  254. }
  255. if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle = option.SplashTitle; //设置提示信息内容
  256. if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow; //双击缩放附图
  257. if (!option.Windows || option.Windows.length <= 0) return null;
  258. if (option.Language)
  259. {
  260. var value=g_JSChartLocalization.GetLanguageID(option.Language);
  261. if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value;
  262. }
  263. if (option.SourceDatatLimit) chart.SetSourceDatatLimit(option.SourceDatatLimit);
  264. if (option.EnableZoomUpDown) chart.EnableZoomUpDown=option.EnableZoomUpDown;
  265. if (option.EnableMoveData) chart.EnableMoveData=option.EnableMoveData;
  266. if (option.TouchMoveMinAngle) chart.TouchMoveMinAngle=option.TouchMoveMinAngle;
  267. if (IFrameSplitOperator.IsBool(option.EnableScrollUpDown)) chart.EnableScrollUpDown=option.EnableScrollUpDown;
  268. if (option.ZoomStepPixel>0) chart.ZoomStepPixel=option.ZoomStepPixel;
  269. if (IFrameSplitOperator.IsNumber(option.DrawMoveWaitTime)) chart.DrawMoveWaitTime=option.DrawMoveWaitTime;
  270. if (IFrameSplitOperator.IsNumber(option.PressTime)) chart.PressTime=option.PressTime;
  271. //创建子窗口
  272. chart.Create(option.Windows.length);
  273. this.SetChartBorder(chart, option);
  274. if (option.KLine)
  275. {
  276. var item=option.KLine;
  277. var klineChart=chart.ChartPaint[0];
  278. if (option.KLine.PageSize > 0)
  279. {
  280. let maxPageSize = chart.GetMaxPageSize();
  281. if (maxPageSize < option.KLine.PageSize) chart.PageSize = maxPageSize;
  282. else chart.PageSize = option.KLine.PageSize;
  283. }
  284. if (option.KLine.InfoDrawType) chart.ChartPaint[0].InfoDrawType = option.KLine.InfoDrawType;
  285. if (IFrameSplitOperator.IsNumber(item.OneLimitBarType)) klineChart.OneLimitBarType=item.OneLimitBarType;
  286. }
  287. if (option.DragDownload)
  288. {
  289. if (option.DragDownload.Day && option.DragDownload.Day.Enable == true) chart.DragDownload.Day.Enable = true;
  290. if (option.DragDownload.Minute && option.DragDownload.Minute.Enable == true) chart.DragDownload.Minute.Enable = true;
  291. }
  292. if (option.IsApiPeriod == true) chart.IsApiPeriod = option.IsApiPeriod;
  293. if (option.CorssCursorTouchEnd == true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
  294. if (option.IsClickShowCorssCursor == true) chart.IsClickShowCorssCursor = option.IsClickShowCorssCursor;
  295. if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw;
  296. if (option.CorssCursorInfo)
  297. {
  298. var item=option.CorssCursorInfo;
  299. if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left = option.CorssCursorInfo.Left;
  300. if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right = option.CorssCursorInfo.Right;
  301. if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom = option.CorssCursorInfo.Bottom;
  302. if (option.CorssCursorInfo.IsShowCorss === false) chart.ChartCorssCursor.IsShowCorss = option.CorssCursorInfo.IsShowCorss;
  303. if (IFrameSplitOperator.IsBool(item.IsShowClose)) chart.ChartCorssCursor.IsShowClose = item.IsShowClose; //Y轴显示收盘价
  304. if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.HPenType)) chart.ChartCorssCursor.HPenType = option.CorssCursorInfo.HPenType;
  305. if (option.CorssCursorInfo.VPenType > 0) chart.ChartCorssCursor.VPenType = option.CorssCursorInfo.VPenType;
  306. if (IFrameSplitOperator.IsNumber(item.DateFormatType)) chart.ChartCorssCursor.StringFormatX.DateFormatType=item.DateFormatType;
  307. if (IFrameSplitOperator.IsNumber(item.PriceFormatType)) chart.ChartCorssCursor.StringFormatY.PriceFormatType=item.PriceFormatType;
  308. if (IFrameSplitOperator.IsNumber(item.DataFormatType)) chart.ChartCorssCursor.StringFormatY.DataFormatType=item.DataFormatType;
  309. }
  310. if (typeof (option.UpdateUICallback) == 'function') //数据到达回调
  311. chart.UpdateUICallback = option.UpdateUICallback;
  312. if (option.Frame)
  313. {
  314. for (var i in option.Frame)
  315. {
  316. var item = option.Frame[i];
  317. if (!chart.Frame.SubFrame[i]) continue;
  318. var subFrame=chart.Frame.SubFrame[i].Frame;
  319. if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount;
  320. if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat;
  321. if (!isNaN(item.Height)) chart.Frame.SubFrame[i].Height = item.Height;
  322. if (item.IsShowBorder == false) chart.Frame.SubFrame[i].Frame.IsShowBorder = item.IsShowBorder;
  323. if (item.IsShowXLine == false) chart.Frame.SubFrame[i].Frame.IsShowXLine = item.IsShowXLine;
  324. if (item.IsShowYLine==false) chart.Frame.SubFrame[i].Frame.IsShowYLine=item.IsShowYLine;
  325. if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign;
  326. if (item.IsShowTitle == false) chart.Frame.SubFrame[i].Frame.IsShowTitle = false;
  327. if (IFrameSplitOperator.IsBool(item.IsShowIndexTitle)) chart.Frame.SubFrame[i].Frame.IsShowTitle=item.IsShowIndexTitle;
  328. if (item.UpdateTitleUICallback && chart.Frame.SubFrame[i].Frame.TitlePaint) chart.Frame.SubFrame[i].Frame.TitlePaint.UpdateUICallback = item.UpdateTitleUICallback;
  329. if (item.IsShowLeftText === false || item.IsShowLeftText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[0] = item.IsShowLeftText; //显示左边刻度
  330. if (item.IsShowRightText === false || item.IsShowRightText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[1] = item.IsShowRightText; //显示右边刻度
  331. if (item.TopSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace = item.TopSpace;
  332. if (item.BottomSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace = item.BottomSpace;
  333. if (item.Custom) chart.Frame.SubFrame[i].Frame.YSplitOperator.Custom = item.Custom;
  334. if (IFrameSplitOperator.IsNumber(item.SplitType))
  335. {
  336. chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitType = item.SplitType;
  337. chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultSplitType=item.SplitType;
  338. }
  339. if (IFrameSplitOperator.IsNumber(item.FilterType)) subFrame.YSplitOperator.FilterType=item.FilterType;
  340. if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) chart.Frame.SubFrame[i].Frame.YSplitOperator.FloatPrecision = item.FloatPrecision; //强制指定小数位数(主图有效)
  341. if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine;
  342. if (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline;
  343. }
  344. }
  345. if (option.KLine)
  346. {
  347. var item=option.KLine;
  348. var klineChart=chart.ChartPaint[0];
  349. if (IFrameSplitOperator.IsBool(item.ShowKLine)) klineChart.IsShow = item.ShowKLine;
  350. if (IFrameSplitOperator.IsBool(item.IsShowMaxMinPrice)) klineChart.IsShowMaxMinPrice = item.IsShowMaxMinPrice;
  351. if (item.PriceGap)
  352. {
  353. if (IFrameSplitOperator.IsBool(item.PriceGap.Enable)) klineChart.PriceGap.Enable=item.PriceGap.Enable;
  354. if (IFrameSplitOperator.IsNumber(item.PriceGap.Count)) klineChart.PriceGap.Count=item.PriceGap.Count;
  355. }
  356. }
  357. if (option.KLineTitle)
  358. {
  359. var item=option.KLineTitle;
  360. if (option.KLineTitle.IsShowName == false) chart.TitlePaint[0].IsShowName = false;
  361. if (option.KLineTitle.IsShowSettingInfo == false) chart.TitlePaint[0].IsShowSettingInfo = false;
  362. if (option.KLineTitle.IsShow == false) chart.TitlePaint[0].IsShow = false;
  363. if (option.KLineTitle.UpdateUICallback) chart.TitlePaint[0].UpdateUICallback = option.KLineTitle.UpdateUICallback
  364. if (option.KLineTitle.LineCount > 1) chart.TitlePaint[0].LineCount = option.KLineTitle.LineCount;
  365. if (IFrameSplitOperator.IsNumber(item.TextSpace)) chart.TitlePaint[0].TextSpace=item.TextSpace;
  366. if (IFrameSplitOperator.IsNumber(item.PeriodSpace)) chart.TitlePaint[0].PeriodSpace=item.PeriodSpace;
  367. if (IFrameSplitOperator.IsNumber(item.DateTimeSpace)) chart.TitlePaint[0].DateTimeSpace=item.DateTimeSpace;
  368. if (IFrameSplitOperator.IsNumber(item.NameSpace)) chart.TitlePaint[0].NameSpace=item.NameSpace;
  369. }
  370. //叠加股票 只支持叠加1个股票
  371. if (option.Overlay)
  372. {
  373. for (var i=0;i<option.Overlay.length;++i )
  374. {
  375. var item = option.Overlay[i];
  376. chart.OverlaySymbol(item.Symbol,item);
  377. }
  378. }
  379. if (option.ExtendChart) //创建扩展画法
  380. {
  381. for (var i in option.ExtendChart)
  382. {
  383. var item = option.ExtendChart[i];
  384. chart.CreateExtendChart(item.Name, item);
  385. }
  386. }
  387. let scriptData = new JSCommonIndexScript.JSIndexScript(); //系统指标
  388. if (option.ColorIndex) //五彩K线
  389. {
  390. var item = option.ColorIndex;
  391. let indexInfo = scriptData.Get(item.Index);
  392. if (indexInfo) chart.ColorIndex = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  393. }
  394. if (option.TradeIndex) //交易指标
  395. {
  396. var item = option.TradeIndex;
  397. let indexInfo = scriptData.Get(item.Index);
  398. if (indexInfo) chart.TradeIndex = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  399. }
  400. for (var i=0; i<option.Windows.length; ++i) //创建子窗口的指标
  401. {
  402. var item = option.Windows[i];
  403. if (item.Script)
  404. {
  405. chart.WindowIndex[i] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行
  406. }
  407. else if (item.API) //使用API挂接指标数据 API:{ Name:指标名字, Script:指标脚本可以为空, Args:参数可以为空, Url:指标执行地址 }
  408. {
  409. var apiItem = item.API;
  410. chart.WindowIndex[i] = new APIScriptIndex(apiItem.Name, apiItem.Script, apiItem.Args, item);
  411. }
  412. else
  413. {
  414. var indexItem = JSIndexMap.Get(item.Index); //自定义指标
  415. if (indexItem)
  416. {
  417. chart.WindowIndex[i] = indexItem.Create();
  418. chart.CreateWindowIndex(i);
  419. }
  420. else //系统指标里查找
  421. {
  422. let indexInfo = scriptData.Get(item.Index);
  423. if (!indexInfo) continue;
  424. JSIndexScript.ModifyAttribute(indexInfo, item);
  425. indexInfo.ID = item.Index;
  426. chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  427. if (item.StringFormat > 0) chart.WindowIndex[i].StringFormat = item.StringFormat;
  428. if (item.FloatPrecision >= 0) chart.WindowIndex[i].FloatPrecision = item.FloatPrecision;
  429. }
  430. }
  431. var frame=chart.Frame.SubFrame[i].Frame;
  432. if (item.Modify != null) chart.Frame.SubFrame[i].Frame.ModifyIndex = item.Modify;
  433. if (item.Change != null) chart.Frame.SubFrame[i].Frame.ChangeIndex = item.Change;
  434. if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) chart.Frame.SubFrame[i].Frame.IsDrawTitleBG=item.IsDrawTitleBG;
  435. if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) chart.Frame.SubFrame[i].Frame.IsShowNameArrow=item.IsShowNameArrow;
  436. if (IFrameSplitOperator.IsBool(item.IsShowTitleArrow)) frame.IsShowTitleArrow=item.IsShowTitleArrow;
  437. if (typeof (item.UpdateUICallback) == 'function') chart.WindowIndex[i].UpdateUICallback = item.UpdateUICallback;
  438. if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight = item.TitleHeight;
  439. if (item.IsShowIndexName == false) chart.Frame.SubFrame[i].Frame.IsShowIndexName = false;
  440. if (item.IndexParamSpace >= 0) chart.Frame.SubFrame[i].Frame.IndexParamSpace = item.IndexParamSpace;
  441. if (item.IndexTitleSpace >= 0) chart.Frame.SubFrame[i].Frame.IndexTitleSpace = item.IndexTitleSpace;
  442. if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) frame.HorizontalReserved=item.HorizontalReserved;
  443. }
  444. //叠加指标
  445. if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
  446. {
  447. for(var i=0;i<option.OverlayIndex.length;++i)
  448. {
  449. var item=option.OverlayIndex[i];
  450. if (item.Windows>=chart.Frame.SubFrame.length) continue;
  451. var itemString = JSON.stringify(item);
  452. var obj = JSON.parse(itemString);
  453. if (item.Index) obj.IndexName=item.Index;
  454. if (item.Windows>=0) obj.WindowIndex=item.Windows;
  455. chart.CreateOverlayWindowsIndex(obj);
  456. }
  457. }
  458. return chart;
  459. }
  460. //自定义指数历史K线图
  461. this.CreateCustomKLineChartContainer = function (option) {
  462. var chart = new CustomKLineChartContainer(this.CanvasElement);
  463. if (option.KLine) //k线图的属性设置
  464. {
  465. if (option.KLine.DragMode >= 0) chart.DragMode = option.KLine.DragMode;
  466. if (option.KLine.Right >= 0) chart.Right = option.KLine.Right;
  467. if (option.KLine.Period >= 0) chart.Period = option.KLine.Period;
  468. if (option.KLine.MaxRequestDataCount > 0) chart.MaxRequestDataCount = option.KLine.MaxRequestDataCount;
  469. if (option.KLine.Info && option.KLine.Info.length > 0) chart.SetKLineInfo(option.KLine.Info, false);
  470. if (option.KLine.KLineDoubleClick == false) chart.MinuteDialog = this.MinuteDialog = null;
  471. if (option.KLine.PageSize > 0) chart.PageSize = option.KLine.PageSize;
  472. if (option.KLine.IsShowTooltip == false) chart.IsShowTooltip = false;
  473. }
  474. if (option.CustomStock) chart.CustomStock = option.CustomStock;
  475. if (option.QueryDate) chart.QueryDate = option.QueryDate;
  476. if (typeof (option.UpdateUICallback) == 'function') chart.UpdateUICallback = option.UpdateUICallback;
  477. if (!option.Windows || option.Windows.length <= 0) return null;
  478. //创建子窗口
  479. chart.Create(option.Windows.length);
  480. if (option.Border) {
  481. if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left = option.Border.Left;
  482. if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right = option.Border.Right;
  483. if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top = option.Border.Top;
  484. if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom = option.Border.Bottom;
  485. }
  486. if (option.IsShowCorssCursorInfo == false) //取消显示十字光标刻度信息
  487. {
  488. chart.ChartCorssCursor.IsShowText = option.IsShowCorssCursorInfo;
  489. }
  490. if (option.Frame) {
  491. for (var i in option.Frame) {
  492. var item = option.Frame[i];
  493. if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount;
  494. if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat;
  495. if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign;
  496. }
  497. }
  498. if (option.KLineTitle) {
  499. if (option.KLineTitle.IsShowName == false) chart.TitlePaint[0].IsShowName = false;
  500. if (option.KLineTitle.IsShowSettingInfo == false) chart.TitlePaint[0].IsShowSettingInfo = false;
  501. }
  502. //创建子窗口的指标
  503. let scriptData = new JSCommonIndexScript.JSIndexScript();
  504. for (var i in option.Windows) {
  505. var item = option.Windows[i];
  506. if (item.Script) {
  507. chart.WindowIndex[i] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行
  508. }
  509. else {
  510. var indexItem = JSIndexMap.Get(item.Index);
  511. if (indexItem) {
  512. chart.WindowIndex[i] = indexItem.Create();
  513. chart.CreateWindowIndex(i);
  514. }
  515. else //系统指标里查找
  516. {
  517. let indexInfo = scriptData.Get(item.Index);
  518. if (!indexInfo) continue;
  519. if (item.Lock) indexInfo.Lock = item.Lock;
  520. chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  521. }
  522. }
  523. if (item.Modify != null)
  524. chart.Frame.SubFrame[i].Frame.ModifyIndex = item.Modify;
  525. if (item.Change != null)
  526. chart.Frame.SubFrame[i].Frame.ChangeIndex = item.Change;
  527. if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight = item.TitleHeight;
  528. }
  529. return chart;
  530. }
  531. //分钟走势图
  532. this.CreateMinuteChartContainer = function (option)
  533. {
  534. var chart = null;
  535. if (option.Type === "分钟走势图横屏") chart = new MinuteChartHScreenContainer(this.CanvasElement);
  536. else chart = new MinuteChartContainer(this.CanvasElement);
  537. if (option.NetworkFilter) chart.NetworkFilter = option.NetworkFilter;
  538. var windowsCount = 2;
  539. if (option.Windows && option.Windows.length > 0) windowsCount += option.Windows.length; //指标窗口从第3个窗口开始
  540. if (option.TouchMoveMinAngle) chart.TouchMoveMinAngle=option.TouchMoveMinAngle;
  541. if (IFrameSplitOperator.IsBool(option.EnableScrollUpDown)) chart.EnableScrollUpDown=option.EnableScrollUpDown;
  542. if (option.Info && option.Info.length > 0) chart.SetMinuteInfo(option.Info, false);
  543. if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle = option.SplashTitle; //设置提示信息内容
  544. if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow; //双击缩放附图
  545. if (IFrameSplitOperator.IsNumber(option.DrawMoveWaitTime)) chart.DrawMoveWaitTime=option.DrawMoveWaitTime;
  546. if (IFrameSplitOperator.IsNumber(option.PressTime)) chart.PressTime=option.PressTime;
  547. if (IFrameSplitOperator.IsBool(option.EnableNightDayBG)) chart.EnableNightDayBG=option.EnableNightDayBG;
  548. if (option.Language)
  549. {
  550. var value=g_JSChartLocalization.GetLanguageID(option.Language);
  551. if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value;
  552. }
  553. chart.Create(windowsCount); //创建子窗口
  554. if (option.CorssCursorTouchEnd == true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
  555. if (IFrameSplitOperator.IsBool(option.IsClickShowCorssCursor)) chart.IsClickShowCorssCursor = option.IsClickShowCorssCursor;
  556. if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw;
  557. if (option.CorssCursorInfo) //十字光标设置
  558. {
  559. var item=option.CorssCursorInfo;
  560. if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left = option.CorssCursorInfo.Left;
  561. if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right = option.CorssCursorInfo.Right;
  562. if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom = option.CorssCursorInfo.Bottom;
  563. if (option.CorssCursorInfo.IsShowCorss === false) chart.ChartCorssCursor.IsShowCorss = option.CorssCursorInfo.IsShowCorss;
  564. if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime;
  565. if (IFrameSplitOperator.IsNumber(item.PriceFormatType)) chart.ChartCorssCursor.StringFormatY.PriceFormatType=item.PriceFormatType;
  566. if (IFrameSplitOperator.IsNumber(item.DataFormatType)) chart.ChartCorssCursor.StringFormatY.DataFormatType=item.DataFormatType;
  567. if (IFrameSplitOperator.IsNumber(item.RightTextFormat)) chart.ChartCorssCursor.TextFormat.Right=item.RightTextFormat;
  568. if (IFrameSplitOperator.IsBool(item.IsOnlyDrawMinute)) chart.ChartCorssCursor.IsOnlyDrawMinute = item.IsOnlyDrawMinute; //Y轴显示收盘价
  569. if (IFrameSplitOperator.IsNumber(item.HPenType)) chart.ChartCorssCursor.HPenType=item.HPenType;
  570. if (IFrameSplitOperator.IsNumber(item.VPenType)) chart.ChartCorssCursor.VPenType=item.VPenType;
  571. }
  572. if (option.MinuteInfo) chart.CreateMinuteInfo(option.MinuteInfo);
  573. if (option.DayCount > 1) chart.DayCount = option.DayCount;
  574. this.SetChartBorder(chart, option);
  575. if (option.Frame)
  576. {
  577. for (var i=0 ;i<option.Frame.length;++i)
  578. {
  579. var item = option.Frame[i];
  580. if (!chart.Frame.SubFrame[i]) continue;
  581. var frame=chart.Frame.SubFrame[i].Frame;
  582. if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount;
  583. if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat;
  584. if (IFrameSplitOperator.IsNumber(item.SplitType))
  585. {
  586. chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitType=item.SplitType;
  587. chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultSplitType=item.SplitType;
  588. }
  589. if (IFrameSplitOperator.IsNumber(item.FilterType)) subFrame.YSplitOperator.FilterType=item.FilterType;
  590. if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign;
  591. if (item.IsShowLeftText === false || item.IsShowLeftText===true ) chart.Frame.SubFrame[i].Frame.IsShowYText[0] = item.IsShowLeftText; //显示左边刻度
  592. if (item.IsShowRightText === false || item.IsShowRightText===true) chart.Frame.SubFrame[i].Frame.IsShowYText[1] = item.IsShowRightText; //显示右边刻度
  593. if (item.Height >= 0) chart.Frame.SubFrame[i].Height = item.Height;
  594. if (item.Custom) chart.Frame.SubFrame[i].Frame.YSplitOperator.Custom = item.Custom;
  595. if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine;
  596. if (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline;
  597. if (IFrameSplitOperator.IsBool(item.IsShowXLine)) chart.Frame.SubFrame[i].Frame.IsShowXLine = item.IsShowXLine;
  598. if (IFrameSplitOperator.IsBool(item.IsShowYLine)) chart.Frame.SubFrame[i].Frame.IsShowYLine=item.IsShowYLine;
  599. if (item.TopSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace = item.TopSpace;
  600. if (item.BottomSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace = item.BottomSpace;
  601. if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) frame.HorizontalReserved=item.HorizontalReserved;
  602. }
  603. chart.UpdateXShowText();
  604. }
  605. if (option.MinuteTitle)
  606. {
  607. var item=option.MinuteTitle;
  608. if (option.MinuteTitle.IsShowName == false) chart.TitlePaint[0].IsShowName = false;
  609. if (option.MinuteTitle.IsShow == false) chart.TitlePaint[0].IsShow = false;
  610. if (option.MinuteTitle.UpdateUICallback) chart.TitlePaint[0].UpdateUICallback = option.MinuteTitle.UpdateUICallback
  611. if (option.MinuteTitle.LineCount > 1) chart.TitlePaint[0].LineCount = option.MinuteTitle.LineCount;
  612. if (IFrameSplitOperator.IsNumber(item.TextSpace)) chart.TitlePaint[0].TextSpace=item.TextSpace;
  613. }
  614. if (option.MinuteVol)
  615. {
  616. var item=option.MinuteVol;
  617. if (IFrameSplitOperator.IsNumber(item.BarColorType)) chart.ChartPaint[2].BarColorType=item.BarColorType;
  618. }
  619. if (typeof (option.UpdateUICallback) == 'function') //数据到达回调
  620. chart.UpdateUICallback = option.UpdateUICallback;
  621. if (option.ExtendChart) //创建扩展画法
  622. {
  623. for (var i in option.ExtendChart) {
  624. var item = option.ExtendChart[i];
  625. chart.CreateExtendChart(item.Name, item);
  626. }
  627. }
  628. //叠加股票 只支持1只股票
  629. if (IFrameSplitOperator.IsNonEmptyArray(option.Overlay))
  630. {
  631. for (var i=0;i<option.Overlay.length; ++i)
  632. {
  633. var item = option.Overlay[i];
  634. chart.OverlaySymbol(item.Symbol,item);
  635. }
  636. }
  637. if (option.MinuteLine)
  638. {
  639. if (option.MinuteLine.IsDrawAreaPrice == false) chart.ChartPaint[0].IsDrawArea = false;
  640. if (option.MinuteLine.IsShowAveragePrice == false)
  641. {
  642. chart.ChartPaint[1].IsShow = false;
  643. chart.TitlePaint[0].IsShowAveragePrice=false; //标题栏均线也不显示
  644. for(var i in chart.ExtendChartPaint)
  645. {
  646. var item=chart.ExtendChartPaint[i];
  647. if (item.ClassName=="MinuteTooltipPaint") item.IsShowAveragePrice=false;
  648. }
  649. }
  650. if (option.MinuteLine.SplitType>0) chart.Frame.SubFrame[0].Frame.YSplitOperator.SplitType=option.MinuteLine.SplitType;
  651. }
  652. let scriptData = new JSCommonIndexScript.JSIndexScript();
  653. for (var i=0; i<option.Windows.length; ++i) //分钟数据指标从第3个指标窗口设置
  654. {
  655. var index=i+2;
  656. var item = option.Windows[i];
  657. if (item.Script)
  658. {
  659. chart.WindowIndex[2+i] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行
  660. }
  661. else if (item.API) //使用API挂接指标数据 API:{ Name:指标名字, Script:指标脚本可以为空, Args:参数可以为空, Url:指标执行地址 }
  662. {
  663. var apiItem = item.API;
  664. chart.WindowIndex[2+i] = new APIScriptIndex(apiItem.Name, apiItem.Script, apiItem.Args, item);
  665. }
  666. else
  667. {
  668. var indexItem = JSIndexMap.Get(item.Index);
  669. if (indexItem)
  670. {
  671. chart.WindowIndex[2+i] = indexItem.Create(); //创建子窗口的指标
  672. chart.CreateWindowIndex(index);
  673. }
  674. else
  675. {
  676. let indexInfo = scriptData.Get(item.Index);
  677. if (!indexInfo) continue;
  678. JSIndexScript.ModifyAttribute(indexInfo, item);
  679. indexInfo.ID=item.Index;
  680. chart.WindowIndex[2+i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  681. if (item.StringFormat > 0) chart.WindowIndex[index].StringFormat = item.StringFormat;
  682. if (item.FloatPrecision >= 0) chart.WindowIndex[index].FloatPrecision = item.FloatPrecision;
  683. }
  684. }
  685. if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[index].Frame.ChartBorder.TitleHeight = item.TitleHeight; //指标标题高度
  686. if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) chart.Frame.SubFrame[index].Frame.IsDrawTitleBG=item.IsDrawTitleBG;
  687. if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) chart.Frame.SubFrame[index].Frame.IsShowNameArrow=item.IsShowNameArrow;
  688. if (IFrameSplitOperator.IsBool(item.IsShowTitleArrow)) chart.Frame.SubFrame[index].Frame.IsShowTitleArrow=item.IsShowTitleArrow;
  689. if (IFrameSplitOperator.IsNumber(item.YSplitType)) chart.Frame.SubFrame[index].Frame.YSplitOperator.SplitType=item.YSplitType;
  690. }
  691. //叠加指标
  692. if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
  693. {
  694. for(var i=0;i<option.OverlayIndex.length;++i)
  695. {
  696. var item=option.OverlayIndex[i];
  697. if (item.Windows>=chart.Frame.SubFrame.length) continue;
  698. var itemString = JSON.stringify(item);
  699. var obj = JSON.parse(itemString);
  700. if (item.Index) obj.IndexName=item.Index;
  701. if (item.Windows>=0) obj.WindowIndex=item.Windows;
  702. chart.CreateOverlayWindowsIndex(obj);
  703. }
  704. }
  705. return chart;
  706. }
  707. //历史分钟走势图
  708. this.CreateHistoryMinuteChartContainer = function (option) {
  709. var chart = new HistoryMinuteChartContainer(this.CanvasElement);
  710. var windowsCount = 2;
  711. if (option.Windows && option.Windows.length > 0) windowsCount += option.Windows.length; //指标窗口从第3个窗口开始
  712. chart.Create(windowsCount); //创建子窗口
  713. if (option.IsShowCorssCursorInfo == false) //取消显示十字光标刻度信息
  714. {
  715. chart.ChartCorssCursor.IsShowText = option.IsShowCorssCursorInfo;
  716. }
  717. if (option.Border) {
  718. if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left = option.Border.Left;
  719. if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right = option.Border.Right;
  720. if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top = option.Border.Top;
  721. if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom = option.Border.Bottom;
  722. }
  723. if (option.Frame) {
  724. for (var i in option.Frame) {
  725. var item = option.Frame[i];
  726. if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount;
  727. if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat;
  728. if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign;
  729. }
  730. }
  731. let scriptData = new JSCommonIndexScript.JSIndexScript();
  732. for (var i in option.Windows) //分钟数据指标从第3个指标窗口设置
  733. {
  734. var item = option.Windows[i];
  735. if (item.Script) {
  736. chart.WindowIndex[2 + parseInt(i)] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行
  737. }
  738. else {
  739. var indexItem = JSIndexMap.Get(item.Index);
  740. if (indexItem) {
  741. chart.WindowIndex[2 + parseInt(i)] = indexItem.Create(); //创建子窗口的指标
  742. chart.CreateWindowIndex(2 + parseInt(i));
  743. }
  744. else {
  745. let indexInfo = scriptData.Get(item.Index);
  746. if (!indexInfo) continue;
  747. if (item.Lock) indexInfo.Lock = item.Lock;
  748. chart.WindowIndex[2 + parseInt(i)] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  749. }
  750. }
  751. if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[2 + parseInt(i)].Frame.ChartBorder.TitleHeight = item.TitleHeight;
  752. }
  753. chart.TradeDate = 20181009;
  754. if (option.HistoryMinute) {
  755. if (option.HistoryMinute.TradeDate) chart.TradeDate = option.HistoryMinute.TradeDate;
  756. if (option.HistoryMinute.IsShowName != null) chart.TitlePaint[0].IsShowName = option.HistoryMinute.IsShowName; //动态标题是否显示股票名称
  757. if (option.HistoryMinute.IsShowDate != null) chart.TitlePaint[0].IsShowDate = option.HistoryMinute.IsShowDate; //动态标题是否显示日期
  758. }
  759. return chart;
  760. }
  761. this.CreateKLineTrainChartContainer = function (option)
  762. {
  763. if (option.Type=="简单K线训练" || option.Type=="简单K线训练横屏")
  764. {
  765. var bHScreen=(option.Type=='简单K线训练横屏'? true:false);
  766. var chart=new KLineTrainSimpleChartContainer(this.CanvasElement,bHScreen);
  767. }
  768. else
  769. {
  770. var bHScreen = (option.Type == 'K线训练横屏' ? true : false);
  771. var chart = new KLineTrainChartContainer(this.CanvasElement, bHScreen);
  772. }
  773. if (option.NetworkFilter) chart.NetworkFilter = option.NetworkFilter;
  774. if (option.IsApiPeriod == true) chart.IsApiPeriod = option.IsApiPeriod;
  775. if (option.KLine) //k线图的属性设置
  776. {
  777. if (option.KLine.Right >= 0) chart.Right = option.KLine.Right;
  778. if (option.KLine.Period >= 0) chart.Period = option.KLine.Period;
  779. if (option.KLine.MaxRequestDataCount > 0) chart.MaxRequestDataCount = option.KLine.MaxRequestDataCount;
  780. if (option.KLine.Info && option.KLine.Info.length > 0) chart.SetKLineInfo(option.KLine.Info, false);
  781. if (option.KLine.PageSize > 0) chart.PageSize = option.KLine.PageSize;
  782. if (option.KLine.IsShowTooltip == false) chart.IsShowTooltip = false;
  783. if (option.KLine.MaxRequestMinuteDayCount > 0) chart.MaxRequestMinuteDayCount = option.KLine.MaxRequestMinuteDayCount;
  784. if (option.KLine.DrawType) chart.KLineDrawType = option.KLine.DrawType;
  785. }
  786. if (option.Train)
  787. {
  788. if (option.Train.DataCount) chart.TrainDataCount = option.Train.DataCount;
  789. if (option.Train.Callback) chart.TrainCallback = option.Train.Callback;
  790. if (option.Train.StartDate) chart.TrainStartDate = option.Train.StartDate;
  791. }
  792. if (!option.Windows || option.Windows.length <= 0) return null;
  793. //创建子窗口
  794. chart.Create(option.Windows.length);
  795. this.SetChartBorder(chart, option);
  796. if (option.ExtendChart) //创建扩展画法
  797. {
  798. for (var i in option.ExtendChart)
  799. {
  800. var item = option.ExtendChart[i];
  801. chart.CreateExtendChart(item.Name, item);
  802. }
  803. }
  804. if (option.IsShowCorssCursorInfo == false) chart.ChartCorssCursor.IsShowText = option.IsShowCorssCursorInfo;//取消显示十字光标刻度信息
  805. if (option.CorssCursorTouchEnd == true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
  806. if (option.IsClickShowCorssCursor == true) chart.IsClickShowCorssCursor = option.IsClickShowCorssCursor;
  807. if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw;
  808. if (option.CorssCursorInfo)
  809. {
  810. var item=option.CorssCursorInfo;
  811. if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left = option.CorssCursorInfo.Left;
  812. if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right = option.CorssCursorInfo.Right;
  813. if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom = option.CorssCursorInfo.Bottom;
  814. if (option.CorssCursorInfo.IsShowCorss === false) chart.ChartCorssCursor.IsShowCorss = option.CorssCursorInfo.IsShowCorss;
  815. if (IFrameSplitOperator.IsBool(item.IsShowClose)) chart.ChartCorssCursor.IsShowClose = item.IsShowClose; //Y轴显示收盘价
  816. if (option.CorssCursorInfo.HPenType > 0) chart.ChartCorssCursor.HPenType = option.CorssCursorInfo.HPenType;
  817. if (option.CorssCursorInfo.VPenType > 0) chart.ChartCorssCursor.VPenType = option.CorssCursorInfo.VPenType;
  818. if (IFrameSplitOperator.IsBool(item.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=item.IsFixXLastTime;
  819. }
  820. if (option.Frame)
  821. {
  822. for (var i in option.Frame)
  823. {
  824. if (!chart.Frame.SubFrame[i]) continue;
  825. var item = option.Frame[i];
  826. if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount;
  827. if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat;
  828. if (item.Height>0) chart.Frame.SubFrame[i].Height = item.Height;
  829. if (item.IsShowLeftText === false || item.IsShowLeftText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[0] = item.IsShowLeftText; //显示左边刻度
  830. if (item.IsShowRightText === false || item.IsShowRightText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[1] = item.IsShowRightText; //显示右边刻度
  831. }
  832. }
  833. if (option.KLine)
  834. {
  835. if (option.KLine.ShowKLine == false) chart.ChartPaint[0].IsShow = false;
  836. if (option.KLine.IsShowMaxMinPrice == false) chart.ChartPaint[0].IsShowMaxMinPrice = false;
  837. }
  838. //股票名称 日期 周期都不显示
  839. chart.TitlePaint[0].IsShowName = false;
  840. chart.TitlePaint[0].IsShowSettingInfo = false;
  841. chart.TitlePaint[0].IsShowDateTime = false;
  842. //创建子窗口的指标
  843. let scriptData = new JSCommonIndexScript.JSIndexScript();
  844. for (var i in option.Windows)
  845. {
  846. var item = option.Windows[i];
  847. if (item.Script)
  848. {
  849. chart.WindowIndex[i] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行
  850. }
  851. else
  852. {
  853. let indexItem = JSIndexMap.Get(item.Index);
  854. if (indexItem)
  855. {
  856. chart.WindowIndex[i] = indexItem.Create();
  857. chart.CreateWindowIndex(i);
  858. }
  859. else
  860. {
  861. let indexInfo = scriptData.Get(item.Index);
  862. if (!indexInfo) continue;
  863. if (item.Lock) indexInfo.Lock = item.Lock;
  864. chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  865. }
  866. }
  867. if (item.Modify != null) chart.Frame.SubFrame[i].Frame.ModifyIndex = item.Modify;
  868. if (item.Change != null) chart.Frame.SubFrame[i].Frame.ChangeIndex = item.Change;
  869. if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight = item.TitleHeight;
  870. }
  871. return chart;
  872. }
  873. //深度图
  874. this.CreateDepthChartContainer=function(option)
  875. {
  876. var chart=null;
  877. chart=new DepthChartContainer(this.CanvasElement);
  878. if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter;
  879. if (option.EnableScrollUpDown==true) chart.EnableScrollUpDown=option.EnableScrollUpDown;
  880. if (IFrameSplitOperator.IsPlusNumber(option.MaxVolRate)) chart.MaxVolRate=option.MaxVolRate;
  881. if (option.ZoomStepPixel>0) chart.ZoomStepPixel=option.ZoomStepPixel;
  882. if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle = option.SplashTitle; //设置提示信息内容
  883. if (option.Language)
  884. {
  885. var value=g_JSChartLocalization.GetLanguageID(option.Language);
  886. if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value;
  887. }
  888. chart.Create(option.Listener);
  889. if (option.Border)
  890. {
  891. if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
  892. else option.Border.Left=chart.Frame.ChartBorder.Left;
  893. if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
  894. else option.Border.Right=chart.Frame.ChartBorder.Right;
  895. if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
  896. else option.Border.Top=chart.Frame.ChartBorder.Top;
  897. if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
  898. else option.Border.Bottom=chart.Frame.ChartBorder.Bottom;
  899. }
  900. if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw;
  901. if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd;
  902. if (option.CorssCursorInfo)
  903. {
  904. var item=option.CorssCursorInfo;
  905. if (IFrameSplitOperator.IsNumber(item.HPenType)) chart.ChartCorssCursor.HPenType=item.HPenType;
  906. if (IFrameSplitOperator.IsNumber(item.VPenType)) chart.ChartCorssCursor.VPenType=item.VPenType;
  907. if (IFrameSplitOperator.IsBool(item.IsShowTooltip)) chart.ChartCorssCursor.IsShowTooltip=item.IsShowTooltip;
  908. }
  909. if (option.Frame)
  910. {
  911. var item=option.Frame
  912. if (item.SplitCount) chart.Frame.YSplitOperator.SplitCount=item.SplitCount;
  913. if (IFrameSplitOperator.IsNumber(item.SplitType)) chart.Frame.YSplitOperator.SplitType=item.SplitType;
  914. if (IFrameSplitOperator.IsNumber(item.Height)) chart.Frame.Height = item.Height;
  915. if (IFrameSplitOperator.IsNumber(item.LineType)) chart.Frame.YSplitOperator.LineType=item.LineType;
  916. if (Array.isArray(item.IgnoreYValue)) chart.Frame.YSplitOperator.IgnoreYValue=item.IgnoreYValue;
  917. if (item.IsShowLeftText===false || item.IsShowLeftText===true)
  918. {
  919. chart.Frame.IsShowYText[0]=item.IsShowLeftText;
  920. chart.Frame.YSplitOperator.IsShowLeftText=item.IsShowLeftText; //显示左边刻度
  921. }
  922. if (item.IsShowRightText===false || item.IsShowRightText===true)
  923. {
  924. chart.Frame.IsShowYText[1]=item.IsShowRightText;
  925. chart.Frame.YSplitOperator.IsShowRightText=item.IsShowRightText; //显示右边刻度
  926. }
  927. if (item.IsShowXLine==false) chart.Frame.IsShowXLine=item.IsShowXLine;
  928. if (item.IsShowYLine==false) chart.Frame.IsShowYLine=item.IsShowYLine;
  929. if (IFrameSplitOperator.IsNumber(item.XSplitCount)) chart.Frame.XSplitOperator.SplitCount=item.XSplitCount;
  930. }
  931. return chart;
  932. }
  933. //根据option内容绘制图形
  934. this.SetOption = function (option)
  935. {
  936. JSConsole.Chart.Log('[JSChart::SetOption]', option)
  937. var chart = null;
  938. switch (option.Type)
  939. {
  940. case "历史K线图":
  941. case '历史K线图横屏':
  942. chart = this.CreateKLineChartContainer(option);
  943. break;
  944. case "自定义指数历史K线图":
  945. chart = this.CreateCustomKLineChartContainer(option);
  946. break;
  947. case "分钟走势图":
  948. case "分钟走势图横屏":
  949. chart = this.CreateMinuteChartContainer(option);
  950. break;
  951. case "历史分钟走势图":
  952. chart = this.CreateHistoryMinuteChartContainer(option);
  953. break;
  954. case 'K线训练':
  955. case 'K线训练横屏':
  956. case "简单K线训练":
  957. case "简单K线训练横屏":
  958. chart = this.CreateKLineTrainChartContainer(option);
  959. break;
  960. case "深度图":
  961. chart=this.CreateDepthChartContainer(option);
  962. break;
  963. default:
  964. return false;
  965. }
  966. if (!chart) return false;
  967. this.JSChartContainer = chart;
  968. if (option.OnCreatedCallback) option.OnCreatedCallback(chart);
  969. //是否自动更新
  970. if (option.IsAutoUpdate == true || option.IsAutoUpate == true) chart.IsAutoUpdate = true;
  971. if (option.AutoUpdateFrequency > 0) chart.AutoUpdateFrequency = option.AutoUpdateFrequency;
  972. //注册事件
  973. for(var i in option.EventCallback)
  974. {
  975. var item=option.EventCallback[i];
  976. chart.AddEventCallback(item);
  977. }
  978. //设置股票代码
  979. if (!option.Symbol) return false;
  980. chart.Draw();
  981. chart.ChangeSymbol(option.Symbol);
  982. this.JSChartContainer.Draw();
  983. }
  984. //切换股票代码接口
  985. this.ChangeSymbol = function (symbol)
  986. {
  987. if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol);
  988. }
  989. //K线切换指标
  990. this.ChangeIndex = function (windowIndex, indexName, option)
  991. {
  992. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeIndex) == 'function')
  993. this.JSChartContainer.ChangeIndex(windowIndex, indexName, option);
  994. }
  995. //切换一个窗口指标,包含叠加指标,以及这个窗口的属性
  996. this.ChangeIndexWindow=function(windowIndex, option)
  997. {
  998. if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeIndexWindow)=='function')
  999. this.JSChartContainer.ChangeIndexWindow(windowIndex, option);
  1000. }
  1001. //切换K线指标
  1002. this.ChangeScriptIndex = function (windowIndex, indexData)
  1003. {
  1004. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeScriptIndex) == 'function')
  1005. this.JSChartContainer.ChangeScriptIndex(windowIndex, indexData);
  1006. }
  1007. //获取当前显示的指标信息
  1008. this.GetIndexInfo = function ()
  1009. {
  1010. if (this.JSChartContainer && typeof (this.JSChartContainer.GetIndexInfo) == 'function')
  1011. return this.JSChartContainer.GetIndexInfo();
  1012. else
  1013. return [];
  1014. }
  1015. //K线周期切换
  1016. this.ChangePeriod = function (period, option)
  1017. {
  1018. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangePeriod) == 'function')
  1019. this.JSChartContainer.ChangePeriod(period, option);
  1020. }
  1021. //切换系统指示
  1022. this.ChangeInstructionIndex = function (indexName)
  1023. {
  1024. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeInstructionIndex) == 'function')
  1025. this.JSChartContainer.ChangeInstructionIndex(indexName);
  1026. }
  1027. //切换自定义指示
  1028. this.ChangeInstructionScriptIndex = function (indexData)
  1029. {
  1030. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeInstructionIndex) == 'function')
  1031. this.JSChartContainer.ChangeInstructionScriptIndex(indexData);
  1032. }
  1033. //增加一个指标窗口
  1034. this.AddIndexWindow=function(indexName,option)
  1035. {
  1036. if (this.JSChartContainer && typeof(this.JSChartContainer.AddIndexWindow)=='function')
  1037. this.JSChartContainer.AddIndexWindow(indexName,option);
  1038. }
  1039. this.AddScriptIndexWindow=function(indexInfo, option)
  1040. {
  1041. if (this.JSChartContainer && typeof(this.JSChartContainer.AddScriptIndexWindow)=='function')
  1042. this.JSChartContainer.AddScriptIndexWindow(indexInfo,option);
  1043. }
  1044. this.AddAPIIndexWindow=function(indexData, option)
  1045. {
  1046. if (this.JSChartContainer && typeof(this.JSChartContainer.AddAPIIndexWindow)=='function')
  1047. this.JSChartContainer.AddAPIIndexWindow(indexData,option);
  1048. }
  1049. //删除一个指标窗口
  1050. this.RemoveIndexWindow=function(id)
  1051. {
  1052. if (this.JSChartContainer && typeof(this.JSChartContainer.RemoveIndexWindow)=='function')
  1053. this.JSChartContainer.RemoveIndexWindow(id);
  1054. }
  1055. //取消指示
  1056. this.CancelInstructionIndex = function ()
  1057. {
  1058. if (this.JSChartContainer && typeof (this.JSChartContainer.CancelInstructionIndex) == 'function')
  1059. this.JSChartContainer.CancelInstructionIndex();
  1060. }
  1061. //切换指标模板
  1062. this.ChangeIndexTemplate = function (option)
  1063. {
  1064. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeIndexTemplate) == 'function') {
  1065. JSConsole.Chart.Log('[JSChart:ChangeIndexTemplate] ', option);
  1066. this.JSChartContainer.ChangeIndexTemplate(option);
  1067. }
  1068. }
  1069. this.CreateChartDrawPicture=function(name,option)
  1070. {
  1071. if(this.JSChartContainer && typeof(this.JSChartContainer.CreateChartDrawPicture)=='function')
  1072. {
  1073. JSConsole.Chart.Log('[JSChart:CreateChartDrawPicture] ', name);
  1074. this.JSChartContainer.CreateChartDrawPicture(name,option);
  1075. }
  1076. }
  1077. //K线复权切换
  1078. this.ChangeRight = function (right)
  1079. {
  1080. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeRight) == 'function')
  1081. this.JSChartContainer.ChangeRight(right);
  1082. }
  1083. //设置当前屏的起始日期 { Date:起始日期(必填), Time:起始时间(分钟K线必填) PageSize:一屏显示的数据个数(可选)}
  1084. this.SetFirstShowDate=function(obj)
  1085. {
  1086. if (this.JSChartContainer && typeof(this.JSChartContainer.SetFirstShowDate)=='function')
  1087. this.JSChartContainer.SetFirstShowDate(obj);
  1088. }
  1089. //K线切换类型 0=实心K线 1=收盘价线 2=美国线 3=空心K线
  1090. this.ChangeKLineDrawType = function (drawType)
  1091. {
  1092. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeKLineDrawType) == 'function')
  1093. this.JSChartContainer.ChangeKLineDrawType(drawType);
  1094. }
  1095. //叠加股票
  1096. this.OverlaySymbol = function (symbol,option)
  1097. {
  1098. if (this.JSChartContainer && typeof (this.JSChartContainer.OverlaySymbol) == 'function')
  1099. this.JSChartContainer.OverlaySymbol(symbol, option);
  1100. }
  1101. //设置强制横屏
  1102. this.ForceLandscape = function (bForceLandscape) {
  1103. if (this.JSChartContainer) {
  1104. JSConsole.Chart.Log("[JSChart::ForceLandscape] bForceLandscape=" + bForceLandscape);
  1105. this.JSChartContainer.IsForceLandscape = bForceLandscape;
  1106. }
  1107. }
  1108. //锁|解锁指标
  1109. this.LockIndex = function (lockData)
  1110. {
  1111. if (this.JSChartContainer && typeof (this.JSChartContainer.LockIndex) == 'function')
  1112. {
  1113. JSConsole.Chart.Log('[JSChart:LockIndex] lockData', lockData);
  1114. this.JSChartContainer.LockIndex(lockData);
  1115. }
  1116. }
  1117. //历史分钟数据 更改日期
  1118. this.ChangeTradeDate = function (tradeDate)
  1119. {
  1120. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeTradeDate) == 'function')
  1121. {
  1122. JSConsole.Chart.Log('[JSChart:ChangeTradeDate] date', tradeDate);
  1123. this.JSChartContainer.ChangeTradeDate(tradeDate);
  1124. }
  1125. }
  1126. //多日走势图
  1127. this.ChangeDayCount = function (count)
  1128. {
  1129. if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeDayCount) == 'function')
  1130. {
  1131. JSConsole.Chart.Log('[JSChart:ChangeDayCount] count', count);
  1132. this.JSChartContainer.ChangeDayCount(count);
  1133. }
  1134. }
  1135. this.StopAutoUpdate = function ()
  1136. {
  1137. if (this.JSChartContainer && typeof (this.JSChartContainer.StopAutoUpdate) == 'function') {
  1138. JSConsole.Chart.Log("[JSChart::StopAutoUpdate] Stop.");
  1139. this.JSChartContainer.StopAutoUpdate();
  1140. }
  1141. }
  1142. this.StopAutoUpdata = this.StopAutoUpdate;
  1143. this.ChartDestory=function()
  1144. {
  1145. if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestory) == 'function') {
  1146. JSConsole.Chart.Log("[JSChart::ChartDestory]");
  1147. this.JSChartContainer.ChartDestory();
  1148. }
  1149. }
  1150. this.OnTouchStart = function (e)
  1151. {
  1152. if (this.JSChartContainer) this.JSChartContainer.ontouchstart(e);
  1153. }
  1154. this.OnTouchMove = function (e)
  1155. {
  1156. if (this.JSChartContainer) this.JSChartContainer.ontouchmove(e);
  1157. }
  1158. this.OnTouchEnd = function (e)
  1159. {
  1160. if (this.JSChartContainer) this.JSChartContainer.ontouchend(e);
  1161. }
  1162. this.SaveToImage = function (callback)
  1163. {
  1164. if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImage) == 'function')
  1165. this.JSChartContainer.SaveToImage(callback);
  1166. }
  1167. this.EnableSplashScreen=function(option)
  1168. {
  1169. if(this.JSChartContainer && typeof(this.JSChartContainer.EnableSplashScreen)=='function')
  1170. this.JSChartContainer.EnableSplashScreen(option);
  1171. }
  1172. //叠加指标
  1173. this.AddOverlayIndex=function(obj) //{WindowIndex:窗口ID, IndexName:指标ID, Identify:叠加指标ID(可选), API}
  1174. {
  1175. if (this.JSChartContainer && typeof(this.JSChartContainer.AddOverlayIndex)=='function')
  1176. this.JSChartContainer.AddOverlayIndex(obj);
  1177. }
  1178. //删除叠加指标
  1179. this.DeleteOverlayWindowsIndex=function(identify)
  1180. {
  1181. if (this.JSChartContainer && typeof(this.JSChartContainer.DeleteOverlayWindowsIndex)=='function')
  1182. this.JSChartContainer.DeleteOverlayWindowsIndex(identify);
  1183. }
  1184. this.ChangePriceGap=function(option)
  1185. {
  1186. if(this.JSChartContainer && typeof(this.JSChartContainer.ChangePriceGap)=='function')
  1187. {
  1188. JSConsole.Chart.Log('[JSChart:ChangePriceGap] ');
  1189. return this.JSChartContainer.ChangePriceGap(option);
  1190. }
  1191. }
  1192. }
  1193. JSChart.LastVersion=null; //最新的版本号
  1194. //初始化
  1195. JSChart.Init = function (uielement) {
  1196. JSConsole.Chart.Log('[JSChart.Init] uielement', uielement);
  1197. var jsChartControl = new JSChart(uielement);
  1198. jsChartControl.OnSize();
  1199. return jsChartControl;
  1200. }
  1201. JSChart.SetDomain = function (domain, cacheDomain) {
  1202. if (domain) {
  1203. g_JSChartResource.Domain = domain;
  1204. g_JSChartResource.Index.StockHistoryDayApiUrl = domain + "/API/StockHistoryDay"; //历史数据api
  1205. g_JSChartResource.Index.MarketLongShortApiUrl = domain + "/API/FactorTiming"; //市场多空
  1206. g_JSChartResource.Index.MarketAttentionApiUrl = domain + "/API/MarketAttention"; //市场关注度
  1207. g_JSChartResource.Index.MarketHeatApiUrl = domain + "/API/MarketHeat"; //行业,指数热度
  1208. }
  1209. if (cacheDomain) g_JSChartResource.CacheDomain = cacheDomain;
  1210. JSCommonComplier.JSComplier.SetDomain(domain, cacheDomain); //编译器数据api域名修改
  1211. }
  1212. //自定义风格
  1213. JSChart.SetStyle = function (style) {
  1214. if (style) g_JSChartResource.SetStyle(style);
  1215. }
  1216. JSChart.GetResource = function () //获取颜色配置 (设置配必须啊在JSChart.Init()之前)
  1217. {
  1218. return g_JSChartResource;
  1219. }
  1220. JSChart.GetMinuteTimeStringData=function()
  1221. {
  1222. return JSCommonCoordinateData.MinuteTimeStringData;
  1223. }
  1224. JSChart.GetMinuteCoordinateData=function()
  1225. {
  1226. return JSCommonCoordinateData.MinuteCoordinateData;
  1227. }
  1228. JSChart.GetKLineZoom = function () //K线缩放配置
  1229. {
  1230. return ZOOM_SEED;
  1231. }
  1232. JSChart.SetKLineZoom=function(aryZoom) //设置K线缩放比例
  1233. {
  1234. ZOOM_SEED.length=0;
  1235. for(var i=0;i<aryZoom.length;++i)
  1236. {
  1237. ZOOM_SEED[i]=aryZoom[i];
  1238. }
  1239. }
  1240. JSChart.SetUSATimeType=function(type) //设置 0=标准时间 1=夏令时间 3=美国时间
  1241. {
  1242. g_NYMEXTimeData.TimeType=type;
  1243. g_COMEXTimeData.TimeType=type;
  1244. g_NYBOTTimeData.TimeType=type;
  1245. g_CBOTTimeData.TimeType=type;
  1246. }
  1247. JSChart.GetChinaFuturesTimeData=function() //获取国内期货交易时间配置
  1248. {
  1249. return g_FuturesTimeData;
  1250. }
  1251. JSChart.GetInternalTimeData=function(name) //内置品种交易时间
  1252. {
  1253. switch(name)
  1254. {
  1255. case "NYMEXTimeData": //纽约商业交易所
  1256. return g_NYMEXTimeData;
  1257. case "COMEXTimeData": //纽约商品交易所
  1258. return g_COMEXTimeData;
  1259. case "NYBOTTimeData": //纽约期货交易所
  1260. return g_NYBOTTimeData;
  1261. case "CBOTTimeData": //芝加哥期货交易所
  1262. return g_CBOTTimeData;
  1263. case "LMETimeData": //伦敦金属交易所
  1264. return g_LMETimeData;
  1265. case "FuturesTimeData": //国内期货
  1266. return g_FuturesTimeData;
  1267. case "TOCOMTimeData": //东京商品交易所(TOCOM
  1268. return g_TOCOMTimeData;
  1269. case "IPETimeData":
  1270. return g_IPETimeData; //美国洲际交易所
  1271. default:
  1272. return null;
  1273. }
  1274. }
  1275. JSChart.GetDivTooltipDataFormat=function() //div tooltip数据格式化
  1276. {
  1277. return g_DivTooltipDataForamt;
  1278. }
  1279. //注册外部扩展图形
  1280. //option:{ Create:创建类方法 }
  1281. JSChart.RegisterExtendChartClass=function(name, option)
  1282. {
  1283. return g_ExtendChartPaintFactory.Add(name,option);
  1284. }
  1285. //一些公共函数
  1286. JSChart.ToFixedPoint=function(value)
  1287. {
  1288. return ToFixedPoint(value);
  1289. }
  1290. JSChart.ToFixedRect=function(value)
  1291. {
  1292. return ToFixedRect(value);
  1293. }
  1294. JSChart.AddPeriodCallback=function(obj) //添加自定义周期方法 { Period:周期ID, Callback:回调 }
  1295. {
  1296. g_DataPlus.AddPeriodCallback(obj);
  1297. }
  1298. JSChart.RemovePeriodCallback=function(obj) //添加自定义周期方法 { Period:周期ID, }
  1299. {
  1300. g_DataPlus.RemovePeriodCallback(obj);
  1301. }
  1302. var JSCHART_OPERATOR_ID =
  1303. {
  1304. OP_SCROLL_LEFT: 1,
  1305. OP_SCROLL_RIGHT: 2,
  1306. OP_ZOOM_OUT: 3, //缩小
  1307. OP_ZOOM_IN: 4, //放大
  1308. OP_GOTO_HOME: 5, //第1页数据
  1309. OP_GOTO_END:6, //第1天的数据
  1310. OP_GOTO:16, //移动到某一个天或某一个分钟
  1311. }
  1312. /*
  1313. 图形控件
  1314. */
  1315. function JSChartContainer(uielement)
  1316. {
  1317. this.ClassName = 'JSChartContainer';
  1318. var _self = this;
  1319. this.Frame; //框架画法
  1320. this.ChartPaint = new Array(); //图形画法
  1321. this.ChartPaintEx = []; //图形扩展画法
  1322. this.ChartInfo = new Array(); //K线上信息地雷
  1323. this.ChartInfoPaint; //信息地理
  1324. this.ExtendChartPaint = new Array(); //扩展画法
  1325. this.TitlePaint = new Array(); //标题画法
  1326. this.OverlayChartPaint = new Array(); //叠加信息画法
  1327. this.ChartDrawPicture = new Array(); //画图工具
  1328. this.CurrentChartDrawPicture = null; //当前的画图工具
  1329. this.SelectChartDrawPicture = null; //当前选中的画图
  1330. this.ChartCorssCursor; //十字光标
  1331. this.IsClickShowCorssCursor = false; //手势点击显示十字光标
  1332. this.ChartSplashPaint = null; //等待提示
  1333. this.LoadDataSplashTitle = '数据加载中';
  1334. this.Canvas = uielement.GetContext("2d"); //画布
  1335. this.UIElement = uielement;
  1336. this.MouseDrag;
  1337. this.DragMode = 1; //拖拽模式 0 禁止拖拽 1 数据拖拽
  1338. this.PhoneTouchInfo; //手机手势信息 {Start:起始点, End:结束点}
  1339. this.EnableScrollUpDown=false; //是否可以上下滚动图形(手机端才有)
  1340. this.TouchTimer = null; //触屏定时器
  1341. this.LastDrawStatus; //最后一次画的状态
  1342. this.LastDrawID=1; //最后一次画的ID
  1343. this.SnapshotType = 0;
  1344. this.CursorIndex = 0; //十字光标X轴索引
  1345. this.LastPoint = new Point(); //鼠标位置
  1346. this.IsForceLandscape = false; //是否强制横屏
  1347. this.CorssCursorTouchEnd = false; //手离开屏幕自动隐藏十字光标
  1348. this.TouchMoveMinAngle=70; //左右移动最小角度
  1349. this.EnableAnimation = false; //是否开启动画
  1350. //坐标轴风格方法 double-更加数值型分割 price-更加股票价格分割
  1351. this.FrameSplitData = new Map();
  1352. this.FrameSplitData.set("double", new SplitData());
  1353. this.FrameSplitData.set("price", new PriceSplitData());
  1354. this.UpdateUICallback; //数据到达通知前端
  1355. this.IsOnTouch = false; //当前是否正式手势操作
  1356. this.PhonePinch=null; //双指操作信息
  1357. this.IsFullDraw=false; //是否使用重绘模式 (可能会卡)
  1358. this.LanguageID = JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
  1359. this.PressTime=800; //长按十字光标显示时间
  1360. this.IsPress=false; //是否长按
  1361. //公共函数转发,不然要导出麻烦
  1362. this.FormatDateString = IFrameSplitOperator.FormatDateString;
  1363. this.FormatValueString = IFrameSplitOperator.FormatValueString;
  1364. this.ToFixedPoint = ToFixedPoint;
  1365. this.ToFixedRect = ToFixedRect;
  1366. this.FormatTimeString = IFrameSplitOperator.FormatTimeString;
  1367. //this.JSCHART_EVENT_ID = JSCHART_EVENT_ID;
  1368. //事件回调
  1369. this.mapEvent = new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,}
  1370. this.NetworkFilter; //网络请求回调 function(data, callback);
  1371. this.IsDestroy=false; //是否已经销毁了
  1372. //手势移动 十字光标
  1373. this.LastMovePoint;
  1374. this.DrawMoveTimer=null;
  1375. this.DrawMoveWaitTime=60;
  1376. //双击缩放附图窗口
  1377. this.EnableZoomIndexWindow=false; //是否支持双击缩放附图窗口
  1378. this.PhoneDBClick=new PhoneDBClick();
  1379. //十字光标长留(手势才有)
  1380. this.ClickModel={ IsShowCorssCursor:false };
  1381. this.EnableClickModel=false;
  1382. this.ChartDestory=function() //销毁
  1383. {
  1384. this.IsDestroy=true;
  1385. this.StopAutoUpdate();
  1386. }
  1387. this.AddEventCallback = function (object) //设置事件回调 {event:事件id, callback:回调函数}
  1388. {
  1389. if (!object || !object.event || !object.callback) return;
  1390. var data = { Callback: object.callback, Source: object };
  1391. this.mapEvent.set(object.event, data);
  1392. }
  1393. this.RemoveEventCallback = function (eventid)
  1394. {
  1395. if (!this.mapEvent.has(eventid)) return;
  1396. this.mapEvent.delete(eventid);
  1397. }
  1398. this.GetEvent=function(eventId)
  1399. {
  1400. if (!this.mapEvent.has(eventId)) return null;
  1401. var item = this.mapEvent.get(eventId);
  1402. return item;
  1403. }
  1404. this.GetEventCallback=this.GetEvent;
  1405. this.GetIndexEvent = function () { return this.GetEvent(JSCHART_EVENT_ID.RECV_INDEX_DATA); } //接收指标数据
  1406. this.GetBarrageEvent=function() { return this.GetEvent(JSCHART_EVENT_ID.BARRAGE_PLAY_END);} //获取弹幕事件
  1407. this.GetEnableSplashEvent=function() { return this.GetEvent(JSCHART_EVENT_ID.ON_ENABLE_SPLASH_DRAW); } //开启/关闭文字提示信息事件
  1408. //判断是单个手指
  1409. this.IsPhoneDragging = function (e)
  1410. {
  1411. // JSConsole.Chart.Log(e);
  1412. var changed = e.changedTouches.length;
  1413. var touching = e.touches.length;
  1414. return changed == 1 && touching == 1;
  1415. }
  1416. //是否是2个手指操所
  1417. this.IsPhonePinching = function (e)
  1418. {
  1419. var changed = e.changedTouches.length;
  1420. var touching = e.touches.length;
  1421. return (changed == 1 || changed == 2) && touching == 2;
  1422. }
  1423. this.IsSingleTouch=function(e) //是否是单点触屏
  1424. {
  1425. var touchCount=e.touches.length;
  1426. return touchCount==1;
  1427. }
  1428. this.GetMoveAngle=function(pt,pt2) //计算角度
  1429. {
  1430. var xMove=Math.abs(pt.X-pt2.X);
  1431. var yMove=Math.abs(pt.Y-pt2.Y);
  1432. var angle=Math.atan(xMove/yMove)*180/Math.PI;
  1433. return angle;
  1434. }
  1435. this.GetToucheData = function (e, isForceLandscape)
  1436. {
  1437. var touches = new Array();
  1438. for (var i = 0; i < e.touches.length; ++i)
  1439. {
  1440. var item = e.touches[i];
  1441. if (isForceLandscape)
  1442. {
  1443. touches.push( { clientX: item.y, clientY: item.x, pageX: item.y, pageY: item.x });
  1444. }
  1445. else
  1446. {
  1447. touches.push( {clientX: item.x, clientY: item.y, pageX: item.x, pageY: item.y });
  1448. }
  1449. }
  1450. return touches;
  1451. }
  1452. this.ClearDrawMoveTimer=function()
  1453. {
  1454. if (this.DrawMoveTimer != null)
  1455. {
  1456. clearTimeout(this.DrawMoveTimer);
  1457. this.DrawMoveTimer=null;
  1458. }
  1459. }
  1460. this.ClearTouchTimer=function()
  1461. {
  1462. if (this.TouchTimer != null)
  1463. {
  1464. clearTimeout(this.TouchTimer);
  1465. this.TouchTimer=null;
  1466. this.IsPress=false;
  1467. }
  1468. }
  1469. //手机拖拽
  1470. this.ontouchstart = function (e)
  1471. {
  1472. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  1473. var jsChart = this;
  1474. //if (jsChart.DragMode == 0) return;
  1475. this.IsOnTouch=true;
  1476. this.IsPress=false;
  1477. this.PhonePinch = null;
  1478. this.TouchDrawCount=0;
  1479. if (this.IsPhoneDragging(e))
  1480. {
  1481. if (jsChart.TryClickLock || this.TryClickIndexTitle)
  1482. {
  1483. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  1484. var x = touches[0].clientX;
  1485. var y = touches[0].clientY;
  1486. if (jsChart.TryClickLock && jsChart.TryClickLock(x, y)) return;
  1487. if (jsChart.TryClickIndexTitle && jsChart.TryClickIndexTitle(x, y)) return;
  1488. }
  1489. //长按2秒,十字光标
  1490. if (this.TouchTimer != null) clearTimeout(this.TouchTimer);
  1491. var bStartTimer=this.ChartCorssCursor.IsShow == true;
  1492. //长按十字光标停留
  1493. if (this.EnableClickModel)
  1494. {
  1495. if (this.ClickModel.IsShowCorssCursor==true) bStartTimer=false;
  1496. else bStartTimer= true;
  1497. }
  1498. var drag =
  1499. {
  1500. "Click": {},
  1501. "LastMove": {}, //最后移动的位置
  1502. };
  1503. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  1504. drag.Click.X = touches[0].clientX;
  1505. drag.Click.Y = touches[0].clientY;
  1506. drag.LastMove.X = touches[0].clientX;
  1507. drag.LastMove.Y = touches[0].clientY;
  1508. if (jsChart.DragMode == 1) jsChart.MouseDrag = drag;
  1509. this.MouseDrag=drag;
  1510. this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } };
  1511. if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false;
  1512. this.SelectChartDrawPicture=null;
  1513. var isDrawPictrue=false;
  1514. if (this.CurrentChartDrawPicture) //画图工具模式
  1515. {
  1516. var drawPicture=this.CurrentChartDrawPicture;
  1517. if (drawPicture.Status==2)
  1518. {
  1519. this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y,true);
  1520. }
  1521. else
  1522. {
  1523. this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true);
  1524. //只有1个点 直接完成
  1525. if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false});
  1526. }
  1527. return;
  1528. }
  1529. else
  1530. {
  1531. var pt=this.PointAbsoluteToRelative(touches[0].clientX,touches[0].clientY, true);
  1532. var drawPictrueData={ X:pt.X, Y:pt.Y, PixelRatio:this.UIElement.PixelRatio };
  1533. if (this.GetChartDrawPictureByPoint(drawPictrueData))
  1534. {
  1535. if (drawPictrueData.ChartDrawPicture.EnableMove===true)
  1536. drawPictrueData.ChartDrawPicture.Status=20;
  1537. drawPictrueData.ChartDrawPicture.ValueToPoint();
  1538. drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex;
  1539. drawPictrueData.ChartDrawPicture.IsSelected=true;
  1540. this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture;
  1541. this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture;
  1542. let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件
  1543. if (event && event.Callback)
  1544. {
  1545. let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture };
  1546. event.Callback(event,sendData,this);
  1547. }
  1548. this.DrawDynamicInfo();
  1549. return;
  1550. }
  1551. }
  1552. if (bStartTimer)
  1553. {
  1554. this.TouchTimer = setTimeout(function () {
  1555. jsChart.IsPress=true;
  1556. if (drag.Click.X == drag.LastMove.X && drag.Click.Y == drag.LastMove.Y) //手指没有移动,出现十字光标
  1557. {
  1558. var mouseDrag = jsChart.MouseDrag;
  1559. jsChart.MouseDrag = null;
  1560. //移动十字光标
  1561. var x = drag.Click.X;
  1562. var y = drag.Click.Y;
  1563. if (jsChart.IsForceLandscape) y = jsChart.UIElement.Height - drag.Click.Y; //强制横屏Y计算
  1564. if (jsChart.EnableClickModel===true) jsChart.ClickModel.IsShowCorssCursor=true;
  1565. jsChart.OnMouseMove(x, y, e);
  1566. }
  1567. }, jsChart.PressTime);
  1568. }
  1569. if (this.EnableZoomIndexWindow)
  1570. {
  1571. this.PhoneDBClick.AddTouchStart(touches[0].clientX, touches[0].clientY, Date.now());
  1572. JSConsole.Chart.Log("[JSChartContainer::OnTouchStart] PhoneDBClick ", this.PhoneDBClick);
  1573. }
  1574. if (this.EnableClickModel)
  1575. {
  1576. //if (this.ClickModel.IsShowCorssCursor===true) this.MoveCorssCursor(drag.Click,e)
  1577. }
  1578. else if (jsChart.IsClickShowCorssCursor)
  1579. {
  1580. var x = drag.Click.X;
  1581. var y = drag.Click.Y;
  1582. jsChart.OnMouseMove(x, y, e,true);
  1583. }
  1584. this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e);
  1585. }
  1586. else if (this.IsPhonePinching(e))
  1587. {
  1588. var phonePinch = { "Start": {}, "Last": {} };
  1589. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  1590. phonePinch.Start = { X: touches[0].pageX, Y: touches[0].pageY, X2: touches[1].pageX, Y2: touches[1].pageY };
  1591. phonePinch.Last = { X: touches[0].pageX, Y: touches[0].pageY, X2: touches[1].pageX, Y2: touches[1].pageY };
  1592. jsChart.PhonePinch = phonePinch;
  1593. }
  1594. }
  1595. this.StartMoveTimer=function(touches, e)
  1596. {
  1597. var x = touches[0].clientX;
  1598. var y = touches[0].clientY;
  1599. this.LastMovePoint={ X:x, Y:y };
  1600. if (this.DrawMoveTimer) return;
  1601. this.DrawMoveTimer=setTimeout(()=>
  1602. {
  1603. if (!this.LastMovePoint) return;
  1604. this.OnMouseMove(this.LastMovePoint.X, this.LastMovePoint.Y, e);
  1605. this.DrawMoveTimer=null;
  1606. }, this.DrawMoveWaitTime);
  1607. }
  1608. this.ontouchmove = function (e)
  1609. {
  1610. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  1611. var jsChart = this;
  1612. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  1613. if (this.IsPhoneDragging(e))
  1614. {
  1615. var drag = jsChart.MouseDrag;
  1616. if (drag == null)
  1617. {
  1618. this.StartMoveTimer(touches, e);
  1619. }
  1620. else
  1621. {
  1622. var moveSetp = Math.abs(drag.LastMove.X - touches[0].clientX);
  1623. moveSetp = parseInt(moveSetp);
  1624. var isMoveCorssCursor=false;
  1625. if (this.EnableClickModel)
  1626. {
  1627. if (this.ClickModel.IsShowCorssCursor===true) isMoveCorssCursor=true;
  1628. else isMoveCorssCursor=false;
  1629. }
  1630. if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true)
  1631. {
  1632. var drawPicture=this.CurrentChartDrawPicture;
  1633. if (drawPicture.Status==1 || drawPicture.Status==2)
  1634. {
  1635. if(moveSetp<5 && moveUpDown<5) return;
  1636. if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY,true))
  1637. {
  1638. this.DrawDynamicInfo();
  1639. }
  1640. }
  1641. else if (drawPicture.Status==3)
  1642. {
  1643. if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY,true))
  1644. {
  1645. this.DrawDynamicInfo();
  1646. }
  1647. }
  1648. else if (drawPicture.Status==20) //画图工具移动
  1649. {
  1650. if(moveSetp<5 && moveUpDown<5) return;
  1651. if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y,true))
  1652. {
  1653. this.DrawDynamicInfo();
  1654. }
  1655. }
  1656. drag.LastMove.X=touches[0].clientX;
  1657. drag.LastMove.Y=touches[0].clientY;
  1658. }
  1659. else if (isMoveCorssCursor)
  1660. {
  1661. jsChart.MouseDrag=null;
  1662. jsChart.MoveCorssCursor(drag.Click,e); //移动十字光标
  1663. }
  1664. else if (jsChart.DragMode == 1) //数据左右拖拽
  1665. {
  1666. var moveAngle=this.GetMoveAngle(drag.LastMove,{X:touches[0].clientX, Y:touches[0].clientY});
  1667. var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY);
  1668. if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true )
  1669. {
  1670. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_TOUCH_SCROLL_UP_DOWN);
  1671. var isEnd=true; //是否退出
  1672. if (event && event.Callback)
  1673. {
  1674. var sendData={ DragData:drag, PreventDefault:false };
  1675. event.Callback(event, sendData, this);
  1676. isEnd=(sendData.PreventDefault===false);
  1677. }
  1678. if (isEnd)
  1679. {
  1680. this.ClearTouchTimer();
  1681. return;
  1682. }
  1683. }
  1684. if (this.EnableMoveData && this.EnableMoveData.Touch===false)
  1685. {
  1686. jsChart.MouseDrag = null;
  1687. return;
  1688. }
  1689. if (moveSetp < 5) return;
  1690. var isLeft = true;
  1691. if (drag.LastMove.X < touches[0].clientX) isLeft = false;//右移数据
  1692. if (jsChart.DataMove(moveSetp, isLeft))
  1693. {
  1694. jsChart.UpdataDataoffset();
  1695. jsChart.UpdatePointByCursorIndex();
  1696. jsChart.UpdateFrameMaxMin();
  1697. jsChart.ResetFrameXYSplit();
  1698. jsChart.Draw();
  1699. this.OnKLinePageChange("OnTouchMove");
  1700. }
  1701. else
  1702. {
  1703. if (jsChart.DragDownloadData) jsChart.DragDownloadData();
  1704. }
  1705. drag.LastMove.X = touches[0].clientX;
  1706. drag.LastMove.Y = touches[0].clientY;
  1707. }
  1708. }
  1709. if (this.PhoneTouchInfo)
  1710. {
  1711. this.PhoneTouchInfo.End.X=touches[0].clientX;
  1712. this.PhoneTouchInfo.End.Y=touches[0].clientY;
  1713. }
  1714. }
  1715. else if (this.IsPhonePinching(e))
  1716. {
  1717. var phonePinch = jsChart.PhonePinch;
  1718. if (!phonePinch) return;
  1719. phonePinch.Operator=null;
  1720. if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return;
  1721. var yHeight = Math.abs(touches[0].pageY - touches[1].pageY);
  1722. var yLastHeight = Math.abs(phonePinch.Last.Y - phonePinch.Last.Y2);
  1723. var yStep = yHeight - yLastHeight;
  1724. var xHeight = Math.abs(touches[0].pageX - touches[1].pageX);
  1725. var xLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2);
  1726. var xStep = xHeight - xLastHeight;
  1727. var minStep=this.ZoomStepPixel;
  1728. if (Math.abs(yStep) < minStep && Math.abs(xStep) < minStep) return;
  1729. var step = yStep;
  1730. if (Math.abs(yStep) < minStep) step = xStep;
  1731. if (step > 0) //放大
  1732. {
  1733. var cursorIndex = { IsLockRight:this.IsZoomLockRight };
  1734. cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0));
  1735. if (!jsChart.Frame.ZoomUp(cursorIndex)) return;
  1736. phonePinch.Operator="ZoomUp";
  1737. jsChart.CursorIndex = cursorIndex.Index;
  1738. jsChart.UpdatePointByCursorIndex();
  1739. jsChart.UpdataDataoffset();
  1740. jsChart.UpdateFrameMaxMin();
  1741. jsChart.ResetFrameXYSplit();
  1742. jsChart.Draw();
  1743. this.OnKLinePageChange("OnTouchMove");
  1744. }
  1745. else //缩小
  1746. {
  1747. var cursorIndex = { IsLockRight:this.IsZoomLockRight };
  1748. cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0));
  1749. if (!jsChart.Frame.ZoomDown(cursorIndex)) return;
  1750. phonePinch.Operator="ZoomDown";
  1751. jsChart.CursorIndex = cursorIndex.Index;
  1752. jsChart.UpdataDataoffset();
  1753. jsChart.UpdatePointByCursorIndex();
  1754. jsChart.UpdateFrameMaxMin();
  1755. jsChart.ResetFrameXYSplit();
  1756. jsChart.Draw();
  1757. this.OnKLinePageChange("OnTouchMove");
  1758. }
  1759. phonePinch.Last = { X: touches[0].pageX, Y: touches[0].pageY, X2: touches[1].pageX, Y2: touches[1].pageY };
  1760. }
  1761. }
  1762. this.ontouchend = function (e)
  1763. {
  1764. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  1765. var bClearDrawPicture=true;
  1766. if (this.CurrentChartDrawPicture)
  1767. {
  1768. var drawPicture=this.CurrentChartDrawPicture;
  1769. if (drawPicture.Status==2 || drawPicture.Status==1 || drawPicture.Status==3)
  1770. {
  1771. drawPicture.PointStatus=drawPicture.Status;
  1772. if (this.FinishChartDrawPicturePoint())
  1773. this.DrawDynamicInfo();
  1774. else
  1775. bClearDrawPicture=false;
  1776. }
  1777. else if (drawPicture.Status==20)
  1778. {
  1779. if (this.FinishMoveChartDrawPicture())
  1780. this.DrawDynamicInfo();
  1781. }
  1782. }
  1783. if (this.EnableZoomIndexWindow)
  1784. {
  1785. var time=Date.now();
  1786. this.PhoneDBClick.AddTouchEnd(time);
  1787. if (this.PhoneDBClick.IsVaildDBClick())
  1788. {
  1789. this.OnTouchDBClick(this.PhoneDBClick.Start);
  1790. this.PhoneDBClick.Clear();
  1791. }
  1792. }
  1793. this.IsOnTouch = false;
  1794. this.LastMovePoint=null;
  1795. if (bClearDrawPicture===true) this.CurrentChartDrawPicture=null;
  1796. JSConsole.Chart.Log('[JSChartContainer:ontouchend] IsOnTouch=' + this.IsOnTouch +' LastDrawStatus=' + this.LastDrawStatus);
  1797. this.ClearDrawMoveTimer();
  1798. this.ClearTouchTimer();
  1799. this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchEnd"}, e);
  1800. this.OnTouchFinished();
  1801. this.TouchDrawCount=0;
  1802. this.PhonePinch=null;
  1803. }
  1804. this.OnTouchFinished=function()
  1805. {
  1806. if (this.EnableClickModel===true)
  1807. {
  1808. if (this.ClickModel.IsShowCorssCursor==true && this.TouchDrawCount>0) return;
  1809. this.ClickModel.IsShowCorssCursor=false;
  1810. this.Draw();
  1811. return;
  1812. }
  1813. this.Draw();//手放开 重新绘制
  1814. }
  1815. this.OnTouchDBClick=function(points)
  1816. {
  1817. var x=points[0].X, y=points[0].Y;
  1818. JSConsole.Chart.Log('[JSChartContainer:OnTouchDBClick] Phone dbclick', x, y);
  1819. var frameId=this.Frame.PtInFrame(x,y);
  1820. JSConsole.Chart.Log("[JSChartContainer::OnTouchDBClick] frameId",frameId);
  1821. if (frameId>=this.Frame.ZoomStartWindowIndex)
  1822. {
  1823. if (this.ZoomIndexWindow(frameId, {X:x, Y:y}))
  1824. {
  1825. this.Frame.SetSizeChage(true);
  1826. this.Draw();
  1827. return true;
  1828. }
  1829. }
  1830. return false;
  1831. }
  1832. this.ZoomIndexWindow=function(frameID, option) //最大化/最小化指标窗口
  1833. {
  1834. if (frameID<0 || frameID>=this.Frame.SubFrame.length) return false;
  1835. return this.Frame.ZoomIndexWindow(frameID, option);
  1836. }
  1837. this.TouchEvent=function(obj,e)
  1838. {
  1839. var eventID=obj.EventID;
  1840. var event=this.GetEvent(eventID);
  1841. if (!event || !event.Callback) return false;
  1842. var drag=this.PhoneTouchInfo
  1843. if (!drag || !drag.Start || !drag.End ) return false;
  1844. var clientX=drag.End.X;
  1845. var clientY=drag.End.Y;
  1846. var x=drag.End.X;
  1847. var y=drag.End.Y;
  1848. var data=
  1849. {
  1850. X:clientX, Y:clientY, FrameID:-1, FunctionName:obj.FunctionName,
  1851. Drag:
  1852. {
  1853. Start:{ X:drag.Start.X, Y:drag.Start.Y },
  1854. End:{ X:drag.End.X, Y:drag.End.Y }
  1855. }
  1856. };
  1857. var isInClient=false;
  1858. var rtClient = new Rect(this.Frame.ChartBorder.GetLeft(), this.Frame.ChartBorder.GetTop(), this.Frame.ChartBorder.GetWidth(), this.Frame.ChartBorder.GetHeight());
  1859. isInClient = rtClient.IsPointIn(x, y);
  1860. if (isInClient)
  1861. {
  1862. if (this.Frame && this.Frame.IsHScreen)
  1863. {
  1864. var yValueExtend={};
  1865. var yValue=this.Frame.GetYData(x,yValueExtend);
  1866. if (IFrameSplitOperator.IsNumber(yValueExtend.FrameID) && yValueExtend.FrameID>=0)
  1867. {
  1868. var xValue=this.Frame.GetXData(y);
  1869. data.FrameID=yValueExtend.FrameID;
  1870. data.Data={ X:xValue, Y:yValue } ;
  1871. }
  1872. }
  1873. else
  1874. {
  1875. var yValueExtend={};
  1876. var yValue=this.Frame.GetYData(y,yValueExtend);
  1877. if (IFrameSplitOperator.IsNumber(yValueExtend.FrameID) && yValueExtend.FrameID>=0)
  1878. {
  1879. var xValue=this.Frame.GetXData(x);
  1880. data.FrameID=yValueExtend.FrameID;
  1881. data.Data={ X:xValue, Y:yValue } ;
  1882. }
  1883. }
  1884. }
  1885. event.Callback(event, data, this);
  1886. return true;
  1887. }
  1888. this.FullDraw=function(drawType)
  1889. {
  1890. var self = this;
  1891. this.Canvas.clearRect(0, 0, this.UIElement.Width, this.UIElement.Height);
  1892. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) //动画
  1893. {
  1894. this.Frame.ClearCoordinateText();
  1895. this.Frame.Draw({ IsEnableSplash:this.ChartSplashPaint.IsEnableSplash}); //框架
  1896. this.ChartSplashPaint.Draw();
  1897. this.LastDrawStatus = 'FullDraw';
  1898. this.Canvas.draw();
  1899. return;
  1900. }
  1901. this.Frame.SetDrawOtherChart(() =>
  1902. {
  1903. for (var i in this.ExtendChartPaint)
  1904. {
  1905. var item = this.ExtendChartPaint[i];
  1906. if (item.IsCallbackDraw) item.Draw();
  1907. }
  1908. });
  1909. this.Frame.Draw(); //框架
  1910. if (this.Frame.DrawCustomVertical)
  1911. {
  1912. var eventCVericalDraw = this.GetEvent(JSCHART_EVENT_ID.ON_CUSTOM_VERTICAL_DRAW);
  1913. this.Frame.DrawCustomVertical(eventCVericalDraw);
  1914. }
  1915. for (var i=0; i<this.ChartPaint.length; ++i) //图形
  1916. {
  1917. var item = this.ChartPaint[i];
  1918. if (item.ChartFrame && this.IsHideFrame(item.ChartFrame)) continue;
  1919. if (item.IsDrawFirst) item.Draw();
  1920. }
  1921. if (this.Frame.DrawOveraly)
  1922. this.Frame.DrawOveraly(true); //画叠加指标
  1923. for (var i=0; i<this.ChartPaint.length; ++i) //图形2 框架内图形
  1924. {
  1925. var item = this.ChartPaint[i];
  1926. if (item.ChartFrame && this.IsHideFrame(item.ChartFrame)) continue;
  1927. if (!item.IsDrawFirst) item.Draw();
  1928. }
  1929. for (var i=0; i<this.ChartPaintEx.length; ++i) //扩展图形
  1930. {
  1931. var item = this.ChartPaintEx[i];
  1932. item.Draw();
  1933. }
  1934. for (var i=0; i<this.OverlayChartPaint.length; ++i) //叠加股票
  1935. {
  1936. var item = this.OverlayChartPaint[i];
  1937. item.Draw();
  1938. }
  1939. if (this.Frame.DrawOveraly)
  1940. this.Frame.DrawOveraly(false); //画叠加指标
  1941. if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal(); //框架内部坐标
  1942. this.KLineIncreaseCustomHorizontal();
  1943. if (this.Frame.DrawCustomHorizontal) this.Frame.DrawCustomHorizontal();
  1944. if (this.ChartInfoPaint) this.ChartInfoPaint.Draw();
  1945. this.Frame.DrawLock();
  1946. this.Frame.DrawLogo();
  1947. var bOnTouchDraw=drawType == 'DrawDynamicInfo' || this.IsOnTouch;
  1948. if (this.EnableClickModel==true) //长按十字长留模式
  1949. {
  1950. bOnTouchDraw=(this.ClickModel.IsShowCorssCursor==true);
  1951. }
  1952. var bDrawTooltip=true;
  1953. if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10) bDrawTooltip=false;
  1954. for (var i=0; i<this.ExtendChartPaint.length; ++i) //动态扩展图形 在动态标题以后画
  1955. {
  1956. var item = this.ExtendChartPaint[i];
  1957. if (item.IsCallbackDraw) continue;
  1958. if (item.ClassName=="KLineTooltipPaint" || item.ClassName=="MinuteTooltipPaint") continue;
  1959. if (item.IsDynamic) continue;
  1960. if (item.DrawAfterTitle) continue; //在绘制标题以后在绘制
  1961. item.Draw();
  1962. }
  1963. if (bOnTouchDraw)
  1964. {
  1965. if (self.ChartCorssCursor && bDrawTooltip) //十字光标
  1966. {
  1967. self.ChartCorssCursor.LastPoint = self.LastPoint;
  1968. self.ChartCorssCursor.CursorIndex = self.CursorIndex;
  1969. self.ChartCorssCursor.Draw();
  1970. }
  1971. }
  1972. var eventTitleDraw = this.GetEvent(JSCHART_EVENT_ID.ON_TITLE_DRAW);
  1973. var eventIndexTitleDraw = this.GetEvent(JSCHART_EVENT_ID.ON_INDEXTITLE_DRAW);
  1974. for (var i=0; i<self.TitlePaint.length; ++i) //标题
  1975. {
  1976. var item = self.TitlePaint[i];
  1977. if (!item.IsDynamic) continue;
  1978. if (item.ClassName == 'DynamicChartTitlePainting') item.OnDrawEvent = eventIndexTitleDraw
  1979. else item.OnDrawEvent = eventTitleDraw;
  1980. item.CursorIndex = self.CursorIndex;
  1981. if (!bOnTouchDraw) //手势离开屏幕 去最后一个数据
  1982. {
  1983. if (this.ChartPaint[0] && this.ChartPaint[0].Data && this.ChartPaint[0].Data.Data)
  1984. {
  1985. var lastDataIndex=this.GetLastDataIndex();
  1986. if (IFrameSplitOperator.IsNumber(lastDataIndex)) item.CursorIndex=lastDataIndex;
  1987. }
  1988. }
  1989. if (item.FullDraw) item.FullDraw();
  1990. }
  1991. if (bOnTouchDraw)
  1992. {
  1993. for (var i=0; i<this.ExtendChartPaint.length; ++i) //动态扩展图形 在动态标题以后画
  1994. {
  1995. var item = this.ExtendChartPaint[i];
  1996. if (item.IsCallbackDraw) continue;
  1997. if (item.ClassName=="KLineTooltipPaint" && !bDrawTooltip) continue;
  1998. if (item.ClassName=="MinuteTooltipPaint" && !bDrawTooltip) continue;
  1999. item.LatestPoint={ X:this.LastPoint.X, Y:this.LastPoint.Y };
  2000. if (item.IsDynamic && item.DrawAfterTitle) item.Draw();
  2001. }
  2002. }
  2003. for(var i=0;i<this.ChartDrawPicture.length;++i)
  2004. {
  2005. var item=this.ChartDrawPicture[i];
  2006. if (item.IsDrawFirst) continue;
  2007. if (item.IsDrawMain && item.IsDrawMain()) continue;
  2008. item.Draw();
  2009. }
  2010. if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10)
  2011. {
  2012. this.CurrentChartDrawPicture.Draw();
  2013. }
  2014. this.LastDrawStatus = 'FullDraw';
  2015. this.Canvas.draw(false);
  2016. }
  2017. //窗口高度是否是0
  2018. this.IsHideFrame=function(frame)
  2019. {
  2020. if (!frame) return false;
  2021. if (!IFrameSplitOperator.IsNumber(frame.Identify)) return false;
  2022. if (frame.Identify<0) return false;
  2023. if (!this.Frame.SubFrame) return false;
  2024. var item= this.Frame.SubFrame[frame.Identify];
  2025. if (!item) return false;
  2026. return item.Height<=0;
  2027. }
  2028. //当前屏K线涨幅Y轴刻度
  2029. this.KLineIncreaseCustomHorizontal=function()
  2030. {
  2031. if (!this.Frame || !this.Frame.SubFrame) return;
  2032. var frame=this.Frame.SubFrame[0].Frame;
  2033. if (!frame) return;
  2034. var defaultfloatPrecision=GetfloatPrecision(this.Symbol);
  2035. var isPercentage=false; //是否是百分比坐标
  2036. if (frame.YSplitOperator && frame.YSplitOperator.CoordinateType==1) isPercentage=true;
  2037. var isOverlayCoordinate=false; //是否包含叠加股票刻度
  2038. for(var i=0;i<frame.CustomHorizontalInfo.length;++i)
  2039. {
  2040. var info=frame.CustomHorizontalInfo[i];
  2041. if (info.Type==4) isOverlayCoordinate=true;
  2042. if ((isPercentage && info.Type==3) || info.Type==2)
  2043. {
  2044. var item=this.ChartPaint[0];
  2045. if (!item) continue;
  2046. var data=item.Data;
  2047. if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) continue;
  2048. if (!IFrameSplitOperator.IsNumber(item.DrawKRange.Start) || !IFrameSplitOperator.IsNumber(item.DrawKRange.End)) continue;
  2049. var startKLine=data.Data[item.DrawKRange.Start];
  2050. var endKLine=data.Data[item.DrawKRange.End];
  2051. var value=(endKLine.Close-startKLine.Close)/startKLine.Close;
  2052. info.Value=endKLine.Close;
  2053. if (info.Type==2)
  2054. {
  2055. info.Message[1]=endKLine.Close.toFixed(defaultfloatPrecision);
  2056. if (endKLine.Close>endKLine.Open) info.LineColor=g_JSChartResource.FrameLatestPrice.UpBarColor;
  2057. else if (endKLine.Close<endKLine.Open) info.LineColor=g_JSChartResource.FrameLatestPrice.DownBarColor;
  2058. else info.LineColor=g_JSChartResource.FrameLatestPrice.UnchagneBarColor;
  2059. }
  2060. else
  2061. {
  2062. info.Message[1]=value.toFixed(2)+"%";
  2063. }
  2064. if (this.Name) info.Title=this.Name;
  2065. }
  2066. }
  2067. if (isOverlayCoordinate)
  2068. {
  2069. //叠加股票自定义刻度需要移除重新添加
  2070. var newCustomHorizontalInfo= frame.CustomHorizontalInfo.filter(function(value, index, ary)
  2071. {
  2072. return value.Type!=4
  2073. });
  2074. frame.CustomHorizontalInfo=newCustomHorizontalInfo;
  2075. }
  2076. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  2077. {
  2078. var item=this.OverlayChartPaint[i];
  2079. if (!item) continue;
  2080. if (item.YInfoType!=4) continue;
  2081. var data=item.Data;
  2082. if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) continue;
  2083. if (!IFrameSplitOperator.IsNumber(item.DrawKRange.Start) || !IFrameSplitOperator.IsNumber(item.DrawKRange.End)) continue;
  2084. var startKLine=data.Data[item.DrawKRange.Start];
  2085. var endKLine=data.Data[item.DrawKRange.End];
  2086. var value=(endKLine.Close-startKLine.Close)/startKLine.Close*100;
  2087. var info=new CoordinateInfo();
  2088. info.Value=endKLine.Close/item.ShowRange.FirstOverlayOpen*item.ShowRange.FirstOpen;
  2089. info.Message[1]=value.toFixed(2)+"%";
  2090. info.LineType=-1;
  2091. info.Type=item.YInfoType; //叠加股票
  2092. info.LineColor=item.Color;
  2093. info.TextColor=g_JSChartResource.FrameLatestPrice.OverlayTextColor;
  2094. if (item.Title) info.Title=item.Title;
  2095. frame.CustomHorizontalInfo.push(info);
  2096. }
  2097. }
  2098. //获取最后一个数据的相对于当前屏的索引
  2099. this.GetLastDataIndex=function()
  2100. {
  2101. if (!this.ChartPaint[0] || !this.ChartPaint[0].Data || !this.ChartPaint[0].Data.Data) return null;
  2102. var hisData=this.ChartPaint[0].Data;
  2103. var dataCount=hisData.Data.length;
  2104. if (dataCount>0) return (dataCount-1)-hisData.DataOffset;
  2105. return null;
  2106. }
  2107. this.Draw = function ()
  2108. {
  2109. if (this.IsDestroy) return;
  2110. if (this.IsFullDraw)
  2111. {
  2112. this.FullDraw('Draw');
  2113. ++this.TouchDrawCount;
  2114. return;
  2115. }
  2116. if (this.IsOnTouch == true && (this.ClassName == 'MinuteChartContainer' || this.ClassName =='MinuteChartHScreenContainer')) return;
  2117. var self = this;
  2118. this.Canvas.clearRect(0, 0, this.UIElement.Width, this.UIElement.Height);
  2119. this.Frame.SetDrawOtherChart(() =>
  2120. {
  2121. for (var i in this.ExtendChartPaint)
  2122. {
  2123. var item = this.ExtendChartPaint[i];
  2124. if (item.IsCallbackDraw) item.Draw();
  2125. }
  2126. });
  2127. //框架
  2128. this.Frame.Draw();
  2129. if (this.Frame.DrawCustomVertical)
  2130. {
  2131. var eventCVericalDraw = this.GetEvent(JSCHART_EVENT_ID.ON_CUSTOM_VERTICAL_DRAW);
  2132. this.Frame.DrawCustomVertical(eventCVericalDraw);
  2133. }
  2134. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash)
  2135. {
  2136. this.Frame.DrawInsideHorizontal();
  2137. this.ChartSplashPaint.Draw();
  2138. this.LastDrawStatus = 'Draw';
  2139. this.Canvas.draw();
  2140. return;
  2141. }
  2142. for (var i=0; i<this.ChartPaint.length; ++i)
  2143. {
  2144. var item = this.ChartPaint[i];
  2145. if (item.IsDrawFirst) item.Draw();
  2146. }
  2147. if (this.Frame.DrawOveraly)
  2148. this.Frame.DrawOveraly(true); //画叠加指标
  2149. //框架内图形
  2150. for (var i=0; i<this.ChartPaint.length; ++i)
  2151. {
  2152. var item = this.ChartPaint[i];
  2153. if (!item.IsDrawFirst) item.Draw();
  2154. }
  2155. for (var i=0; i<this.ChartPaintEx.length; ++i)
  2156. {
  2157. var item = this.ChartPaintEx[i];
  2158. item.Draw();
  2159. }
  2160. //叠加股票
  2161. for (var i=0; i<this.OverlayChartPaint.length; ++i)
  2162. {
  2163. var item = this.OverlayChartPaint[i];
  2164. item.Draw();
  2165. }
  2166. if (this.Frame.DrawOveraly)
  2167. this.Frame.DrawOveraly(false); //画叠加指标
  2168. //框架外图形
  2169. for (var i=0; i<this.ExtendChartPaint.length; ++i)
  2170. {
  2171. var item = this.ExtendChartPaint[i];
  2172. if (item.IsCallbackDraw) continue;
  2173. if (!item.IsDynamic && !item.IsAnimation) item.Draw();
  2174. }
  2175. //框架内部坐标
  2176. if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal();
  2177. if (this.Frame.DrawCustomHorizontal) this.Frame.DrawCustomHorizontal();
  2178. if (this.ChartInfoPaint) this.ChartInfoPaint.Draw();
  2179. this.Frame.DrawLock();
  2180. this.Frame.DrawLogo();
  2181. var eventTitleDraw = this.GetEvent(JSCHART_EVENT_ID.ON_TITLE_DRAW);
  2182. var eventIndexTitleDraw = this.GetEvent(JSCHART_EVENT_ID.ON_INDEXTITLE_DRAW);
  2183. for (var i=0; i<this.TitlePaint.length; ++i)
  2184. {
  2185. var item = this.TitlePaint[i];
  2186. if (!item.IsDynamic) continue;
  2187. if (item.ClassName == 'DynamicChartTitlePainting') item.OnDrawEvent = eventIndexTitleDraw
  2188. else item.OnDrawEvent = eventTitleDraw;
  2189. if (typeof (item.DrawTitle) == 'function') item.DrawTitle();
  2190. }
  2191. for(var i=0;i<this.ChartDrawPicture.length;++i)
  2192. {
  2193. var item=this.ChartDrawPicture[i];
  2194. if (item.IsDrawFirst) continue;
  2195. if (item.IsDrawMain && item.IsDrawMain()) continue;
  2196. item.Draw();
  2197. }
  2198. if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10)
  2199. {
  2200. this.CurrentChartDrawPicture.Draw();
  2201. }
  2202. this.LastDrawStatus='Draw';
  2203. if (this.IsOnTouch) //手势移动的时候不保存图片
  2204. {
  2205. this.Canvas.draw(false);
  2206. }
  2207. else
  2208. {
  2209. ++this.LastDrawID;
  2210. //坑!!.画图是异步, 保存当前屏图放在回调里面
  2211. //JSConsole.Chart.Log('[JSChartContainer:Draw][ID=' + this.UIElement.ID + '] draw and save snapshot. DrawID=' + this.LastDrawID + ' .....');
  2212. var lastDrawID=this.LastDrawID;
  2213. this.Canvas.draw(false, function ()
  2214. {
  2215. //if (lastDrawID == self.LastDrawID)
  2216. self.Frame.Snapshot(self.SnapshotType); //只保存最后一次的截图
  2217. //JSConsole.Chart.Log('[JSChartContainer:Draw] finish. DrawID('+ lastDrawID +','+ self.LastDrawID +')');
  2218. });
  2219. }
  2220. //JSConsole.Chart.Log('[JSChartContainer:Draw][ID=' + this.UIElement.ID + '] draw dynamic info ......');
  2221. //动态标题都不画了(Canvas.draw 异步画的,如果下面再画会被截屏进去) 只有数据移动的时候在画
  2222. }
  2223. //画动态信息
  2224. this.TempImage=null;
  2225. this.DrawDynamicInfo = function ()
  2226. {
  2227. if (this.IsFullDraw)
  2228. {
  2229. this.FullDraw('DrawDynamicInfo');
  2230. ++this.TouchDrawCount;
  2231. return;
  2232. }
  2233. var self = this;
  2234. var width = this.Frame.ChartBorder.GetChartWidth();
  2235. var height = this.Frame.ChartBorder.GetChartHeight();
  2236. if (self.SnapshotType==1)
  2237. {
  2238. if (this.Frame.ScreenImageData == null) return;
  2239. wx.canvasPutImageData({
  2240. canvasId: this.UIElement.ID,
  2241. x: 0,y: 0,width: width,height: height,
  2242. data: this.Frame.ScreenImageData,
  2243. success(res) { self.DrawDynamicChart(true); }
  2244. })
  2245. }
  2246. else
  2247. {
  2248. if (this.Frame.ScreenImagePath == null) return;
  2249. if (self.Canvas && self.Canvas.DomNode) //新版本2D画布
  2250. {
  2251. //JSConsole.Chart.Log("[DrawDynamicInfo] ScreenImagePath ", this.Frame.ScreenImagePath);
  2252. if (!this.TempImage) this.TempImage= self.Canvas.DomNode.createImage(); //新版本的必须要装成image类 比较坑
  2253. this.TempImage.src = this.Frame.ScreenImagePath;
  2254. //JSConsole.Chart.Log("[DrawDynamicInfo] tempImage ", this.TempImage);
  2255. this.TempImage.onload=()=>
  2256. {
  2257. //JSConsole.Chart.Log("[DrawDynamicInfo] onload ", self.TempImage);
  2258. self.Canvas.clearRect(0, 0, width, height);
  2259. self.Canvas.drawImage(self.TempImage, 0, 0, width, height);
  2260. self.DrawDynamicChart(false);
  2261. }
  2262. }
  2263. else
  2264. {
  2265. self.Canvas.drawImage(this.Frame.ScreenImagePath, 0, 0, width, height);
  2266. self.DrawDynamicChart(false);
  2267. }
  2268. }
  2269. }
  2270. this.DrawDynamicChart = function (bReserve)
  2271. {
  2272. var self = this;
  2273. if (self.ChartCorssCursor)
  2274. {
  2275. self.ChartCorssCursor.LastPoint = self.LastPoint;
  2276. self.ChartCorssCursor.CursorIndex = self.CursorIndex;
  2277. self.ChartCorssCursor.Draw();
  2278. }
  2279. for (var i in self.TitlePaint)
  2280. {
  2281. var item = self.TitlePaint[i];
  2282. if (!item.IsDynamic) continue;
  2283. item.CursorIndex = self.CursorIndex;
  2284. item.Draw();
  2285. }
  2286. for (var i in this.ExtendChartPaint) //动态扩展图形 在动态标题以后画
  2287. {
  2288. var item = this.ExtendChartPaint[i];
  2289. if (item.IsDynamic && item.DrawAfterTitle) item.Draw();
  2290. }
  2291. if (this.EnableAnimation)
  2292. {
  2293. for (var i in this.ExtendChartPaint) //动画
  2294. {
  2295. var item = this.ExtendChartPaint[i];
  2296. if (item.IsAnimation === true) item.Draw();
  2297. }
  2298. }
  2299. this.LastDrawStatus = 'DrawDynamicInfo';
  2300. JSConsole.Chart.Log('[JSChartContainer:DrawDynamicChart][ID=' + this.UIElement.ID + '] draw .....');
  2301. self.Canvas.draw(bReserve, function () {
  2302. JSConsole.Chart.Log('[JSChartContainer:DrawDynamicChart] finish.');
  2303. });
  2304. }
  2305. this.DrawAnimation = function () //绘制动画 如弹幕
  2306. {
  2307. if (!this.EnableAnimation) return;
  2308. if (this.Frame.ScreenImagePath && !this.IsOnTouch)
  2309. {
  2310. for (var i in this.ExtendChartPaint)
  2311. {
  2312. var item = this.ExtendChartPaint[i];
  2313. if (item.IsAnimation === true) item.IsMoveStep = true; //移动弹幕
  2314. }
  2315. this.DrawDynamicInfo();
  2316. }
  2317. var self = this;
  2318. this.UIElement.WebGLCanvas.requestAnimationFrame(() => { this.DrawAnimation(); });
  2319. }
  2320. this.StartAnimation = function (option)
  2321. {
  2322. JSConsole.Chart.Log('[JSChartContainer::StartAnimation] ', this.UIElement.WebGLCanvas);
  2323. if (!this.UIElement.WebGLCanvas) return;
  2324. var bCreated = false; //是否已经创建了弹幕画法
  2325. var barrageData = null;
  2326. for (var i in this.ExtendChartPaint)
  2327. {
  2328. var item = this.ExtendChartPaint[i];
  2329. if (item.ClassName === 'BarragePaint')
  2330. {
  2331. bCreated = true;
  2332. barrageData = item.BarrageList;
  2333. break;
  2334. }
  2335. }
  2336. if (!bCreated)
  2337. {
  2338. var chart = new BarragePaint();
  2339. chart.Canvas = this.Canvas;
  2340. chart.ChartBorder = this.Frame.ChartBorder;
  2341. chart.ChartFrame = this.Frame;
  2342. chart.HQChart = this;
  2343. chart.SetOption(option);
  2344. this.ExtendChartPaint.push(chart);
  2345. barrageData = chart.BarrageList;
  2346. }
  2347. this.EnableAnimation = true;
  2348. var self = this;
  2349. this.UIElement.WebGLCanvas.requestAnimationFrame(()=> { this.DrawAnimation(); });
  2350. return barrageData;
  2351. }
  2352. this.StopAnimation = function ()
  2353. {
  2354. this.EnableAnimation = false;
  2355. this.DrawDynamicInfo();
  2356. }
  2357. this.OnMouseMove = function (x, y, e, bFullDraw)
  2358. {
  2359. var lastY = this.LastPoint.Y;
  2360. this.LastPoint.X = x;
  2361. this.LastPoint.Y = y;
  2362. var lastCursorIndex = this.CursorIndex;
  2363. this.CursorIndex = this.Frame.GetXData(x);
  2364. if ( this.ClassName=="KLineChartContainer" || this.ClassName=="KLineChartHScreenContainer" )
  2365. {
  2366. if (lastCursorIndex == this.CursorIndex && Math.abs(lastY - y) < 1) return; //一个一个数据移动
  2367. }
  2368. else
  2369. {
  2370. if (parseInt(lastCursorIndex - 0.5) == parseInt(this.CursorIndex - 0.5) && Math.abs(lastY - y) < 1) return; //一个一个数据移动
  2371. }
  2372. if (bFullDraw)
  2373. {
  2374. this.FullDraw();
  2375. }
  2376. else
  2377. {
  2378. if (this.IsForceLandscape) this.Draw();//横屏图片太大不让贴,分两张图贴,多次截图的函数是坏的, 直接重画了
  2379. else this.DrawDynamicInfo();
  2380. }
  2381. }
  2382. this.MoveCorssCursor=function(point, e)
  2383. {
  2384. var x = point.X;
  2385. var y = point.Y;
  2386. this.OnMouseMove(x,y,e,true);
  2387. }
  2388. this.OnDoubleClick = function (x, y, e)
  2389. {
  2390. //JSConsole.Chart.Log(e);
  2391. }
  2392. this.UpdatePointByCursorIndex = function ()
  2393. {
  2394. this.LastPoint.X = this.Frame.GetXFromIndex(this.CursorIndex);
  2395. var index = Math.abs(this.CursorIndex - 0.5);
  2396. index = parseInt(index.toFixed(0));
  2397. if (this.ClassName == 'KLineChartContainer') index = this.CursorIndex;
  2398. var data = this.Frame.Data;
  2399. if (data.DataOffset + index >= data.Data.length)
  2400. {
  2401. return;
  2402. }
  2403. var close = data.Data[data.DataOffset + index].Close;
  2404. this.LastPoint.Y = this.Frame.GetYFromData(close);
  2405. }
  2406. this.ResetFrameXYSplit = function ()
  2407. {
  2408. if (typeof (this.Frame.ResetXYSplit) == 'function') this.Frame.ResetXYSplit();
  2409. }
  2410. this.UpdateFrameMaxMinV2=function()
  2411. {
  2412. var mapFrame=new Map(); //key=frameid, value:{ ChartPaint:[] }
  2413. for(var i=0;i<this.Frame.SubFrame.length;++i)
  2414. {
  2415. var subItem=this.Frame.SubFrame[i];
  2416. if (!subItem || !subItem.Frame) continue;
  2417. var frame=subItem.Frame;
  2418. frame.YCustomSplit=true; //自定义刻度每次都调用
  2419. var key=frame.Identify;
  2420. var item=
  2421. {
  2422. ID:key, Frame:frame, ChartPaint:[] , Max:null, Min:null,
  2423. OverlayFrame:[], //共享坐标
  2424. SingleOverlay:[], //独立坐标
  2425. MainOverlayFrame:[null, null], //叠加坐标在主坐标显示[0]=left [1]=right
  2426. };
  2427. for(var j=0;j<subItem.OverlayIndex.length;++j)
  2428. {
  2429. var overlayItem=subItem.OverlayIndex[j];
  2430. var overlayFrame=overlayItem.Frame;
  2431. if (overlayFrame.IsShowMainFrame===1) item.MainOverlayFrame[0]= overlayFrame;
  2432. else if (overlayFrame.IsShowMainFrame===2) item.MainOverlayFrame[1]= overlayFrame;
  2433. if (overlayFrame.IsShareY)
  2434. {
  2435. if (!overlayFrame.MainFrame) continue;
  2436. if (overlayFrame.IsCalculateYMaxMin===false) continue; //叠加坐标Y轴不调整
  2437. item.OverlayFrame.push(overlayFrame);
  2438. for(var k=0; k<overlayItem.ChartPaint.length; ++k)
  2439. {
  2440. var chart=overlayItem.ChartPaint[k];
  2441. item.ChartPaint.push(chart);
  2442. }
  2443. }
  2444. else
  2445. {
  2446. item.SingleOverlay.push(overlayItem);
  2447. }
  2448. }
  2449. mapFrame.set(key, item);
  2450. }
  2451. for(var i=0;i<this.ChartPaint.length;++i)
  2452. {
  2453. var chart=this.ChartPaint[i];
  2454. var key=chart.ChartFrame.Identify;
  2455. if (!mapFrame.has(key)) continue;
  2456. var finder=mapFrame.get(key);
  2457. finder.ChartPaint.push(chart);
  2458. }
  2459. for(var i=0;i<this.OverlayChartPaint.length;++i)
  2460. {
  2461. var chart=this.OverlayChartPaint[i];
  2462. if (!chart.ChartFrame) continue;
  2463. var key=chart.ChartFrame.Identify;
  2464. if (!mapFrame.has(key)) continue;
  2465. var finder=mapFrame.get(key);
  2466. finder.ChartPaint.push(chart);
  2467. }
  2468. for(var mapItem of mapFrame)
  2469. {
  2470. var item=mapItem[1];
  2471. var frame=item.Frame;
  2472. //计算主框架最大最小
  2473. for(var i=0;i<item.ChartPaint.length;++i)
  2474. {
  2475. var chart=item.ChartPaint[i];
  2476. if (chart.IsShow==false) continue; //隐藏的图形不计算
  2477. if (chart.NotSupportMessage) continue;
  2478. if (!chart.ChartFrame) continue;
  2479. var range=chart.GetMaxMin();
  2480. if (range==null || range.Max==null || range.Min==null) continue;
  2481. if (item.Max==null || item.Max<range.Max) item.Max=range.Max;
  2482. if (item.Min==null || item.Min>range.Min) item.Min=range.Min;
  2483. }
  2484. if (item.Frame.YSpecificMaxMin) //固定坐标
  2485. {
  2486. item.Min=item.Frame.YSpecificMaxMin.Max;
  2487. item.Max=item.Frame.YSpecificMaxMin.Min;
  2488. }
  2489. if (!IFrameSplitOperator.IsNumber(frame.YMaxMin.Max) || frame.YMaxMin.Max!=item.Max)
  2490. {
  2491. frame.YMaxMin.Max=item.Max;
  2492. frame.XYSplit=true;
  2493. }
  2494. if (!IFrameSplitOperator.IsNumber(frame.YMaxMin.Min) || frame.YMaxMin.Min!=item.Min)
  2495. {
  2496. frame.YMaxMin.Min=item.Min
  2497. frame.XYSplit=true;
  2498. }
  2499. if (frame.XYSplit)
  2500. {
  2501. var max=10, min=0;
  2502. if (item.Max!=null) max=item.Max;
  2503. if (item.Min!=null) min=item.Min;
  2504. frame.HorizontalMax=max;
  2505. frame.HorizontalMin=min;
  2506. }
  2507. else
  2508. {
  2509. frame.XSplit=true;
  2510. }
  2511. //共享Y轴叠加指标坐标同步
  2512. for(var j=0;j<item.OverlayFrame.length;++j)
  2513. {
  2514. item.OverlayFrame[j].XYSplit=true;
  2515. }
  2516. //叠加坐标显示在主图坐标 需要同步
  2517. for(var i=0;i<item.MainOverlayFrame.length;++i)
  2518. {
  2519. var subItem=item.MainOverlayFrame[i];
  2520. if (subItem) subItem.XYSplit=true;
  2521. }
  2522. //独立坐标叠加指标
  2523. for(var i=0;i<item.SingleOverlay.length;++i)
  2524. {
  2525. var overlayItem=item.SingleOverlay[i];
  2526. overlayItem.UpdateFrameMaxMin();
  2527. }
  2528. }
  2529. }
  2530. this.UpdateFrameMaxMin = function ()
  2531. {
  2532. this.UpdateFrameMaxMinV2();
  2533. return;
  2534. var frameMaxMinData = new Array();
  2535. var chartPaint = new Array();
  2536. for (var i=0; i<this.ChartPaint.length; ++i)
  2537. {
  2538. var item=this.ChartPaint[i];
  2539. if (item.IsShow==false) continue; //隐藏的图形不计算
  2540. chartPaint.push(item);
  2541. }
  2542. for (var i=0; i<this.OverlayChartPaint.length; ++i)
  2543. {
  2544. chartPaint.push(this.OverlayChartPaint[i]);
  2545. }
  2546. for (var i=0; i<chartPaint.length; ++i)
  2547. {
  2548. var paint = chartPaint[i];
  2549. var range = paint.GetMaxMin();
  2550. if (range == null || range.Max == null || range.Min == null) continue;
  2551. var frameItem = null;
  2552. for (var j=0; j<frameMaxMinData.length; ++j)
  2553. {
  2554. if (frameMaxMinData[j].Frame == paint.ChartFrame)
  2555. {
  2556. frameItem = frameMaxMinData[j];
  2557. break;
  2558. }
  2559. }
  2560. if (frameItem)
  2561. {
  2562. if (frameItem.Range.Max < range.Max) frameItem.Range.Max = range.Max;
  2563. if (frameItem.Range.Min > range.Min) frameItem.Range.Min = range.Min;
  2564. }
  2565. else
  2566. {
  2567. frameItem = { OverlayFrame:[] };
  2568. frameItem.Frame = paint.ChartFrame;
  2569. frameItem.Range = range;
  2570. frameMaxMinData.push(frameItem);
  2571. }
  2572. }
  2573. var mapFrame=new Map();
  2574. for(var i=0;i<frameMaxMinData.length;++i)
  2575. {
  2576. var item=frameMaxMinData[i];
  2577. mapFrame.set(item.Frame.Identify,item);
  2578. }
  2579. //叠加坐标Y轴使用主图指标, 最大最小值
  2580. for(var i=0;i<this.Frame.SubFrame.length;++i)
  2581. {
  2582. var subFrame=this.Frame.SubFrame[i];
  2583. for(var j=0;j<subFrame.OverlayIndex.length;++j)
  2584. {
  2585. var overlayItem=subFrame.OverlayIndex[j];
  2586. var overlayFrame=overlayItem.Frame;
  2587. if (overlayFrame.IsShareY!=true) continue;
  2588. if (!overlayFrame.MainFrame) continue;
  2589. if (!mapFrame.has(overlayFrame.MainFrame.Identify)) continue;
  2590. var frameItem=mapFrame.get(overlayFrame.MainFrame.Identify);
  2591. if (!frameItem) continue;
  2592. frameItem.OverlayFrame.push(overlayFrame);
  2593. if (overlayFrame.IsCalculateYMaxMin===false) continue; //叠加坐标Y轴不调整
  2594. for(var k=0; k<overlayItem.ChartPaint.length; ++k)
  2595. {
  2596. var paint=overlayItem.ChartPaint[k];
  2597. var range=paint.GetMaxMin();
  2598. if (range==null || range.Max==null || range.Min==null) continue;
  2599. if (frameItem.Range.Max<range.Max) frameItem.Range.Max=range.Max;
  2600. if (frameItem.Range.Min>range.Min) frameItem.Range.Min=range.Min;
  2601. }
  2602. }
  2603. }
  2604. for (var i=0; i<frameMaxMinData.length; ++i)
  2605. {
  2606. var item = frameMaxMinData[i];
  2607. if (!item.Frame || !item.Range) continue;
  2608. if (item.Range.Max == null || item.Range.Min == null) continue;
  2609. if (item.Frame.YSpecificMaxMin)
  2610. {
  2611. item.Frame.HorizontalMax = item.Frame.YSpecificMaxMin.Max;
  2612. item.Frame.HorizontalMin = item.Frame.YSpecificMaxMin.Min;
  2613. }
  2614. else
  2615. {
  2616. item.Frame.HorizontalMax = item.Range.Max;
  2617. item.Frame.HorizontalMin = item.Range.Min;
  2618. }
  2619. item.Frame.XYSplit = true;
  2620. for(var j=0; j<item.OverlayFrame.length; ++j)
  2621. {
  2622. item.OverlayFrame[j].XYSplit=true;
  2623. }
  2624. }
  2625. //更新独立子坐标
  2626. for(var i=0;i<this.Frame.SubFrame.length;++i)
  2627. {
  2628. var subFrame=this.Frame.SubFrame[i];
  2629. for(var j=0;j<subFrame.OverlayIndex.length;++j)
  2630. {
  2631. var overlayItem=subFrame.OverlayIndex[j];
  2632. if (overlayItem.Frame.IsShareY===true) continue;
  2633. overlayItem.UpdateFrameMaxMin();
  2634. }
  2635. }
  2636. }
  2637. this.DataMoveLeft = function () {
  2638. var data = null;
  2639. if (!this.Frame.Data) data = this.Frame.Data;
  2640. else data = this.Frame.SubFrame[0].Frame.Data;
  2641. if (!data) return false;
  2642. if (data.DataOffset <= 0) return false;
  2643. --data.DataOffset;
  2644. return true;
  2645. }
  2646. this.DataMoveRight = function () {
  2647. var data = null;
  2648. if (!this.Frame.Data) data = this.Frame.Data;
  2649. else data = this.Frame.SubFrame[0].Frame.Data;
  2650. if (!data) return false;
  2651. var xPointcount = 0;
  2652. if (this.Frame.XPointCount) xPointcount = this.Frame.XPointCount;
  2653. else xPointcount = this.Frame.SubFrame[0].Frame.XPointCount;
  2654. if (!xPointcount) return false;
  2655. if (xPointcount + data.DataOffset >= data.Data.length) return false;
  2656. ++data.DataOffset;
  2657. return true;
  2658. }
  2659. this.UpdataDataoffset = function ()
  2660. {
  2661. var data = null;
  2662. if (this.Frame.Data) data = this.Frame.Data;
  2663. else data = this.Frame.SubFrame[0].Frame.Data;
  2664. if (!data) return;
  2665. for (var i=0; i<this.ChartPaint.length; ++i)
  2666. {
  2667. var item = this.ChartPaint[i];
  2668. if (!item.Data) continue;
  2669. item.Data.DataOffset = data.DataOffset;
  2670. }
  2671. for (var i=0; i<this.OverlayChartPaint.length; ++i)
  2672. {
  2673. var item = this.OverlayChartPaint[i];
  2674. if (!item.Data) continue;
  2675. item.Data.DataOffset = data.DataOffset;
  2676. }
  2677. //叠加指标当前显示的数据偏移
  2678. for (var i=0; i<this.Frame.SubFrame.length; ++i)
  2679. {
  2680. var subFrame=this.Frame.SubFrame[i];
  2681. for(var j=0; j<subFrame.OverlayIndex.length; ++j)
  2682. {
  2683. var overlayItem=subFrame.OverlayIndex[j];
  2684. for(var k=0; k<overlayItem.ChartPaint.length; ++k)
  2685. {
  2686. var item=overlayItem.ChartPaint[k];
  2687. if (!item.Data) continue;
  2688. item.Data.DataOffset=data.DataOffset;
  2689. }
  2690. }
  2691. }
  2692. }
  2693. this.DataMove = function (step, isLeft)
  2694. {
  2695. step=parseInt(step/this.StepPixel);
  2696. if (step<=0) return false;
  2697. var data = null;
  2698. if (!this.Frame.Data) data = this.Frame.Data;
  2699. else data = this.Frame.SubFrame[0].Frame.Data;
  2700. if (!data) return false;
  2701. var xPointcount = 0;
  2702. if (this.Frame.XPointCount) xPointcount = this.Frame.XPointCount;
  2703. else xPointcount = this.Frame.SubFrame[0].Frame.XPointCount;
  2704. if (!xPointcount) return false;
  2705. if (isLeft) //-->
  2706. {
  2707. if (this.RightSpaceCount > 0)
  2708. {
  2709. if (xPointcount + data.DataOffset >= data.Data.length + this.RightSpaceCount) return false;
  2710. data.DataOffset += step;
  2711. if (data.DataOffset + xPointcount >= data.Data.length + this.RightSpaceCount)
  2712. data.DataOffset = data.Data.length - (xPointcount - this.RightSpaceCount);
  2713. }
  2714. else
  2715. {
  2716. if (xPointcount + data.DataOffset >= data.Data.length) return false;
  2717. data.DataOffset += step;
  2718. if (data.DataOffset + xPointcount >= data.Data.length)
  2719. data.DataOffset = data.Data.length - xPointcount;
  2720. }
  2721. return true;
  2722. }
  2723. else //<--
  2724. {
  2725. if (data.DataOffset <= 0) return false;
  2726. data.DataOffset -= step;
  2727. if (data.DataOffset < 0) data.DataOffset = 0;
  2728. return true;
  2729. }
  2730. }
  2731. //获取鼠标在当前子窗口id
  2732. this.GetSubFrameIndex = function (x, y) {
  2733. if (!this.Frame.SubFrame || this.Frame.SubFrame.length <= 0) return -1;
  2734. for (var i in this.Frame.SubFrame) {
  2735. var frame = this.Frame.SubFrame[i].Frame;
  2736. var left = frame.ChartBorder.GetLeft();
  2737. var top = frame.ChartBorder.GetTop();
  2738. var height = frame.ChartBorder.GetHeight();
  2739. var width = frame.ChartBorder.GetWidth();
  2740. this.Canvas.rect(left, top, width, height);
  2741. if (this.Canvas.isPointInPath(x, y)) return parseInt(i);
  2742. }
  2743. return 0;
  2744. }
  2745. //根据X坐标获取数据索引
  2746. this.GetDataIndexByPoint = function (x) {
  2747. var frame = this.Frame;
  2748. if (this.Frame.SubFrame && this.Frame.SubFrame.length > 0) frame = this.Frame.SubFrame[0].Frame;
  2749. var data = null;
  2750. if (this.Frame.Data)
  2751. data = this.Frame.Data;
  2752. else
  2753. data = this.Frame.SubFrame[0].Frame.Data;
  2754. if (!data || !frame) return;
  2755. var index = parseInt(frame.GetXData(x));
  2756. //JSConsole.Chart.Log('x='+ x +' date='+data.Data[data.DataOffset+index].Date);
  2757. return data.DataOffset + index;
  2758. }
  2759. this.SaveToImage = function (callback)
  2760. {
  2761. let width = this.UIElement.Width;
  2762. let height = this.UIElement.Height;;
  2763. JSConsole.Chart.Log('[JSChartContainer::SaveToImage]', this.UIElement);
  2764. wx.canvasToTempFilePath({
  2765. x: 0,
  2766. y: 0,
  2767. width: width,
  2768. height: height,
  2769. canvasId: this.UIElement.ID,
  2770. success: function (res)
  2771. {
  2772. let data = { ImagePath: res.tempFilePath, Width: width, Height: height };
  2773. if (typeof (callback) == 'function') callback(data);
  2774. }
  2775. })
  2776. }
  2777. //全屏提示信息 { Title:提示信息, Draw:false/true 是否立即重绘, }
  2778. this.EnableSplashScreen=function(option)
  2779. {
  2780. if (!this.ChartSplashPaint) return;
  2781. if (!option) return;
  2782. if (IFrameSplitOperator.IsString(option.Title)) this.ChartSplashPaint.SetTitle(option.Title);
  2783. this.ChartSplashPaint.EnableSplash(true);
  2784. if (option.Draw===false) return;
  2785. this.Draw();
  2786. }
  2787. //设置指标窗口属性 windowItem=SetOption.Windows[i], frameItem=SetOption.Frames[i];
  2788. this.SetSubFrameAttribute=function(subFrame, windowItem, frameItem)
  2789. {
  2790. if (!subFrame || !subFrame.Frame) return;
  2791. var frame=subFrame.Frame;
  2792. if (windowItem)
  2793. {
  2794. if (IFrameSplitOperator.IsNumber(windowItem.IndexParamSpace)) frame.IndexParamSpace = windowItem.IndexParamSpace;
  2795. if (IFrameSplitOperator.IsNumber(windowItem.IndexTitleSpace))frame.IndexTitleSpace = windowItem.IndexTitleSpace;
  2796. if (IFrameSplitOperator.IsBool(windowItem.IsDrawTitleBG)) frame.IsDrawTitleBG=windowItem.IsDrawTitleBG;
  2797. if (IFrameSplitOperator.IsBool(windowItem.IsShowNameArrow)) frame.IsShowNameArrow=windowItem.IsShowNameArrow;
  2798. if (IFrameSplitOperator.IsBool(windowItem.IsShowTitleArrow)) frame.IsShowTitleArrow=windowItem.IsShowTitleArrow;
  2799. }
  2800. if (frameItem)
  2801. {
  2802. if (IFrameSplitOperator.IsNumber(frameItem.SplitCount)) frame.YSplitOperator.SplitCount = frameItem.SplitCount;
  2803. if (IFrameSplitOperator.IsBool(frameItem.IsShowBorder)) frame.IsShowBorder = frameItem.IsShowBorder;
  2804. if (IFrameSplitOperator.IsBool(frameItem.IsShowXLine)) frame.IsShowXLine = frameItem.IsShowXLine;
  2805. if (IFrameSplitOperator.IsBool(frameItem.IsShowYLine)) frame.IsShowYLine=frameItem.IsShowYLine;
  2806. if (IFrameSplitOperator.IsBool(frameItem.IsShowLeftText)) frame.IsShowYText[0] = frameItem.IsShowLeftText; //显示左边刻度
  2807. if (IFrameSplitOperator.IsBool(frameItem.IsShowRightText)) frame.IsShowYText[1] = frameItem.IsShowRightText; //显示右边刻度
  2808. }
  2809. }
  2810. this.AddNewSubFrame=function(option)
  2811. {
  2812. var index=this.Frame.SubFrame.length;
  2813. var subFrame=this.CreateSubFrameItem(index);
  2814. this.Frame.SubFrame[index]=subFrame;
  2815. var titlePaint=new DynamicChartTitlePainting();
  2816. titlePaint.Frame=this.Frame.SubFrame[index].Frame;
  2817. titlePaint.Canvas=this.Canvas;
  2818. titlePaint.LanguageID=this.LanguageID;
  2819. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  2820. this.TitlePaint[index+1]=titlePaint;
  2821. if (option)
  2822. {
  2823. if (option.Window)
  2824. {
  2825. var item=option.Window;
  2826. if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) subFrame.Frame.IsDrawTitleBG=item.IsDrawTitleBG;
  2827. if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) subFrame.Frame.IsShowNameArrow=item.IsShowNameArrow;
  2828. }
  2829. if (IFrameSplitOperator.IsNumber(option.SplitCount)) subFrame.Frame.YSplitOperator.SplitCount=option.SplitCount;
  2830. if (IFrameSplitOperator.IsNumber(option.TitleHeight)) subFrame.Frame.ChartBorder.TitleHeight=option.TitleHeight;
  2831. if (IFrameSplitOperator.IsBool(option.IsShowTitleArrow)) subFrame.Frame.IsShowTitleArrow=option.IsShowTitleArrow;
  2832. if (IFrameSplitOperator.IsBool(option.IsShowIndexName)) subFrame.Frame.IsShowIndexName=option.IsShowIndexName;
  2833. if (IFrameSplitOperator.IsBool(option.IsShowOverlayIndexName)) subFrame.Frame.IsShowOverlayIndexName=option.IsShowOverlayIndexName;
  2834. if (IFrameSplitOperator.IsNumber(option.IndexParamSpace)) subFrame.Frame.IndexParamSpace=option.IndexParamSpace;
  2835. if (IFrameSplitOperator.IsNumber(option.IndexTitleSpace)) subFrame.Frame.IndexTitleSpace=option.IndexTitleSpace;
  2836. if (IFrameSplitOperator.IsBool(option.IsShowXLine)) subFrame.Frame.IsShowXLine=option.IsShowXLine;
  2837. if (IFrameSplitOperator.IsBool(option.IsShowYLine)) subFrame.Frame.IsShowYLine=option.IsShowYLine;
  2838. if (IFrameSplitOperator.IsBool(option.IsShowIndexTitle)) subFrame.Frame.IsShowTitle=option.IsShowIndexTitle;
  2839. if (IFrameSplitOperator.IsBool(option.IsShowLeftText)) subFrame.Frame.IsShowYText[0] = option.IsShowLeftText; //显示左边刻度
  2840. if (IFrameSplitOperator.IsBool(option.IsShowRightText)) subFrame.Frame.IsShowYText[1] = option.IsShowRightText; //显示右边刻度
  2841. }
  2842. //最后一个显示X轴坐标
  2843. for(var i=0;i<this.Frame.SubFrame.length;++i)
  2844. {
  2845. var item=this.Frame.SubFrame[i].Frame;
  2846. if (i==this.Frame.SubFrame.length-1) item.XSplitOperator.ShowText=true;
  2847. else item.XSplitOperator.ShowText=false;
  2848. }
  2849. this.UpdataDataoffset(); //更新数据偏移
  2850. this.Frame.SetSizeChage(true);
  2851. if (this.UpdateXShowText) this.UpdateXShowText();
  2852. this.ResetFrameXYSplit();
  2853. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  2854. this.Draw();
  2855. return index;
  2856. }
  2857. //增加一个指标窗口
  2858. this.AddIndexWindow=function(indexName,option)
  2859. {
  2860. //查找系统指标
  2861. let scriptData = new JSCommonIndexScript.JSIndexScript();
  2862. let indexInfo = scriptData.Get(indexName);
  2863. if (!indexInfo) return;
  2864. JSIndexScript.ModifyAttribute(indexInfo, option);
  2865. var index=this.AddNewSubFrame(option);
  2866. /*
  2867. var indexData =
  2868. {
  2869. Name:indexInfo.Name, Script:indexInfo.Script, Args: indexInfo.Args, ID:indexName ,
  2870. //扩展属性 可以是空
  2871. KLineType:indexInfo.KLineType, YSpecificMaxMin:indexInfo.YSpecificMaxMin, YSplitScale:indexInfo.YSplitScale,
  2872. FloatPrecision:indexInfo.FloatPrecision, Condition:indexInfo.Condition,StringFormat:indexInfo.StringFormat,
  2873. OutName:indexInfo.OutName
  2874. };
  2875. if (option)
  2876. {
  2877. if (option.FloatPrecision>=0) indexData.FloatPrecision=option.FloatPrecision;
  2878. if (option.StringFormat>0) indexData.StringFormat=option.StringFormat;
  2879. if (option.Args) indexData.Args=option.Args;
  2880. }
  2881. */
  2882. this.WindowIndex[index] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args,indexInfo); //脚本执行
  2883. if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer")
  2884. var bindData=this.SourceData;
  2885. else
  2886. var bindData=this.ChartPaint[0].Data;
  2887. this.BindIndexData(index,bindData); //执行脚本
  2888. }
  2889. //增加一个自定义指标窗口
  2890. this.AddScriptIndexWindow=function(indexInfo, option)
  2891. {
  2892. if (!indexInfo || !indexInfo.Script || !indexInfo.Name) return;
  2893. var index=this.AddNewSubFrame(option);
  2894. this.WindowIndex[index] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo)
  2895. if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer")
  2896. var bindData=this.SourceData;
  2897. else
  2898. var bindData=this.ChartPaint[0].Data;
  2899. this.BindIndexData(index,bindData); //执行脚本
  2900. }
  2901. //增加一个远程指标窗口
  2902. this.AddAPIIndexWindow=function(indexInfo, option)
  2903. {
  2904. if (!indexInfo.API) return;
  2905. var apiItem = indexInfo.API;
  2906. var index=this.AddNewSubFrame(option);
  2907. this.WindowIndex[index] = new APIScriptIndex(apiItem.Name, apiItem.Script, apiItem.Args, indexInfo);
  2908. if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer")
  2909. var bindData=this.SourceData;
  2910. else
  2911. var bindData=this.ChartPaint[0].Data;
  2912. this.BindIndexData(index,bindData); //执行脚本
  2913. }
  2914. this.SetLanguage=function(language)
  2915. {
  2916. var languageID=g_JSChartLocalization.GetLanguageID(language);
  2917. if (!IFrameSplitOperator.IsNumber(languageID))
  2918. {
  2919. console.warn(`[JSChartContainer::SetLanguage] language=${language} error`);
  2920. return;
  2921. }
  2922. if (this.LanguageID==languageID) return;
  2923. this.LanguageID=languageID;
  2924. if (this.ChartCorssCursor && this.ChartCorssCursor.StringFormatY) this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID;
  2925. for(var i=0; i<this.TitlePaint.length; ++i)
  2926. {
  2927. var item=this.TitlePaint[i];
  2928. if (item) item.LanguageID=this.LanguageID;
  2929. }
  2930. for(var i=0; i<this.ExtendChartPaint.length; ++i) //tooltip 等扩展图形
  2931. {
  2932. var item=this.ExtendChartPaint[i];
  2933. if (item) item.LanguageID=this.LanguageID;
  2934. }
  2935. if (this.Frame && this.Frame.SetLanguage) this.Frame.SetLanguage(this.LanguageID);
  2936. this.Frame.SetSizeChage(true);
  2937. this.Draw();
  2938. }
  2939. this.CreateOverlayFrame=function()
  2940. {
  2941. switch(this.ClassName)
  2942. {
  2943. case "KLineChartContainer":
  2944. return new OverlayKLineFrame();
  2945. case "KLineChartHScreenContainer":
  2946. return new OverlayKLineHScreenFrame();
  2947. case "MinuteChartContainer":
  2948. return new OverlayMinuteFrame();
  2949. case "MinuteChartHScreenContainer":
  2950. return new OverlayMinuteHScreenFrame();
  2951. }
  2952. }
  2953. this.GetMainData=function()
  2954. {
  2955. switch(this.ClassName)
  2956. {
  2957. case "MinuteChartContainer":
  2958. case "MinuteChartHScreenContainer":
  2959. return this.SourceData;
  2960. case "KLineChartContainer":
  2961. case "KLineChartHScreenContainer":
  2962. return this.ChartPaint[0].Data;
  2963. }
  2964. }
  2965. this.BindAllOverlayIndexData=function(hisData)
  2966. {
  2967. if (!this.Frame || !this.Frame.SubFrame) return;
  2968. //叠加指标
  2969. for(var i=0;i<this.Frame.SubFrame.length;++i)
  2970. {
  2971. var item=this.Frame.SubFrame[i];
  2972. for(var j=0; j<item.OverlayIndex.length; ++j)
  2973. {
  2974. var overlayItem=item.OverlayIndex[j];
  2975. this.BindOverlayIndexData(overlayItem,i,hisData)
  2976. }
  2977. }
  2978. }
  2979. //叠加指标
  2980. this.BindOverlayIndexData=function(overlayItem, windowIndex, hisData)
  2981. {
  2982. if (!overlayItem.Script) return;
  2983. if (typeof(overlayItem.Script.RequestData)=='function')
  2984. {
  2985. overlayItem.Script.RequestData(this,windowIndex,hisData);
  2986. return;
  2987. }
  2988. if (typeof(overlayItem.Script.ExecuteScript)=='function')
  2989. {
  2990. overlayItem.Script.ExecuteScript(this,windowIndex,hisData);
  2991. return;
  2992. }
  2993. overlayItem.Script.BindData(this,windowIndex,hisData);
  2994. }
  2995. this.GetOverlayIndexEvent=function()
  2996. {
  2997. return this.GetEventCallback(JSCHART_EVENT_ID.RECV_OVERLAY_INDEX_DATA);
  2998. }
  2999. //删除指定窗口的所有叠加指标
  3000. this.DeleteWindowsOverlayIndex=function(windowIndex)
  3001. {
  3002. if (!IFrameSplitOperator.IsNumber(windowIndex)) return;
  3003. if (windowIndex<0 || windowIndex>=this.Frame.SubFrame.length) return;
  3004. var subFrame=this.Frame.SubFrame[windowIndex];
  3005. if (!IFrameSplitOperator.IsNonEmptyArray(subFrame.OverlayIndex)) return;
  3006. var aryIndexID=[];
  3007. for(var i=0; i<subFrame.OverlayIndex.length; ++i)
  3008. {
  3009. var overlayItem=subFrame.OverlayIndex[i];
  3010. aryIndexID.push(overlayItem.Identify);
  3011. for(var j=0;j<overlayItem.ChartPaint.length;++j) //图形销毁事件
  3012. {
  3013. var overlayChart=overlayItem.ChartPaint[j];
  3014. if (overlayChart && overlayChart.OnDestroy) overlayChart.OnDestroy();
  3015. }
  3016. overlayItem.ChartPaint=[];
  3017. }
  3018. subFrame.OverlayIndex=[];
  3019. var titlePaint=this.TitlePaint[windowIndex+1];
  3020. for(var i=0;i<aryIndexID.length;++i)
  3021. {
  3022. var identify=aryIndexID[i];
  3023. if (titlePaint.OverlayIndex.has(identify))
  3024. titlePaint.OverlayIndex.delete(identify);
  3025. if (titlePaint.OverlayDynamicTitle.has(identify))
  3026. titlePaint.OverlayDynamicTitle.delete(identify);
  3027. }
  3028. }
  3029. //删除叠加指标, 没有重绘
  3030. this.DeleteOverlayIndex=function(identify, windowIndex)
  3031. {
  3032. var findIndex=null;
  3033. if (IFrameSplitOperator.IsNumber(windowIndex))
  3034. {
  3035. if (windowIndex>=0 && windowIndex<this.Frame.SubFrame.length)
  3036. {
  3037. var item=this.Frame.SubFrame[windowIndex];
  3038. for(var j=0; j<item.OverlayIndex.length; ++j)
  3039. {
  3040. var overlayItem=item.OverlayIndex[j];
  3041. if (overlayItem.Identify===identify)
  3042. {
  3043. for(var k=0;k<overlayItem.ChartPaint.length;++k) //图形销毁事件
  3044. {
  3045. var overlayChart=overlayItem.ChartPaint[k];
  3046. if (overlayChart && overlayChart.OnDestroy) overlayChart.OnDestroy();
  3047. }
  3048. item.OverlayIndex.splice(j, 1);
  3049. findIndex=windowIndex
  3050. break;
  3051. }
  3052. }
  3053. }
  3054. }
  3055. else
  3056. {
  3057. for(var i=0; i<this.Frame.SubFrame.length; ++i)
  3058. {
  3059. var item=this.Frame.SubFrame[i];
  3060. for(var j=0; j<item.OverlayIndex.length; ++j)
  3061. {
  3062. var overlayItem=item.OverlayIndex[j];
  3063. if (overlayItem.Identify===identify)
  3064. {
  3065. for(var k=0;k<overlayItem.ChartPaint.length;++k) //图形销毁事件
  3066. {
  3067. var overlayChart=overlayItem.ChartPaint[k];
  3068. if (overlayChart && overlayChart.OnDestroy) overlayChart.OnDestroy();
  3069. }
  3070. item.OverlayIndex.splice(j, 1);
  3071. findIndex=i;
  3072. break;
  3073. }
  3074. }
  3075. }
  3076. }
  3077. if (findIndex==null)
  3078. {
  3079. console.warn(`[JSChartContainer::DeleteOverlayIndex] can't find overlay index. [identify=${identify}]`);
  3080. return false;
  3081. }
  3082. var windowsIndex=findIndex+1;
  3083. var titlePaint=this.TitlePaint[windowsIndex];
  3084. if (titlePaint.OverlayIndex.has(identify))
  3085. titlePaint.OverlayIndex.delete(identify);
  3086. if (titlePaint.OverlayDynamicTitle.has(identify))
  3087. titlePaint.OverlayDynamicTitle.delete(identify);
  3088. return true;
  3089. }
  3090. //获取扩展画法
  3091. this.GetExtendChartByClassName=function(name)
  3092. {
  3093. for(var i=0; i<this.ExtendChartPaint.length; ++i)
  3094. {
  3095. var item=this.ExtendChartPaint[i];
  3096. if (item.ClassName==name) return { Index:i, Chart:item };
  3097. }
  3098. return null
  3099. }
  3100. //获取多个扩展画法
  3101. this.GetExtendChartByClassNameV2=function(name)
  3102. {
  3103. var aryChart=[];
  3104. for(var i=0; i<this.ExtendChartPaint.length; ++i)
  3105. {
  3106. var item=this.ExtendChartPaint[i];
  3107. if (item.ClassName==name)
  3108. {
  3109. aryChart.push({ Index:i, Chart:item });
  3110. }
  3111. }
  3112. if (aryChart.length<=0) return null;
  3113. return aryChart;
  3114. }
  3115. //画图工具
  3116. //把X, Y绝对位置转成的相对位置的点
  3117. this.PointAbsoluteToRelative=function(x, y)
  3118. {
  3119. var pt={ X:x, Y:y };
  3120. //var uiRect=this.getBoundingClientRect(); //dom返回的是没有放大倍数的值
  3121. //pt.X=x-uiRect.left; //手机端 dom返回的是没有放大倍数的值
  3122. //pt.Y=y-uiRect.top;
  3123. return pt;
  3124. }
  3125. //获取当前的点对应的 画图工具的图形
  3126. //data.X data.Y 鼠标位置 返回 data.ChartDrawPicture 数据在画图工具 data.PointIndex 在画图工具对应点索引
  3127. this.GetChartDrawPictureByPoint=function(data)
  3128. {
  3129. var x=data.X*data.PixelRatio;
  3130. var y=data.Y*data.PixelRatio;
  3131. for(var i=0;i<this.ChartDrawPicture.length; ++i)
  3132. {
  3133. var item =this.ChartDrawPicture[i];
  3134. var pointIndex=item.IsPointIn(x, y, this.ChartDrawOption);
  3135. if (pointIndex===false) continue;
  3136. if (pointIndex>=0)
  3137. {
  3138. data.ChartDrawPicture=item;
  3139. data.PointIndex=pointIndex;
  3140. return true;
  3141. }
  3142. }
  3143. return false;
  3144. }
  3145. this.SetChartDrawPictureFirstPoint = function (x, y)
  3146. {
  3147. var drawPicture = this.CurrentChartDrawPicture;
  3148. if (!drawPicture) return false;
  3149. if (!this.Frame.SubFrame || this.Frame.SubFrame.length <= 0) return false;
  3150. for (var i=0; i<this.Frame.SubFrame.length; ++i)
  3151. {
  3152. var frame = this.Frame.SubFrame[i].Frame;
  3153. var left = frame.ChartBorder.GetLeft();
  3154. var right=frame.ChartBorder.GetRight();
  3155. var top = frame.ChartBorder.GetTopEx();
  3156. var bottom=frame.ChartBorder.GetBottomEx();
  3157. var height = bottom-top;
  3158. var width = frame.ChartBorder.GetWidth();
  3159. if (x>=left && x<=right && y>=top && y<=bottom)
  3160. {
  3161. drawPicture.Frame = frame;
  3162. break;
  3163. }
  3164. }
  3165. if (!drawPicture.Frame) return false;
  3166. drawPicture.Point[0] = new Point();
  3167. drawPicture.Point[0].X = x ;
  3168. drawPicture.Point[0].Y = y;
  3169. drawPicture.Status = 1; //第1个点完成
  3170. return true;
  3171. }
  3172. this.SetChartDrawPictureSecondPoint = function (x, y)
  3173. {
  3174. var drawPicture = this.CurrentChartDrawPicture;
  3175. if (!drawPicture) return false;
  3176. drawPicture.Point[1] = new Point();
  3177. drawPicture.Point[1].X = x;
  3178. drawPicture.Point[1].Y = y;
  3179. drawPicture.Status = 2; //设置第2个点
  3180. return true;
  3181. }
  3182. //xStep,yStep 移动的偏移量
  3183. this.MoveChartDrawPicture = function (xStep, yStep)
  3184. {
  3185. var drawPicture = this.CurrentChartDrawPicture;
  3186. if (!drawPicture) return false;
  3187. //JSConsole.Chart.Log("xStep="+xStep+" yStep="+yStep);
  3188. drawPicture.Move(xStep, yStep);
  3189. return true;
  3190. }
  3191. this.FinishChartDrawPicturePoint = function ()
  3192. {
  3193. var drawPicture = this.CurrentChartDrawPicture;
  3194. if (!drawPicture) return false;
  3195. if (drawPicture.PointCount != drawPicture.Point.length) return false;
  3196. drawPicture.Status = 10; //完成
  3197. drawPicture.PointToValue();
  3198. this.ChartDrawPicture.push(drawPicture);
  3199. this.CurrentChartDrawPicture = null;
  3200. //通知上层画好了
  3201. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FINISH_DRAWPICTURE); //完成画图工具事件
  3202. if (event && event.Callback)
  3203. {
  3204. let sendData={ DrawPicture: drawPicture };
  3205. event.Callback(event,sendData,this);
  3206. }
  3207. //单个回调
  3208. if (drawPicture.FinishedCallback) drawPicture.FinishedCallback(drawPicture);
  3209. if (drawPicture.OnFinish) drawPicture.OnFinish();
  3210. return true;
  3211. }
  3212. this.FinishMoveChartDrawPicture = function ()
  3213. {
  3214. var drawPicture = this.CurrentChartDrawPicture;
  3215. if (!drawPicture) return false;
  3216. if (drawPicture.PointCount != drawPicture.Point.length) return false;
  3217. drawPicture.Status = 10; //完成
  3218. drawPicture.PointToValue();
  3219. this.CurrentChartDrawPicture = null;
  3220. return true;
  3221. }
  3222. //清空所有的画线工具
  3223. this.ClearChartDrawPicture = function (drawPicture)
  3224. {
  3225. if (!drawPicture)
  3226. {
  3227. this.ChartDrawPicture = [];
  3228. this.Draw();
  3229. }
  3230. else
  3231. {
  3232. for (var i=0;i<this.ChartDrawPicture.length;++i)
  3233. {
  3234. if (this.ChartDrawPicture[i] == drawPicture)
  3235. {
  3236. this.ChartDrawPicture.splice(i, 1);
  3237. this.Draw();
  3238. }
  3239. }
  3240. }
  3241. }
  3242. //获取画图工具当前选中图形的Guid
  3243. this.GetActiveDrawPicture=function()
  3244. {
  3245. var result={ Move: { Guid:null }, Select:{ Guid:null }, MoveOn: {Guid:null} };
  3246. if (this.CurrentChartDrawPicture)
  3247. result.Move={ Guid: this.CurrentChartDrawPicture.Guid };
  3248. if (this.SelectChartDrawPicture)
  3249. result.Select={ Guid:this.SelectChartDrawPicture.Guid, Chart:this.SelectChartDrawPicture };
  3250. if (this.MoveOnChartDrawPicture)
  3251. result.MoveOn={ Guid:this.MoveOnChartDrawPicture.Guid };
  3252. return result;
  3253. }
  3254. //获取当天的显示的指标
  3255. this.GetIndexInfo = function ()
  3256. {
  3257. var aryIndex = [];
  3258. for(var i=0, j=0; i<this.WindowIndex.length; ++i)
  3259. {
  3260. var item = this.WindowIndex[i];
  3261. if (!item) continue;
  3262. var info = { Name: item.Name, WindowIndex:i, IsOverlay:false };
  3263. if (item.ID) info.ID = item.ID;
  3264. if (IFrameSplitOperator.IsNonEmptyArray(item.Arguments)) //参数
  3265. {
  3266. info.Args=[];
  3267. for(j=0;j<item.Arguments.length;++j)
  3268. {
  3269. var argItem=item.Arguments[j];
  3270. info.Args.push( { Name:argItem.Name, Value:argItem.Value} );
  3271. }
  3272. }
  3273. aryIndex.push(info);
  3274. }
  3275. this.GetOverlayIndexInfo(aryIndex); //叠加指标
  3276. return aryIndex;
  3277. }
  3278. //获取叠加指标
  3279. this.GetOverlayIndexInfo=function(aryIndex)
  3280. {
  3281. for(var i=0, j=0, k=0; i<this.Frame.SubFrame.length; ++i)
  3282. {
  3283. var item=this.Frame.SubFrame[i];
  3284. if (!IFrameSplitOperator.IsNonEmptyArray(item.OverlayIndex)) continue;
  3285. for(j=0; j<item.OverlayIndex.length; ++j)
  3286. {
  3287. var overlayItem=item.OverlayIndex[j];
  3288. if (!overlayItem.Script) continue;
  3289. var indexData=overlayItem.Script;
  3290. var info={ Name:indexData.Name, ID:indexData.ID, WindowIndex:i, IsOverlay:true, Identify:overlayItem.Identify };
  3291. if (IFrameSplitOperator.IsNonEmptyArray(indexData.Arguments)) //参数
  3292. {
  3293. info.Args=[];
  3294. for(k=0;k<indexData.Arguments.length;++k)
  3295. {
  3296. var argItem=indexData.Arguments[k];
  3297. info.Args.push( { Name:argItem.Name, Value:argItem.Value} );
  3298. }
  3299. }
  3300. aryIndex.push(info);
  3301. }
  3302. }
  3303. }
  3304. //删除扩展画法
  3305. this.DeleteExtendChartByID=function(id)
  3306. {
  3307. for(var i=0;i<this.ExtendChartPaint.length;++i)
  3308. {
  3309. var item=this.ExtendChartPaint[i];
  3310. if (item.ID==id)
  3311. {
  3312. this.ExtendChartPaint.splice(i, 1);
  3313. return true;
  3314. }
  3315. }
  3316. return false;
  3317. }
  3318. //切换窗口指标 option={ Window:{}, OverlayIndex:[], Frame:{ }, Delete:{Window:true/false, Overlay:true/false }}
  3319. this.ChangeIndexWindow=function(windowIndex, option)
  3320. {
  3321. JSConsole.Chart.Log('[KLineChartContainer::ChangeIndexWindow] windowIndex, option', windowIndex, option);
  3322. if (windowIndex<0 || windowIndex>=this.Frame.SubFrame.length) return false;
  3323. if (!option) return false;
  3324. var frame=this.Frame.SubFrame[windowIndex];
  3325. if (option.Delete)
  3326. {
  3327. var item=option.Delete;
  3328. if (item.Window===true) this.DeleteIndexPaint(windowIndex); //删除主指标
  3329. if (item.Overlay===true) this.DeleteWindowsOverlayIndex(windowIndex); //清空叠加指标
  3330. }
  3331. //清空标题栏
  3332. var titleIndex=windowIndex+1;
  3333. this.TitlePaint[titleIndex].Data=[];
  3334. this.TitlePaint[titleIndex].Title=null;
  3335. if (option.Window) //主指标
  3336. {
  3337. this.DeleteIndexPaint(windowIndex); //删除主指标
  3338. var item=option.Window;
  3339. if (item.Script) //自定义指标脚本
  3340. {
  3341. this.WindowIndex[windowIndex]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行
  3342. }
  3343. else if (item.API) //后台指标
  3344. {
  3345. var apiItem=item.API;
  3346. this.WindowIndex[windowIndex]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item);
  3347. }
  3348. else
  3349. {
  3350. var indexID=item.Index;
  3351. var indexItem=JSIndexMap.Get(indexID);
  3352. if (indexItem)
  3353. {
  3354. this.WindowIndex[windowIndex]=indexItem.Create();
  3355. this.CreateWindowIndex(windowIndex);
  3356. }
  3357. else
  3358. {
  3359. var systemScript = new JSIndexScript();
  3360. var indexInfo = systemScript.Get(indexID);
  3361. if (indexInfo)
  3362. {
  3363. JSIndexScript.ModifyAttribute(indexInfo,item);
  3364. this.WindowIndex[windowIndex]=new ScriptIndex(indexInfo.Name,indexInfo.Script,indexInfo.Args,indexInfo); //脚本执行
  3365. }
  3366. }
  3367. }
  3368. this.SetSubFrameAttribute(frame, item, option.Frame);
  3369. }
  3370. //叠加指标
  3371. var aryOverlayIndex=[];
  3372. if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
  3373. {
  3374. this.DeleteWindowsOverlayIndex(windowIndex); //清空叠加指标
  3375. for(var i=0;i<option.OverlayIndex.length;++i)
  3376. {
  3377. var item=option.OverlayIndex[i];
  3378. if (item.Index) item.IndexName=item.Index;
  3379. item.WindowIndex=windowIndex;
  3380. if (item.Windows>=0) item.WindowIndex=item.Windows;
  3381. var overlay=this.CreateOverlayWindowsIndex(item);
  3382. if (!overlay) continue;
  3383. aryOverlayIndex.push({ WindowsIndex:item.WindowIndex, Overlay:overlay });
  3384. }
  3385. }
  3386. //刷新指标
  3387. var bindData=this.ChartPaint[0].Data;
  3388. this.BindIndexData(windowIndex,bindData); //请求主指标
  3389. for(var i=0;i<aryOverlayIndex.length;++i) //请求叠加指标
  3390. {
  3391. var item=aryOverlayIndex[i];
  3392. this.BindOverlayIndexData(item.Overlay,item.WindowsIndex,bindData);
  3393. }
  3394. this.UpdataDataoffset(); //更新数据偏移
  3395. this.ResetFrameXYSplit();
  3396. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  3397. this.Draw();
  3398. }
  3399. this.ResetOverlaySymbolStatus=function()
  3400. {
  3401. for(var i=0;i<this.OverlayChartPaint.length; ++i)
  3402. {
  3403. var item=this.OverlayChartPaint[i];
  3404. item.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID;
  3405. }
  3406. }
  3407. }
  3408. function ToFixed(number, precision)
  3409. {
  3410. var b = 1;
  3411. if (isNaN(number)) return number;
  3412. if (number < 0) b = -1;
  3413. var multiplier = Math.pow(10, precision);
  3414. var value = Math.round(Math.abs(number) * multiplier) / multiplier * b;
  3415. if (/^(\d+(?:\.\d+)?)(e)([\-]?\d+)$/.test(value))
  3416. var s = value.toFixed2(precision);
  3417. else
  3418. var s = value.toString();
  3419. var rs = s.indexOf('.');
  3420. if (rs < 0 && precision > 0)
  3421. {
  3422. rs = s.length;
  3423. s += '.';
  3424. }
  3425. while (s.length <= rs + precision)
  3426. {
  3427. s += '0';
  3428. }
  3429. return s;
  3430. }
  3431. Number.prototype.toFixed2 = Number.prototype.toFixed; //备份下老的
  3432. Number.prototype.toFixed = function (precision) {
  3433. return ToFixed(this, precision)
  3434. }
  3435. function Guid()
  3436. {
  3437. function S4()
  3438. {
  3439. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  3440. }
  3441. return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  3442. }
  3443. //修正线段有毛刺
  3444. function ToFixedPoint(value) {
  3445. //return value;
  3446. return parseInt(value) + 0.5;
  3447. }
  3448. function ToFixedRect(value) {
  3449. //return value;
  3450. // With a bitwise or.
  3451. //rounded = (0.5 + somenum) | 0;
  3452. // A double bitwise not.
  3453. //rounded = ~~ (0.5 + somenum);
  3454. // Finally, a left bitwise shift.
  3455. var rounded;
  3456. return rounded = (0.5 + value) << 0;
  3457. }
  3458. function Point() {
  3459. this.X;
  3460. this.Y;
  3461. }
  3462. function SelectRectData() {
  3463. this.Data; //主数据
  3464. this.JSChartContainer; //行情控件
  3465. this.Start; //数据起始位子
  3466. this.End; //数据结束位置
  3467. this.XStart;//X坐标起始位置
  3468. this.XEnd; //X位置结束为止
  3469. }
  3470. //边框信息
  3471. function ChartBorder()
  3472. {
  3473. this.UIElement;
  3474. //四周间距
  3475. this.Left = 50;
  3476. this.Right = 80;
  3477. this.Top = 50;
  3478. this.Bottom = 50;
  3479. this.TitleHeight = 15; //标题高度
  3480. //上下间距
  3481. this.TopSpace = 0;
  3482. this.BottomSpace = 0;
  3483. this.LeftExtendWidth=0; //左边扩展图形宽度
  3484. this.RightExtendWidth=0;
  3485. this.GetBorder=function()
  3486. {
  3487. var data=
  3488. {
  3489. Left:this.Left,
  3490. LeftEx:this.Left+this.LeftExtendWidth,
  3491. Right:this.UIElement.Width-this.Right,
  3492. RightEx:this.UIElement.Width-this.Right-this.RightExtendWidth,
  3493. Top:this.Top,
  3494. TopEx:this.Top+this.TitleHeight+this.TopSpace,
  3495. TopTitle:this.Top+this.TitleHeight,
  3496. Bottom:this.UIElement.Height-this.Bottom,
  3497. BottomEx:this.UIElement.Height-this.Bottom-this.BottomSpace,
  3498. ChartWidth:this.UIElement.Width,
  3499. ChartHeight:this.UIElement.Height
  3500. };
  3501. return data;
  3502. }
  3503. this.GetHScreenBorder=function()
  3504. {
  3505. var data=
  3506. {
  3507. Left:this.Left,
  3508. LeftEx:this.Left+this.BottomSpace,
  3509. Right:this.UIElement.Width-this.Right,
  3510. RightEx:this.UIElement.Width-this.Right-this.TitleHeight- this.TopSpace,
  3511. RightTitle:this.UIElement.Width-this.Right-this.TitleHeight,
  3512. Top:this.Top,
  3513. TopEx:this.Top+this.LeftExtendWidth,
  3514. Bottom:this.UIElement.Height-this.Bottom,
  3515. BottomEx:this.UIElement.Height-this.Bottom-this.RightExtendWidth,
  3516. ChartWidth:this.UIElement.Width,
  3517. ChartHeight:this.UIElement.Height
  3518. };
  3519. return data;
  3520. }
  3521. this.GetChartWidth = function () {
  3522. return this.UIElement.Width;
  3523. }
  3524. this.GetChartHeight = function () {
  3525. return this.UIElement.Height;
  3526. }
  3527. this.GetLeft = function () {
  3528. return this.Left;
  3529. }
  3530. this.GetRight = function () {
  3531. return this.UIElement.Width - this.Right;
  3532. }
  3533. this.GetTop = function () {
  3534. return this.Top;
  3535. }
  3536. this.GetTopEx = function () //去掉标题,上面间距
  3537. {
  3538. return this.Top + this.TitleHeight + this.TopSpace;
  3539. }
  3540. this.GetTopTitle = function () //去掉标题
  3541. {
  3542. return this.Top + this.TitleHeight;
  3543. }
  3544. this.GetBottom = function () {
  3545. return this.UIElement.Height - this.Bottom;
  3546. }
  3547. this.GetBottomEx = function () {
  3548. return this.UIElement.Height - this.Bottom - this.BottomSpace;
  3549. }
  3550. this.GetWidth = function () {
  3551. return this.UIElement.Width - this.Left - this.Right;
  3552. }
  3553. this.GetHeight = function () {
  3554. return this.UIElement.Height - this.Top - this.Bottom;
  3555. }
  3556. this.GetHeightEx = function () //去掉标题的高度 上下间距
  3557. {
  3558. return this.UIElement.Height - this.Top - this.Bottom - this.TitleHeight - this.TopSpace - this.BottomSpace;
  3559. }
  3560. this.GetRightEx = function () //横屏去掉标题高度的 上面间距
  3561. {
  3562. return this.UIElement.Width - this.Right - this.TitleHeight - this.TopSpace;
  3563. }
  3564. this.GetWidthEx = function () //横屏去掉标题宽度 上下间距
  3565. {
  3566. return this.UIElement.Width - this.Left - this.Right - this.TitleHeight - this.TopSpace - this.BottomSpace;
  3567. }
  3568. this.GetLeftEx = function () //横屏
  3569. {
  3570. return this.Left + this.BottomSpace;
  3571. }
  3572. this.GetRightTitle = function ()//横屏
  3573. {
  3574. return this.UIElement.Width - this.Right - this.TitleHeight;
  3575. }
  3576. this.GetTitleHeight = function () {
  3577. return this.TitleHeight;
  3578. }
  3579. }
  3580. function SubFrameItem()
  3581. {
  3582. this.Frame;
  3583. this.Height;
  3584. this.OverlayIndex=[]; //叠加指标
  3585. }
  3586. function OverlayIndexItem()
  3587. {
  3588. this.Frame;
  3589. this.ChartPaint=[];
  3590. this.Identify=Guid();
  3591. this.Scprit; //脚本
  3592. this.UpdateFrameMaxMin=function() //调整坐标最大 最小值
  3593. {
  3594. var value={ Max:null, Min:null }
  3595. if (this.Frame.IsShareY) //共享Y轴坐标
  3596. {
  3597. this.Frame.XYSplit=true;
  3598. return;
  3599. }
  3600. if (this.Frame.YSpecificMaxMin) //固定坐标
  3601. {
  3602. value.Max=this.Frame.YSpecificMaxMin.Max;
  3603. value.Min=this.Frame.YSpecificMaxMin.Min;
  3604. }
  3605. else
  3606. {
  3607. for(var i=0; i<this.ChartPaint.length; ++i)
  3608. {
  3609. var paint=this.ChartPaint[i];
  3610. var range=paint.GetMaxMin();
  3611. if (IFrameSplitOperator.IsNumber(range.Max))
  3612. {
  3613. if (value.Max==null || value.Max<range.Max) value.Max=range.Max;
  3614. }
  3615. if (IFrameSplitOperator.IsNumber(range.Min))
  3616. {
  3617. if (value.Min==null || value.Min>range.Min) value.Min=range.Min;
  3618. }
  3619. }
  3620. }
  3621. if (!IFrameSplitOperator.IsNumber(this.Frame.YMaxMin.Max) || this.Frame.YMaxMin.Max!=value.Max)
  3622. {
  3623. this.Frame.YMaxMin.Max=value.Max;
  3624. this.Frame.XYSplit=true;
  3625. }
  3626. if (!IFrameSplitOperator.IsNumber(this.Frame.YMaxMin.Min) || this.Frame.YMaxMin.Min!=value.Min)
  3627. {
  3628. this.Frame.YMaxMin.Min=value.Min;
  3629. this.Frame.XYSplit=true;
  3630. }
  3631. if (this.Frame.XYSplit)
  3632. {
  3633. var max=10, min=0;
  3634. if (value.Max!=null) max=value.Max;
  3635. if (value.Min!=null) min=value.Min;
  3636. this.Frame.HorizontalMax=max;
  3637. this.Frame.HorizontalMin=min;
  3638. }
  3639. else
  3640. {
  3641. this.Frame.XYSplit=true;
  3642. }
  3643. }
  3644. }
  3645. //行情框架
  3646. function HQTradeFrame()
  3647. {
  3648. this.ClassName='HQTradeFrame';
  3649. this.SubFrame = new Array(); //SubFrameItem 数组
  3650. this.SizeChange = true; //大小是否改变
  3651. this.ChartBorder;
  3652. this.Canvas; //画布
  3653. this.ScreenImagePath; //截图路径
  3654. this.ScreenImageData=null; //截图数据
  3655. this.Data; //主数据
  3656. this.Position; //画布的位置
  3657. this.SizeChange = true;
  3658. this.SnapshotID=0;
  3659. this.CurrentSnapshotID=0;
  3660. this.SnapshotStatus=0; //0空闲 1工作
  3661. this.AutoLeftBorder=null; //{ Blank:10 留白宽度, MinWidth:最小宽度 }
  3662. this.AutoRightBorder=null; //{ Blank:10 留白宽度, MinWidth:最小宽度 }
  3663. this.ZoomWindowsInfo=null; //附图指标缩放,备份信息
  3664. this.ZoomStartWindowIndex=1; //允许缩放窗口起始位置
  3665. this.CalculateChartBorder = function () //计算每个子框架的边框信息
  3666. {
  3667. if (this.SubFrame.length <= 0) return;
  3668. var top = this.ChartBorder.GetTop();
  3669. var height = this.ChartBorder.GetHeight();
  3670. var totalHeight = 0;
  3671. for (var i=0; i<this.SubFrame.length; ++i)
  3672. {
  3673. var item = this.SubFrame[i];
  3674. totalHeight += item.Height;
  3675. }
  3676. for (var i=0; i<this.SubFrame.length; ++i)
  3677. {
  3678. var item = this.SubFrame[i];
  3679. item.Frame.ChartBorder.Top = top;
  3680. item.Frame.ChartBorder.Left = this.ChartBorder.Left;
  3681. item.Frame.ChartBorder.Right = this.ChartBorder.Right;
  3682. var frameHeight = height * (item.Height / totalHeight) + top;
  3683. item.Frame.ChartBorder.Bottom = this.ChartBorder.GetChartHeight() - frameHeight;
  3684. top = frameHeight;
  3685. }
  3686. if (this.GetEventCallback)
  3687. {
  3688. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SIZE_FRAME);
  3689. if (event && event.Callback)
  3690. {
  3691. var sendData={ SubFrame:this.SubFrame };
  3692. event.Callback(event, sendData, this);
  3693. }
  3694. }
  3695. }
  3696. this.GetScaleTextWidth=function()
  3697. {
  3698. var width={ Left:null, Right:null };
  3699. for(var i=0; i<this.SubFrame.length; ++i)
  3700. {
  3701. var item=this.SubFrame[i];
  3702. if (item.Height<=0) continue;
  3703. var frame=item.Frame;
  3704. if (!frame) continue;
  3705. if (!frame.XSplitOperator) continue;
  3706. var maxValue=frame.HorizontalMax; //最大最小要还原
  3707. var minValue=frame.HorizontalMin;
  3708. frame.YSplitOperator.Operator();
  3709. var value=frame.GetScaleTextWidth();
  3710. frame.HorizontalMax=maxValue;
  3711. frame.HorizontalMin=minValue;
  3712. if (value && value.TextWidth)
  3713. {
  3714. var widthItem=value.TextWidth;
  3715. if (IFrameSplitOperator.IsNumber(widthItem.Left))
  3716. {
  3717. if (width.Left==null || width.Left<widthItem.Left) width.Left=widthItem.Left;
  3718. }
  3719. if (IFrameSplitOperator.IsNumber(widthItem.Right))
  3720. {
  3721. if (width.Right==null || width.Right<widthItem.Right) width.Right=widthItem.Right;
  3722. }
  3723. }
  3724. }
  3725. return width;
  3726. }
  3727. this.IsFrameXYSplit=function()
  3728. {
  3729. for(var i in this.SubFrame)
  3730. {
  3731. if (this.SubFrame[i].Frame.XYSplit) return true;
  3732. }
  3733. return false;
  3734. }
  3735. this.Draw = function (option)
  3736. {
  3737. if (this.SizeChange === true) this.CalculateChartBorder();
  3738. var isSplash=false; //是否过场动画
  3739. if (option && option.IsEnableSplash===true) isSplash=true;
  3740. if (isSplash==false && (this.AutoLeftBorder || this.AutoRightBorder) &&this.IsFrameXYSplit())
  3741. {
  3742. var textWidth=this.GetScaleTextWidth();
  3743. if (IFrameSplitOperator.IsNumber(textWidth.Left) && this.AutoLeftBorder)
  3744. {
  3745. var blank=0;
  3746. if (IFrameSplitOperator.IsNumber(this.AutoLeftBorder.Blank)) blank=this.AutoLeftBorder.Blank;
  3747. var value=textWidth.Left+blank;
  3748. if (IFrameSplitOperator.IsNumber(this.AutoLeftBorder.MinWidth))
  3749. {
  3750. if (this.AutoLeftBorder.MinWidth>value) value=this.AutoLeftBorder.MinWidth;
  3751. }
  3752. if (this.IsHScreen) this.ChartBorder.Top=value;
  3753. else this.ChartBorder.Left=value;
  3754. for(var i=0; i<this.SubFrame.length; ++i)
  3755. {
  3756. var item=this.SubFrame[i];
  3757. if (this.IsHScreen) item.Frame.ChartBorder.Top=value;
  3758. else item.Frame.ChartBorder.Left=value;
  3759. }
  3760. }
  3761. if (IFrameSplitOperator.IsNumber(textWidth.Right) && this.AutoRightBorder)
  3762. {
  3763. var blank=0;
  3764. if (IFrameSplitOperator.IsNumber(this.AutoRightBorder.Blank)) blank=this.AutoRightBorder.Blank;
  3765. var value=textWidth.Right+blank;
  3766. if (IFrameSplitOperator.IsNumber(this.AutoRightBorder.MinWidth))
  3767. {
  3768. if (this.AutoRightBorder.MinWidth>value) value=this.AutoRightBorder.MinWidth;
  3769. }
  3770. if (this.IsHScreen) this.ChartBorder.Bottom=value;
  3771. else this.ChartBorder.Right=value;
  3772. for(var i=0; i<this.SubFrame.length; ++i)
  3773. {
  3774. var item=this.SubFrame[i];
  3775. if (this.IsHScreen) item.Frame.ChartBorder.Bottom=value;
  3776. else item.Frame.ChartBorder.Right=value;
  3777. }
  3778. }
  3779. }
  3780. for (var i=0; i<this.SubFrame.length; ++i)
  3781. {
  3782. var item = this.SubFrame[i];
  3783. if (item.Height <= 0) continue;
  3784. item.Frame.Draw();
  3785. for(var j=0; j<item.OverlayIndex.length; ++j)
  3786. {
  3787. var overlayItem=item.OverlayIndex[j];
  3788. //把主坐标部分设置给子坐标下来
  3789. overlayItem.Frame.DataWidth=item.Frame.DataWidth;
  3790. overlayItem.Frame.DistanceWidth=item.Frame.DistanceWidth;
  3791. overlayItem.Frame.XPointCount=item.Frame.XPointCount;
  3792. if (overlayItem.ChartPaint.length>0 && overlayItem.Frame)
  3793. {
  3794. overlayItem.Frame.Draw();
  3795. }
  3796. }
  3797. }
  3798. this.SizeChange = false;
  3799. }
  3800. this.DrawOveraly=function(bDrawFirst)
  3801. {
  3802. for(var i=0; i<this.SubFrame.length; ++i)
  3803. {
  3804. var item=this.SubFrame[i];
  3805. if (item.Height<=0) continue; //高度是0 不画
  3806. for(var j=0;j<item.OverlayIndex.length; ++j)
  3807. {
  3808. var overlayItem=item.OverlayIndex[j];
  3809. for(var k=0; k<overlayItem.ChartPaint.length; ++k)
  3810. {
  3811. var chartItem=overlayItem.ChartPaint[k];
  3812. if (chartItem.IsShow)
  3813. {
  3814. if (bDrawFirst)
  3815. {
  3816. if (chartItem.IsDrawFirst) chartItem.Draw();
  3817. }
  3818. else
  3819. {
  3820. if (!chartItem.IsDrawFirst) chartItem.Draw();
  3821. }
  3822. }
  3823. }
  3824. }
  3825. }
  3826. }
  3827. this.DrawLock = function ()
  3828. {
  3829. for (var i in this.SubFrame)
  3830. {
  3831. var item = this.SubFrame[i];
  3832. item.Frame.DrawLock();
  3833. }
  3834. }
  3835. this.DrawLogo=function()
  3836. {
  3837. for(var i=0;i<this.SubFrame.length;++i)
  3838. {
  3839. var item=this.SubFrame[i];
  3840. if (item.Frame.DrawLogo)
  3841. {
  3842. item.Frame.DrawLogo();
  3843. break;
  3844. }
  3845. }
  3846. }
  3847. this.DrawInsideHorizontal = function ()
  3848. {
  3849. for (var i=0; i<this.SubFrame.length; ++i)
  3850. {
  3851. var item = this.SubFrame[i];
  3852. if (item.Height <= 0) continue;
  3853. item.Frame.DrawInsideHorizontal();
  3854. }
  3855. }
  3856. this.DrawCustomHorizontal = function () //定制Y坐标
  3857. {
  3858. for (var i=0; i<this.SubFrame.length; ++i)
  3859. {
  3860. var item = this.SubFrame[i];
  3861. if (item.Frame.DrawCustomHorizontal) item.Frame.DrawCustomHorizontal();
  3862. }
  3863. }
  3864. this.DrawCustomVertical = function (event) //定制X坐标
  3865. {
  3866. for (var i in this.SubFrame)
  3867. {
  3868. var item = this.SubFrame[i];
  3869. item.Frame.DrawCustomVerticalEvent = event;
  3870. if (item.Frame.DrawCustomVertical) item.Frame.DrawCustomVertical();
  3871. }
  3872. }
  3873. this.SetSizeChage = function (sizeChange)
  3874. {
  3875. this.SizeChange = sizeChange;
  3876. for (var i in this.SubFrame)
  3877. {
  3878. var item = this.SubFrame[i];
  3879. item.Frame.SizeChange = sizeChange;
  3880. }
  3881. //画布的位置
  3882. this.Position =
  3883. {
  3884. X: this.ChartBorder.UIElement.offsetLeft,
  3885. Y: this.ChartBorder.UIElement.offsetTop,
  3886. W: this.ChartBorder.UIElement.clientWidth,
  3887. H: this.ChartBorder.UIElement.clientHeight
  3888. };
  3889. }
  3890. this.SetDrawOtherChart = function (callback) //在画完框架以后调用的扩展画法
  3891. {
  3892. for (var i in this.SubFrame)
  3893. {
  3894. var item = this.SubFrame[i];
  3895. item.Frame.DrawOtherChart = callback;
  3896. }
  3897. }
  3898. this.Snapshot=function(type)
  3899. {
  3900. if (type == 1) this.SnapshotImageData();
  3901. else this.SnapshotImagePath();
  3902. }
  3903. //图形快照
  3904. this.SnapshotImagePath = function ()
  3905. {
  3906. var self = this;
  3907. var width = this.ChartBorder.GetChartWidth();
  3908. var height = this.ChartBorder.GetChartHeight();
  3909. //JSConsole.Chart.Log('[HQTradeFrame::SnapshotImageData][ID=' + this.ChartBorder.UIElement.ID + '] invoke canvasToTempFilePath' + '(width=' + width + ',height=' + height + ')' + ' SnapshotStatus='+ this.SnapshotStatus);
  3910. //if (this.SnapshotStatus==1) return;
  3911. ++this.SnapshotID;
  3912. var id = this.SnapshotID;
  3913. this.SnapshotStatus=1;
  3914. if (this.Canvas && this.Canvas.DomNode) //新版2D画布
  3915. {
  3916. wx.canvasToTempFilePath({
  3917. x: 0,
  3918. y: 0,
  3919. width: width,
  3920. height: height,
  3921. canvas: this.Canvas.DomNode,
  3922. success: function (res) {
  3923. self.ScreenImagePath = res.tempFilePath;
  3924. self.SnapshotStatus = 0;
  3925. self.CurrentSnapshotID = id;
  3926. JSConsole.Chart.Log(`[HQTradeFrame::SnapshotImagePath] SnapshotID(${self.SnapshotID}, ${self.CurrentSnapshotID}), Path=${res.tempFilePath}`);
  3927. }
  3928. })
  3929. }
  3930. else
  3931. {
  3932. wx.canvasToTempFilePath({
  3933. x: 0,
  3934. y: 0,
  3935. width: width,
  3936. height: height,
  3937. canvasId: this.ChartBorder.UIElement.ID,
  3938. success: function (res) {
  3939. self.ScreenImagePath = res.tempFilePath;
  3940. self.SnapshotStatus = 0;
  3941. self.CurrentSnapshotID = id;
  3942. //JSConsole.Chart.Log('[HQTradeFrame::SnapshotImagePath] SnapshotID(' + self.SnapshotID + ',' + self.CurrentSnapshotID + ') Path ='+ res.tempFilePath);
  3943. }
  3944. })
  3945. }
  3946. }
  3947. this.SnapshotImageData=function()
  3948. {
  3949. var self = this;
  3950. var width = this.ChartBorder.GetChartWidth();
  3951. var height = this.ChartBorder.GetChartHeight();
  3952. JSConsole.Chart.Log(`[HQTradeFrame::SnapshotImageData][ID=${this.ChartBorder.UIElement.ID} invoke canvasGetImageData(${width}, ${height}) SnapshotStatus=${this.SnapshotStatus}`);
  3953. ++this.SnapshotID;
  3954. var id = this.SnapshotID;
  3955. this.SnapshotStatus = 1;
  3956. wx.canvasGetImageData({
  3957. canvasId: this.ChartBorder.UIElement.ID,
  3958. x: 0,
  3959. y: 0,
  3960. width: width,
  3961. height: height,
  3962. success(res)
  3963. {
  3964. self.ScreenImageData = res.data;
  3965. self.SnapshotStatus = 0;
  3966. self.CurrentSnapshotID = id;
  3967. JSConsole.Chart.Log(`[HQTradeFrame::SnapshotImageData] SnapshotID=${self.SnapshotID}, CurrentSnapshotID=${self.CurrentSnapshotID}, size=${res.data.length}`);
  3968. }
  3969. })
  3970. }
  3971. this.GetXData = function (x) { return this.SubFrame[0].Frame.GetXData(x); }
  3972. this.GetYData = function (y, outObject) //outObject 可以保存返回的额外数据)
  3973. {
  3974. var frame;
  3975. for (var i=0; i<this.SubFrame.length; ++i)
  3976. {
  3977. var item = this.SubFrame[i];
  3978. var left = item.Frame.ChartBorder.GetLeft();
  3979. var top = item.Frame.ChartBorder.GetTopEx();
  3980. var width = item.Frame.ChartBorder.GetWidth();
  3981. var height = item.Frame.ChartBorder.GetHeightEx();
  3982. var rtItem = new Rect(left, top, width, height);
  3983. if (rtItem.IsPointIn(left, y))
  3984. {
  3985. frame = item.Frame;
  3986. if (outObject) outObject.FrameID = i;
  3987. break;
  3988. }
  3989. }
  3990. if (frame != null)
  3991. {
  3992. var yValue=frame.GetYData(y);
  3993. if (frame.YSplitOperator.CoordinateType == 1) //百分比坐标 右边显示百分比信息
  3994. {
  3995. var firstOpenPrice = frame.YSplitOperator.GetFirstOpenPrice();
  3996. outObject.RightYValue = ((yValue - firstOpenPrice) / firstOpenPrice * 100).toFixed(2) + '%';
  3997. }
  3998. if (frame.GetMainOverlayFrame)
  3999. {
  4000. var aryOverlayFrame=frame.GetMainOverlayFrame();
  4001. if (aryOverlayFrame)
  4002. {
  4003. if (aryOverlayFrame[0]) //左侧
  4004. {
  4005. var leftFrame=aryOverlayFrame[0];
  4006. var value=leftFrame.GetYData(y);
  4007. outObject.RightYValue=yValue;
  4008. yValue=value;
  4009. }
  4010. if (aryOverlayFrame[1]) //右侧
  4011. {
  4012. var rightFrame=aryOverlayFrame[1];
  4013. var value=rightFrame.GetYData(y);
  4014. outObject.RightYValue=value;
  4015. }
  4016. }
  4017. }
  4018. return yValue;
  4019. }
  4020. }
  4021. this.GetXFromIndex = function (index) { return this.SubFrame[0].Frame.GetXFromIndex(index); }
  4022. this.GetYFromData = function (value) { return this.SubFrame[0].Frame.GetYFromData(value); }
  4023. this.PtInFrame=function(x,y) //鼠标哪个指标窗口
  4024. {
  4025. for(var i=0; i<this.SubFrame.length; ++i)
  4026. {
  4027. var item=this.SubFrame[i];
  4028. var left=item.Frame.ChartBorder.GetLeft();
  4029. var top=item.Frame.ChartBorder.GetTop();
  4030. var width=item.Frame.ChartBorder.GetWidth();
  4031. var height=item.Frame.ChartBorder.GetHeight();
  4032. var rtClient = new Rect(left, top, width, height);
  4033. var isInClient = rtClient.IsPointIn(x, y);
  4034. if (isInClient)
  4035. {
  4036. return i; //转成整形
  4037. }
  4038. }
  4039. return -1;
  4040. }
  4041. this.SetDayCount=function(dayCount)
  4042. {
  4043. for(var i=0;i<this.SubFrame.length;++i)
  4044. {
  4045. var item=this.SubFrame[i];
  4046. if (!item.Frame) continue;
  4047. item.Frame.DayCount=dayCount;
  4048. }
  4049. }
  4050. this.ZoomUp = function (cursorIndex)
  4051. {
  4052. var result = this.SubFrame[0].Frame.ZoomUp(cursorIndex);
  4053. this.UpdateAllFrame();
  4054. return result;
  4055. }
  4056. this.ZoomDown = function (cursorIndex)
  4057. {
  4058. var result = this.SubFrame[0].Frame.ZoomDown(cursorIndex);
  4059. this.UpdateAllFrame();
  4060. return result;
  4061. }
  4062. this.SetXShowCount=function(showCount)
  4063. {
  4064. var result=this.SubFrame[0].Frame.SetXShowCount(showCount);
  4065. this.UpdateAllFrame();
  4066. return result;
  4067. }
  4068. this.GetXShowCount=function()
  4069. {
  4070. var xPointcount=-1;
  4071. if (!IFrameSplitOperator.IsNonEmptyArray(this.SubFrame)) return xPointcount;
  4072. var subFrame=this.SubFrame[0];
  4073. if (!subFrame.Frame) return xPointcount;
  4074. xPointcount=subFrame.Frame.XPointCount;
  4075. return xPointcount;
  4076. }
  4077. this.SetDataWidth=function(dataWidth)
  4078. {
  4079. var obj=this.SubFrame[0].Frame.SetDataWidth(dataWidth);
  4080. this.UpdateAllFrame();
  4081. return obj;
  4082. }
  4083. this.OnSize=function()
  4084. {
  4085. var obj={};
  4086. this.SubFrame[0].Frame.OnSize(obj);
  4087. this.UpdateAllFrame();
  4088. return obj;
  4089. }
  4090. this.UpdateAllFrame=function()
  4091. {
  4092. var mainFrame=this.SubFrame[0].Frame;
  4093. for (var i = 1; i < this.SubFrame.length; ++i)
  4094. {
  4095. var item=this.SubFrame[i];
  4096. item.Frame.XPointCount = mainFrame.XPointCount;
  4097. item.Frame.ZoomIndex = mainFrame.ZoomIndex;
  4098. item.Frame.DataWidth = mainFrame.DataWidth;
  4099. item.Frame.DistanceWidth = mainFrame.DistanceWidth;
  4100. item.Frame.LastCalculateStatus.Width=mainFrame.LastCalculateStatus.Width;
  4101. item.Frame.LastCalculateStatus.XPointCount=mainFrame.LastCalculateStatus.XPointCount;
  4102. }
  4103. }
  4104. //设置重新计算刻度坐标
  4105. this.ResetXYSplit = function ()
  4106. {
  4107. for (let i in this.SubFrame)
  4108. {
  4109. this.SubFrame[i].Frame.XYSplit = true;
  4110. }
  4111. }
  4112. //清空Y轴坐标的最大最小值
  4113. this.ClearYCoordinateMaxMin=function(windowIndex)
  4114. {
  4115. if (IFrameSplitOperator.IsNumber(windowIndex))
  4116. {
  4117. var subItem=this.SubFrame[windowIndex];
  4118. if (!subItem || !subItem.Frame) return;
  4119. var frame=subItem.Frame;
  4120. if (frame.YMaxMin)
  4121. {
  4122. frame.YMaxMin.Max=null;
  4123. frame.YMaxMin.Min=null;
  4124. }
  4125. }
  4126. else
  4127. {
  4128. for(var i=0;i<this.SubFrame.length;++i)
  4129. {
  4130. var subItem=this.SubFrame[i];
  4131. var frame=subItem.Frame;
  4132. if (frame.YMaxMin)
  4133. {
  4134. frame.YMaxMin.Max=null;
  4135. frame.YMaxMin.Min=null;
  4136. }
  4137. }
  4138. }
  4139. }
  4140. this.SetLanguage=function(languageID)
  4141. {
  4142. for(let i in this.SubFrame)
  4143. {
  4144. var item=this.SubFrame[i];
  4145. if (item && item.Frame )
  4146. {
  4147. if (item.Frame.YSplitOperator) item.Frame.YSplitOperator.LanguageID=languageID;
  4148. if (item.Frame.XSplitOperator) item.Frame.XSplitOperator.LanguageID=languageID;
  4149. }
  4150. }
  4151. }
  4152. this.GetCurrentPageSize = function () //获取当前页显示的数据个数
  4153. {
  4154. if (this.SubFrame.length <= 0) return null;
  4155. var item = this.SubFrame[0];
  4156. if (!item || !item.Frame) return null;
  4157. return item.Frame.XPointCount;
  4158. }
  4159. this.ClearCoordinateText=function(option) //清空X,Y轴刻度文字, 线段保留
  4160. {
  4161. for(var i=0;i<this.SubFrame.length;++i)
  4162. {
  4163. var item=this.SubFrame[i];
  4164. if (!item.Frame) continue;
  4165. item.Frame.ClearCoordinateText(option);
  4166. }
  4167. }
  4168. this.RestoreIndexWindows=function()
  4169. {
  4170. if (!this.ZoomWindowsInfo) return false;
  4171. var subFrame=this.SubFrame[this.ZoomWindowsInfo.FrameID];
  4172. for(var i=this.ZoomStartWindowIndex;i<this.ZoomWindowsInfo.Data.length; ++i)
  4173. {
  4174. var restoreItem=this.ZoomWindowsInfo.Data[i];
  4175. var frameItem=this.SubFrame[i];
  4176. frameItem.Height=restoreItem.Height;
  4177. frameItem.Frame.IsMinSize=false;
  4178. frameItem.Frame.XSplitOperator.ShowText=restoreItem.ShowXText;
  4179. frameItem.Frame.XYSplit=true;
  4180. }
  4181. this.ZoomWindowsInfo=null;
  4182. return true;
  4183. }
  4184. this.ZoomIndexWindow=function(frameID, option)
  4185. {
  4186. var subFrame=this.SubFrame[frameID];
  4187. if (!subFrame) return false;
  4188. if (this.ZoomWindowsInfo) //还原
  4189. {
  4190. return this.RestoreIndexWindows();
  4191. }
  4192. else //放大
  4193. {
  4194. var zoomInfo={ FrameID:frameID, Data:[] }; //备份下放大前各个窗口的高度
  4195. for(var i=0; i<this.SubFrame.length; ++i)
  4196. {
  4197. var item=this.SubFrame[i];
  4198. zoomInfo.Data[i]={ Height:item.Height, ShowXText:item.Frame.XSplitOperator.ShowText };
  4199. }
  4200. this.ZoomWindowsInfo=zoomInfo;
  4201. var totalHeight=0;
  4202. for(var i=this.ZoomStartWindowIndex;i<this.SubFrame.length;++i)
  4203. {
  4204. var item=this.SubFrame[i];
  4205. var frame=item.Frame;
  4206. frame.XYSplit=true;
  4207. totalHeight+=item.Height;
  4208. if (i!=frameID)
  4209. {
  4210. item.Height=0;
  4211. frame.IsMinSize=true; //最小化
  4212. frame.XSplitOperator.ShowText=false;
  4213. }
  4214. }
  4215. subFrame.Height=totalHeight;
  4216. subFrame.Frame.XSplitOperator.ShowText=true;
  4217. return true;
  4218. }
  4219. }
  4220. }
  4221. //行情框架横屏
  4222. function HQTradeHScreenFrame() {
  4223. this.newMethod = HQTradeFrame; //派生
  4224. this.newMethod();
  4225. delete this.newMethod;
  4226. this.ClassName='HQTradeHScreenFrame';
  4227. this.IsHScreen = true; //是否是横屏
  4228. this.CalculateChartBorder = function () //计算每个子框架的边框信息
  4229. {
  4230. if (this.SubFrame.length <= 0) return;
  4231. var right = this.ChartBorder.Right;
  4232. var left = this.ChartBorder.GetRight();
  4233. var width = this.ChartBorder.GetWidth();
  4234. var totalHeight = 0;
  4235. for (var i in this.SubFrame) {
  4236. var item = this.SubFrame[i];
  4237. totalHeight += item.Height;
  4238. }
  4239. for (var i in this.SubFrame) {
  4240. var item = this.SubFrame[i];
  4241. item.Frame.ChartBorder.Top = this.ChartBorder.Top;
  4242. item.Frame.ChartBorder.Bottom = this.ChartBorder.Bottom;
  4243. var frameWidth = width * (item.Height / totalHeight);
  4244. item.Frame.ChartBorder.Right = right;
  4245. item.Frame.ChartBorder.Left = left - frameWidth;
  4246. right += frameWidth;
  4247. left -= frameWidth;
  4248. }
  4249. }
  4250. this.GetYData = function (x, outObject)
  4251. {
  4252. var frame;
  4253. for (var i=0; i<this.SubFrame.length; ++i)
  4254. {
  4255. var item = this.SubFrame[i];
  4256. var left = item.Frame.ChartBorder.GetLeftEx();
  4257. var top = item.Frame.ChartBorder.GetTop();
  4258. var width = item.Frame.ChartBorder.GetWidthEx();
  4259. var height = item.Frame.ChartBorder.GetHeight();
  4260. var rtItem = new Rect(left, top, width, height);
  4261. if (rtItem.IsPointIn(x, top))
  4262. {
  4263. frame = item.Frame;
  4264. if (outObject) outObject.FrameID = i;
  4265. break;
  4266. }
  4267. }
  4268. if (frame != null)
  4269. {
  4270. var xValue=frame.GetYData(x);
  4271. if (frame.GetMainOverlayFrame)
  4272. {
  4273. var aryOverlayFrame=frame.GetMainOverlayFrame();
  4274. if (aryOverlayFrame)
  4275. {
  4276. if (aryOverlayFrame[0]) //左侧
  4277. {
  4278. var leftFrame=aryOverlayFrame[0];
  4279. var value=leftFrame.GetYData(x);
  4280. outObject.RightYValue=xValue;
  4281. xValue=value;
  4282. }
  4283. if (aryOverlayFrame[1]) //右侧
  4284. {
  4285. var rightFrame=aryOverlayFrame[1];
  4286. var value=rightFrame.GetYData(x);
  4287. outObject.RightYValue=value;
  4288. }
  4289. }
  4290. }
  4291. return xValue;
  4292. }
  4293. }
  4294. }
  4295. function TooltipData() //提示信息
  4296. {
  4297. this.ChartPaint;
  4298. this.Data;
  4299. }
  4300. //基础图形的XY坐标互换柱子
  4301. function ChartXYSubBar() {
  4302. this.newMethod = ChartBar; //派生
  4303. this.newMethod();
  4304. delete this.newMethod;
  4305. this.BarID = 0;
  4306. this.Draw = function () {
  4307. if (this.NotSupportMessage) {
  4308. this.DrawNotSupportmessage();
  4309. return;
  4310. }
  4311. var dataWidth = this.ChartFrame.DataWidth;
  4312. var distanceWidth = this.ChartFrame.DistanceWidth;
  4313. var chartTop = this.ChartBorder.GetTopEx();
  4314. var xPointCount = this.ChartFrame.XPointCount;
  4315. var yOffset = this.ChartBorder.GetBottom() - distanceWidth / 2.0 - 2.0;
  4316. var xMiddle = this.ChartFrame.GetXFromIndex(0); //0 刻度
  4317. if (dataWidth >= 4) {
  4318. var barCount = this.ChartFrame.BarCount;
  4319. var subBarWidth = dataWidth;
  4320. var subBarOffset = 0;
  4321. if (barCount > 0) //多柱子需要把框架柱子宽度的平均分割
  4322. {
  4323. subBarWidth = dataWidth / barCount;
  4324. subBarOffset = subBarWidth * this.BarID;
  4325. //JSConsole.Chart.Log('[ChartXYSubBar::Draw] ', subBarWidth, this.BarID, subBarOffset);
  4326. }
  4327. xMiddle = ToFixedRect(xMiddle); //调整为整数
  4328. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, yOffset -= (dataWidth + distanceWidth)) {
  4329. var value = this.Data.Data[i];
  4330. if (value == null || value == 0) continue;
  4331. var yBottom = yOffset + subBarOffset;
  4332. var yTop = yOffset + subBarOffset - dataWidth;
  4333. if (yBottom < chartTop) break;
  4334. var x = this.ChartFrame.GetXFromIndex(value);
  4335. if (value > 0) {
  4336. this.Canvas.fillStyle = this.UpBarColor;
  4337. let barWidth = ToFixedRect(Math.abs(x - xMiddle));
  4338. let barHeight = subBarWidth;
  4339. if (Math.abs(chartTop - yBottom) < dataWidth) subBarWidth = Math.abs(chartTop - yBottom); //最后一根柱子可能会超出框架
  4340. this.Canvas.fillRect(xMiddle, ToFixedRect(yTop), barWidth, ToFixedRect(barHeight + 0.5));
  4341. }
  4342. else {
  4343. this.Canvas.fillStyle = this.DownBarColor;
  4344. //高度调整为整数
  4345. let barWidth = ToFixedRect(Math.abs(x - xMiddle));
  4346. let barHeight = subBarWidth;
  4347. if (Math.abs(chartTop - yBottom) < subBarWidth) barHeight = Math.abs(chartTop - yBottom); //最后一根柱子可能会超出框架
  4348. this.Canvas.fillRect(xMiddle, ToFixedRect(yTop), -barWidth, ToFixedRect(barHeight + 0.5));
  4349. }
  4350. }
  4351. }
  4352. else //太细了 直接画柱子
  4353. {
  4354. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, yOffset -= (dataWidth + distanceWidth)) {
  4355. var value = this.Data.Data[i];
  4356. if (value == null || value == 0) continue;
  4357. var yBottom = yOffset;
  4358. var yTop = yOffset - dataWidth;
  4359. if (yTop < chartTop) break;
  4360. var x = this.ChartFrame.GetXFromIndex(value);
  4361. var y = this.ChartFrame.GetYFromData(j);
  4362. if (value > 0) this.Canvas.strokeStyle = this.UpBarColor;
  4363. else this.Canvas.strokeStyle = this.DownBarColor;
  4364. this.Canvas.beginPath();
  4365. this.Canvas.moveTo(ToFixedPoint(x), y);
  4366. this.Canvas.lineTo(ToFixedPoint(xMiddle), y);
  4367. this.Canvas.stroke();
  4368. }
  4369. }
  4370. }
  4371. }
  4372. function ChartSubBar() {
  4373. this.newMethod = ChartBar; //派生
  4374. this.newMethod();
  4375. delete this.newMethod;
  4376. this.BarID = 0;
  4377. this.Draw = function () {
  4378. if (this.NotSupportMessage) {
  4379. this.DrawNotSupportmessage();
  4380. return;
  4381. }
  4382. var dataWidth = this.ChartFrame.DataWidth;
  4383. var distanceWidth = this.ChartFrame.DistanceWidth;
  4384. var chartright = this.ChartBorder.GetRight();
  4385. var xPointCount = this.ChartFrame.XPointCount;
  4386. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  4387. var yBottom = this.ChartFrame.GetYFromData(0);
  4388. if (dataWidth >= 4) {
  4389. var barCount = this.ChartFrame.BarCount;
  4390. var subBarWidth = dataWidth;
  4391. var subBarOffset = 0;
  4392. if (barCount > 0) //多柱子需要把框架柱子宽度的平均分割
  4393. {
  4394. subBarWidth = dataWidth / barCount;
  4395. subBarOffset = subBarWidth * this.BarID;
  4396. //JSConsole.Chart.Log('[ChartSubBar::Draw] ', subBarWidth, this.BarID, subBarOffset);
  4397. }
  4398. yBottom = ToFixedRect(yBottom); //调整为整数
  4399. for (let i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
  4400. var value = this.Data.Data[i];
  4401. if (value == null || value == 0) continue;
  4402. var left = xOffset + subBarOffset
  4403. var right = xOffset + subBarOffset + subBarWidth;
  4404. if (left > chartright) break;
  4405. var x = this.ChartFrame.GetXFromIndex(j);
  4406. var y = this.ChartFrame.GetYFromData(value);
  4407. if (value > 0) {
  4408. this.Canvas.fillStyle = this.UpBarColor;
  4409. //高度调整为整数
  4410. let height = ToFixedRect(Math.abs(yBottom - y));
  4411. let barWidth = subBarWidth;
  4412. if (chartright - left < subBarWidth) barWidth = chartright - left;
  4413. if (yBottom - y > 0) y = yBottom - height;
  4414. else y = yBottom + height;
  4415. this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(barWidth), height);
  4416. }
  4417. else {
  4418. this.Canvas.fillStyle = this.DownBarColor;
  4419. //高度调整为整数
  4420. let height = ToFixedRect(Math.abs(yBottom - y));
  4421. let barWidth = subBarWidth;
  4422. if (chartright - left < subBarWidth) barWidth = chartright - left;
  4423. if (yBottom - y > 0) y = yBottom - height;
  4424. else y = yBottom + height;
  4425. this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(subBarWidth), -height);
  4426. }
  4427. }
  4428. }
  4429. else //太细了 直接画柱子
  4430. {
  4431. for (let i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
  4432. var value = this.Data.Data[i];
  4433. if (value == null || value == 0) continue;
  4434. var left = xOffset;
  4435. var right = xOffset + dataWidth;
  4436. if (right > chartright) break;
  4437. var x = this.ChartFrame.GetXFromIndex(j);
  4438. var y = this.ChartFrame.GetYFromData(value);
  4439. if (value > 0) this.Canvas.strokeStyle = this.UpBarColor;
  4440. else this.Canvas.strokeStyle = this.DownBarColor;
  4441. this.Canvas.beginPath();
  4442. this.Canvas.moveTo(ToFixedPoint(x), y);
  4443. this.Canvas.lineTo(ToFixedPoint(x), yBottom);
  4444. this.Canvas.stroke();
  4445. }
  4446. }
  4447. }
  4448. }
  4449. //柱子 支持横屏
  4450. function ChartBar() {
  4451. this.newMethod = IChartPainting; //派生
  4452. this.newMethod();
  4453. delete this.newMethod;
  4454. this.UpBarColor = g_JSChartResource.UpBarColor;
  4455. this.DownBarColor = g_JSChartResource.DownBarColor;
  4456. this.Draw = function () {
  4457. if (this.NotSupportMessage) {
  4458. this.DrawNotSupportmessage();
  4459. return;
  4460. }
  4461. var isHScreen = (this.ChartFrame.IsHScreen === true);
  4462. var dataWidth = this.ChartFrame.DataWidth;
  4463. var distanceWidth = this.ChartFrame.DistanceWidth;
  4464. var chartright = this.ChartBorder.GetRight();
  4465. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  4466. var xPointCount = this.ChartFrame.XPointCount;
  4467. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  4468. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  4469. var bFirstPoint = true;
  4470. var drawCount = 0;
  4471. var yBottom = this.ChartFrame.GetYFromData(0);
  4472. if (dataWidth >= 4) {
  4473. yBottom = ToFixedRect(yBottom); //调整为整数
  4474. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
  4475. var value = this.Data.Data[i];
  4476. if (value == null || value == 0) continue;
  4477. var left = xOffset;
  4478. var right = xOffset + dataWidth;
  4479. if (right > chartright) break;
  4480. var x = this.ChartFrame.GetXFromIndex(j);
  4481. var y = this.ChartFrame.GetYFromData(value);
  4482. if (value > 0) {
  4483. this.Canvas.fillStyle = this.UpBarColor;
  4484. if (isHScreen) {
  4485. let height = ToFixedRect(Math.abs(yBottom - y)); //高度调整为整数
  4486. y = Math.min(yBottom, y);
  4487. this.Canvas.fillRect(y, ToFixedRect(left), height, ToFixedRect(dataWidth));
  4488. }
  4489. else {
  4490. let height = ToFixedRect(Math.abs(yBottom - y)); //高度调整为整数
  4491. if (yBottom - y > 0) y = yBottom - height;
  4492. else y = yBottom + height;
  4493. this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), height);
  4494. }
  4495. }
  4496. else {
  4497. this.Canvas.fillStyle = this.DownBarColor;
  4498. //高度调整为整数
  4499. let height = ToFixedRect(Math.abs(yBottom - y));
  4500. if (yBottom - y > 0) y = yBottom - height;
  4501. else y = yBottom + height;
  4502. this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), -height);
  4503. }
  4504. }
  4505. }
  4506. else //太细了 直接画柱子
  4507. {
  4508. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
  4509. var value = this.Data.Data[i];
  4510. if (value == null || value == 0) continue;
  4511. var left = xOffset;
  4512. var right = xOffset + dataWidth;
  4513. if (right > chartright) break;
  4514. var x = this.ChartFrame.GetXFromIndex(j);
  4515. var y = this.ChartFrame.GetYFromData(value);
  4516. if (value > 0) this.Canvas.strokeStyle = this.UpBarColor;
  4517. else this.Canvas.strokeStyle = this.DownBarColor;
  4518. this.Canvas.beginPath();
  4519. if (isHScreen) {
  4520. this.Canvas.moveTo(y, ToFixedPoint(x));
  4521. this.Canvas.lineTo(yBottom, ToFixedPoint(x));
  4522. }
  4523. else {
  4524. this.Canvas.moveTo(ToFixedPoint(x), y);
  4525. this.Canvas.lineTo(ToFixedPoint(x), yBottom);
  4526. }
  4527. this.Canvas.stroke();
  4528. }
  4529. }
  4530. }
  4531. this.GetMaxMin = function () {
  4532. var xPointCount = this.ChartFrame.XPointCount;
  4533. var range = {};
  4534. range.Min = 0;
  4535. range.Max = null;
  4536. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) {
  4537. var value = this.Data.Data[i];
  4538. if (range.Max == null) range.Max = value;
  4539. if (range.Max < value) range.Max = value;
  4540. if (range.Min > value) range.Min = value;
  4541. }
  4542. return range;
  4543. }
  4544. }
  4545. /*
  4546. 指标列表 指标信息都在这里,不够后面再加字段
  4547. */
  4548. function JSIndexMap() {
  4549. }
  4550. JSIndexMap.Get = function (id) {
  4551. var indexMap = new Map(
  4552. [
  4553. //公司自己的指标
  4554. ["市场多空", { IsMainIndex: false, Create: function () { return new MarketLongShortIndex() } }],
  4555. ["市场择时", { IsMainIndex: false, Create: function () { return new MarketTimingIndex() } }],
  4556. ["市场关注度", { IsMainIndex: false, Create: function () { return new MarketAttentionIndex() } }],
  4557. ["指数热度", { IsMainIndex: false, Create: function () { return new MarketHeatIndex() } }],
  4558. ["自定义指数热度", { IsMainIndex: false, Create: function () { return new CustonIndexHeatIndex() }, Name: '自定义指数热度' }],
  4559. ["财务粉饰", { IsMainIndex: false, Create: function () { return new BenfordIndex() } }],
  4560. //能图指标
  4561. //["能图-趋势", { IsMainIndex: false, Create: function () { return new LighterIndex1() }, Name: '大盘/个股趋势' }],
  4562. //["能图-位置研判", { IsMainIndex: false, Create: function () { return new LighterIndex2() }, Name: '位置研判' }],
  4563. //["能图-点位研判", { IsMainIndex: false, Create: function () { return new LighterIndex3() }, Name: '点位研判' }],
  4564. //["能图-资金分析", { IsMainIndex: false, Create: function () { return new LighterIndex4() }, Name: '资金分析' }],
  4565. //["能图-市场关注度", { IsMainIndex: false, Create: function () { return new LighterIndex5() }, Name: '市场关注度' }]
  4566. ]
  4567. );
  4568. return indexMap.get(id);
  4569. }
  4570. /////////////////////////////////////////////////////////////////////////////////////////////
  4571. // K线图 控件
  4572. // this.ChartPaint[0] K线画法 这个不要修改
  4573. //
  4574. //
  4575. function KLineChartContainer(uielement)
  4576. {
  4577. var _self = this;
  4578. this.newMethod = JSChartContainer; //派生
  4579. this.newMethod(uielement);
  4580. delete this.newMethod;
  4581. this.ClassName = 'KLineChartContainer';
  4582. this.WindowIndex = new Array();
  4583. this.ColorIndex; //五彩K线
  4584. this.TradeIndex; //交易指标/专家系统
  4585. this.Symbol;
  4586. this.Name;
  4587. this.Period = 0; //周期 0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 9=季线 10=分笔线 11=120分钟 12=240分钟
  4588. this.RightFormula=0 //复权公式 0=简单复权, 1=复权因子复权
  4589. this.IsApiPeriod = false; //使用API计算周期
  4590. this.Right = 0; //复权 0 不复权 1 前复权 2 后复权
  4591. this.SourceData; //原始的历史数据
  4592. this.MaxRequestDataCount = 3000; //数据个数
  4593. this.MaxRequestMinuteDayCount = 5; //分钟数据请求的天数
  4594. this.PageSize = 200; //每页数据个数
  4595. this.KLineDrawType = 0; //0=K线 1=收盘价线 2=美国线
  4596. this.LoadDataSplashTitle = '下载历史数据';
  4597. this.IsAutoUpdate = false; //是否自动更新行情数据
  4598. this.AutoUpdateFrequency = 30000; //30秒更新一次数据
  4599. this.AutoUpdateTimer=null; //自动定时器
  4600. this.RightSpaceCount=1;
  4601. this.SourceDataLimit = new Map(); //每个周期缓存数据最大个数 key=周期 value=最大个数
  4602. this.IsZoomLockRight=false;
  4603. this.KLineSize=null; //{ DataWidth:, }
  4604. this.StepPixel = 4; //移动一个数据需要的像素
  4605. this.ZoomStepPixel = 5; //放大缩小手势需要的最小像素
  4606. this.EnableZoomUpDown=null; //是否手势/键盘/鼠标允许缩放{ Touch:true/false, Mouse:true/false, Keyboard:true/false, Wheel:true/false }
  4607. this.EnableMoveData=null; //是否可以移动K线 { Touch:true/false }
  4608. this.DragDownload = {
  4609. Day: { Enable: false, IsEnd: false, Status: 0 }, //日线数据拖拽下载(暂不支持) Status: 0空闲 1 下载中
  4610. Minute: { Enable: false, IsEnd: false, Status: 0 } //分钟数据拖拽下载
  4611. };
  4612. this.KLineApiUrl = g_JSChartResource.Domain + "/API/KLine2"; //历史K线api地址
  4613. this.MinuteKLineApiUrl = g_JSChartResource.Domain + '/API/KLine3'; //历史分钟数据
  4614. this.RealtimeApiUrl = g_JSChartResource.Domain + "/API/Stock"; //实时行情api地址
  4615. this.KLineMatchUrl = g_JSChartResource.Domain + "/API/KLineMatch"; //形态匹配
  4616. this.DragMinuteKLineApiUrl = g_JSChartResource.Domain + '/API/KLine4'; //拖动数据下载
  4617. this.DragKLineApiUrl = g_JSChartResource.Domain + '/API/KLine5'; //拖动日K数据下载
  4618. this.BeforeBindMainData = null; //function(funcName) 在BindMainData() 调用前回调用
  4619. this.AfterBindMainData = null; //function(funcName) 在BindMainData() 调用前后调用
  4620. this.ResetDragDownload = function ()
  4621. {
  4622. this.DragDownload.Day.Status = 0;
  4623. this.DragDownload.Day.IsEnd=false;
  4624. this.DragDownload.Minute.Status = 0;
  4625. this.DragDownload.Minute.IsEnd=false;
  4626. }
  4627. this.AddCustomKLine=function(kline, option)
  4628. {
  4629. var klineChart=this.ChartPaint[0];
  4630. if (!klineChart) return;
  4631. if (!kline) return;
  4632. if (!klineChart.CustomKLine) klineChart.CustomKLine=new Map();
  4633. if (Array.isArray(kline))
  4634. {
  4635. for(var i=0;i<kline.length;++i)
  4636. {
  4637. var item=kline[i];
  4638. klineChart.CustomKLine.set(item.Key, item.Data);
  4639. }
  4640. }
  4641. else if (kline)
  4642. {
  4643. klineChart.CustomKLine.set(kline.Key, kline.Data);
  4644. }
  4645. if (option && option.Draw==true) this.Draw();
  4646. }
  4647. this.ClearCustomKLine=function(option)
  4648. {
  4649. var klineChart=this.ChartPaint[0];
  4650. if (!klineChart) return;
  4651. klineChart.ClearCustomKLine();
  4652. if (option && option.Draw==true) this.Draw();
  4653. }
  4654. this.ChartOperator = function (obj) //图形控制函数 {ID:JSCHART_OPERATOR_ID, ...参数 }
  4655. {
  4656. var id = obj.ID;
  4657. if (id === JSCHART_OPERATOR_ID.OP_SCROLL_LEFT || id === JSCHART_OPERATOR_ID.OP_SCROLL_RIGHT) //左右移动 { Step:移动数据个数 }
  4658. {
  4659. var isLeft = (id === JSCHART_OPERATOR_ID.OP_SCROLL_LEFT ? true : false);
  4660. var step = 1;
  4661. if (obj.Step > 0) step = obj.Step;
  4662. if (this.DataMove(step * this.StepPixel, isLeft)) //每次移动一个数据
  4663. {
  4664. this.UpdataDataoffset();
  4665. this.UpdatePointByCursorIndex();
  4666. this.UpdateFrameMaxMin();
  4667. this.ResetFrameXYSplit();
  4668. this.Draw();
  4669. }
  4670. else
  4671. {
  4672. if (id===JSCHART_OPERATOR_ID.OP_SCROLL_RIGHT && this.DragDownloadData)
  4673. this.DragDownloadData();
  4674. }
  4675. }
  4676. else if (id === JSCHART_OPERATOR_ID.OP_ZOOM_IN || id === JSCHART_OPERATOR_ID.OP_ZOOM_OUT) //缩放
  4677. {
  4678. var cursorIndex = {};
  4679. cursorIndex.Index = parseInt(Math.abs(this.CursorIndex - 0.5).toFixed(0));
  4680. if (id === JSCHART_OPERATOR_ID.OP_ZOOM_IN)
  4681. {
  4682. if (!this.Frame.ZoomUp(cursorIndex)) return;
  4683. }
  4684. else
  4685. {
  4686. if (!this.Frame.ZoomDown(cursorIndex)) return;
  4687. }
  4688. this.CursorIndex = cursorIndex.Index;
  4689. this.UpdataDataoffset();
  4690. this.UpdatePointByCursorIndex();
  4691. this.UpdateFrameMaxMin();
  4692. this.Draw();
  4693. }
  4694. else if (id === JSCHART_OPERATOR_ID.OP_GOTO_HOME) //返回最新
  4695. {
  4696. var hisData = this.ChartOperator_Temp_GetHistroyData();
  4697. if (!hisData) return; //数据还没有到达
  4698. var showCount=this.Frame.SubFrame[0].Frame.XPointCount; //获取一屏显示的数据个数
  4699. showCount-=this.RightSpaceCount;
  4700. var index=hisData.Data.length-showCount;
  4701. hisData.DataOffset=index;
  4702. this.CursorIndex=0;
  4703. this.LastPoint.X=null;
  4704. this.LastPoint.Y=null;
  4705. JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO_HOME, dataOffset=${hisData.DataOffset} CursorIndex=${this.CursorIndex} PageSize=${showCount}`);
  4706. this.ChartOperator_Temp_Update();
  4707. }
  4708. else if (id===JSCHART_OPERATOR_ID.OP_GOTO_END)
  4709. {
  4710. var hisData=this.ChartOperator_Temp_GetHistroyData();
  4711. if (!hisData) return; //数据还没有到达
  4712. hisData.DataOffset=0;
  4713. this.CursorIndex=0;
  4714. this.LastPoint.X=null;
  4715. this.LastPoint.Y=null;
  4716. JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO_END `);
  4717. this.ChartOperator_Temp_Update();
  4718. }
  4719. else if (id==JSCHART_OPERATOR_ID.OP_GOTO) //{ Date:日期, Time: , PageSize:(可选)}
  4720. {
  4721. if (!IFrameSplitOperator.IsNumber(obj.Date)) return;
  4722. var hisData=this.ChartOperator_Temp_GetHistroyData();
  4723. if (!hisData) return; //数据还没有到达
  4724. var index=null;
  4725. if (ChartData.IsDayPeriod(this.Period,true))
  4726. {
  4727. for(var i=0;i<hisData.Data.length;++i)
  4728. {
  4729. var item=hisData.Data[i];
  4730. if (item.Date>=obj.Date)
  4731. {
  4732. index=i;
  4733. break;
  4734. }
  4735. }
  4736. }
  4737. else if (ChartData.IsMinutePeriod(this.Period,true))
  4738. {
  4739. let findTime=obj.Time;
  4740. if (IFrameSplitOperator.IsPlusNumber(findTime))
  4741. {
  4742. for(var i=0;i<hisData.Data.length;++i)
  4743. {
  4744. var item=hisData.Data[i];
  4745. if (item.Date>obj.Date || (item.Date==obj.Date && item.Time>=findTime))
  4746. {
  4747. index=i;
  4748. break;
  4749. }
  4750. }
  4751. }
  4752. else //只有日期
  4753. {
  4754. for(var i=0;i<hisData.Data.length;++i)
  4755. {
  4756. var item=hisData.Data[i];
  4757. if (item.Date>=obj.Date)
  4758. {
  4759. index=i;
  4760. break;
  4761. }
  4762. }
  4763. }
  4764. }
  4765. if (index===null)
  4766. {
  4767. JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO can't find date=${obj.Date} time=${obj.Time}`);
  4768. return;
  4769. }
  4770. var oldXPointCount=this.Frame.SubFrame[0].Frame.XPointCount;
  4771. var xPointCount=oldXPointCount;
  4772. if (obj.PageSize>0) //调整一屏显示的个数
  4773. {
  4774. xPointCount=obj.PageSize;
  4775. }
  4776. if (xPointCount!=oldXPointCount)
  4777. {
  4778. //设置X轴显示数据个数
  4779. this.Frame.SetXShowCount(xPointCount);
  4780. }
  4781. hisData.DataOffset=index;
  4782. this.CursorIndex=0;
  4783. this.LastPoint.X=null;
  4784. this.LastPoint.Y=null;
  4785. this.ChartOperator_Temp_Update();
  4786. }
  4787. }
  4788. //内部函数
  4789. this.ChartOperator_Temp_GetHistroyData=function()
  4790. {
  4791. var hisData=null;
  4792. if (!this.Frame.Data) hisData=this.Frame.Data;
  4793. else hisData=this.Frame.SubFrame[0].Frame.Data;
  4794. if (!hisData) return null; //数据还没有到达
  4795. return hisData;
  4796. }
  4797. this.ChartOperator_Temp_Update=function()
  4798. {
  4799. this.UpdataDataoffset(); //更新数据偏移
  4800. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  4801. this.Frame.SetSizeChage(true);
  4802. this.Draw();
  4803. this.UpdatePointByCursorIndex(); //更新十字光标位子
  4804. }
  4805. //创建windowCount 窗口个数
  4806. this.Create = function (windowCount)
  4807. {
  4808. this.UIElement.JSChartContainer = this;
  4809. //创建十字光标
  4810. this.ChartCorssCursor = new ChartCorssCursor();
  4811. this.ChartCorssCursor.Canvas = this.Canvas;
  4812. this.ChartCorssCursor.StringFormatX = g_DivTooltipDataForamt.Create("CorssCursor_XStringFormat");
  4813. this.ChartCorssCursor.StringFormatX.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4814. this.ChartCorssCursor.StringFormatX.LanguageID=this.LanguageID;
  4815. this.ChartCorssCursor.StringFormatY = g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat");
  4816. this.ChartCorssCursor.StringFormatY.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4817. this.ChartCorssCursor.StringFormatY.LanguageID = this.LanguageID;
  4818. this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4819. //创建等待提示
  4820. this.ChartSplashPaint = new ChartSplashPaint();
  4821. this.ChartSplashPaint.Canvas = this.Canvas;
  4822. this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle;
  4823. this.ChartSplashPaint.HQChart=this;
  4824. //创建框架容器
  4825. this.Frame = new HQTradeFrame();
  4826. this.Frame.ChartBorder = new ChartBorder();
  4827. this.Frame.ChartBorder.UIElement = this.UIElement;
  4828. this.Frame.ChartBorder.Top = 30;
  4829. this.Frame.ChartBorder.Left = 5;
  4830. this.Frame.ChartBorder.Bottom = 20;
  4831. this.Frame.Canvas = this.Canvas;
  4832. this.Frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4833. this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架
  4834. this.ChartSplashPaint.Frame = this.Frame;
  4835. this.CreateChildWindow(windowCount);
  4836. this.CreateMainKLine();
  4837. //子窗口动态标题
  4838. for (var i in this.Frame.SubFrame)
  4839. {
  4840. var titlePaint = new DynamicChartTitlePainting();
  4841. titlePaint.Frame = this.Frame.SubFrame[i].Frame;
  4842. titlePaint.Canvas = this.Canvas;
  4843. titlePaint.LanguageID = this.LanguageID;
  4844. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4845. this.Frame.SubFrame[i].Frame.TitlePaint = titlePaint;
  4846. this.TitlePaint.push(titlePaint);
  4847. }
  4848. this.ChartCorssCursor.StringFormatX.Frame = this.Frame.SubFrame[0].Frame;
  4849. this.ChartCorssCursor.StringFormatY.Frame=this.Frame;
  4850. }
  4851. //创建子窗口
  4852. this.CreateChildWindow = function (windowCount)
  4853. {
  4854. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME);
  4855. for (var i = 0; i < windowCount; ++i)
  4856. {
  4857. var border = new ChartBorder();
  4858. border.UIElement = this.UIElement;
  4859. var frame = new KLineFrame();
  4860. frame.Canvas = this.Canvas;
  4861. frame.ChartBorder = border;
  4862. frame.Identify = i; //窗口序号
  4863. frame.RightSpaceCount = this.RightSpaceCount; //右边
  4864. frame.HorizontalMax = 20;
  4865. frame.HorizontalMin = 10;
  4866. if (i == 0)
  4867. {
  4868. frame.YSplitOperator = new FrameSplitKLinePriceY();
  4869. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price');
  4870. frame.YSplitOperator.FrameSplitData2 = this.FrameSplitData.get('double');
  4871. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4872. frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4873. border.BottomSpace = 12; //主图上下留空间
  4874. border.TopSpace = 12;
  4875. }
  4876. else
  4877. {
  4878. frame.YSplitOperator = new FrameSplitY();
  4879. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double');
  4880. frame.YSplitOperator.LanguageID = this.LanguageID;
  4881. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  4882. }
  4883. frame.YSplitOperator.Frame = frame;
  4884. frame.YSplitOperator.ChartBorder = border;
  4885. frame.XSplitOperator = new FrameSplitKLineX();
  4886. frame.XSplitOperator.Frame = frame;
  4887. frame.XSplitOperator.ChartBorder = border;
  4888. frame.XSplitOperator.GetEventCallback =(id)=> { return this.GetEventCallback(id); }
  4889. if (i != windowCount - 1) frame.XSplitOperator.ShowText = false;
  4890. for (var j = frame.HorizontalMin; j <= frame.HorizontalMax; j += 1)
  4891. {
  4892. frame.HorizontalInfo[j] = new CoordinateInfo();
  4893. frame.HorizontalInfo[j].Value = j;
  4894. if (i == 0 && j == frame.HorizontalMin) continue;
  4895. frame.HorizontalInfo[j].Message[1] = j.toString();
  4896. frame.HorizontalInfo[j].Font = "14px 微软雅黑";
  4897. }
  4898. var subFrame = new SubFrameItem();
  4899. frame.FrameData.SubFrameItem=subFrame;
  4900. subFrame.Frame = frame;
  4901. if (i == 0) subFrame.Height = 20;
  4902. else subFrame.Height = 10;
  4903. this.Frame.SubFrame[i] = subFrame;
  4904. if (event && event.Callback)
  4905. {
  4906. var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i };
  4907. event.Callback(event, sendData, this);
  4908. }
  4909. }
  4910. }
  4911. this.CreateSubFrameItem = function (id)
  4912. {
  4913. var border = new ChartBorder();
  4914. border.UIElement = this.UIElement;
  4915. var frame = new KLineFrame();
  4916. frame.Canvas = this.Canvas;
  4917. frame.ChartBorder = border;
  4918. frame.Identify = id; //窗口序号
  4919. if (this.ModifyIndexDialog) frame.ModifyIndexEvent = this.ModifyIndexDialog.DoModal; //绑定菜单事件
  4920. if (this.ChangeIndexDialog) frame.ChangeIndexEvent = this.ChangeIndexDialog.DoModal;
  4921. frame.HorizontalMax = 20;
  4922. frame.HorizontalMin = 10;
  4923. frame.YSplitOperator = new FrameSplitY();
  4924. frame.YSplitOperator.LanguageID = this.LanguageID;
  4925. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double');
  4926. frame.YSplitOperator.Frame = frame;
  4927. frame.YSplitOperator.ChartBorder = border;
  4928. frame.XSplitOperator = new FrameSplitKLineX();
  4929. frame.XSplitOperator.Frame = frame;
  4930. frame.XSplitOperator.ChartBorder = border;
  4931. frame.XSplitOperator.ShowText = false;
  4932. frame.XSplitOperator.Period=this.Period;
  4933. frame.XSplitOperator.GetEventCallback =(id)=> { return this.GetEventCallback(id); }
  4934. //K线数据绑定
  4935. var xPointCouont = this.Frame.SubFrame[0].Frame.XPointCount;
  4936. frame.XPointCount = xPointCouont;
  4937. frame.Data = this.ChartPaint[0].Data;
  4938. for (var j = frame.HorizontalMin; j <= frame.HorizontalMax; j += 1)
  4939. {
  4940. frame.HorizontalInfo[j] = new CoordinateInfo();
  4941. frame.HorizontalInfo[j].Value = j;
  4942. frame.HorizontalInfo[j].Message[1] = j.toString();
  4943. frame.HorizontalInfo[j].Font = "14px 微软雅黑";
  4944. }
  4945. var subFrame = new SubFrameItem();
  4946. frame.FrameData.SubFrameItem=subFrame;
  4947. subFrame.Frame = frame;
  4948. subFrame.Height = 10;
  4949. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME);
  4950. if (event && event.Callback)
  4951. {
  4952. var sendData={ SubFrame:subFrame, WindowIndex:id };
  4953. event.Callback(event, sendData, this);
  4954. }
  4955. return subFrame;
  4956. }
  4957. //创建主图K线画法
  4958. this.CreateMainKLine = function ()
  4959. {
  4960. var kline = new ChartKLine();
  4961. kline.Canvas = this.Canvas;
  4962. kline.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  4963. kline.ChartFrame = this.Frame.SubFrame[0].Frame;
  4964. kline.Name = "Main-KLine";
  4965. kline.DrawType = this.KLineDrawType;
  4966. kline.GetEventCallback=(id)=>{ return this.GetEventCallback(id); };
  4967. this.ChartPaint[0] = kline;
  4968. this.TitlePaint[0] = new DynamicKLineTitlePainting();
  4969. this.TitlePaint[0].Frame = this.Frame.SubFrame[0].Frame;
  4970. this.TitlePaint[0].Canvas = this.Canvas;
  4971. this.TitlePaint[0].LanguageID = this.LanguageID;
  4972. this.TitlePaint[0].HQChart=this;
  4973. }
  4974. //绑定主图K线数据
  4975. this.BindMainData = function (hisData, showCount)
  4976. {
  4977. this.ChartPaint[0].Data = hisData;
  4978. this.ChartPaint[0].Symbol = this.Symbol;
  4979. if (this.KLineSize)
  4980. {
  4981. if (this.KLineSize.DataWidth==null)
  4982. {
  4983. showCount=this.Frame.SubFrame[0].Frame.XPointCount-this.RightSpaceCount;
  4984. }
  4985. else
  4986. {
  4987. var obj=this.Frame.SetDataWidth(this.KLineSize.DataWidth);
  4988. showCount=obj.XPointCount-this.RightSpaceCount;
  4989. this.KLineSize.DataWidth=null;
  4990. }
  4991. }
  4992. for (var i in this.Frame.SubFrame)
  4993. {
  4994. var item = this.Frame.SubFrame[i].Frame;
  4995. item.XPointCount = showCount + this.RightSpaceCount;
  4996. item.Data = this.ChartPaint[0].Data;
  4997. item.XSplitOperator.Symbol = this.Symbol;
  4998. item.XSplitOperator.Period = this.Period;
  4999. }
  5000. this.TitlePaint[0].Data = this.ChartPaint[0].Data; //动态标题
  5001. this.TitlePaint[0].Symbol = this.Symbol;
  5002. this.TitlePaint[0].Name = this.Name;
  5003. this.TitlePaint[0].Period = this.Period;
  5004. this.ChartCorssCursor.StringFormatX.Data = this.ChartPaint[0].Data; //十字光标
  5005. this.Frame.Data = this.ChartPaint[0].Data;
  5006. for(var i=0; i<this.OverlayChartPaint.length; ++i) //K线叠加 主图股票数据绑定到叠加上
  5007. {
  5008. var item=this.OverlayChartPaint[i];
  5009. item.MainData=this.ChartPaint[0].Data;
  5010. }
  5011. var dataOffset = hisData.Data.length - showCount;
  5012. if (dataOffset < 0) dataOffset = 0;
  5013. this.ChartPaint[0].Data.DataOffset = dataOffset;
  5014. this.ChartCorssCursor.StringFormatY.Symbol = this.Symbol;
  5015. this.CursorIndex = showCount;
  5016. if (this.CursorIndex + dataOffset >= hisData.Data.length) this.CursorIndex = hisData.Data.length - 1 - dataOffset;
  5017. if (this.CursorIndex < 0) this.CursorIndex = 0; //不一定对啊
  5018. }
  5019. this.UpdateMainData = function (hisData, lastDataCount) //更新主图数据(不会放大缩小数据)
  5020. {
  5021. var frameHisdata = null;
  5022. if (!this.Frame.Data) frameHisdata = this.Frame.Data;
  5023. else if (this.Frame.SubFrame && this.Frame.SubFrame[0]) frameHisdata = this.Frame.SubFrame[0].Frame.Data;
  5024. if (!frameHisdata) return;
  5025. var xPointCount=this.Frame.SubFrame[0].Frame.XPointCount; //当前一屏能显示的数据个数
  5026. var newDataCount = 0;
  5027. if (lastDataCount > 0 && hisData.Data.length > lastDataCount)
  5028. {
  5029. newDataCount = hisData.Data.length - lastDataCount;
  5030. JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`);
  5031. }
  5032. else if (lastDataCount==0 && hisData.Data.length>xPointCount) //历史数据为空,当前收到数据大于一屏的数据,显示最新数据
  5033. {
  5034. newDataCount=hisData.Data.length-xPointCount;
  5035. JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] history data is empty. [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`);
  5036. }
  5037. this.ChartPaint[0].Data = hisData;
  5038. this.ChartPaint[0].Symbol = this.Symbol;
  5039. if (hisData.Data.length>xPointCount) //不满一屏的, 不需要调整索引
  5040. this.ChartPaint[0].Data.DataOffset = frameHisdata.DataOffset + newDataCount; //加上数据增加的个数
  5041. for (var i in this.Frame.SubFrame)
  5042. {
  5043. var item = this.Frame.SubFrame[i].Frame;
  5044. item.Data = this.ChartPaint[0].Data;
  5045. if (i==0)
  5046. {
  5047. item.YSplitOperator.Symbol = this.Symbol;
  5048. item.YSplitOperator.Data = this.ChartPaint[0].Data; //K线数据
  5049. item.YSplitOperator.Period = this.Period; //周期
  5050. }
  5051. }
  5052. this.TitlePaint[0].Data = this.ChartPaint[0].Data; //动态标题
  5053. this.TitlePaint[0].Symbol = this.Symbol;
  5054. this.TitlePaint[0].Name = this.Name;
  5055. this.ChartCorssCursor.StringFormatX.Data = this.ChartPaint[0].Data; //十字光标
  5056. this.Frame.Data = this.ChartPaint[0].Data;
  5057. for (var i=0;i<this.OverlayChartPaint.length;++i) //主图股票数据绑定到叠加股票上
  5058. {
  5059. var item = this.OverlayChartPaint[i];
  5060. item.MainData = this.ChartPaint[0].Data;
  5061. }
  5062. this.ChartCorssCursor.StringFormatY.Symbol = this.Symbol;
  5063. }
  5064. //创建指定窗口指标
  5065. this.CreateWindowIndex = function (windowIndex)
  5066. {
  5067. this.WindowIndex[windowIndex].Create(this, windowIndex);
  5068. }
  5069. this.BindIndexData = function (windowIndex, hisData)
  5070. {
  5071. if (!this.WindowIndex[windowIndex]) return;
  5072. if (typeof (this.WindowIndex[windowIndex].RequestData) == "function") //数据需要另外下载的.
  5073. {
  5074. this.WindowIndex[windowIndex].RequestData(this, windowIndex, hisData);
  5075. return;
  5076. }
  5077. if (typeof (this.WindowIndex[windowIndex].ExecuteScript) == 'function') //脚本指标
  5078. {
  5079. this.WindowIndex[windowIndex].ExecuteScript(this, windowIndex, hisData);
  5080. return;
  5081. }
  5082. this.WindowIndex[windowIndex].BindData(this, windowIndex, hisData);
  5083. }
  5084. //执行指示(专家指示 五彩K线)
  5085. this.BindInstructionIndexData = function (hisData)
  5086. {
  5087. if (this.ColorIndex && typeof (this.ColorIndex.ExecuteScript) == 'function') //五彩K线
  5088. {
  5089. this.ColorIndex.ExecuteScript(this, 0, hisData);
  5090. }
  5091. if (this.TradeIndex && typeof (this.TradeIndex.ExecuteScript) == 'function') //交易指标
  5092. {
  5093. this.TradeIndex.ExecuteScript(this, 0, hisData);
  5094. }
  5095. }
  5096. //获取子窗口的所有画法
  5097. this.GetChartPaint = function (windowIndex)
  5098. {
  5099. var paint = new Array();
  5100. for (var i in this.ChartPaint)
  5101. {
  5102. if (i == 0) continue; //第1个K线数据除外
  5103. var item = this.ChartPaint[i];
  5104. if (item.ChartFrame == this.Frame.SubFrame[windowIndex].Frame)
  5105. paint.push(item);
  5106. }
  5107. return paint;
  5108. }
  5109. this.AutoUpdateEvent = function (bStart, explain) //自定更新事件, 是给websocket使用
  5110. {
  5111. var eventID = bStart ? JSCHART_EVENT_ID.RECV_START_AUTOUPDATE : JSCHART_EVENT_ID.RECV_STOP_AUTOUPDATE;
  5112. if (!this.mapEvent.has(eventID)) return;
  5113. var self = this;
  5114. var event = this.mapEvent.get(eventID);
  5115. var data = { Stock: { Symbol: this.Symbol, Name: this.Name, Right: this.Right, Period: this.Period }, Explain:explain };
  5116. if (bStart)
  5117. {
  5118. data.Callback = function (data) //数据到达更新回调
  5119. {
  5120. if (ChartData.IsDayPeriod(self.Period, true)) self.RecvRealtimeData(data);
  5121. else if (ChartData.IsMinutePeriod(self.Period, true)) self.RecvMinuteRealtimeData(data);
  5122. else if (ChartData.IsSecondPeriod(self.Period)) self.RecvMinuteRealtimeData(data);
  5123. }
  5124. }
  5125. event.Callback(event, data, this);
  5126. }
  5127. this.RequestHistoryData = function ()
  5128. {
  5129. var self = this;
  5130. this.CancelAutoUpdate();
  5131. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  5132. this.ChartSplashPaint.EnableSplash(true);
  5133. this.ResetDragDownload();
  5134. this.Draw();
  5135. if (this.NetworkFilter)
  5136. {
  5137. var obj =
  5138. {
  5139. Name: 'KLineChartContainer::RequestHistoryData', //类名::
  5140. Explain: '日K数据',
  5141. Request: {
  5142. Url: self.KLineApiUrl, Type: 'POST',
  5143. Data:
  5144. {
  5145. symbol: self.Symbol, count: self.MaxRequestDataCount, field: ["name", "symbol", "yclose", "open", "price", "high", "low", "vol"] ,
  5146. period:this.Period,
  5147. right:this.Right
  5148. }
  5149. },
  5150. Self: this,
  5151. PreventDefault: false
  5152. };
  5153. this.NetworkFilter(obj, function (data) {
  5154. self.ChartSplashPaint.EnableSplash(false);
  5155. self.RecvHistoryData(data);
  5156. self.AutoUpdateEvent(true, "KLineChartContainer::RequestHistoryData");
  5157. self.AutoUpdate();
  5158. });
  5159. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  5160. }
  5161. JSNetwork.HttpRequest({
  5162. url: this.KLineApiUrl,
  5163. data:
  5164. {
  5165. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  5166. "symbol": self.Symbol,
  5167. "start": -1,
  5168. "count": self.MaxRequestDataCount
  5169. },
  5170. method: 'POST',
  5171. dataType: 'json',
  5172. success: function (data) {
  5173. self.ChartSplashPaint.EnableSplash(false);
  5174. self.RecvHistoryData(data);
  5175. self.AutoUpdateEvent(true,"KLineChartContainer::RequestHistoryData");
  5176. self.AutoUpdate();
  5177. }
  5178. });
  5179. }
  5180. this.RecvHistoryData = function (recvData)
  5181. {
  5182. var data = recvData.data;
  5183. var aryDayData = KLineChartContainer.JsonDataToHistoryData(data);
  5184. //原始数据
  5185. var sourceData = new ChartData();
  5186. sourceData.Data = aryDayData;
  5187. sourceData.DataType = 0; //0=日线数据 1=分钟数据
  5188. sourceData.Symbol = data.symbol;
  5189. this.SourceData = sourceData;
  5190. if (this.BeforeBindMainData) this.BeforeBindMainData("RecvHistoryData");
  5191. //显示的数据
  5192. var bindData = new ChartData();
  5193. bindData.Data = aryDayData;
  5194. bindData.Right = this.Right;
  5195. bindData.Period = this.Period;
  5196. bindData.DataType = 0;
  5197. if (bindData.Right > 0 && !this.IsApiPeriod) //复权
  5198. {
  5199. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  5200. bindData.Data = rightData;
  5201. }
  5202. if (ChartData.IsDayPeriod(bindData.Period, false) && !this.IsApiPeriod) //周期数据
  5203. {
  5204. var periodData = bindData.GetPeriodData(bindData.Period);
  5205. bindData.Data = periodData;
  5206. }
  5207. //绑定数据
  5208. this.Symbol = data.symbol;
  5209. this.Name = data.name;
  5210. this.BindMainData(bindData, this.PageSize);
  5211. if (this.AfterBindMainData) this.AfterBindMainData("RecvHistoryData");
  5212. this.Frame.SetSizeChage(true); //数据到达通知坐标框架
  5213. var firstSubFrame; //主窗口
  5214. if (this.Frame.SubFrame[0]) firstSubFrame=this.Frame.SubFrame[0].Frame;
  5215. if (firstSubFrame && firstSubFrame.YSplitOperator)
  5216. {
  5217. firstSubFrame.YSplitOperator.Symbol = this.Symbol; //绑定代码
  5218. firstSubFrame.YSplitOperator.Data = this.ChartPaint[0].Data; //K线数据
  5219. firstSubFrame.YSplitOperator.Period=this.Period; //周期
  5220. }
  5221. //请求叠加数据 (主数据下载完再下载))
  5222. this.ReqeustKLineInfoData({ FunctionName:"RecvHistoryData" });
  5223. this.RequestOverlayHistoryData();
  5224. //刷新画图
  5225. this.UpdataDataoffset(); //更新数据偏移
  5226. this.UpdatePointByCursorIndex(); //更新十字光标位子
  5227. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  5228. this.Frame.SetSizeChage(true);
  5229. this.Draw();
  5230. this.BindInstructionIndexData(bindData); //执行指示脚本
  5231. for (var i = 0; i < this.Frame.SubFrame.length; ++i) //执行指标
  5232. {
  5233. this.BindIndexData(i, bindData);
  5234. }
  5235. //叠加指标
  5236. this.BindAllOverlayIndexData(bindData);
  5237. if (this.mapEvent.has(JSCHART_EVENT_ID.RECV_HISTROY_DATA))
  5238. {
  5239. var event = this.mapEvent.get(JSCHART_EVENT_ID.RECV_HISTROY_DATA);
  5240. var data = { HistoryData: bindData, Stock: { Symbol: this.Symbol, Name: this.Name } }
  5241. event.Callback(event, data, this);
  5242. }
  5243. else //老的回调暂时保留
  5244. {
  5245. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistroyData', this); //单词拼写错误, 请使用下面的回调
  5246. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistoryData', this);
  5247. }
  5248. }
  5249. this.RequestHistoryMinuteData = function ()
  5250. {
  5251. var self = this;
  5252. this.CancelAutoUpdate();
  5253. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  5254. this.ChartSplashPaint.EnableSplash(true);
  5255. this.ResetDragDownload();
  5256. this.Draw();
  5257. if (this.NetworkFilter)
  5258. {
  5259. var obj =
  5260. {
  5261. Name: 'KLineChartContainer::ReqeustHistoryMinuteData', //类名
  5262. Explain: '1分钟K线数据',
  5263. Request:
  5264. {
  5265. Url: self.MinuteKLineApiUrl, Type: 'POST', Data: {
  5266. symbol: self.Symbol, count: self.MaxRequestMinuteDayCount,
  5267. field: ["name", "symbol", "yclose", "open", "price", "high", "low", "vol"],
  5268. period:this.Period,
  5269. right:this.Right
  5270. }
  5271. },
  5272. Self: this,
  5273. PreventDefault: false
  5274. };
  5275. this.NetworkFilter(obj, function (data) {
  5276. self.ChartSplashPaint.EnableSplash(false);
  5277. self.RecvMinuteHistoryData(data);
  5278. self.AutoUpdateEvent(true,"KLineChartContainer::ReqeustHistoryMinuteData");
  5279. self.AutoUpdate();
  5280. });
  5281. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  5282. }
  5283. JSNetwork.HttpRequest({
  5284. url: this.MinuteKLineApiUrl,
  5285. data:
  5286. {
  5287. "field": ["name","symbol","yclose","open","price","high","low","vol"],
  5288. "symbol": self.Symbol,
  5289. "start": -1,
  5290. "count": self.MaxRequestMinuteDayCount
  5291. },
  5292. method: 'POST',
  5293. dataType: "json",
  5294. success: function (data)
  5295. {
  5296. self.ChartSplashPaint.EnableSplash(false);
  5297. self.RecvMinuteHistoryData(data);
  5298. self.AutoUpdateEvent(true,"KLineChartContainer::ReqeustHistoryMinuteData");
  5299. self.AutoUpdate();
  5300. }
  5301. });
  5302. }
  5303. this.ReqeustHistoryMinuteData=this.RequestHistoryMinuteData;
  5304. this.RecvMinuteHistoryData = function (recvData)
  5305. {
  5306. var data = recvData.data;
  5307. var aryDayData = KLineChartContainer.JsonDataToMinuteHistoryData(data);
  5308. //原始数据
  5309. var sourceData = new ChartData();
  5310. sourceData.Data = aryDayData;
  5311. sourceData.DataType = 1; //0=日线数据 1=分钟数据
  5312. sourceData.Symbol = data.symbol;
  5313. this.SourceData = sourceData;
  5314. if (this.BeforeBindMainData) this.BeforeBindMainData("RecvMinuteHistoryData");
  5315. //显示的数据
  5316. var bindData = new ChartData();
  5317. bindData.Data = aryDayData;
  5318. bindData.Right = this.Right;
  5319. bindData.Period = this.Period;
  5320. bindData.DataType = 1;
  5321. bindData.Symbol = data.symbol;
  5322. if (bindData.Right>0 && !this.IsApiPeriod && this.RightFormula>=1) //复权
  5323. {
  5324. var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula } );
  5325. bindData.Data=rightData;
  5326. }
  5327. if (ChartData.IsMinutePeriod(bindData.Period, false) && !this.IsApiPeriod) //周期数据
  5328. {
  5329. var periodData = bindData.GetPeriodData(bindData.Period);
  5330. bindData.Data = periodData;
  5331. }
  5332. //绑定数据
  5333. this.Symbol = data.symbol;
  5334. this.Name = data.name;
  5335. this.BindMainData(bindData, this.PageSize);
  5336. if (this.AfterBindMainData) this.AfterBindMainData("RecvMinuteHistoryData");
  5337. this.Frame.SetSizeChage(true);
  5338. var firstSubFrame; //主窗口
  5339. if (this.Frame.SubFrame[0]) firstSubFrame=this.Frame.SubFrame[0].Frame;
  5340. if (firstSubFrame && firstSubFrame.YSplitOperator)
  5341. {
  5342. firstSubFrame.YSplitOperator.Symbol = this.Symbol; //绑定代码
  5343. firstSubFrame.YSplitOperator.Data = this.ChartPaint[0].Data; //K线数据
  5344. }
  5345. for(var i=0; i<this.OverlayChartPaint.length; ++i) //叠加股票 清空
  5346. {
  5347. var item=this.OverlayChartPaint[i];
  5348. item.Data=null;
  5349. //item.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID;
  5350. }
  5351. //刷新画图
  5352. this.UpdataDataoffset(); //更新数据偏移
  5353. this.UpdatePointByCursorIndex(); //更新十字光标位子
  5354. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  5355. this.Frame.SetSizeChage(true);
  5356. this.Draw();
  5357. this.RequestOverlayHistoryMinuteData(); //请求叠加数据 (主数据下载完再下载)
  5358. this.BindInstructionIndexData(bindData); //执行指示脚本
  5359. for (var i = 0; i < this.Frame.SubFrame.length; ++i) //指标
  5360. {
  5361. this.BindIndexData(i, bindData);
  5362. }
  5363. //叠加指标
  5364. this.BindAllOverlayIndexData(bindData);
  5365. if (this.mapEvent.has(JSCHART_EVENT_ID.RECV_HISTROY_DATA))
  5366. {
  5367. var event = this.mapEvent.get(JSCHART_EVENT_ID.RECV_HISTROY_DATA);
  5368. var data = { HistoryData: bindData, Stock: { Symbol: this.Symbol, Name: this.Name } }
  5369. event.Callback(event, data, this);
  5370. }
  5371. else
  5372. {
  5373. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteHistoryData', this);
  5374. }
  5375. }
  5376. //请求实时行情数据
  5377. this.RequestRealtimeData = function ()
  5378. {
  5379. var self = this;
  5380. var arySymbol=[self.Symbol];
  5381. for(var i=0; i<this.OverlayChartPaint.length; ++i) //叠加的股票更新
  5382. {
  5383. var item=this.OverlayChartPaint[i];
  5384. if (!item.Symbol) continue;
  5385. if (!item.MainData) continue; //等待主图股票数据未下载完
  5386. if (item.Status!=OVERLAY_STATUS_ID.STATUS_FINISHED_ID) continue;
  5387. arySymbol.push(item.Symbol);
  5388. }
  5389. if (this.NetworkFilter)
  5390. {
  5391. var dateRange=null;
  5392. var hisData=this.ChartOperator_Temp_GetHistroyData();
  5393. if (hisData) dateRange=hisData.GetDateRange();
  5394. var obj =
  5395. {
  5396. Name: 'KLineChartContainer::RequestRealtimeData', //类名::函数名
  5397. Explain: '当天最新日线数据',
  5398. Request:
  5399. {
  5400. Url: self.RealtimeApiUrl, Data: {
  5401. symbol: arySymbol,
  5402. field: ["name", "symbol", "yclose", "open", "price", "high", "low", "vol", "amount", "date", "time"],
  5403. period:this.Period,
  5404. right:this.Right,
  5405. dateRange:dateRange
  5406. }, Type: 'POST'
  5407. },
  5408. Self: this,
  5409. PreventDefault: false
  5410. };
  5411. this.NetworkFilter(obj, function (data) {
  5412. self.RecvRealtimeData(data);
  5413. self.AutoUpdate();
  5414. });
  5415. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  5416. }
  5417. JSNetwork.HttpRequest({
  5418. url: this.RealtimeApiUrl,
  5419. data:
  5420. {
  5421. "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","time"],
  5422. "symbol": arySymbol,
  5423. "start": -1
  5424. },
  5425. method: 'POST',
  5426. dataType: "json",
  5427. async: true,
  5428. success: function (data) {
  5429. self.RecvRealtimeData(data);
  5430. self.AutoUpdate();
  5431. }
  5432. });
  5433. }
  5434. this.RecvRealtimeData = function (recvdata)
  5435. {
  5436. if (this.IsOnTouch == true) return; //正在操作中不更新数据
  5437. var data=recvdata.data;
  5438. var realtimeData = KLineChartContainer.JsonDataToRealtimeData(data, this.Symbol);
  5439. if (!realtimeData)
  5440. {
  5441. JSConsole.Chart.Log('[KLineChartContainer::RecvRealtimeData] recvdata error', recvdata);
  5442. return;
  5443. }
  5444. var item = this.SourceData.Data[this.SourceData.Data.length - 1]; //最新的一条数据
  5445. var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数
  5446. if (this.SourceData.Data.length==0) //第1条数据
  5447. {
  5448. var newItem =new HistoryData();
  5449. HistoryData.CopyTo(newItem, realtimeData);
  5450. this.SourceData.Data.push(newItem);
  5451. }
  5452. else if (item.Date == realtimeData.Date) //实时行情数据更新
  5453. {
  5454. JSConsole.Chart.Log('[KLineChartContainer::RecvRealtimeData] update kline by minute data', realtimeData);
  5455. HistoryData.CopyTo(item, realtimeData);
  5456. }
  5457. else if (item.Date < realtimeData.Date) //新增加数据
  5458. {
  5459. JSConsole.Chart.Log('[KLineChartContainer::RecvRealtimeData] insert kline by minute data', realtimeData);
  5460. var newItem = new HistoryData();
  5461. HistoryData.CopyTo(newItem, realtimeData);
  5462. //没有前收盘就用上一个数据的收盘价
  5463. if (!IFrameSplitOperator.IsNumber(newItem.YClose) && this.SourceData.Data.length>0)
  5464. newItem.YClose=this.SourceData.Data[this.SourceData.Data.length-1].YClose;
  5465. this.SourceData.Data.push(newItem);
  5466. }
  5467. else
  5468. {
  5469. return;
  5470. }
  5471. var bindData = new ChartData();
  5472. bindData.Data = this.SourceData.Data;
  5473. bindData.Period = this.Period;
  5474. bindData.Right = this.Right;
  5475. bindData.DataType = this.SourceData.DataType;
  5476. bindData.Symbol = this.Symbol;
  5477. if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period,true) && !this.IsApiPeriod) //复权(日线数据才复权)
  5478. {
  5479. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  5480. bindData.Data = rightData;
  5481. }
  5482. if (!this.IsApiPeriod)
  5483. {
  5484. if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理)
  5485. {
  5486. var periodData = bindData.GetPeriodData(bindData.Period);
  5487. bindData.Data = periodData;
  5488. }
  5489. }
  5490. //绑定数据
  5491. this.UpdateMainData(bindData, lastDataCount);
  5492. this.UpdateOverlayRealtimeData(data); //更新叠加股票数据
  5493. this.Frame.SetSizeChage(true);
  5494. this.BindInstructionIndexData(bindData); //执行指示脚本
  5495. for (var i = 0; i < this.Frame.SubFrame.length; ++i) {
  5496. this.BindIndexData(i, bindData);
  5497. }
  5498. //刷新画图
  5499. this.UpdataDataoffset(); //更新数据偏移
  5500. this.UpdatePointByCursorIndex(); //更新十字光标位子
  5501. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  5502. this.Frame.SetSizeChage(true);
  5503. this.Draw();
  5504. this.SendKLineUpdateEvent(bindData);
  5505. //叠加指标计算
  5506. this.BindAllOverlayIndexData(bindData);
  5507. }
  5508. this.UpdateOverlayRealtimeData=function(data)
  5509. {
  5510. if (!IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) return;
  5511. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  5512. {
  5513. var item=this.OverlayChartPaint[i];
  5514. if (!item.Symbol) continue;
  5515. if (!item.MainData) continue; //等待主图股票数据未下载完
  5516. if (item.Status!=OVERLAY_STATUS_ID.STATUS_FINISHED_ID) continue;
  5517. var realtimeData=KLineChartContainer.JsonDataToRealtimeData(data,item.Symbol); //获取叠加股票的最新数据
  5518. if (!realtimeData) continue;
  5519. var sourceData=item.SourceData; //叠加股票的所有数据
  5520. var latestData=sourceData.Data[sourceData.Data.length-1]; //最新的一条数据
  5521. if (latestData.Date==realtimeData.Date) //实时行情数据更新
  5522. {
  5523. JSConsole.Chart.Log('[KLineChartContainer::UpdateOverlayRealtimeData] update kline by minute data',realtimeData);
  5524. latestData.Close=realtimeData.Close;
  5525. latestData.High=realtimeData.High;
  5526. latestData.Low=realtimeData.Low;
  5527. latestData.Vol=realtimeData.Vol;
  5528. latestData.Amount=realtimeData.Amount;
  5529. }
  5530. else if (latestData.Date<realtimeData.Date) //新增加数据
  5531. {
  5532. JSConsole.Chart.Log('[KLineChartContainer::UpdateOverlayRealtimeData] insert kline by minute data',realtimeData);
  5533. var newItem =new HistoryData();
  5534. newItem.YClose=realtimeData.YClose;
  5535. newItem.Open=realtimeData.Open;
  5536. newItem.Close=realtimeData.Close;
  5537. newItem.High=realtimeData.High;
  5538. newItem.Low=realtimeData.Low;
  5539. newItem.Vol=realtimeData.Vol;
  5540. newItem.Amount=realtimeData.Amount;
  5541. newItem.Date=realtimeData.Date;
  5542. sourceData.Data.push(newItem);
  5543. }
  5544. else
  5545. {
  5546. continue;
  5547. }
  5548. var bindData=new ChartData();
  5549. bindData.Data=sourceData.Data;
  5550. bindData.Period=this.Period;
  5551. bindData.Right=this.Right;
  5552. bindData.DataType=0;
  5553. if (bindData.Right>0 && MARKET_SUFFIX_NAME.IsSHSZStockA(data.symbol) && !this.IsApiPeriod) //复权数据 ,A股才有有复权
  5554. {
  5555. var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  5556. bindData.Data=rightData;
  5557. }
  5558. var aryOverlayData=this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  5559. bindData.Data=aryOverlayData;
  5560. if (ChartData.IsDayPeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据
  5561. {
  5562. var periodData=bindData.GetPeriodData(bindData.Period);
  5563. bindData.Data=periodData;
  5564. }
  5565. item.Data=bindData;
  5566. }
  5567. }
  5568. this.GetHistoryDataCount = function ()
  5569. {
  5570. var frameHisdata = null;
  5571. if (!this.Frame.Data) frameHisdata = this.Frame.Data;
  5572. else if (this.Frame.SubFrame && this.Frame.SubFrame[0]) frameHisdata = this.Frame.SubFrame[0].Frame.Data;
  5573. if (!frameHisdata) return -1;
  5574. var lastDataCount = frameHisdata.Data.length; //上一个的数据长度
  5575. return lastDataCount;
  5576. }
  5577. this.RequestMinuteRealtimeData = function ()
  5578. {
  5579. var self = this;
  5580. var arySymbol=[self.Symbol];
  5581. for(var i=0; i<this.OverlayChartPaint.length; ++i) //叠加的股票更新
  5582. {
  5583. var item=this.OverlayChartPaint[i];
  5584. if (!item.Symbol) continue;
  5585. if (!item.MainData) continue; //等待主图股票数据未下载完
  5586. if (item.Status!=OVERLAY_STATUS_ID.STATUS_FINISHED_ID) continue;
  5587. arySymbol.push(item.Symbol);
  5588. }
  5589. if (this.NetworkFilter)
  5590. {
  5591. var dateRange=null;
  5592. var hisData=this.ChartOperator_Temp_GetHistroyData();
  5593. if (hisData) dateRange=hisData.GetDateRange();
  5594. var obj =
  5595. {
  5596. Name: 'KLineChartContainer::RequestMinuteRealtimeData', //类名::
  5597. Explain: '当天1分钟K线数据',
  5598. Request: {
  5599. Url: self.RealtimeApiUrl, Data: {
  5600. symbol: arySymbol,
  5601. field: ["name", "symbol", "price", "yclose", "minutecount", "minute", "date", "time"],
  5602. period:this.Period,
  5603. right:this.Right,
  5604. dateRange:dateRange
  5605. }, Type: 'POST'
  5606. },
  5607. Self: this,
  5608. PreventDefault: false
  5609. };
  5610. this.NetworkFilter(obj, function (data) {
  5611. self.RecvMinuteRealtimeData(data);
  5612. self.AutoUpdate();
  5613. });
  5614. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  5615. }
  5616. JSNetwork.HttpRequest({
  5617. url: this.RealtimeApiUrl,
  5618. data:
  5619. {
  5620. "field": ["name", "symbol", "price", "yclose", "minutecount", "minute", "date", "time"],
  5621. "symbol": arySymbol,
  5622. "start": -1
  5623. },
  5624. method: 'POST',
  5625. dataType: "json",
  5626. async: true,
  5627. success: function (data) {
  5628. self.RecvMinuteRealtimeData(data);
  5629. self.AutoUpdate();
  5630. }
  5631. });
  5632. }
  5633. this.SetSourceDatatLimit = function (aryLimit)
  5634. {
  5635. this.SourceDataLimit = new Map();
  5636. for (var i in aryLimit)
  5637. {
  5638. var item = aryLimit[i];
  5639. this.SourceDataLimit.set(item.Period, item.MaxCount); //每个周期缓存数据最大个数 key=周期 value=最大个数
  5640. JSConsole.Chart.Log(`[KLineChartContainer::SetSourceDatatLimit] Period=${item.Period}, MaxCount=${item.MaxCount}`);
  5641. }
  5642. }
  5643. this.ReduceSourceData = function ()
  5644. {
  5645. if (!this.SourceDataLimit) return;
  5646. if (!this.SourceDataLimit.has(this.Period)) return;
  5647. var limitCount = this.SourceDataLimit.get(this.Period);
  5648. if (limitCount < 50) return;
  5649. var frameHisdata = null;
  5650. if (!this.Frame.Data) frameHisdata = this.Frame.Data;
  5651. else if (this.Frame.SubFrame && this.Frame.SubFrame[0]) frameHisdata = this.Frame.SubFrame[0].Frame.Data;
  5652. if (!frameHisdata) return;
  5653. var dataOffset = frameHisdata.DataOffset;
  5654. var removeCount = 0;
  5655. while (this.SourceData.Data.length > limitCount)
  5656. {
  5657. this.SourceData.Data.shift();
  5658. --dataOffset;
  5659. ++removeCount;
  5660. }
  5661. if (removeCount > 0)
  5662. {
  5663. if (dataOffset < 0) dataOffset = 0;
  5664. frameHisdata.DataOffset = dataOffset;
  5665. JSConsole.Chart.Log(`[KLineChartContainer::ReduceSourceData] remove data ${removeCount}, dataOffset=${dataOffset}`);
  5666. }
  5667. }
  5668. this.RecvMinuteRealtimeData = function (recvData)
  5669. {
  5670. var data=recvData.data;
  5671. if (this.IsOnTouch == true) return; //正在操作中不更新数据
  5672. if (data.ver == 2.0)
  5673. {
  5674. this.RecvMinuteRealtimeDataV2(data); //v2.0数据版本
  5675. return;
  5676. }
  5677. if (!data.stock || !data.stock[0] || this.Symbol != data.stock[0].symbol) return;
  5678. var realtimeData = KLineChartContainer.JsonDataToMinuteRealtimeData(data);
  5679. if (!realtimeData) return;
  5680. if (this.IsApiPeriod) this.ReduceSourceData(); //减少数据
  5681. var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数
  5682. var lastSourceDataCount = this.SourceData.Data.length;
  5683. if (!this.SourceData.MergeMinuteData(realtimeData)) return;
  5684. JSConsole.Chart.Log(`[KLineChartContainer::RecvMinuteRealtimeData] update kline by 1 minute data [${lastSourceDataCount}->${this.SourceData.Data.length}]`);
  5685. var bindData = new ChartData();
  5686. bindData.Data = this.SourceData.Data;
  5687. bindData.Period = this.Period;
  5688. bindData.Right = this.Right;
  5689. bindData.DataType = this.SourceData.DataType;
  5690. bindData.Symbol = this.Symbol;
  5691. if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period,true) && !this.IsApiPeriod) //复权(日线数据才复权)
  5692. {
  5693. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  5694. bindData.Data = rightData;
  5695. }
  5696. if (!this.IsApiPeriod)
  5697. {
  5698. if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理)
  5699. {
  5700. var periodData = bindData.GetPeriodData(bindData.Period);
  5701. bindData.Data = periodData;
  5702. }
  5703. }
  5704. //绑定数据
  5705. this.UpdateMainData(bindData, lastDataCount);
  5706. this.Frame.SetSizeChage(true);
  5707. this.BindInstructionIndexData(bindData); //执行指示脚本
  5708. for (var i = 0; i < this.Frame.SubFrame.length; ++i) {
  5709. this.BindIndexData(i, bindData);
  5710. }
  5711. //刷新画图
  5712. this.UpdataDataoffset(); //更新数据偏移
  5713. this.UpdatePointByCursorIndex(); //更新十字光标位子
  5714. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  5715. this.Frame.SetSizeChage(true);
  5716. this.Draw();
  5717. this.SendKLineUpdateEvent(bindData);
  5718. //叠加指标计算
  5719. this.BindAllOverlayIndexData(bindData);
  5720. }
  5721. this.RecvMinuteRealtimeDataV2 = function (data) //新版本的
  5722. {
  5723. if (this.IsOnTouch == true) return; //正在操作中不更新数据
  5724. var aryMinuteData = KLineChartContainer.JsonDataToMinuteHistoryData(data);
  5725. if (!aryMinuteData || aryMinuteData.length <= 0) return;
  5726. if (this.IsApiPeriod) this.ReduceSourceData(); //减少数据
  5727. var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数
  5728. if (!this.SourceData.MergeMinuteData(aryMinuteData)) return;
  5729. JSConsole.Chart.Log(`[KLineChartContainer::RecvMinuteRealtimeDataV2] update kline by 1 minute data [${lastDataCount}->${this.SourceData.Data.length}]`);
  5730. var bindData = new ChartData();
  5731. bindData.Data = this.SourceData.Data;
  5732. bindData.Period = this.Period;
  5733. bindData.Right = this.Right;
  5734. bindData.DataType = this.SourceData.DataType;
  5735. bindData.Symbol = this.Symbol;
  5736. if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period, true) && !this.IsApiPeriod) //复权(日线数据才复权)
  5737. {
  5738. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  5739. bindData.Data = rightData;
  5740. }
  5741. if ((ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) && !this.IsApiPeriod) //周期数据 (0= 日线,4=1分钟线 不需要处理)
  5742. {
  5743. var periodData = bindData.GetPeriodData(bindData.Period);
  5744. bindData.Data = periodData;
  5745. }
  5746. //绑定数据
  5747. this.UpdateMainData(bindData, lastDataCount);
  5748. this.UpdateOverlayMinuteRealtimeData(data); //更新叠加股票数据
  5749. this.Frame.SetSizeChage(true);
  5750. this.BindInstructionIndexData(bindData); //执行指示脚本
  5751. for (var i = 0; i < this.Frame.SubFrame.length; ++i) {
  5752. this.BindIndexData(i, bindData);
  5753. }
  5754. //刷新画图
  5755. this.UpdataDataoffset(); //更新数据偏移
  5756. this.UpdatePointByCursorIndex(); //更新十字光标位子
  5757. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  5758. this.Frame.SetSizeChage(true);
  5759. this.Draw();
  5760. this.SendKLineUpdateEvent(bindData);
  5761. //更新叠加指标
  5762. this.BindAllOverlayIndexData(bindData);
  5763. }
  5764. //更新当天的全量分钟数据
  5765. this.UpdateOverlayMinuteRealtimeData=function(data)
  5766. {
  5767. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  5768. {
  5769. var item=this.OverlayChartPaint[i];
  5770. if (!item.Symbol) continue;
  5771. if (!item.MainData) continue; //等待主图股票数据未下载完
  5772. if (item.Status!=OVERLAY_STATUS_ID.STATUS_FINISHED_ID) continue;
  5773. if (data.ver==2.0)
  5774. var realtimeData=KLineChartContainer.JsonDataToMinuteRealtimeDataV2(data,item.Symbol); //获取叠加股票的最新数据
  5775. else
  5776. var realtimeData=KLineChartContainer.JsonDataToMinuteRealtimeData(data,item.Symbol); //获取叠加股票的最新数据
  5777. if (!realtimeData) continue;
  5778. var sourceData=item.SourceData; //叠加股票的所有数据
  5779. if (!sourceData.MergeMinuteData(realtimeData)) return;
  5780. var bindData=new ChartData();
  5781. bindData.Data=sourceData.Data;
  5782. bindData.Period=this.Period;
  5783. bindData.Right=this.Right;
  5784. bindData.DataType=0;
  5785. var aryOverlayData=this.SourceData.GetOverlayMinuteData(bindData.Data,this.IsApiPeriod); //和主图数据拟合以后的数据
  5786. bindData.Data=aryOverlayData;
  5787. if (ChartData.IsMinutePeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据
  5788. {
  5789. var periodData=bindData.GetPeriodData(bindData.Period);
  5790. bindData.Data=periodData;
  5791. }
  5792. item.Data=bindData;
  5793. }
  5794. }
  5795. this.SendKLineUpdateEvent = function (bindData)
  5796. {
  5797. var event = this.GetEvent(JSCHART_EVENT_ID.RECV_KLINE_UPDATE_DATA);
  5798. if (event && event.Callback)
  5799. {
  5800. var data = { HistoryData: bindData, Stock: { Symbol: this.Symbol, Name: this.Name } }
  5801. event.Callback(event, data, this);
  5802. return true;
  5803. }
  5804. return false;
  5805. }
  5806. this.ClearIndexPaint=function() //清空指标
  5807. {
  5808. if (this.Frame && this.Frame.SubFrame)
  5809. {
  5810. for(var i=0;i<this.Frame.SubFrame.length;++i)
  5811. {
  5812. this.DeleteIndexPaint(i, true);
  5813. var item=this.Frame.SubFrame[i];
  5814. for(var j=0; j<item.OverlayIndex.length; ++j ) //清空叠加指标
  5815. {
  5816. var overlayItem=item.OverlayIndex[j];
  5817. for(var k=0;k< overlayItem.ChartPaint.length;++k)
  5818. {
  5819. var overlayChart=overlayItem.ChartPaint[k];
  5820. if (overlayChart && overlayChart.OnDestroy) overlayChart.OnDestroy();
  5821. }
  5822. overlayItem.ChartPaint=[];
  5823. }
  5824. }
  5825. }
  5826. //清空叠加标题
  5827. for(var i=1;i<this.TitlePaint.length;++i)
  5828. {
  5829. var item=this.TitlePaint[i];
  5830. item.OverlayIndex=new Map();
  5831. }
  5832. }
  5833. //周期切换
  5834. this.ChangePeriod = function (period, option)
  5835. {
  5836. var isChangeKLineDrawType = false;
  5837. var right=null; //复权
  5838. if (option && option.KLine)
  5839. {
  5840. if (IFrameSplitOperator.IsNumber(option.KLine.DrawType)) isChangeKLineDrawType = true;
  5841. if (IFrameSplitOperator.IsNumber(option.KLine.Right)) right=option.KLine.Right;
  5842. };
  5843. if (this.Period == period)
  5844. {
  5845. if (isChangeKLineDrawType) this.ChangeKLineDrawType(option.KLine.DrawType);
  5846. return;
  5847. }
  5848. if (isChangeKLineDrawType) this.ChangeKLineDrawType(option.KLine.DrawType, false); //切换K线类型, 不重绘
  5849. var isDataTypeChange = true;
  5850. if (this.SourceData)
  5851. {
  5852. var isDataTypeChange=false;
  5853. if (period > CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END)
  5854. {
  5855. if (this.SourceData.DataType != 0) isDataTypeChange = true;
  5856. }
  5857. else if ((period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END) ||
  5858. (period > CUSTOM_SECOND_PERIOD_START && period <= CUSTOM_SECOND_PERIOD_END))
  5859. {
  5860. if (this.SourceData.DataType != 1) isDataTypeChange = true;
  5861. }
  5862. else
  5863. {
  5864. switch (period)
  5865. {
  5866. case 0: //日线
  5867. case 1: //周
  5868. case 2: //月
  5869. case 3: //年
  5870. case 21: //双周
  5871. if (this.SourceData.DataType != 0) isDataTypeChange = true;
  5872. break;
  5873. case 4: //1分钟
  5874. case 5: //5分钟
  5875. case 6: //15分钟
  5876. case 7: //30分钟
  5877. case 8: //60分钟
  5878. case 11: //2小时
  5879. case 12: //4小时
  5880. if (this.SourceData.DataType != 1) isDataTypeChange = true;
  5881. break;
  5882. }
  5883. }
  5884. }
  5885. this.Period = period;
  5886. if (right!=null) this.Right=right;
  5887. this.ClearCustomKLine();
  5888. if (isDataTypeChange == false && !this.IsApiPeriod)
  5889. {
  5890. this.Update();
  5891. return;
  5892. }
  5893. if (ChartData.IsDayPeriod(this.Period, true))
  5894. {
  5895. this.ClearIndexPaint();
  5896. this.CancelAutoUpdate(); //先停止更新
  5897. this.AutoUpdateEvent(false,"KLineChartContainer::ChangePeriod");
  5898. this.ResetOverlaySymbolStatus();
  5899. this.Frame.ClearYCoordinateMaxMin();
  5900. this.RequestHistoryData(); //请求日线数据
  5901. //this.ReqeustKLineInfoData();
  5902. }
  5903. else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period))
  5904. {
  5905. this.ClearIndexPaint();
  5906. this.CancelAutoUpdate(); //先停止更新
  5907. this.AutoUpdateEvent(false,"KLineChartContainer::ChangePeriod");
  5908. this.ResetOverlaySymbolStatus();
  5909. this.Frame.ClearYCoordinateMaxMin();
  5910. this.RequestHistoryMinuteData(); //请求分钟数据
  5911. }
  5912. }
  5913. //复权切换
  5914. this.ChangeRight = function (right)
  5915. {
  5916. if (!MARKET_SUFFIX_NAME.IsEnableRight(this.Period,this.Symbol,this.RightFormula)) return;
  5917. if (right < 0 || right > 2) return;
  5918. if (this.Right == right) return;
  5919. this.Right = right;
  5920. if (!this.IsApiPeriod)
  5921. {
  5922. this.Update();
  5923. return;
  5924. }
  5925. else
  5926. {
  5927. if (ChartData.IsDayPeriod(this.Period, true))
  5928. {
  5929. this.CancelAutoUpdate(); //先停止更新
  5930. this.AutoUpdateEvent(false,"KLineChartContainer::ChangeRight");
  5931. this.RequestHistoryData(); //请求日线数据
  5932. //this.ReqeustKLineInfoData();
  5933. }
  5934. else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period))
  5935. {
  5936. this.CancelAutoUpdate(); //先停止更新
  5937. this.AutoUpdateEvent(false,"KLineChartContainer::ChangeRight");
  5938. this.RequestHistoryMinuteData(); //请求分钟数据
  5939. }
  5940. }
  5941. }
  5942. //设置第1屏的起始日期
  5943. this.SetFirstShowDate=function(obj)
  5944. {
  5945. if (!obj || !obj.Date) return;
  5946. var option={ ID:JSCHART_OPERATOR_ID.OP_GOTO, Date:obj.Date };
  5947. if (IFrameSplitOperator.IsNumber(obj.Time)) option.Time=obj.Time;
  5948. if (IFrameSplitOperator.IsNumber(obj.PageSize)) option.PageSize=obj.PageSize;
  5949. this.ChartOperator(option);
  5950. }
  5951. //删除某一个窗口的指标 bCallDestory=是否调用图形销毁函数
  5952. this.DeleteIndexPaint = function (windowIndex, bCallDestroy)
  5953. {
  5954. if (!this.Frame.SubFrame[windowIndex]) return;
  5955. var subFrame=this.Frame.SubFrame[windowIndex].Frame;
  5956. if (!subFrame) return;
  5957. var paint=[]; //踢出当前窗口的指标画法
  5958. for (var i=0;i<this.ChartPaint.length; ++i)
  5959. {
  5960. let item = this.ChartPaint[i];
  5961. var bFind=(item.ChartFrame.Guid==subFrame.Guid || item.ChartFrame==subFrame);
  5962. if (i == 0 || !bFind)
  5963. {
  5964. paint.push(item);
  5965. }
  5966. else
  5967. {
  5968. if (bCallDestroy===true)
  5969. {
  5970. if (item && item.OnDestroy) item.OnDestroy(); //图形销毁
  5971. }
  5972. }
  5973. }
  5974. subFrame.YSpecificMaxMin = null; //清空指定最大最小值
  5975. subFrame.IsLocked = false; //解除上锁
  5976. subFrame.YSplitScale = null; //清空固定刻度
  5977. subFrame.YSplitOperator.SplitType=subFrame.YSplitOperator.DefaultSplitType; //还原Y坐标分割模式
  5978. this.ChartPaint = paint;
  5979. //清空东条标题
  5980. var titleIndex = windowIndex + 1;
  5981. this.TitlePaint[titleIndex].Data = [];
  5982. this.TitlePaint[titleIndex].Title = null;
  5983. }
  5984. this.ShowKLine = function (isShow) //显示隐藏主图K线
  5985. {
  5986. if (this.ChartPaint.length <= 0 || !this.ChartPaint[0]) return;
  5987. this.ChartPaint[0].IsShow = isShow;
  5988. }
  5989. this.SetInstructionData = function (type, instructionData) //设置指示数据
  5990. {
  5991. if (this.ChartPaint.length <= 0 || !this.ChartPaint[0]) return;
  5992. if (type == 2) //五彩K线
  5993. {
  5994. this.ChartPaint[0].ColorData = instructionData.Data;
  5995. }
  5996. else if (type == 1) //专家指示
  5997. {
  5998. this.ChartPaint[0].TradeData = { Sell: instructionData.Sell, Buy: instructionData.Buy };
  5999. }
  6000. }
  6001. this.ChangeInstructionIndex = function (indexName)
  6002. {
  6003. let scriptData = new JSCommonIndexScript.JSIndexScript();
  6004. let indexInfo = scriptData.Get(indexName);
  6005. if (!indexInfo) return;
  6006. if (indexInfo.InstructionType != 1 && indexInfo.InstructionType != 2) return;
  6007. this.ChangeInstructionScriptIndex(indexInfo);
  6008. }
  6009. this.ChangeInstructionScriptIndex = function (indexData)
  6010. {
  6011. if (indexData.InstructionType == 1) //交易系统
  6012. {
  6013. this.TradeIndex = new ScriptIndex(indexData.Name, indexData.Script, indexData.Args, indexData); //脚本执行
  6014. }
  6015. else if (indexData.InstructionType == 2) //五彩K线
  6016. {
  6017. this.ColorIndex = new ScriptIndex(indexData.Name, indexData.Script, indexData.Args, indexData); //脚本执行
  6018. }
  6019. else
  6020. {
  6021. return;
  6022. }
  6023. var bindData = this.ChartPaint[0].Data;
  6024. this.BindInstructionIndexData(bindData);
  6025. this.UpdataDataoffset(); //更新数据偏移
  6026. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6027. this.Draw();
  6028. }
  6029. this.CancelInstructionIndex = function () //取消指示数据
  6030. {
  6031. if (this.ChartPaint.length <= 0 || !this.ChartPaint[0]) return;
  6032. this.ColorIndex=null;
  6033. this.TradeIndex=null;
  6034. this.ChartPaint[0].ColorData = null; //五彩K线数据取消掉
  6035. this.ChartPaint[0].TradeData = null; //交易系统数据取消
  6036. this.UpdataDataoffset(); //更新数据偏移
  6037. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6038. this.Draw();
  6039. }
  6040. //切换成 脚本指标
  6041. this.ChangeScriptIndex = function (windowIndex, indexData)
  6042. {
  6043. this.DeleteIndexPaint(windowIndex, true);
  6044. this.WindowIndex[windowIndex] = new ScriptIndex(indexData.Name, indexData.Script, indexData.Args, indexData); //脚本执行
  6045. this.Frame.ClearYCoordinateMaxMin(windowIndex);
  6046. var bindData = this.ChartPaint[0].Data;
  6047. this.BindIndexData(windowIndex, bindData); //执行脚本
  6048. this.UpdataDataoffset(); //更新数据偏移
  6049. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6050. this.Draw();
  6051. }
  6052. //K线移动
  6053. this.OnKLinePageChange=function(eventid)
  6054. {
  6055. if (!this.ChartPaint[0]) return;
  6056. var bindData=this.ChartPaint[0].Data;
  6057. for(var i=0;i<this.WindowIndex.length;++i)
  6058. {
  6059. var item=this.WindowIndex[i];
  6060. if (!item) continue;
  6061. if (item.IsUsePageData===true) this.BindIndexData(i,bindData, { Type:1 }); //执行脚本
  6062. }
  6063. //叠加指标
  6064. for(var i=0;i<this.Frame.SubFrame.length;++i)
  6065. {
  6066. var item=this.Frame.SubFrame[i];
  6067. for(var j=0; j<item.OverlayIndex.length; ++j)
  6068. {
  6069. var overlayItem=item.OverlayIndex[j];
  6070. if (overlayItem && overlayItem.Script && overlayItem.Script.IsUsePageData==true)
  6071. this.BindOverlayIndexData(overlayItem,i,bindData);
  6072. }
  6073. }
  6074. }
  6075. //切换api指标
  6076. this.ChangeAPIIndex = function (windowIndex, indexData)
  6077. {
  6078. this.DeleteIndexPaint(windowIndex, true);
  6079. //使用API挂接指标数据 API:{ Name:指标名字, Script:指标脚本可以为空, Args:参数可以为空, Url:指标执行地址 }
  6080. var apiItem = indexData.API;
  6081. this.WindowIndex[windowIndex] = new APIScriptIndex(apiItem.Name, apiItem.Script, apiItem.Args, indexData);
  6082. this.Frame.ClearYCoordinateMaxMin(windowIndex);
  6083. var bindData = this.ChartPaint[0].Data;
  6084. this.BindIndexData(windowIndex, bindData); //执行脚本
  6085. this.UpdataDataoffset(); //更新数据偏移
  6086. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6087. this.Draw();
  6088. }
  6089. //切换指标 指定切换窗口指标
  6090. this.ChangeIndex = function (windowIndex, indexName, option)
  6091. {
  6092. if (option && option.API) //切换api指标
  6093. return this.ChangeAPIIndex(windowIndex, option);
  6094. var indexItem = JSIndexMap.Get(indexName);
  6095. if (!indexItem)
  6096. {
  6097. //查找系统指标
  6098. let scriptData = new JSCommonIndexScript.JSIndexScript();
  6099. let indexInfo = scriptData.Get(indexName);
  6100. if (!indexInfo) return;
  6101. if (indexInfo.IsMainIndex)
  6102. {
  6103. windowIndex = 0; //主图指标只能在主图显示
  6104. }
  6105. else
  6106. {
  6107. if (windowIndex == 0) windowIndex = 1; //幅图指标,不能再主图显示
  6108. }
  6109. let indexData = indexInfo;
  6110. if (option)
  6111. {
  6112. if (option.FloatPrecision >= 0) indexData.FloatPrecision = option.FloatPrecision;
  6113. if (option.StringFormat > 0) indexData.StringFormat = option.StringFormat;
  6114. if (option.Args) indexData.Args = option.Args;
  6115. if (IFrameSplitOperator.IsNumber(option.IsShortTitle)) indexData.IsShortTitle=option.IsShortTitle;
  6116. }
  6117. return this.ChangeScriptIndex(windowIndex, indexData, option);
  6118. }
  6119. //主图指标
  6120. if (indexItem.IsMainIndex)
  6121. {
  6122. if (windowIndex > 0) windowIndex = 0; //主图指标只能在主图显示
  6123. }
  6124. else
  6125. {
  6126. if (windowIndex == 0) windowIndex = 1; //幅图指标,不能再主图显示
  6127. }
  6128. var paint = new Array(); //踢出当前窗口的指标画法
  6129. for (var i in this.ChartPaint)
  6130. {
  6131. var item = this.ChartPaint[i];
  6132. if (i == 0 || item.ChartFrame != this.Frame.SubFrame[windowIndex].Frame) paint.push(item);
  6133. }
  6134. //清空指定最大最小值
  6135. this.Frame.SubFrame[windowIndex].Frame.YSpecificMaxMin = null;
  6136. this.Frame.SubFrame[windowIndex].Frame.YSplitScale=null;
  6137. this.ChartPaint = paint;
  6138. //清空东条标题
  6139. var titleIndex = windowIndex + 1;
  6140. this.TitlePaint[titleIndex].Data = [];
  6141. this.TitlePaint[titleIndex].Title = null;
  6142. this.WindowIndex[windowIndex] = indexItem.Create();
  6143. this.CreateWindowIndex(windowIndex);
  6144. var bindData = this.ChartPaint[0].Data;
  6145. this.BindIndexData(windowIndex, bindData);
  6146. this.UpdataDataoffset(); //更新数据偏移
  6147. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6148. this.Draw();
  6149. }
  6150. this.ChangeKLineDrawType = function (drawType, isDraw)
  6151. {
  6152. if (this.KLineDrawType == drawType) return;
  6153. this.KLineDrawType = drawType;
  6154. for (var i in this.ChartPaint)
  6155. {
  6156. var item = this.ChartPaint[i];
  6157. if (i == 0) item.DrawType = this.KLineDrawType;
  6158. else if (item.ClassName == 'ChartVolStick') item.KLineDrawType = this.KLineDrawType
  6159. }
  6160. for(var i=0; i<this.OverlayChartPaint.length; ++i) //叠加K线样式修改
  6161. {
  6162. var item=this.OverlayChartPaint[i];
  6163. item.DrawType=this.KLineDrawType;
  6164. }
  6165. if (isDraw == false) return;
  6166. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6167. this.Frame.SetSizeChage(true);
  6168. this.Draw();
  6169. }
  6170. this.ChangeIndexTemplate = function (option) //切换指标模板 可以设置指标窗口个数 每个窗口的指标
  6171. {
  6172. if (!option.Windows) return;
  6173. var count = option.Windows.length;
  6174. if (count <= 0) return;
  6175. var currentLength = this.Frame.SubFrame.length;
  6176. var period=null, right=null, symbol=null;
  6177. if (option.KLine)
  6178. {
  6179. if (IFrameSplitOperator.IsNumber(option.KLine.Period) && option.KLine.Period!=this.Period) period=option.KLine.Period; //周期
  6180. if (IFrameSplitOperator.IsNumber(option.KLine.Right) && option.KLine.Right!=this.Right) right=option.KLine.Right; //复权
  6181. }
  6182. if (option.Symbol) symbol=option.Symbol;
  6183. var bRefreshData= (period!=null || right!=null || symbol!=null);
  6184. for (var i = 0; i < currentLength; ++i) //清空所有的指标图型
  6185. {
  6186. this.DeleteIndexPaint(i, true);
  6187. var frame = this.Frame.SubFrame[i];
  6188. frame.YSpecificMaxMin = null;
  6189. frame.IsLocked = false;
  6190. frame.YSplitScale = null;
  6191. }
  6192. if (currentLength > count)
  6193. {
  6194. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME);
  6195. for(var i=currentLength-1;i>=count;--i)
  6196. {
  6197. if (event && event.Callback)
  6198. {
  6199. var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i };
  6200. event.Callback(event, sendData, this);
  6201. }
  6202. }
  6203. this.Frame.SubFrame.splice(count, currentLength - count);
  6204. this.WindowIndex.splice(count, currentLength - count);
  6205. this.TitlePaint.splice(count+1,currentLength-count);
  6206. }
  6207. else
  6208. {
  6209. for (var i = currentLength; i < count; ++i) //创建新的指标窗口
  6210. {
  6211. var subFrame = this.CreateSubFrameItem(i);
  6212. this.Frame.SubFrame[i] = subFrame;
  6213. var titlePaint = new DynamicChartTitlePainting();
  6214. titlePaint.Frame = this.Frame.SubFrame[i].Frame;
  6215. titlePaint.Canvas = this.Canvas;
  6216. titlePaint.LanguageID = this.LanguageID;
  6217. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  6218. this.TitlePaint[i + 1] = titlePaint;
  6219. }
  6220. }
  6221. var systemScript = new JSCommonIndexScript.JSIndexScript();
  6222. for (var i = 0; i < count; ++i)
  6223. {
  6224. var windowIndex = i;
  6225. var item=option.Windows[i];
  6226. var frameItem=null;
  6227. if(option.Frame && option.Frame.length>i) frameItem=option.Frame[i];
  6228. var titleIndex = windowIndex + 1;
  6229. this.TitlePaint[titleIndex].Data = [];
  6230. this.TitlePaint[titleIndex].Title = null;
  6231. this.DeleteWindowsOverlayIndex(i); //清空叠加指标
  6232. if (item.Script) //自定义指标
  6233. {
  6234. this.WindowIndex[i]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行
  6235. }
  6236. else if (item.API) //后台指标
  6237. {
  6238. var apiItem=item.API;
  6239. this.WindowIndex[i]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item);
  6240. }
  6241. else
  6242. {
  6243. var indexID = item.Index;
  6244. var indexItem = JSIndexMap.Get(indexID);
  6245. if (indexItem)
  6246. {
  6247. this.WindowIndex[i] = indexItem.Create();
  6248. this.CreateWindowIndex(windowIndex);
  6249. }
  6250. else
  6251. {
  6252. var indexInfo = systemScript.Get(indexID);
  6253. if (indexInfo)
  6254. {
  6255. JSIndexScript.ModifyAttribute(indexInfo,item);
  6256. this.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行
  6257. }
  6258. }
  6259. }
  6260. this.SetSubFrameAttribute(this.Frame.SubFrame[i], item, frameItem);
  6261. }
  6262. //最后一个显示X轴坐标
  6263. for (var i = 0; i < this.Frame.SubFrame.length; ++i)
  6264. {
  6265. var item = this.Frame.SubFrame[i].Frame;
  6266. if (i == this.Frame.SubFrame.length - 1) item.XSplitOperator.ShowText = true;
  6267. else item.XSplitOperator.ShowText = false;
  6268. }
  6269. //叠加指标
  6270. var aryOverlayIndex=[];
  6271. if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
  6272. {
  6273. for(var i=0;i<option.OverlayIndex.length;++i)
  6274. {
  6275. var item=option.OverlayIndex[i];
  6276. if (item.Index) item.IndexName=item.Index;
  6277. if (item.Windows>=0) item.WindowIndex=item.Windows;
  6278. var overlay=this.CreateOverlayWindowsIndex(item);
  6279. if (!overlay) continue;
  6280. aryOverlayIndex.push({ WindowsIndex:item.WindowIndex, Overlay:overlay });
  6281. }
  6282. }
  6283. this.Frame.SetSizeChage(true);
  6284. if (!bRefreshData)
  6285. {
  6286. var bindData = this.ChartPaint[0].Data;
  6287. for(var i=0; i<count; ++i) //重新请求指标
  6288. {
  6289. this.BindIndexData(i, bindData);
  6290. }
  6291. for(var i=0;i<aryOverlayIndex.length;++i)
  6292. {
  6293. var item=aryOverlayIndex[i];
  6294. this.BindOverlayIndexData(item.Overlay,item.WindowsIndex,bindData);
  6295. }
  6296. this.UpdataDataoffset(); //更新数据偏移
  6297. this.ResetFrameXYSplit();
  6298. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6299. this.Draw();
  6300. }
  6301. else
  6302. {
  6303. if (!symbol) symbol=this.Symbol;
  6304. var optionData={ KLine:{} };
  6305. if (IFrameSplitOperator.IsNumber(period)) optionData.KLine.Period=period;
  6306. if (IFrameSplitOperator.IsNumber(right)) optionData.KLine.Right=right;
  6307. this.ChangeSymbol(symbol, optionData);
  6308. }
  6309. }
  6310. this.RemoveIndexWindow=function(id)
  6311. {
  6312. JSConsole.Chart.Log('[KLineChartContainer::RemoveIndexWindow] remove id', id);
  6313. if (id==0) return;
  6314. if (!this.Frame.SubFrame) return;
  6315. if (id>=this.Frame.SubFrame.length) return;
  6316. var delFrame=this.Frame.SubFrame[id].Frame;
  6317. this.DeleteIndexPaint(id, true);
  6318. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME);
  6319. if (event && event.Callback)
  6320. {
  6321. var sendData={ SubFrame:this.Frame.SubFrame[id], WindowIndex:id };
  6322. event.Callback(event, sendData, this);
  6323. }
  6324. this.Frame.SubFrame.splice(id,1);
  6325. this.WindowIndex.splice(id,1);
  6326. this.TitlePaint.splice(id+1,1); //删除对应的动态标题
  6327. for(var i=0;i<this.Frame.SubFrame.length;++i)
  6328. {
  6329. var item=this.Frame.SubFrame[i].Frame;
  6330. if (i==this.Frame.SubFrame.length-1) item.XSplitOperator.ShowText=true;
  6331. else item.XSplitOperator.ShowText=false;
  6332. item.Identify=i;
  6333. }
  6334. if (this.ChartDrawPicture.length>0)
  6335. {
  6336. var aryDrawPicture=[];
  6337. for(var i=0;i<this.ChartDrawPicture.length;++i)
  6338. {
  6339. var item=this.ChartDrawPicture[i];
  6340. if (item.Frame==delFrame) continue;
  6341. aryDrawPicture.push(item);
  6342. }
  6343. this.ChartDrawPicture=aryDrawPicture;
  6344. }
  6345. this.Frame.SetSizeChage(true);
  6346. this.UpdateFrameMaxMin();
  6347. this.ResetFrameXYSplit();
  6348. this.Draw();
  6349. }
  6350. this.CreateExtendChart = function (name, option) //创建扩展图形
  6351. {
  6352. var chart;
  6353. switch (name)
  6354. {
  6355. case 'KLineTooltip':
  6356. if (option.Create && typeof(option.Create)=='function') chart=option.Create();
  6357. else chart = new KLineTooltipPaint();
  6358. chart.Canvas = this.Canvas;
  6359. chart.ChartBorder = this.Frame.ChartBorder;
  6360. chart.ChartFrame = this.Frame;
  6361. chart.HQChart = this;
  6362. option.LanguageID = this.LanguageID;
  6363. chart.SetOption(option);
  6364. this.ExtendChartPaint.push(chart);
  6365. return chart;
  6366. case '背景图':
  6367. chart = new BackgroundPaint();
  6368. chart.Canvas = this.Canvas;
  6369. chart.ChartBorder = this.Frame.ChartBorder;
  6370. chart.ChartFrame = this.Frame;
  6371. chart.HQChart = this;
  6372. chart.SetOption(option);
  6373. this.ExtendChartPaint.push(chart);
  6374. return chart;
  6375. default:
  6376. chart=g_ExtendChartPaintFactory.Create(name);
  6377. if (!chart) return null;
  6378. chart.Canvas=this.Canvas;
  6379. chart.ChartBorder=this.Frame.ChartBorder;
  6380. chart.ChartFrame=this.Frame;
  6381. chart.HQChart=this;
  6382. chart.SetOption(option);
  6383. this.ExtendChartPaint.push(chart);
  6384. return chart;
  6385. }
  6386. }
  6387. //锁|解锁指标 { Index:指标名字,IsLocked:是否要锁上,Callback:回调 }
  6388. this.LockIndex = function (lockData) {
  6389. if (!lockData) return;
  6390. if (!lockData.IndexName) return;
  6391. for (let i in this.WindowIndex) {
  6392. let item = this.WindowIndex[i];
  6393. if (!item) conintue;
  6394. if (item.Name == lockData.IndexName) {
  6395. item.SetLock(lockData);
  6396. this.Update();
  6397. break;
  6398. }
  6399. }
  6400. }
  6401. this.TryClickLock = function (x, y)
  6402. {
  6403. for (let i in this.Frame.SubFrame)
  6404. {
  6405. var item = this.Frame.SubFrame[i];
  6406. if (!item.Frame.IsLocked) continue;
  6407. if (!item.Frame.LockPaint) continue;
  6408. var tooltip = new TooltipData();
  6409. if (!item.Frame.LockPaint.GetTooltipData(x, y, tooltip)) continue;
  6410. tooltip.HQChart = this;
  6411. if (tooltip.Data.Callback) tooltip.Data.Callback(tooltip);
  6412. return true;
  6413. }
  6414. return false;
  6415. }
  6416. this.TryClickIndexTitle=function(x,y)
  6417. {
  6418. for(var i in this.TitlePaint)
  6419. {
  6420. var item=this.TitlePaint[i];
  6421. if (!item.IsClickTitle) continue;
  6422. if (!item.IsClickTitle(x,y)) continue;
  6423. var data={ Point:{X:x, Y:y}, Title:item.Title, FrameID:item.Frame.Identify };
  6424. JSConsole.Chart.Log('[KLineChartContainer::TryClickIndexTitle] click title ', data);
  6425. var event=this.GetEvent(JSCHART_EVENT_ID.ON_CLICK_INDEXTITLE);
  6426. if (event && event.Callback) event.Callback(event,data,this);
  6427. return true;
  6428. }
  6429. return false;
  6430. }
  6431. this.StopAutoUpdate = function ()
  6432. {
  6433. this.IsAutoUpdate = false;
  6434. this.CancelAutoUpdate();
  6435. this.AutoUpdateEvent(false,"KLineChartContainer::StopAutoUpdate");
  6436. }
  6437. this.Update = function ()
  6438. {
  6439. if (!this.SourceData) return;
  6440. if (this.BeforeBindMainData) this.BeforeBindMainData('Update');
  6441. var bindData = new ChartData();
  6442. bindData.Data = this.SourceData.Data;
  6443. bindData.Period = this.Period;
  6444. bindData.Right = this.Right;
  6445. bindData.DataType = this.SourceData.DataType;
  6446. bindData.Symbol = this.Symbol;
  6447. if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period, true)) //复权(日线数据才复权)
  6448. {
  6449. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  6450. bindData.Data = rightData;
  6451. }
  6452. else if (bindData.Right>0 && ChartData.IsMinutePeriod(bindData.Period,true) && this.RightFormula>=1) //复权(分钟数据复权, 复权因子模式)
  6453. {
  6454. var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  6455. bindData.Data=rightData;
  6456. }
  6457. if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理))
  6458. {
  6459. var periodData = bindData.GetPeriodData(bindData.Period);
  6460. bindData.Data = periodData;
  6461. }
  6462. //绑定数据
  6463. this.BindMainData(bindData, this.PageSize);
  6464. if (this.AfterBindMainData) this.AfterBindMainData("Update");
  6465. var firstSubFrame=null;
  6466. for (var i = 0; i < this.Frame.SubFrame.length; ++i)
  6467. {
  6468. if (i==0) firstSubFrame=this.Frame.SubFrame[i].Frame;
  6469. this.BindIndexData(i, bindData);
  6470. }
  6471. //绑定K线数据到Y轴分割
  6472. if (firstSubFrame && firstSubFrame.YSplitOperator)
  6473. {
  6474. firstSubFrame.YSplitOperator.Symbol=this.Symbol;
  6475. firstSubFrame.YSplitOperator.Data=this.ChartPaint[0].Data; //K线数据
  6476. firstSubFrame.YSplitOperator.Period=this.Period; //周期
  6477. }
  6478. //叠加数据周期调整
  6479. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  6480. {
  6481. var item=this.OverlayChartPaint[i];
  6482. if (!item.SourceData) continue;
  6483. if (ChartData.IsMinutePeriod(this.Period, true)) //分钟不支持 清空掉
  6484. {
  6485. var bindData=new ChartData();
  6486. bindData.Data=item.SourceData.Data;
  6487. bindData.Period=this.Period;
  6488. bindData.Right=this.Right;
  6489. var aryOverlayData=this.SourceData.GetOverlayMinuteData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  6490. bindData.Data=aryOverlayData;
  6491. if (ChartData.IsMinutePeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据
  6492. {
  6493. var periodData=bindData.GetPeriodData(bindData.Period);
  6494. bindData.Data=periodData;
  6495. }
  6496. item.Data=bindData;
  6497. }
  6498. else
  6499. {
  6500. var bindData = new ChartData();
  6501. bindData.Data = item.SourceData.Data;
  6502. bindData.Period = this.Period;
  6503. bindData.Right = this.Right;
  6504. if (bindData.Right > 0 && MARKET_SUFFIX_NAME.IsSHSZStockA(item.Symbol)) //复权数据
  6505. {
  6506. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  6507. bindData.Data = rightData;
  6508. }
  6509. var aryOverlayData = this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  6510. bindData.Data = aryOverlayData;
  6511. if (ChartData.IsDayPeriod(bindData.Period, false)) //周期数据
  6512. {
  6513. var periodData = bindData.GetPeriodData(bindData.Period);
  6514. bindData.Data = periodData;
  6515. }
  6516. item.Data=bindData;
  6517. }
  6518. }
  6519. this.ReqeustKLineInfoData({FunctionName:"Update"});
  6520. //刷新画图
  6521. this.UpdataDataoffset(); //更新数据偏移
  6522. this.UpdatePointByCursorIndex(); //更新十字光标位子
  6523. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6524. this.Frame.SetSizeChage(true);
  6525. this.Draw();
  6526. }
  6527. //切换股票代码 option={ KLine:{Right:, Period: } }
  6528. this.ChangeSymbol = function (symbol, option)
  6529. {
  6530. this.CancelAutoUpdate(); //先停止更新
  6531. this.AutoUpdateEvent(false,"KLineChartContainer::ChangeSymbol");
  6532. this.ClearCustomKLine();
  6533. this.Frame.ClearYCoordinateMaxMin();
  6534. this.Symbol = symbol;
  6535. if (option && option.KLine)
  6536. {
  6537. var item=option.KLine;
  6538. if (IFrameSplitOperator.IsNumber(item.Right)) this.Right=item.Right;
  6539. if (IFrameSplitOperator.IsNumber(item.Period)) this.Period=item.Period;
  6540. }
  6541. if (IsIndexSymbol(symbol)) this.Right = 0; //指数没有复权
  6542. this.ClearIndexPaint();
  6543. if (ChartData.IsDayPeriod(this.Period, true))
  6544. {
  6545. this.ResetOverlaySymbolStatus();
  6546. this.RequestHistoryData(); //请求日线数据
  6547. //this.ReqeustKLineInfoData();
  6548. }
  6549. else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period))
  6550. {
  6551. this.ResetOverlaySymbolStatus();
  6552. this.RequestHistoryMinuteData(); //请求分钟数据
  6553. }
  6554. }
  6555. this.ReqeustKLineInfoData = function (obj)
  6556. {
  6557. if (obj && obj.FunctionName=="RecvDragDayData") //增量更新
  6558. {
  6559. obj.Update=true;
  6560. }
  6561. else
  6562. {
  6563. if (this.ChartPaint.length > 0)
  6564. {
  6565. var klinePaint = this.ChartPaint[0];
  6566. klinePaint.InfoData = new Map();
  6567. }
  6568. obj.Update=false;
  6569. }
  6570. //信息地雷信息
  6571. for (var i in this.ChartInfo)
  6572. {
  6573. this.ChartInfo[i].RequestData(this,obj);
  6574. }
  6575. }
  6576. //设置K线信息地雷
  6577. this.SetKLineInfo = function (aryInfo, bUpdate)
  6578. {
  6579. this.ChartInfo = []; //清空信息地雷
  6580. for (var i=0; i<aryInfo.length; ++i)
  6581. {
  6582. var infoItem = JSKLineInfoMap.Get(aryInfo[i]);
  6583. if (!infoItem) continue;
  6584. var item = infoItem.Create();
  6585. item.MaxRequestDataCount = this.MaxRequestDataCount;
  6586. this.ChartInfo.push(item);
  6587. }
  6588. if (bUpdate == true) this.ReqeustKLineInfoData({ FunctionName:"SetKLineInfo" });
  6589. }
  6590. //添加信息地雷
  6591. this.AddKLineInfo=function(infoName, bUpdate)
  6592. {
  6593. var classInfo=JSKLineInfoMap.GetClassInfo(infoName);
  6594. if (!classInfo)
  6595. {
  6596. console.warn("[KLineChartContainer::AddKLineInfo] can't find infoname=", infoName);
  6597. return;
  6598. }
  6599. for(var i=0; i<this.ChartInfo.length; ++i)
  6600. {
  6601. var item=this.ChartInfo[i];
  6602. if (item.ClassName==classInfo.ClassName) //已经存在
  6603. return;
  6604. }
  6605. var infoItem=JSKLineInfoMap.Get(infoName);
  6606. if (!infoItem) return;
  6607. var item=infoItem.Create();
  6608. item.MaxRequestDataCount=this.MaxRequestDataCount;
  6609. this.ChartInfo.push(item);
  6610. if (bUpdate==true)
  6611. {
  6612. item.RequestData(this); //这个页面全部刷新
  6613. }
  6614. }
  6615. //删除信息地理
  6616. this.DeleteKLineInfo=function(infoName)
  6617. {
  6618. var classInfo=JSKLineInfoMap.GetClassInfo(infoName);
  6619. if (!classInfo)
  6620. {
  6621. console.warn(`[KLineChartContainer::DeleteKLineInfo] can't find infoname=${infoName}`);
  6622. return;
  6623. }
  6624. for(var i=0; i<this.ChartInfo.length; ++i)
  6625. {
  6626. var item=this.ChartInfo[i];
  6627. if (item.ClassName==classInfo.ClassName)
  6628. {
  6629. this.ChartInfo.splice(i,1);
  6630. this.UpdataChartInfo();
  6631. this.Draw();
  6632. break;
  6633. }
  6634. }
  6635. }
  6636. this.SetPolicyInfo = function (aryPolicy, bUpdate)
  6637. {
  6638. if (!aryPolicy || !aryPolicy.length) return;
  6639. var infoItem = JSKLineInfoMap.Get('策略选股');
  6640. if (!infoItem) return;
  6641. var policyInfo = infoItem.Create();
  6642. policyInfo.SetPolicyList(aryPolicy);
  6643. policyInfo.MaxRequestDataCount = this.MaxRequestDataCount;
  6644. this.ChartInfo.push(policyInfo);
  6645. if (bUpdate == true) this.ReqeustKLineInfoData();
  6646. }
  6647. //叠加股票
  6648. this.OverlaySymbol = function (symbol,option)
  6649. {
  6650. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  6651. {
  6652. var item=this.OverlayChartPaint[i];
  6653. if (item.Symbol===symbol)
  6654. {
  6655. console.warn(`[KLineChartContainer::OverlaySymbol] overlay symbol=${symbol} exist.`)
  6656. return false;
  6657. }
  6658. }
  6659. var paint=new ChartOverlayKLine();
  6660. paint.Canvas=this.Canvas;
  6661. paint.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder;
  6662. paint.ChartFrame=this.Frame.SubFrame[0].Frame;
  6663. paint.Name="Overlay-KLine";
  6664. paint.DrawType=this.KLineDrawType;
  6665. paint.Symbol=symbol;
  6666. paint.Identify=`Overlay-KLine-${symbol}`;
  6667. if (option && option.Color) paint.Color=option.Color;
  6668. else paint.Color=g_JSChartResource.OverlaySymbol.Color[g_JSChartResource.OverlaySymbol.Random%g_JSChartResource.OverlaySymbol.Color.length];
  6669. paint.SetOption(option);
  6670. ++g_JSChartResource.OverlaySymbol.Random;
  6671. if (this.ChartPaint[0] && this.ChartPaint[0].Data && this.SourceData) paint.MainData=this.ChartPaint[0].Data; //绑定主图数据
  6672. this.OverlayChartPaint.push(paint);
  6673. if (ChartData.IsDayPeriod(this.Period, true)) this.RequestOverlayHistoryData(); //请求日线数据
  6674. else if (ChartData.IsMinutePeriod(this.Period,true)) this.RequestOverlayHistoryMinuteData(); //请求分钟历史数据
  6675. return true;
  6676. }
  6677. this.GetRequestDataCount = function () //K线请求数据个数 (由于可以拖拽下载历史数据,所有原来固定个数的就不能用了)
  6678. {
  6679. var result = { MaxRequestDataCount: this.MaxRequestDataCount, MaxRequestMinuteDayCount: this.MaxRequestMinuteDayCount };
  6680. if (!this.SourceData || !this.SourceData.Data || this.SourceData.Data.length <= 0) return result;
  6681. if (ChartData.IsDayPeriod(this.Period, true))
  6682. {
  6683. var lCount = this.SourceData.Data.length;
  6684. if (lCount > result.MaxRequestDataCount) result.MaxRequestDataCount = lCount;
  6685. }
  6686. else if (ChartData.IsMinutePeriod(this.Period, true))
  6687. {
  6688. var date=null;
  6689. var lCount=0;
  6690. for(var i=0;i<this.SourceData.Data.length; ++i)
  6691. {
  6692. var item=this.SourceData.Data[i];
  6693. if (item.Date!=date) ++lCount;
  6694. date=item.Date;
  6695. }
  6696. if (lCount>result.MaxRequestMinuteDayCount) result.MaxRequestMinuteDayCount=lCount;
  6697. }
  6698. return result;
  6699. }
  6700. this.RequestSingleOverlayHistoryData=function(symbol, dataCount, firstDate, item)
  6701. {
  6702. var self = this;
  6703. item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID;
  6704. if (this.NetworkFilter)
  6705. {
  6706. var obj=
  6707. {
  6708. Name:'KLineChartContainer::RequestOverlayHistoryData', //类名::
  6709. Explain:'叠加股票日K线数据',
  6710. Request:{ Url:self.KLineApiUrl, Data: { symbol: symbol, count: dataCount.MaxRequestDataCount,"first":{ date: firstDate },
  6711. field:["name","symbol","yclose","open","price","high",'vol','amount'] }, Type:'POST' },
  6712. Self:this,
  6713. PreventDefault:false
  6714. };
  6715. this.NetworkFilter(obj, function(data)
  6716. {
  6717. item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID;
  6718. self.RecvOverlayHistoryData(data,item);
  6719. });
  6720. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  6721. }
  6722. }
  6723. this.RequestOverlayHistoryData = function ()
  6724. {
  6725. if (!this.OverlayChartPaint.length) return;
  6726. if (!this.SourceData || !this.SourceData.Data) return; //主图数据还没有到完
  6727. var dataCount=this.GetRequestDataCount();
  6728. var firstDate=this.SourceData.Data[0].Date;
  6729. for(var i=0;i<this.OverlayChartPaint.length;++i)
  6730. {
  6731. var item=this.OverlayChartPaint[i];
  6732. if (!item.MainData) continue; //等待主图股票数据未下载完
  6733. if (item.Status!=OVERLAY_STATUS_ID.STATUS_NONE_ID) continue;
  6734. var symbol=item.Symbol;
  6735. if (!symbol) continue;
  6736. this.RequestSingleOverlayHistoryData(symbol, dataCount, firstDate, item);
  6737. }
  6738. }
  6739. this.RecvOverlayHistoryData = function (recvData, paint)
  6740. {
  6741. if (paint.IsDelete) return;
  6742. var data = recvData.data;
  6743. var aryDayData = KLineChartContainer.JsonDataToHistoryData(data);
  6744. //原始叠加数据
  6745. var sourceData = new ChartData();
  6746. sourceData.Data = aryDayData;
  6747. var bindData = new ChartData();
  6748. bindData.Data = aryDayData;
  6749. bindData.Period = this.Period;
  6750. bindData.Right = this.Right;
  6751. if (bindData.Right > 0 && !IsIndexSymbol(data.symbol)) //复权数据 ,指数没有复权)
  6752. {
  6753. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  6754. bindData.Data = rightData;
  6755. }
  6756. var aryOverlayData = this.SourceData.GetOverlayData(bindData.Data); //和主图数据拟合以后的数据
  6757. bindData.Data = aryOverlayData;
  6758. if (ChartData.IsDayPeriod(bindData.Period, false)) //周期数据
  6759. {
  6760. var periodData = bindData.GetPeriodData(bindData.Period);
  6761. bindData.Data = periodData;
  6762. }
  6763. paint.Data = bindData;
  6764. paint.SourceData = sourceData;
  6765. paint.Title = data.name;
  6766. paint.Symbol = data.symbol;
  6767. paint.Status=OVERLAY_STATUS_ID.STATUS_FINISHED_ID;
  6768. this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType = 1; //调整为百份比坐标
  6769. this.UpdataDataoffset(); //更新数据偏移
  6770. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6771. this.Frame.SetSizeChage(true);
  6772. this.Draw();
  6773. }
  6774. this.RequestSingleHistoryMinuteData=function(symbol, dataCount, firstDate,firstTime, item)
  6775. {
  6776. var self=this;
  6777. item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID;
  6778. if (this.NetworkFilter)
  6779. {
  6780. var obj=
  6781. {
  6782. Name:'KLineChartContainer::RequestOverlayHistoryMinuteData', //类名::
  6783. Explain:'叠加股票分钟K线数据',
  6784. Request:{ Url:self.MinuteKLineApiUrl, Data: { symbol: symbol, count: dataCount.MaxRequestMinuteDayCount,"first":{ date: firstDate, time:firstTime },
  6785. field:["name","symbol","yclose","open","price","high",'vol','amount'] }, Type:'POST' },
  6786. Self:this,
  6787. PreventDefault:false
  6788. };
  6789. this.NetworkFilter(obj, function(data)
  6790. {
  6791. item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID;
  6792. self.RecvOveralyHistoryMinuteData(data,item);
  6793. });
  6794. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  6795. }
  6796. }
  6797. this.RequestOverlayHistoryMinuteData=function()
  6798. {
  6799. if (!this.OverlayChartPaint.length) return;
  6800. if (!this.SourceData || !this.SourceData.Data) return; //主图数据还没有到完
  6801. var dataCount=this.GetRequestDataCount();
  6802. var firstDate=this.SourceData.Data[0].Date;
  6803. var firstTime=this.SourceData.Data[0].Time;
  6804. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  6805. {
  6806. var item=this.OverlayChartPaint[i];
  6807. if (!item.MainData) continue; //等待主图股票数据未下载完
  6808. if (item.Status!=OVERLAY_STATUS_ID.STATUS_NONE_ID) continue;
  6809. var symbol=item.Symbol;
  6810. if (!symbol) continue;
  6811. this.RequestSingleHistoryMinuteData(symbol,dataCount,firstDate,firstTime, item );
  6812. }
  6813. }
  6814. this.RecvOveralyHistoryMinuteData=function(recvData,paint)
  6815. {
  6816. if (paint.IsDelete) return;
  6817. var data=recvData.data;
  6818. var aryDayData=KLineChartContainer.JsonDataToMinuteHistoryData(data);
  6819. if (!aryDayData) return;
  6820. //原始叠加数据
  6821. var sourceData=new ChartData();
  6822. sourceData.Data=aryDayData;
  6823. sourceData.DataType=1; //0=日线数据 1=分钟数据
  6824. var bindData=new ChartData();
  6825. bindData.Data=aryDayData;
  6826. bindData.Period=this.Period;
  6827. bindData.Right=this.Right;
  6828. bindData.DataType=1;
  6829. var aryOverlayData=this.SourceData.GetOverlayMinuteData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  6830. bindData.Data=aryOverlayData;
  6831. if (ChartData.IsMinutePeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据, API周期数据不用计算
  6832. {
  6833. var periodData=bindData.GetPeriodData(bindData.Period);
  6834. bindData.Data=periodData;
  6835. }
  6836. paint.Data=bindData;
  6837. paint.SourceData=sourceData;
  6838. paint.Title=data.name;
  6839. paint.Symbol=data.symbol;
  6840. paint.Status=OVERLAY_STATUS_ID.STATUS_FINISHED_ID; //数据下载完成
  6841. this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=1; //调整为百份比坐标
  6842. this.UpdataDataoffset(); //更新数据偏移
  6843. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  6844. this.Frame.SetSizeChage(true);
  6845. this.Draw();
  6846. }
  6847. //取消叠加股票
  6848. this.ClearOverlaySymbol = function ()
  6849. {
  6850. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  6851. {
  6852. var item=this.OverlayChartPaint[i];
  6853. item.IsDelete=true;
  6854. }
  6855. this.OverlayChartPaint=[];
  6856. this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType = 0; //调整一般坐标
  6857. this.UpdateFrameMaxMin();
  6858. this.Draw();
  6859. }
  6860. //删除一个叠加股票
  6861. this.DeleteOverlaySymbol=function(symbol)
  6862. {
  6863. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  6864. {
  6865. var item=this.OverlayChartPaint[i];
  6866. if (item.Symbol===symbol)
  6867. {
  6868. item.IsDelete=true;
  6869. this.OverlayChartPaint.splice(i,1);
  6870. if (this.OverlayChartPaint.length<=0) this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=0; //调整一般坐标
  6871. this.UpdateFrameMaxMin();
  6872. this.Draw();
  6873. return true;
  6874. }
  6875. }
  6876. console.warn(`[KLineChartContainer::DeleteOverlaySymbol] overlay symbol=${symbol} not exist.`)
  6877. return false;
  6878. }
  6879. //创建画图工具
  6880. this.CreateChartDrawPicture = function (name, option, callback)
  6881. {
  6882. var drawPicture=null;
  6883. var item=IChartDrawPicture.GetDrawPictureByName(name);
  6884. if (item) drawPicture=item.Create();
  6885. if (!drawPicture) return false;
  6886. drawPicture.Canvas=this.Canvas;
  6887. drawPicture.Status=0;
  6888. drawPicture.Symbol=this.Symbol;
  6889. drawPicture.Period=this.Period;
  6890. drawPicture.Right=this.Right;
  6891. drawPicture.Option=this.ChartDrawOption;
  6892. drawPicture.PixelRatio=this.UIElement.PixelRatio;
  6893. if (callback) drawPicture.FinishedCallback=callback; //完成通知上层回调
  6894. if (option) drawPicture.SetOption(option);
  6895. var self=this;
  6896. drawPicture.Update=function() //更新回调函数
  6897. {
  6898. self.DrawDynamicInfo();
  6899. };
  6900. drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); }
  6901. this.CurrentChartDrawPicture=drawPicture;
  6902. //JSConsole.Chart.Log("[KLineChartContainer::CreateChartDrawPicture] ", name,this.CurrentChartDrawPicture);
  6903. return true;
  6904. }
  6905. //更新信息地雷
  6906. this.UpdataChartInfo = function ()
  6907. {
  6908. //TODO: 根据K线数据日期来做map, 不在K线上的合并到下一个k线日期里面
  6909. var mapInfoData = new Map();
  6910. if (this.Period==0) //日线数据 根据日期
  6911. {
  6912. for (var i in this.ChartInfo)
  6913. {
  6914. var infoData = this.ChartInfo[i].Data;
  6915. for (var j in infoData)
  6916. {
  6917. var item = infoData[j];
  6918. if (mapInfoData.has(item.Date.toString()))
  6919. mapInfoData.get(item.Date.toString()).Data.push(item);
  6920. else
  6921. mapInfoData.set(item.Date.toString(), { Data: new Array(item) });
  6922. }
  6923. }
  6924. }
  6925. else if (ChartData.IsDayPeriod(this.Period,false))
  6926. {
  6927. mapInfoData=new Map();
  6928. var hisData=this.ChartPaint[0].Data;
  6929. if (hisData && hisData.Data && hisData.Data.length>0)
  6930. {
  6931. var fristKItem=hisData.Data[0];
  6932. var aryInfo=[];
  6933. for(var i in this.ChartInfo)
  6934. {
  6935. var infoItem=this.ChartInfo[i];
  6936. for(var j in infoItem.Data)
  6937. {
  6938. var item=infoItem.Data[j];
  6939. if (item.Date>=fristKItem.Date) //在K线范围内的才显示
  6940. aryInfo.push(item);
  6941. }
  6942. }
  6943. aryInfo.sort(function(a,b) { return a.Date-b.Date }); //排序
  6944. for(var i=0;i<hisData.Data.length;)
  6945. {
  6946. var kItem=hisData.Data[i]; //K线数据
  6947. if (aryInfo.length<=0) break;
  6948. var infoItem=aryInfo[0];
  6949. if (kItem.Date<infoItem.Date)
  6950. {
  6951. ++i;
  6952. continue;
  6953. }
  6954. //信息地雷日期<K线上的日期 就是属于这个K线上的
  6955. if (mapInfoData.has(kItem.Date.toString()))
  6956. mapInfoData.get(kItem.Date.toString()).Data.push(infoItem);
  6957. else
  6958. mapInfoData.set(kItem.Date.toString(),{Data:new Array(infoItem)});
  6959. aryInfo.shift();
  6960. //JSConsole.Chart.Log('[KLineChartContainer::UpdataChartInfo]',item);
  6961. }
  6962. }
  6963. }
  6964. var klinePaint = this.ChartPaint[0];
  6965. klinePaint.InfoData = mapInfoData;
  6966. var titlePaint = this.TitlePaint[0];
  6967. if (titlePaint) titlePaint.InfoData = mapInfoData;
  6968. }
  6969. //接收到窗口指标数据 订阅模式
  6970. this.RecvWindowIndex=function(index, data)
  6971. {
  6972. var indexItem=this.WindowIndex[index];
  6973. if (!indexItem) return;
  6974. if (typeof(indexItem.RecvSubscribeData)=="function")
  6975. {
  6976. var hisData=this.ChartPaint[0].Data;
  6977. indexItem.RecvSubscribeData(data,this,index,hisData);
  6978. }
  6979. }
  6980. //更新窗口指标
  6981. this.UpdateWindowIndex = function (index)
  6982. {
  6983. var bindData = new ChartData();
  6984. bindData.Data = this.SourceData.Data;
  6985. bindData.Period = this.Period;
  6986. bindData.Right = this.Right;
  6987. if (this.IsApiPeriod)
  6988. {
  6989. }
  6990. else
  6991. {
  6992. if (bindData.Right > 0) //复权
  6993. {
  6994. var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  6995. bindData.Data = rightData;
  6996. }
  6997. if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据
  6998. {
  6999. var periodData = bindData.GetPeriodData(bindData.Period);
  7000. bindData.Data = periodData;
  7001. }
  7002. }
  7003. this.WindowIndex[index].BindData(this, index, bindData);
  7004. this.UpdataDataoffset(); //更新数据偏移
  7005. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  7006. this.Draw();
  7007. }
  7008. //修改参数指标
  7009. this.ChangeWindowIndexParam = function (index) {
  7010. this.WindowIndex[index].Index[0].Param += 1;
  7011. this.WindowIndex[index].Index[1].Param += 1;
  7012. this.UpdateWindowIndex(index);
  7013. }
  7014. this.OnDoubleClick = function (x, y, e)
  7015. {
  7016. var tooltip = new TooltipData();
  7017. for (var i in this.ChartPaint)
  7018. {
  7019. var item = this.ChartPaint[i];
  7020. if (item.GetTooltipData(x, y, tooltip))
  7021. break;
  7022. }
  7023. if (!tooltip.Data) return;
  7024. e.data = { Chart: this, Tooltip: tooltip };
  7025. }
  7026. this.CancelAutoUpdate=function() //关闭停止更新
  7027. {
  7028. if (this.AutoUpdateTimer)
  7029. {
  7030. clearTimeout(this.AutoUpdateTimer);
  7031. this.AutoUpdateTimer = null;
  7032. }
  7033. }
  7034. //数据自动更新
  7035. this.AutoUpdate = function (waitTime) //waitTime 更新时间
  7036. {
  7037. this.CancelAutoUpdate();
  7038. if (!this.IsAutoUpdate) return;
  7039. if (!this.Symbol) return;
  7040. if (this.IsDestroy) return;
  7041. var self = this;
  7042. var marketStatus = MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol);
  7043. if (marketStatus == 0 || marketStatus == 3) return; //闭市,盘后
  7044. var frequency = this.AutoUpdateFrequency;
  7045. if (marketStatus == 1) //盘前
  7046. {
  7047. this.AutoUpdateTimer=setTimeout(function () { self.AutoUpdate(); }, frequency);
  7048. }
  7049. else if (marketStatus == 2) //盘中
  7050. {
  7051. this.AutoUpdateTimer=setTimeout(function ()
  7052. {
  7053. if (ChartData.IsDayPeriod(self.Period, true))
  7054. {
  7055. self.RequestRealtimeData(); //更新最新行情
  7056. //self.ReqeustKLineInfoData();
  7057. }
  7058. else if (ChartData.IsMinutePeriod(self.Period, true) || ChartData.IsSecondPeriod(self.Period))
  7059. {
  7060. self.RequestMinuteRealtimeData(); //请求分钟数据
  7061. }
  7062. }, frequency);
  7063. }
  7064. }
  7065. this.GetMaxPageSize = function ()
  7066. {
  7067. let width = this.Frame.ChartBorder.GetWidth();
  7068. let barWidth = (ZOOM_SEED[ZOOM_SEED.length - 1][0] + ZOOM_SEED[ZOOM_SEED.length - 1][1]);
  7069. let pageSize = parseInt(width / barWidth) - 8;
  7070. JSConsole.Chart.Log(`[KLineChartContainer::GetMaxPageSize] width=${width} barWidth=${barWidth} pageSize=${pageSize}`);
  7071. return pageSize
  7072. }
  7073. //数据拖拽下载
  7074. this.DragDownloadData = function ()
  7075. {
  7076. var data = null;
  7077. if (!this.Frame.Data) data = this.Frame.Data;
  7078. else data = this.Frame.SubFrame[0].Frame.Data;
  7079. if (!data) return false;
  7080. if (data.DataOffset > 0) return;
  7081. if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period)) //下载分钟数据
  7082. {
  7083. JSConsole.Chart.Log(`[KLineChartContainer.DragDownloadData] Minute:[Enable=${this.DragDownload.Minute.Enable}, IsEnd=${this.DragDownload.Minute.IsEnd}, Status=${this.DragDownload.Minute.Status}, Period=${this.Period}]`);
  7084. if (!this.DragDownload.Minute.Enable) return;
  7085. if (this.DragDownload.Minute.IsEnd) return; //全部下载完了
  7086. if (this.DragDownload.Minute.Status != 0) return;
  7087. this.RequestDragMinuteData();
  7088. }
  7089. else if (ChartData.IsDayPeriod(this.Period, true)) // 下载日线
  7090. {
  7091. JSConsole.Chart.Log(`[KLineChartContainer.DragDownloadData] Day:[Enable=${this.DragDownload.Minute.Enable}, IsEnd=${this.DragDownload.Minute.IsEnd}, Status=${this.DragDownload.Minute.Status}]`);
  7092. if (!this.DragDownload.Day.Enable) return;
  7093. if (this.DragDownload.Day.IsEnd) return; //全部下载完了
  7094. if (this.DragDownload.Day.Status != 0) return;
  7095. this.RequestDragDayData();
  7096. }
  7097. }
  7098. this.RequestDragMinuteData = function ()
  7099. {
  7100. var option=
  7101. {
  7102. FuncName:'KLineChartContainer::RequestDragMinuteData',
  7103. FuncExplain:"拖拽分钟|秒K线数据下载",
  7104. RecvFuncName:"RecvDragMinuteData",
  7105. Download:this.DragDownload.Minute,
  7106. Url:this.DragMinuteKLineApiUrl,
  7107. Count:this.MaxRequestMinuteDayCount,
  7108. XShowCount:this.Frame.GetXShowCount(),
  7109. };
  7110. this.RequestPreviousMinuteData(option);
  7111. }
  7112. this.RequestPreviousMinuteData=function(option)
  7113. {
  7114. var funcName=option.FuncName;
  7115. var funcExplain=option.FuncExplain;
  7116. var download=option.Download;
  7117. var url=option.Url;
  7118. var count=option.Count; //请求数据个数
  7119. var self = this;
  7120. this.AutoUpdateEvent(false, funcName); //停止自动更新
  7121. this.CancelAutoUpdate();
  7122. download.Status = 1;
  7123. var firstItem=null;
  7124. if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data))
  7125. firstItem = this.SourceData.Data[0]; //最新的一条数据
  7126. else
  7127. firstItem={Date:null, Time:null};
  7128. var postData =
  7129. {
  7130. "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol"],
  7131. "symbol": self.Symbol,
  7132. "enddate": firstItem.Date,
  7133. "endtime": firstItem.Time,
  7134. "count": count,
  7135. "first": { date: firstItem.Date, time: firstItem.Time },
  7136. };
  7137. if (IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint))
  7138. {
  7139. postData.overlay=[];
  7140. for(var i=0;i<this.OverlayChartPaint.length;++i)
  7141. {
  7142. var item=this.OverlayChartPaint[i];
  7143. postData.overlay.push({ symbol:item.Symbol });
  7144. }
  7145. }
  7146. if (this.NetworkFilter)
  7147. {
  7148. var obj =
  7149. {
  7150. Name: funcName, //类名::函数
  7151. Explain: funcExplain,
  7152. Request: { Url: url, Type: 'POST', Data: postData, Period:this.Period, Right:this.Right },
  7153. DragDownload: download,
  7154. Option:option,
  7155. Self: this,
  7156. ZoomData:option.ZoomData,
  7157. PreventDefault: false
  7158. };
  7159. this.NetworkFilter(obj, function (data)
  7160. {
  7161. self.RecvPreviousMinuteData(data, option);
  7162. download.Status = 0;
  7163. self.AutoUpdateEvent(true, funcName); //自动更新
  7164. self.AutoUpdate();
  7165. });
  7166. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  7167. }
  7168. }
  7169. //分钟K线拖动 !!没有做叠加分钟K线
  7170. this.RecvPreviousMinuteData=function(recvdata, option)
  7171. {
  7172. var download=option.Download;
  7173. var data=recvdata.data;
  7174. var aryDayData = KLineChartContainer.JsonDataToMinuteHistoryData(data);
  7175. if (!aryDayData || aryDayData.length<=0)
  7176. {
  7177. download.IsEnd=true;
  7178. JSConsole.Chart.Log(`[KLineChartContainer.RecvPreviousMinuteData] ${this.Symbol} data end. FuncName=${option.FuncName}`);
  7179. this.Draw();
  7180. return;
  7181. }
  7182. var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数
  7183. var endIndex=null;
  7184. if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data))
  7185. {
  7186. var firstData=this.SourceData.Data[0];
  7187. for(var i=aryDayData.length-1;i>=0;--i)
  7188. {
  7189. var item=aryDayData[i];
  7190. if (firstData.Date>item.Date || (firstData.Date==item.Date && firstData.Time>item.Time))
  7191. {
  7192. endIndex=i;
  7193. break;
  7194. }
  7195. else if (firstData.Date==item.Date && firstData.Time==item.Time)
  7196. {
  7197. firstData.YClose=item.YClose;
  7198. endIndex=i-1;
  7199. break;
  7200. }
  7201. }
  7202. }
  7203. else
  7204. {
  7205. endIndex=aryDayData.length-1;
  7206. }
  7207. if (endIndex==null && endIndex<0) return;
  7208. for(var i=0;i<aryDayData.length && i<=endIndex;++i) //数据往前插
  7209. {
  7210. var item=aryDayData[i];
  7211. this.SourceData.Data.splice(i,0,item);
  7212. }
  7213. var bindData=new ChartData();
  7214. bindData.Data=this.SourceData.Data;
  7215. bindData.Period=this.Period;
  7216. bindData.Right=this.Right;
  7217. bindData.DataType=this.SourceData.DataType;
  7218. bindData.Symbol=this.Symbol;
  7219. if (!this.IsApiPeriod)
  7220. {
  7221. if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理)
  7222. {
  7223. var periodData = bindData.GetPeriodData(bindData.Period);
  7224. bindData.Data = periodData;
  7225. }
  7226. }
  7227. //绑定数据
  7228. this.UpdateMainData(bindData, lastDataCount);
  7229. if (option) //缩放需要调整当前屏的位置
  7230. {
  7231. if (option.ZoomData)
  7232. {
  7233. var zoomData=option.ZoomData;
  7234. var showCount=zoomData.PageSize-zoomData.RightSpaceCount; //一屏显示的数据个数
  7235. bindData.DataOffset= bindData.Data.length-showCount;
  7236. if (bindData.DataOffset<0) bindData.DataOffset=0;
  7237. }
  7238. else if (IFrameSplitOperator.IsNumber(option.DataOffset))
  7239. {
  7240. bindData.DataOffset+=option.DataOffset;
  7241. if (bindData.DataOffset<0) bindData.DataOffset=0;
  7242. }
  7243. }
  7244. this.UpdateOverlayDragMinuteData(data);
  7245. this.BindInstructionIndexData(bindData); //执行指示脚本
  7246. for (var i = 0; i < this.Frame.SubFrame.length; ++i)
  7247. {
  7248. this.BindIndexData(i, bindData);
  7249. }
  7250. //刷新画图
  7251. this.UpdataDataoffset(); //更新数据偏移
  7252. this.UpdatePointByCursorIndex(); //更新十字光标位子
  7253. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  7254. this.Frame.SetSizeChage(true);
  7255. this.Draw();
  7256. //叠加指标计算
  7257. this.BindAllOverlayIndexData(bindData);
  7258. }
  7259. this.MergeOverlaySymbolMinuteData=function(item, aryOverlayData)
  7260. {
  7261. if (!item.Symbol) false;
  7262. if (!IFrameSplitOperator.IsNonEmptyArray(aryOverlayData)) return false;
  7263. var findData=null;
  7264. for(var i=0;i<aryOverlayData.length;++i) //查找对应的叠加股票数据
  7265. {
  7266. var overlayItem=aryOverlayData[i];
  7267. if (overlayItem.symbol==item.Symbol)
  7268. {
  7269. findData=overlayItem;
  7270. break;
  7271. }
  7272. }
  7273. if (!findData) return false;
  7274. var aryDayData=KLineChartContainer.JsonDataToMinuteHistoryData(findData);
  7275. var sourceData=item.SourceData; //叠加股票的所有数据
  7276. var firstData=sourceData.Data[0];
  7277. var endIndex=null;
  7278. for(var i=aryDayData.length-1;i>=0;--i)
  7279. {
  7280. var itemData=aryDayData[i];
  7281. if (firstData.Date>itemData.Date)
  7282. {
  7283. endIndex=i;
  7284. break;
  7285. }
  7286. else if (firstData.Date==itemData.Date && firstData.Time>itemData.Time)
  7287. {
  7288. endIndex=i;
  7289. break;
  7290. }
  7291. else if (firstData.Date==itemData.Date && firstData.Time==itemData.Time)
  7292. {
  7293. firstData.YClose=itemData.YClose;
  7294. endIndex=i-1;
  7295. break;
  7296. }
  7297. }
  7298. if (endIndex==null && endIndex<0) return false;
  7299. for(var i=0; i<aryDayData.length && i<=endIndex;++i) //数据往前插
  7300. {
  7301. var itemData=aryDayData[i];
  7302. sourceData.Data.splice(i,0,itemData);
  7303. }
  7304. var bindData=new ChartData();
  7305. bindData.Data=sourceData.Data;
  7306. bindData.Period=this.Period;
  7307. bindData.Right=this.Right;
  7308. bindData.DataType=0;
  7309. var aryOverlayData=this.SourceData.GetOverlayMinuteData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  7310. bindData.Data=aryOverlayData;
  7311. if (ChartData.IsMinutePeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据
  7312. {
  7313. var periodData=bindData.GetPeriodData(bindData.Period);
  7314. bindData.Data=periodData;
  7315. }
  7316. item.Data=bindData;
  7317. return true;
  7318. }
  7319. this.UpdateOverlayDragMinuteData=function(data)
  7320. {
  7321. if (!IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) return;
  7322. var aryRecvOverlayData=data.overlay;
  7323. for(var i=0;i<this.OverlayChartPaint.length; ++i)
  7324. {
  7325. var item=this.OverlayChartPaint[i];
  7326. if (!item.Symbol) continue;
  7327. var bUpdate=false;
  7328. if (item.MainData && item.Status==OVERLAY_STATUS_ID.STATUS_FINISHED_ID) //等待主图股票数据未下载完
  7329. {
  7330. bUpdate=this.MergeOverlaySymbolMinuteData(item,aryRecvOverlayData);
  7331. }
  7332. if (!bUpdate) //没有更新数据 手动跟主图数据对齐
  7333. {
  7334. if (item.Data && IFrameSplitOperator.IsNonEmptyArray(item.Data.Data))
  7335. {
  7336. var bindData=item.Data;
  7337. var aryOverlayData=this.SourceData.GetOverlayMinuteData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  7338. bindData.Data=aryOverlayData;
  7339. }
  7340. }
  7341. }
  7342. }
  7343. this.RequestDragDayData = function ()
  7344. {
  7345. var option=
  7346. {
  7347. FuncName:'KLineChartContainer::RequestDragDayData',
  7348. FuncExplain:"拖拽日K数据下载",
  7349. RecvFuncName:"RecvDragDayData",
  7350. Download:this.DragDownload.Day,
  7351. Url:this.DragKLineApiUrl,
  7352. Count:this.MaxRequestDataCount,
  7353. XShowCount:this.Frame.GetXShowCount(),
  7354. };
  7355. this.RequestPreviousDayData(option);
  7356. }
  7357. //请求拖动或缩放的日线历史数据
  7358. this.RequestPreviousDayData=function(option)
  7359. {
  7360. var funcName=option.FuncName;
  7361. var funcExplain=option.FuncExplain;
  7362. var download=option.Download;
  7363. var url=option.Url;
  7364. var count=option.Count; //请求数据个数
  7365. var self = this;
  7366. this.AutoUpdateEvent(false, funcName); //停止自动更新
  7367. this.CancelAutoUpdate();
  7368. var download = this.DragDownload.Day;
  7369. download.Status = 1;
  7370. var firstItem =null;
  7371. if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data))
  7372. firstItem = this.SourceData.Data[0]; //最新的一条数据
  7373. else
  7374. firstItem={Date:null};
  7375. var postData =
  7376. {
  7377. "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol"],
  7378. "symbol": self.Symbol,
  7379. "enddate": firstItem.Date,
  7380. "count": count,
  7381. "first": { date: firstItem.Date }
  7382. };
  7383. if (IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint))
  7384. {
  7385. postData.overlay=[];
  7386. for(var i=0;i<this.OverlayChartPaint.length;++i)
  7387. {
  7388. var item=this.OverlayChartPaint[i];
  7389. if (item.Symbol) postData.overlay.push( { symbol:item.Symbol } );
  7390. }
  7391. }
  7392. if (this.NetworkFilter)
  7393. {
  7394. var obj =
  7395. {
  7396. Name: funcName, //类名::函数
  7397. Explain: funcExplain,
  7398. Request: { Url: url, Type: 'POST', Data: postData , Period:this.Period, Right:this.Right },
  7399. DragDownload: download,
  7400. Option:option,
  7401. Self: this,
  7402. ZoomData:option.ZoomData,
  7403. PreventDefault: false
  7404. };
  7405. this.NetworkFilter(obj, function (data)
  7406. {
  7407. self.RecvPreviousDayData(data, option);
  7408. download.Status = 0;
  7409. self.AutoUpdateEvent(true, funcName); //自动更新
  7410. self.AutoUpdate();
  7411. });
  7412. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  7413. }
  7414. }
  7415. this.RecvPreviousDayData = function (recvdata, option)
  7416. {
  7417. var download=option.Download;
  7418. var data = recvdata.data;
  7419. var aryDayData = KLineChartContainer.JsonDataToHistoryData(data);
  7420. if (!aryDayData || aryDayData.length<=0)
  7421. {
  7422. download.IsEnd=true; //下完了
  7423. JSConsole.Chart.Log(`[KLineChartContainer.RecvPreviousDayData] ${this.Symbol} data end. FuncName=${option.FuncName}`);
  7424. return;
  7425. }
  7426. var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数
  7427. var endIndex=null;
  7428. if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data))
  7429. {
  7430. var firstData=this.SourceData.Data[0];
  7431. for(var i=aryDayData.length-1;i>=0;--i)
  7432. {
  7433. var item=aryDayData[i];
  7434. if (firstData.Date>item.Date)
  7435. {
  7436. endIndex=i;
  7437. break;
  7438. }
  7439. else if (firstData.Date==item.Date)
  7440. {
  7441. firstData.YClose=item.YClose;
  7442. endIndex=i-1;
  7443. break;
  7444. }
  7445. }
  7446. }
  7447. else
  7448. {
  7449. var firstData={ Date:null };
  7450. endIndex=aryDayData.length-1;
  7451. }
  7452. if (endIndex==null && endIndex<0) return;
  7453. for(var i=0; i<aryDayData.length && i<=endIndex;++i) //数据往前插
  7454. {
  7455. var item=aryDayData[i];
  7456. this.SourceData.Data.splice(i,0,item);
  7457. }
  7458. var bindData = new ChartData();
  7459. bindData.Data = this.SourceData.Data;
  7460. bindData.Period = this.Period;
  7461. bindData.Right = this.Right;
  7462. bindData.DataType = this.SourceData.DataType;
  7463. bindData.Symbol = this.Symbol;
  7464. if (!this.IsApiPeriod)
  7465. {
  7466. if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理)
  7467. {
  7468. var periodData = bindData.GetPeriodData(bindData.Period);
  7469. bindData.Data = periodData;
  7470. }
  7471. }
  7472. //绑定数据
  7473. this.UpdateMainData(bindData, lastDataCount);
  7474. if (option) //缩放需要调整当前屏的位置
  7475. {
  7476. if (option.ZoomData)
  7477. {
  7478. var zoomData=option.ZoomData;
  7479. var showCount=zoomData.PageSize-zoomData.RightSpaceCount; //一屏显示的数据个数
  7480. bindData.DataOffset= bindData.Data.length-showCount;
  7481. if (bindData.DataOffset<0) bindData.DataOffset=0;
  7482. }
  7483. else if (IFrameSplitOperator.IsNumber(option.DataOffset))
  7484. {
  7485. bindData.DataOffset+=option.DataOffset;
  7486. if (bindData.DataOffset<0) bindData.DataOffset=0;
  7487. }
  7488. }
  7489. this.UpdateOverlayDragDayData(data);
  7490. this.BindInstructionIndexData(bindData); //执行指示脚本
  7491. for (var i = 0; i < this.Frame.SubFrame.length; ++i)
  7492. {
  7493. this.BindIndexData(i, bindData);
  7494. }
  7495. //刷新画图
  7496. this.UpdataDataoffset(); //更新数据偏移
  7497. this.UpdatePointByCursorIndex(); //更新十字光标位子
  7498. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  7499. this.Frame.SetSizeChage(true);
  7500. this.Draw();
  7501. //更新信息地雷
  7502. this.ReqeustKLineInfoData( { FunctionName:option.RecvFuncName, StartDate:firstData.Date } );
  7503. //叠加指标计算
  7504. this.BindAllOverlayIndexData(bindData);
  7505. }
  7506. this.MergeOverlaySymbolDayData=function(item, aryOverlayData)
  7507. {
  7508. if (!item.Symbol) return false;
  7509. if (!IFrameSplitOperator.IsNonEmptyArray(aryOverlayData)) return false;
  7510. var findData=null;
  7511. for(var i=0;i<aryOverlayData.length;++i) //查找对应的叠加股票数据
  7512. {
  7513. var overlayItem=aryOverlayData[i];
  7514. if (overlayItem.symbol==item.Symbol)
  7515. {
  7516. findData=overlayItem;
  7517. break;
  7518. }
  7519. }
  7520. if (!findData) false;
  7521. var aryDayData=KLineChartContainer.JsonDataToHistoryData(findData);
  7522. var sourceData=item.SourceData; //叠加股票的所有数据
  7523. var firstData=sourceData.Data[0];
  7524. var endIndex=null;
  7525. for(var i=aryDayData.length-1;i>=0;--i)
  7526. {
  7527. var itemData=aryDayData[i];
  7528. if (firstData.Date>itemData.Date)
  7529. {
  7530. endIndex=i;
  7531. break;
  7532. }
  7533. else if (firstData.Date==itemData.Date)
  7534. {
  7535. firstData.YClose=itemData.YClose;
  7536. endIndex=i-1;
  7537. break;
  7538. }
  7539. }
  7540. if (endIndex==null && endIndex<0) return false;
  7541. for(var i=0; i<aryDayData.length && i<=endIndex;++i) //数据往前插
  7542. {
  7543. var itemData=aryDayData[i];
  7544. sourceData.Data.splice(i,0,itemData);
  7545. }
  7546. var bindData=new ChartData();
  7547. bindData.Data=sourceData.Data;
  7548. bindData.Period=this.Period;
  7549. bindData.Right=this.Right;
  7550. bindData.DataType=0;
  7551. if (bindData.Right>0 && MARKET_SUFFIX_NAME.IsSHSZStockA(findData.symbol) && !this.IsApiPeriod) //复权数据 ,A股才有有复权
  7552. {
  7553. var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula });
  7554. bindData.Data=rightData;
  7555. }
  7556. var aryOverlayData=this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  7557. bindData.Data=aryOverlayData;
  7558. if (ChartData.IsDayPeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据
  7559. {
  7560. var periodData=bindData.GetPeriodData(bindData.Period);
  7561. bindData.Data=periodData;
  7562. }
  7563. item.Data=bindData;
  7564. return true;
  7565. }
  7566. //更新叠加数据
  7567. this.UpdateOverlayDragDayData=function(data)
  7568. {
  7569. if (!IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) return;
  7570. var aryRecvOverlayData=data.overlay;
  7571. for(var i=0;i<this.OverlayChartPaint.length; ++i)
  7572. {
  7573. var item=this.OverlayChartPaint[i];
  7574. if (!item.Symbol) continue;
  7575. var bUpdate=false;
  7576. if (item.MainData && item.Status==OVERLAY_STATUS_ID.STATUS_FINISHED_ID) //等待主图股票数据未下载完
  7577. {
  7578. bUpdate=this.MergeOverlaySymbolDayData(item, aryRecvOverlayData);
  7579. }
  7580. if (!bUpdate) //没有更新数据 手动跟主图数据对齐
  7581. {
  7582. if (item.Data && IFrameSplitOperator.IsNonEmptyArray(item.Data.Data))
  7583. {
  7584. var bindData=item.Data;
  7585. var aryOverlayData=this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据
  7586. bindData.Data=aryOverlayData;
  7587. }
  7588. }
  7589. }
  7590. }
  7591. this.SetCustomVerical = function (windowId, data)
  7592. {
  7593. if (!this.Frame) return;
  7594. if (windowId >= this.Frame.SubFrame.length) return;
  7595. var item = this.Frame.SubFrame[windowId];
  7596. if (item.Frame) item.Frame.CustomVerticalInfo = data;
  7597. }
  7598. this.OnSize=function()
  7599. {
  7600. if (!this.Frame) return;
  7601. if (!this.Frame.OnSize) return;
  7602. var obj=this.Frame.OnSize();
  7603. this.Frame.SetSizeChage(true);
  7604. if (obj.Changed)
  7605. {
  7606. this.UpdataDataoffset();
  7607. this.UpdatePointByCursorIndex();
  7608. this.UpdateFrameMaxMin();
  7609. }
  7610. this.Draw();
  7611. }
  7612. this.AddOverlayIndex=function(obj)
  7613. {
  7614. var overlay=this.CreateOverlayWindowsIndex(obj);
  7615. if (!overlay) return;
  7616. var bindData=this.ChartPaint[0].Data;
  7617. this.BindOverlayIndexData(overlay,obj.WindowIndex,bindData);
  7618. this.UpdataDataoffset(); //更新数据偏移
  7619. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  7620. this.Draw();
  7621. }
  7622. //创建一个叠加指标
  7623. this.CreateOverlayWindowsIndex=function(obj) // {WindowIndex:, IndexName:, Identify:, ShowRightText:, API:}
  7624. {
  7625. let indexName=obj.IndexName;
  7626. let windowIndex=obj.WindowIndex;
  7627. var apiItem=null, indexInfo=null, indexCustom=null;
  7628. if (obj.API)
  7629. {
  7630. apiItem=obj.API;
  7631. }
  7632. else if (obj.Script) //动态执行脚本
  7633. {
  7634. indexInfo={ Script:obj.Script, ID:obj.indexName, Name:obj.indexName};
  7635. if (obj.Name) indexInfo.Name=obj.Name;
  7636. }
  7637. else
  7638. {
  7639. let scriptData = new JSCommonIndexScript.JSIndexScript();
  7640. indexInfo = scriptData.Get(indexName); //系统指标
  7641. if (!indexInfo)
  7642. {
  7643. indexCustom=JSIndexMap.Get(indexName); //定制指标
  7644. if (!indexCustom)
  7645. {
  7646. console.warn(`[KLineChartContainer::CreateOverlayIndex] can not find index[${indexName}]`);
  7647. return null;
  7648. }
  7649. }
  7650. }
  7651. var subFrame=this.Frame.SubFrame[windowIndex];
  7652. subFrame.Interval=this.OverlayIndexFrameWidth;
  7653. var overlayFrame=new OverlayIndexItem();
  7654. if (obj.Identify) overlayFrame.Identify=obj.Identify; //由外部指定id
  7655. var frame= this.CreateOverlayFrame();
  7656. frame.Canvas=this.Canvas;
  7657. frame.MainFrame=subFrame.Frame;
  7658. frame.ChartBorder=subFrame.Frame.ChartBorder;
  7659. if (IFrameSplitOperator.IsBool(obj.IsShareY)) frame.IsShareY=obj.IsShareY;
  7660. if (IFrameSplitOperator.IsBool(obj.IsCalculateYMaxMin)) frame.IsCalculateYMaxMin=obj.IsCalculateYMaxMin; //是否计算Y最大最小值
  7661. if (IFrameSplitOperator.IsNumber(obj.IsShowMainFrame)) frame.IsShowMainFrame=obj.IsShowMainFrame;
  7662. frame.YSplitOperator=new FrameSplitY();
  7663. frame.YSplitOperator.LanguageID=this.LanguageID;
  7664. frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double');
  7665. frame.YSplitOperator.Frame=frame;
  7666. frame.YSplitOperator.ChartBorder=frame.ChartBorder;
  7667. frame.YSplitOperator.SplitCount=subFrame.Frame.YSplitOperator.SplitCount;
  7668. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); };
  7669. frame.YSplitOperator.OverlayIdentify=overlayFrame.Identify;
  7670. overlayFrame.Frame=frame;
  7671. if (apiItem)
  7672. {
  7673. var apiIndex=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,obj, true);
  7674. apiIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息
  7675. overlayFrame.Script=apiIndex;
  7676. }
  7677. else if (indexInfo)
  7678. {
  7679. JSIndexScript.ModifyAttribute(indexInfo, obj);
  7680. var scriptIndex=new OverlayScriptIndex(indexInfo.Name,indexInfo.Script,indexInfo.Args,indexInfo); //脚本执行
  7681. scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息
  7682. overlayFrame.Script=scriptIndex;
  7683. }
  7684. else
  7685. {
  7686. var scriptIndex=indexCustom.Create();
  7687. scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息
  7688. scriptIndex.Create(this,windowIndex);
  7689. overlayFrame.Script=scriptIndex;
  7690. }
  7691. subFrame.OverlayIndex.push(overlayFrame);
  7692. return overlayFrame;
  7693. }
  7694. this.DeleteOverlayWindowsIndex=function(identify) //删除叠加指标
  7695. {
  7696. if (!this.DeleteOverlayIndex(identify, null)) return;
  7697. this.Frame.ResetXYSplit(true);
  7698. this.Draw();
  7699. }
  7700. this.ChangePriceGap=function(obj)
  7701. {
  7702. if (!obj) return;
  7703. var klineChart=this.ChartPaint[0];
  7704. if (!klineChart) return;
  7705. if (IFrameSplitOperator.IsNumber(obj.Count)) klineChart.PriceGap.Count=obj.Count;
  7706. if (IFrameSplitOperator.IsBool(obj.Enable)) klineChart.PriceGap.Enable=obj.Enable;
  7707. this.Draw();
  7708. }
  7709. }
  7710. //API 返回数据 转化为array[]
  7711. KLineChartContainer.JsonDataToHistoryData = function (data)
  7712. {
  7713. var list = data.data;
  7714. var aryDayData = new Array();
  7715. if (!list) return aryDayData;
  7716. var upperSymbol = null;
  7717. if (data.symbol) upperSymbol = data.symbol.toUpperCase();
  7718. var isFutures = false; //是否是期货
  7719. isFutures = MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol);
  7720. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, position = 8;
  7721. var fclose=9, yfclose=10; //结算价, 前结算价
  7722. var bfactor=11, afactor=12; //前, 后复权因子
  7723. var colorData=JSCHART_DATA_FIELD_ID.KLINE_COLOR_DATA;
  7724. var extendDataIndex=JSCHART_DATA_FIELD_ID.KLINE_DAY_EXTENDDATA; //k线扩展数据
  7725. for (var i = 0; i < list.length; ++i)
  7726. {
  7727. var item = new HistoryData();
  7728. var jsData = list[i];
  7729. item.Date = jsData[date];
  7730. item.Open = jsData[open];
  7731. item.YClose = jsData[yclose];
  7732. item.Close = jsData[close];
  7733. item.High = jsData[high];
  7734. item.Low = jsData[low];
  7735. item.Vol = jsData[vol]; //原始单位股
  7736. item.Amount = jsData[amount];
  7737. //可选配置
  7738. if (IFrameSplitOperator.IsNumber(jsData[position])) item.Position = jsData[position];//期货持仓
  7739. if (IFrameSplitOperator.IsNumber(jsData[fclose])) item.FClose=jsData[fclose]; //期货结算价
  7740. if (IFrameSplitOperator.IsNumber(jsData[yfclose])) item.YFClose=jsData[yfclose]; //期货前结算价
  7741. if (IFrameSplitOperator.IsNumber(jsData[bfactor])) item.BFactor=jsData[bfactor]; //前复权因子
  7742. if (IFrameSplitOperator.IsNumber(jsData[afactor])) item.AFactor=jsData[afactor]; //后复权因子
  7743. if (!IFrameSplitOperator.IsNumber(item.Open)) continue;
  7744. if (jsData[colorData]) item.ColorData=jsData[colorData];
  7745. if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex];
  7746. aryDayData.push(item);
  7747. }
  7748. return aryDayData;
  7749. }
  7750. KLineChartContainer.JsonDataToRealtimeData = function (data, symbol)
  7751. {
  7752. if (!data) return null;
  7753. if (!IFrameSplitOperator.IsNonEmptyArray(data.stock)) return null;
  7754. var stock=null;
  7755. for(var i=0;i<data.stock.length;++i)
  7756. {
  7757. var item=data.stock[i];
  7758. if (item && item.symbol==symbol)
  7759. {
  7760. stock=item;
  7761. break;
  7762. }
  7763. }
  7764. if (!stock) return null;
  7765. var upperSymbol = symbol.toUpperCase();
  7766. var isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  7767. var item = new HistoryData();
  7768. item.Date = stock.date;
  7769. item.Open = stock.open;
  7770. item.YClose = stock.yclose;
  7771. item.High = stock.high;
  7772. item.Low = stock.low;
  7773. item.Vol=stock.vol; //单位股
  7774. item.Amount = stock.amount;
  7775. item.Close = stock.price;
  7776. if (IFrameSplitOperator.IsNumber(stock.position)) item.Position = stock.position; //持仓量
  7777. if (IFrameSplitOperator.IsNumber(stock.bfactor)) item.BFactor=stock.bfactor; //前复权因子
  7778. if (IFrameSplitOperator.IsNumber(stock.afactor)) item.AFactor=stock.afactor; //后复权因子
  7779. if (stock.colordata) item.ColorData=stock.colordata; //自定义颜色
  7780. if (stock.extendData) item.ExtendData=stock.extendData;
  7781. return item;
  7782. }
  7783. //分钟K线叠加数据增量更新v2版本
  7784. KLineChartContainer.JsonDataToMinuteRealtimeDataV2=function(data,symbol)
  7785. {
  7786. if (!data || !data.overlay || !symbol) return null;
  7787. var overlayData=null;
  7788. for(var i=0;i<data.overlay.length;++i) //overlay={ symbol:, name:, data:[] }
  7789. {
  7790. var item=data.overlay[i];
  7791. if (item.symbol==symbol)
  7792. {
  7793. overlayData=item;
  7794. break;
  7795. }
  7796. }
  7797. if (!overlayData) return null;
  7798. var upperSymbol=symbol.toUpperCase();
  7799. var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  7800. var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //是否是期货
  7801. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8, position=9;
  7802. var orderFlow=JSCHART_DATA_FIELD_ID.KLINE_ORDERFLOW;
  7803. var yClose=null;
  7804. var aryMinuteData=[];
  7805. for (var i = 0; i < overlayData.data.length; ++i)
  7806. {
  7807. var item = new HistoryData();
  7808. var jsData=overlayData.data[i];
  7809. item.Date = jsData[date];
  7810. item.Open = jsData[open];
  7811. item.YClose = jsData[yclose];
  7812. item.Close = jsData[close];
  7813. item.High = jsData[high];
  7814. item.Low = jsData[low];
  7815. item.Vol = jsData[vol]; //股
  7816. item.Amount = jsData[amount];
  7817. item.Time=jsData[time];
  7818. if (IFrameSplitOperator.IsNumber(jsData[position])) item.Position=jsData[position]; //期货持仓
  7819. if (!IFrameSplitOperator.IsNumber(item.YClose))
  7820. {
  7821. if (IFrameSplitOperator.IsNumber(yClose)) item.YClose=yClose;
  7822. }
  7823. if (IFrameSplitOperator.IsNumber(item.Close)) yClose=item.Close;
  7824. if (jsData[orderFlow]) item.OrderFlow=jsData[orderFlow];
  7825. aryMinuteData.push(item);
  7826. }
  7827. return aryMinuteData;
  7828. }
  7829. KLineChartContainer.JsonDataToMinuteRealtimeData = function (data)
  7830. {
  7831. var symbol = data.stock[0].symbol;
  7832. var upperSymbol = symbol.toUpperCase();
  7833. var isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  7834. var isFutures = MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol);
  7835. var aryMinuteData = new Array();
  7836. var preClose = data.stock[0].yclose; //前一个数据价格
  7837. var date = data.stock[0].date;
  7838. if (isFutures && data.stock[0].yclearing) preClose = data.stock[0].yclearing; //期货使用昨结算价
  7839. for (var i=0; i<data.stock[0].minute.length; ++i)
  7840. {
  7841. var jsData = data.stock[0].minute[i];
  7842. var item = new HistoryData();
  7843. item.Close = jsData.price;
  7844. item.Open = jsData.open;
  7845. item.High = jsData.high;
  7846. item.Low = jsData.low;
  7847. item.Vol = jsData.vol; //单位股
  7848. item.Amount = jsData.amount;
  7849. if (jsData.date > 0) item.Date = jsData.date;
  7850. else item.Date = date;
  7851. item.Time = jsData.time;
  7852. item.YClose = preClose;
  7853. if (IFrameSplitOperator.IsNumber(jsData.position)) item.Position = jsData.position; //持仓量
  7854. if (!IFrameSplitOperator.IsNumber(item.Close)) //当前没有价格 使用上一个价格填充
  7855. {
  7856. item.Close = preClose;
  7857. item.Open = item.High = item.Low = item.Close;
  7858. }
  7859. //价格是0的 都用空
  7860. if (!IFrameSplitOperator.IsNumber(item.Open)) item.Open = null;
  7861. if (!IFrameSplitOperator.IsNumber(item.Close)) item.Close = null;
  7862. if (!IFrameSplitOperator.IsNumber(item.High)) item.High = null;
  7863. if (!IFrameSplitOperator.IsNumber(item.Low)) item.Low = null;
  7864. //上次价格
  7865. if (IFrameSplitOperator.IsNumber(jsData.price)) preClose = jsData.price;
  7866. aryMinuteData[i] = item;
  7867. }
  7868. return aryMinuteData;
  7869. }
  7870. //API 返回数据 转化为array[]
  7871. KLineChartContainer.JsonDataToMinuteHistoryData = function (data)
  7872. {
  7873. var upperSymbol = null;
  7874. if (data.symbol) upperSymbol = data.symbol.toUpperCase();
  7875. var isSHSZ = false;
  7876. if (upperSymbol) isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  7877. var isFutures = false; //是否是期货
  7878. if (upperSymbol) isFutures = MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol);
  7879. var list = data.data;
  7880. var aryDayData = new Array();
  7881. var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8, position = 9;
  7882. var fclose=10, yfclose=11; //结算价, 前结算价
  7883. var bfactor=12, afactor=13; //前, 后复权因子
  7884. var colorData=JSCHART_DATA_FIELD_ID.KLINE_COLOR_DATA;
  7885. var extendDataIndex=JSCHART_DATA_FIELD_ID.KLINE_MINUTE_EXTENDDATA; //k线扩展数据
  7886. for (var i = 0; i < list.length; ++i)
  7887. {
  7888. var item = new HistoryData();
  7889. var jsData=list[i];
  7890. item.Date = jsData[date];
  7891. item.Open = jsData[open];
  7892. item.YClose = jsData[yclose];
  7893. item.Close = jsData[close];
  7894. item.High = jsData[high];
  7895. item.Low = jsData[low];
  7896. item.Vol = jsData[vol]; //原始单位股
  7897. item.Amount = jsData[amount];
  7898. item.Time = jsData[time];
  7899. if (IFrameSplitOperator.IsNumber(jsData[position])) item.Position = jsData[position]; //期货持仓
  7900. if (IFrameSplitOperator.IsNumber(jsData[fclose])) item.FClose=jsData[fclose]; //期货结算价
  7901. if (IFrameSplitOperator.IsNumber(jsData[yfclose])) item.YFClose=jsData[yfclose]; //期货前结算价
  7902. if (IFrameSplitOperator.IsNumber(jsData[bfactor])) item.BFactor=jsData[bfactor]; //前复权因子
  7903. if (IFrameSplitOperator.IsNumber(jsData[afactor])) item.AFactor=jsData[afactor]; //后复权因子
  7904. if (jsData[colorData]) item.ColorData=jsData[colorData];
  7905. if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex];
  7906. aryDayData.push(item);
  7907. }
  7908. return aryDayData;
  7909. }
  7910. ///////////////////////////////////////////////////////////////////////////////////////////
  7911. // 走势图
  7912. //
  7913. function MinuteChartContainer(uielement)
  7914. {
  7915. this.newMethod = JSChartContainer; //派生
  7916. this.newMethod(uielement);
  7917. delete this.newMethod;
  7918. this.ClassName = 'MinuteChartContainer';
  7919. this.WindowIndex = new Array();
  7920. this.Symbol;
  7921. this.Name;
  7922. this.SourceData; //原始的历史数据
  7923. this.OverlaySourceData; //叠加的原始数据
  7924. this.IsAutoUpdate = false; //是否自动更新行情数据
  7925. this.AutoUpdateFrequency = 30000; //30秒更新一次数据
  7926. this.AutoUpdateTimer=null; //更新定时器
  7927. this.TradeDate = 0; //行情交易日期
  7928. this.LoadDataSplashTitle = '下载分钟数据';
  7929. this.UpdateUICallback; //数据到达回调
  7930. this.DayCount = 1; //显示几天的数据
  7931. this.DayData; //多日分钟数据
  7932. this.ZoomStepPixel = 50; //放大缩小手势需要的最小像素
  7933. this.MinuteApiUrl = g_JSChartResource.Domain + "/API/Stock";
  7934. this.HistoryMinuteApiUrl = g_JSChartResource.Domain + "/API/StockMinuteData"; //历史分钟数据
  7935. this.DataStatus={ MultiDay:false, LatestDay:false }; //MultiDay=多日 LatestDay:当天
  7936. this.EnableNightDayBG=false; //是否启动夜盘背景色
  7937. //手机拖拽
  7938. this.ontouchstart = function (e)
  7939. {
  7940. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  7941. this.IsPress=false;
  7942. this.IsOnTouch = true;
  7943. this.TouchDrawCount=0;
  7944. var jsChart = this;
  7945. if (jsChart.DragMode == 0) return;
  7946. if (this.IsPhoneDragging(e))
  7947. {
  7948. if (this.TryClickLock || this.TryClickIndexTitle)
  7949. {
  7950. var touches = this.GetToucheData(e, this.IsForceLandscape);
  7951. var x = touches[0].clientX;
  7952. var y = touches[0].clientY;
  7953. if (this.TryClickLock && this.TryClickLock(x, y)) return;
  7954. if (this.TryClickIndexTitle && this.TryClickIndexTitle(x, y)) return;
  7955. }
  7956. //长按2秒,十字光标
  7957. this.ClearTouchTimer();
  7958. var drag =
  7959. {
  7960. "Click": {},
  7961. "LastMove": {}, //最后移动的位置
  7962. };
  7963. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  7964. drag.Click.X = touches[0].clientX;
  7965. drag.Click.Y = touches[0].clientY;
  7966. drag.LastMove.X = touches[0].clientX;
  7967. drag.LastMove.Y = touches[0].clientY;
  7968. this.MouseDrag=drag;
  7969. this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } };
  7970. if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false;
  7971. this.SelectChartDrawPicture=null;
  7972. if (this.CurrentChartDrawPicture) //画图工具模式
  7973. {
  7974. var drawPicture=this.CurrentChartDrawPicture;
  7975. if (drawPicture.Status==2)
  7976. {
  7977. this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y,true);
  7978. }
  7979. else
  7980. {
  7981. this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true);
  7982. //只有1个点 直接完成
  7983. if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false});
  7984. }
  7985. return;
  7986. }
  7987. else
  7988. {
  7989. var pt=this.PointAbsoluteToRelative(touches[0].clientX,touches[0].clientY, true);
  7990. var drawPictrueData={ X:pt.X, Y:pt.Y, PixelRatio:this.UIElement.PixelRatio };
  7991. if (this.GetChartDrawPictureByPoint(drawPictrueData))
  7992. {
  7993. if (drawPictrueData.ChartDrawPicture.EnableMove===true)
  7994. drawPictrueData.ChartDrawPicture.Status=20;
  7995. drawPictrueData.ChartDrawPicture.ValueToPoint();
  7996. drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex;
  7997. drawPictrueData.ChartDrawPicture.IsSelected=true;
  7998. this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture;
  7999. this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture;
  8000. let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件
  8001. if (event && event.Callback)
  8002. {
  8003. let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture };
  8004. event.Callback(event,sendData,this);
  8005. }
  8006. this.DrawDynamicInfo();
  8007. return;
  8008. }
  8009. }
  8010. var T_ShowCorssCursor=()=>
  8011. {
  8012. if (this.ChartCorssCursor.IsShow === true) //移动十字光标
  8013. {
  8014. var x = drag.Click.X;
  8015. var y = drag.Click.Y;
  8016. if (jsChart.IsForceLandscape) y = jsChart.UIElement.Height - drag.Click.Y; //强制横屏Y计算
  8017. jsChart.OnMouseMove(x, y, e);
  8018. }
  8019. }
  8020. if (this.EnableZoomIndexWindow)
  8021. {
  8022. this.PhoneDBClick.AddTouchStart(touches[0].clientX, touches[0].clientY, Date.now());
  8023. JSConsole.Chart.Log("[MinuteChartContainer::OnTouchStart] PhoneDBClick ", this.PhoneDBClick);
  8024. }
  8025. if (this.EnableScrollUpDown==true)
  8026. {
  8027. this.TouchTimer=setTimeout(()=>
  8028. {
  8029. this.MouseDrag=null;
  8030. this.IsPress=true;
  8031. T_ShowCorssCursor();
  8032. }, this.PressTime);
  8033. }
  8034. var bStartTimer=true; //长按计时开始
  8035. if (this.EnableClickModel)
  8036. {
  8037. if (this.ClickModel.IsShowCorssCursor==true) bStartTimer=false;
  8038. else bStartTimer= true;
  8039. }
  8040. if (bStartTimer)
  8041. {
  8042. this.ClearTouchTimer();
  8043. this.TouchTimer = setTimeout(()=>{
  8044. jsChart.IsPress=true;
  8045. if (drag.Click.X == drag.LastMove.X && drag.Click.Y == drag.LastMove.Y) //手指没有移动,出现十字光标
  8046. {
  8047. jsChart.MouseDrag = null;
  8048. //移动十字光标
  8049. var x = drag.Click.X;
  8050. var y = drag.Click.Y;
  8051. if (jsChart.EnableClickModel===true) jsChart.ClickModel.IsShowCorssCursor=true;
  8052. jsChart.OnMouseMove(x, y, e);
  8053. }
  8054. }, jsChart.PressTime);
  8055. }
  8056. else if (!this.EnableClickModel)
  8057. {
  8058. if (this.EnableScrollUpDown==false)
  8059. T_ShowCorssCursor();
  8060. else if (this.IsClickShowCorssCursor)
  8061. T_ShowCorssCursor();
  8062. }
  8063. this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e);
  8064. }
  8065. else if (this.IsPhonePinching(e))
  8066. {
  8067. var phonePinch = { "Start": {}, "Last": {} };
  8068. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  8069. phonePinch.Start = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY };
  8070. phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY };
  8071. jsChart.PhonePinch = phonePinch;
  8072. }
  8073. }
  8074. this.ontouchmove = function (e)
  8075. {
  8076. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  8077. var jsChart = this;
  8078. var drag = jsChart.MouseDrag;
  8079. var touches = this.GetToucheData(e, jsChart.IsForceLandscape);
  8080. if (this.IsPhoneDragging(e))
  8081. {
  8082. if (drag == null)
  8083. {
  8084. var x = touches[0].clientX;
  8085. var y = touches[0].clientY;
  8086. this.LastMovePoint={ X:x, Y:y };
  8087. if (this.DrawMoveTimer) return;
  8088. this.DrawMoveTimer=setTimeout(()=>
  8089. {
  8090. if (!this.LastMovePoint) return;
  8091. this.OnMouseMove(this.LastMovePoint.X, this.LastMovePoint.Y, e);
  8092. this.DrawMoveTimer=null;
  8093. }, this.DrawMoveWaitTime);
  8094. }
  8095. else
  8096. {
  8097. var moveAngle=this.GetMoveAngle(drag.LastMove,{X:touches[0].clientX, Y:touches[0].clientY});
  8098. var moveSetp=Math.abs(drag.LastMove.X-touches[0].clientX);
  8099. var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY);
  8100. moveSetp=parseInt(moveSetp);
  8101. if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true)
  8102. {
  8103. var drawPicture=this.CurrentChartDrawPicture;
  8104. if (drawPicture.Status==1 || drawPicture.Status==2)
  8105. {
  8106. if(moveSetp<5 && moveUpDown<5) return;
  8107. if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY,true))
  8108. {
  8109. this.DrawDynamicInfo();
  8110. }
  8111. }
  8112. else if (drawPicture.Status==3)
  8113. {
  8114. if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY,true))
  8115. {
  8116. this.DrawDynamicInfo();
  8117. }
  8118. }
  8119. else if (drawPicture.Status==20) //画图工具移动
  8120. {
  8121. if(moveSetp<5 && moveUpDown<5) return;
  8122. if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y,true))
  8123. {
  8124. this.DrawDynamicInfo();
  8125. }
  8126. }
  8127. drag.LastMove.X=touches[0].clientX;
  8128. drag.LastMove.Y=touches[0].clientY;
  8129. }
  8130. else
  8131. {
  8132. if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true )
  8133. { //上下滚动
  8134. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_TOUCH_SCROLL_UP_DOWN);
  8135. var isEnd=true; //是否退出
  8136. if (event && event.Callback)
  8137. {
  8138. var sendData={ DragData:drag, PreventDefault:false };
  8139. event.Callback(event, sendData, this);
  8140. isEnd=(sendData.PreventDefault===false);
  8141. }
  8142. if (isEnd)
  8143. {
  8144. this.ClearTouchTimer();
  8145. return;
  8146. }
  8147. }
  8148. if (drag!=null)
  8149. {
  8150. this.ClearTouchTimer();
  8151. this.MouseDrag=null;
  8152. var x = touches[0].clientX;
  8153. var y = touches[0].clientY;
  8154. this.OnMouseMove(x,y,e);
  8155. }
  8156. }
  8157. }
  8158. }
  8159. else if (this.IsPhonePinching(e))
  8160. {
  8161. var phonePinch = jsChart.PhonePinch;
  8162. if (!phonePinch) return;
  8163. if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return;
  8164. var yHeight = Math.abs(touches[0].pageY - touches[1].pageY);
  8165. var yLastHeight = Math.abs(phonePinch.Last.Y - phonePinch.Last.Y2);
  8166. var yStep = yHeight - yLastHeight;
  8167. var xHeight = Math.abs(touches[0].pageX - touches[1].pageX);
  8168. var xLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2);
  8169. var xStep = xHeight - xLastHeight;
  8170. var minStep=this.ZoomStepPixel;
  8171. if (Math.abs(yStep) < minStep && Math.abs(xStep) < minStep) return;
  8172. if (Math.abs(xStep) > minStep)
  8173. {
  8174. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_MINUTE_TOUCH_ZOOM)
  8175. if (event && event.Callback)
  8176. {
  8177. var data={ XStep:xStep, YStep:yStep, PreventDefault:false };
  8178. event.Callback(event,data,this);
  8179. if (data.PreventDefault)
  8180. {
  8181. this.PhonePinch=null;
  8182. this.ClearTouchTimer();
  8183. return;
  8184. }
  8185. }
  8186. }
  8187. phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY };
  8188. }
  8189. if (this.PhoneTouchInfo)
  8190. {
  8191. this.PhoneTouchInfo.End.X=touches[0].clientX;
  8192. this.PhoneTouchInfo.End.Y=touches[0].clientY;
  8193. }
  8194. }
  8195. //创建
  8196. //windowCount 窗口个数
  8197. this.Create = function (windowCount)
  8198. {
  8199. this.UIElement.JSChartContainer = this;
  8200. //创建十字光标
  8201. this.ChartCorssCursor = new ChartCorssCursor();
  8202. this.ChartCorssCursor.Canvas = this.Canvas;
  8203. this.ChartCorssCursor.StringFormatX = new HQMinuteTimeStringFormat();
  8204. this.ChartCorssCursor.StringFormatX.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8205. this.ChartCorssCursor.StringFormatY = g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat");
  8206. this.ChartCorssCursor.StringFormatY.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8207. this.ChartCorssCursor.StringFormatY.LanguageID = this.LanguageID;
  8208. this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8209. //创建等待提示
  8210. this.ChartSplashPaint = new ChartSplashPaint();
  8211. this.ChartSplashPaint.Canvas = this.Canvas;
  8212. this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle;
  8213. this.ChartSplashPaint.HQChart=this;
  8214. //创建框架容器
  8215. this.Frame = new HQTradeFrame();
  8216. this.Frame.ChartBorder = new ChartBorder();
  8217. this.Frame.ChartBorder.UIElement = this.UIElement;
  8218. this.Frame.ChartBorder.Top = 25;
  8219. this.Frame.ChartBorder.Left = 50;
  8220. this.Frame.ChartBorder.Bottom = 20;
  8221. this.Frame.Canvas = this.Canvas;
  8222. this.Frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8223. this.Frame.ZoomStartWindowIndex=2;
  8224. this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架
  8225. this.ChartSplashPaint.Frame = this.Frame;
  8226. this.CreateChildWindow(windowCount);
  8227. this.CreateMainKLine();
  8228. //子窗口动态标题
  8229. for (var i=0; i<this.Frame.SubFrame.length; ++i)
  8230. {
  8231. var titlePaint = new DynamicChartTitlePainting();
  8232. if (i==0 || i==1) titlePaint.IsShowMainIndexTitle=false;
  8233. titlePaint.Frame = this.Frame.SubFrame[i].Frame;
  8234. titlePaint.Canvas = this.Canvas;
  8235. titlePaint.LanguageID = this.LanguageID;
  8236. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8237. this.TitlePaint.push(titlePaint);
  8238. }
  8239. this.ChartCorssCursor.StringFormatX.Frame = this.Frame.SubFrame[0].Frame;
  8240. this.ChartCorssCursor.StringFormatY.Frame=this.Frame;
  8241. }
  8242. //创建子窗口
  8243. this.CreateChildWindow = function (windowCount)
  8244. {
  8245. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME);
  8246. for (var i = 0; i < windowCount; ++i)
  8247. {
  8248. var border = new ChartBorder();
  8249. border.UIElement = this.UIElement;
  8250. var frame = new MinuteFrame();
  8251. frame.Canvas = this.Canvas;
  8252. frame.ChartBorder = border;
  8253. frame.Identify=i;
  8254. if (i < 2) frame.ChartBorder.TitleHeight = 0;
  8255. frame.XPointCount = 243;
  8256. frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8257. frame.HQChart=this;
  8258. var DEFAULT_HORIZONTAL = [9, 8, 7, 6, 5, 4, 3, 2, 1];
  8259. frame.HorizontalMax = DEFAULT_HORIZONTAL[0];
  8260. frame.HorizontalMin = DEFAULT_HORIZONTAL[DEFAULT_HORIZONTAL.length - 1];
  8261. if (i == 0)
  8262. {
  8263. frame.YSplitOperator = new FrameSplitMinutePriceY();
  8264. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price');
  8265. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8266. frame.YSplitOperator.HQChart=this;
  8267. }
  8268. else
  8269. {
  8270. frame.YSplitOperator = new FrameSplitY();
  8271. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double');
  8272. frame.YSplitOperator.LanguageID = this.LanguageID;
  8273. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8274. }
  8275. frame.YSplitOperator.Frame = frame;
  8276. frame.YSplitOperator.ChartBorder = border;
  8277. frame.XSplitOperator = new FrameSplitMinuteX();
  8278. frame.XSplitOperator.Frame = frame;
  8279. frame.XSplitOperator.ChartBorder = border;
  8280. frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8281. if (i != windowCount - 1) frame.XSplitOperator.ShowText = false;
  8282. frame.XSplitOperator.Operator();
  8283. for (var j in DEFAULT_HORIZONTAL)
  8284. {
  8285. frame.HorizontalInfo[j] = new CoordinateInfo();
  8286. frame.HorizontalInfo[j].Value = DEFAULT_HORIZONTAL[j];
  8287. if (i == 0 && j == frame.HorizontalMin) continue;
  8288. frame.HorizontalInfo[j].Message[1] = DEFAULT_HORIZONTAL[j].toString();
  8289. frame.HorizontalInfo[j].Font = "14px 微软雅黑";
  8290. }
  8291. var subFrame = new SubFrameItem();
  8292. frame.FrameData.SubFrameItem=subFrame;
  8293. subFrame.Frame = frame;
  8294. if (i == 0) subFrame.Height = 20;
  8295. else subFrame.Height = 10;
  8296. this.Frame.SubFrame[i] = subFrame;
  8297. if (event && event.Callback)
  8298. {
  8299. var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i };
  8300. event.Callback(event, sendData, this);
  8301. }
  8302. }
  8303. }
  8304. this.CreateSubFrameItem=function(id)
  8305. {
  8306. var border=new ChartBorder();
  8307. border.UIElement=this.UIElement;
  8308. var frame=new MinuteFrame();
  8309. frame.Canvas=this.Canvas;
  8310. frame.ChartBorder=border;
  8311. frame.Identify=id; //窗口序号
  8312. frame.XPointCount=243;
  8313. frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); };
  8314. frame.HQChart=this;
  8315. if (id>=2)
  8316. {
  8317. if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.DoModal; //绑定菜单事件
  8318. if (this.ChangeIndexDialog) frame.ChangeIndexEvent=this.ChangeIndexDialog.DoModal;
  8319. }
  8320. var DEFAULT_HORIZONTAL=[9,8,7,6,5,4,3,2,1];
  8321. frame.HorizontalMax=DEFAULT_HORIZONTAL[0];
  8322. frame.HorizontalMin=DEFAULT_HORIZONTAL[DEFAULT_HORIZONTAL.length-1];
  8323. frame.YSplitOperator=new FrameSplitY();
  8324. frame.YSplitOperator.LanguageID=this.LanguageID;
  8325. frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double');
  8326. frame.YSplitOperator.Frame=frame;
  8327. frame.YSplitOperator.ChartBorder=border;
  8328. frame.XSplitOperator=new FrameSplitMinuteX();
  8329. frame.XSplitOperator.Frame=frame;
  8330. frame.XSplitOperator.ChartBorder=border;
  8331. frame.XSplitOperator.ShowText=false;
  8332. frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8333. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8334. //K线数据绑定
  8335. var xPointCouont=this.Frame.SubFrame[0].Frame.XPointCount;
  8336. frame.XPointCount=xPointCouont;
  8337. frame.Data=this.ChartPaint[0].Data;
  8338. for(var j in DEFAULT_HORIZONTAL)
  8339. {
  8340. frame.HorizontalInfo[j]= new CoordinateInfo();
  8341. frame.HorizontalInfo[j].Value=DEFAULT_HORIZONTAL[j];
  8342. frame.HorizontalInfo[j].Message[1]=DEFAULT_HORIZONTAL[j].toString();
  8343. frame.HorizontalInfo[j].Font="14px 微软雅黑";
  8344. }
  8345. var subFrame=new SubFrameItem();
  8346. subFrame.Frame=frame;
  8347. subFrame.Height=10;
  8348. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME);
  8349. if (event && event.Callback)
  8350. {
  8351. var sendData={ SubFrame:subFrame, WindowIndex:id };
  8352. event.Callback(event, sendData, this);
  8353. }
  8354. return subFrame;
  8355. }
  8356. this.UpdateXShowText=function()
  8357. {
  8358. var bLastFrame=true;
  8359. for(var i=this.Frame.SubFrame.length-1;i>=0;--i)
  8360. {
  8361. var item=this.Frame.SubFrame[i].Frame;
  8362. var subFrame=this.Frame.SubFrame[i];
  8363. if (bLastFrame)
  8364. {
  8365. item.XSplitOperator.ShowText=true;
  8366. if (subFrame.Height>0) bLastFrame=false;
  8367. }
  8368. else
  8369. {
  8370. item.XSplitOperator.ShowText=false;
  8371. }
  8372. }
  8373. }
  8374. //删除某一个窗口的指标 bCallDestory=是否调用图形销毁函数
  8375. this.DeleteIndexPaint = function (windowIndex, bCallDestroy)
  8376. {
  8377. if (!this.Frame.SubFrame[windowIndex]) return;
  8378. var subFrame=this.Frame.SubFrame[windowIndex].Frame;
  8379. if (!subFrame) return;
  8380. var paint=[];
  8381. for (var i=0;i<this.ChartPaint.length;++i) //踢出当前窗口的指标画法
  8382. {
  8383. let item = this.ChartPaint[i];
  8384. var bFind=(item.ChartFrame.Guid==subFrame.Guid || item.ChartFrame==subFrame);
  8385. if (i == 0 || !bFind)
  8386. {
  8387. paint.push(item);
  8388. }
  8389. else
  8390. {
  8391. if (bCallDestroy===true)
  8392. {
  8393. if (item && item.OnDestroy) item.OnDestroy(); //图形销毁
  8394. }
  8395. }
  8396. }
  8397. //清空指定最大最小值
  8398. subFrame.YSpecificMaxMin = null;
  8399. subFrame.IsLocked = false; //解除上锁
  8400. subFrame.YSplitOperator.SplitType=subFrame.YSplitOperator.DefaultSplitType; //还原Y坐标分割模式
  8401. this.ChartPaint = paint;
  8402. //清空东条标题
  8403. var titleIndex = windowIndex + 1;
  8404. this.TitlePaint[titleIndex].Data = [];
  8405. this.TitlePaint[titleIndex].Title = null;
  8406. }
  8407. this.CreateStockInfo = function () {
  8408. this.ExtendChartPaint[0] = new StockInfoExtendChartPaint();
  8409. this.ExtendChartPaint[0].Canvas = this.Canvas;
  8410. this.ExtendChartPaint[0].ChartBorder = this.Frame.ChartBorder;
  8411. this.ExtendChartPaint[0].ChartFrame = this.Frame;
  8412. this.Frame.ChartBorder.Right = 300;
  8413. }
  8414. //创建主图K线画法
  8415. this.CreateMainKLine = function ()
  8416. {
  8417. //分钟线
  8418. var minuteLine = new ChartMinutePriceLine();
  8419. minuteLine.Canvas = this.Canvas;
  8420. minuteLine.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  8421. minuteLine.ChartFrame = this.Frame.SubFrame[0].Frame;
  8422. minuteLine.Name = "Minute-Line";
  8423. minuteLine.Color = g_JSChartResource.Minute.PriceColor;
  8424. minuteLine.LineWidth=g_JSChartResource.Minute.PriceLineWidth;
  8425. minuteLine.AreaColor = g_JSChartResource.Minute.AreaPriceColor;
  8426. this.ChartPaint[0] = minuteLine;
  8427. //分钟线均线
  8428. var averageLine = new ChartMinutePriceLine();
  8429. averageLine.Canvas = this.Canvas;
  8430. averageLine.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  8431. averageLine.ChartFrame = this.Frame.SubFrame[0].Frame;
  8432. averageLine.Name = "Minute-Average-Line";
  8433. averageLine.Color = g_JSChartResource.Minute.AvPriceColor;
  8434. averageLine.IsDrawArea = false;
  8435. this.ChartPaint[1] = averageLine;
  8436. //成交量柱子
  8437. var chartVol = new ChartMinuteVolumBar();
  8438. chartVol.Color = g_JSChartResource.Minute.VolBarColor;
  8439. chartVol.Canvas = this.Canvas;
  8440. chartVol.ChartBorder = this.Frame.SubFrame[1].Frame.ChartBorder;
  8441. chartVol.ChartFrame = this.Frame.SubFrame[1].Frame;
  8442. chartVol.Name = "Minute-Vol-Bar";
  8443. this.ChartPaint[2] = chartVol;
  8444. //持仓线
  8445. var chartPosition=new ChartSubLine();
  8446. chartPosition.Color = g_JSChartResource.Minute.PriceColor;
  8447. chartPosition.Canvas = this.Canvas;
  8448. chartPosition.ChartBorder = this.Frame.SubFrame[1].Frame.ChartBorder;
  8449. chartPosition.ChartFrame = this.Frame.SubFrame[1].Frame;
  8450. chartPosition.Name = "Minute-Position-Line";
  8451. this.ChartPaint[3] = chartPosition;
  8452. this.TitlePaint[0] = new DynamicMinuteTitlePainting();
  8453. this.TitlePaint[0].Frame = this.Frame.SubFrame[0].Frame;
  8454. this.TitlePaint[0].Canvas = this.Canvas;
  8455. this.TitlePaint[0].LanguageID = this.LanguageID;
  8456. this.TitlePaint[0].HQChart=this;
  8457. }
  8458. //切换成 脚本指标
  8459. this.ChangeScriptIndex = function (windowIndex, indexData)
  8460. {
  8461. this.DeleteIndexPaint(windowIndex, true);
  8462. this.WindowIndex[windowIndex] = new ScriptIndex(indexData.Name, indexData.Script, indexData.Args, indexData); //脚本执行
  8463. var bindData = this.SourceData;
  8464. this.BindIndexData(windowIndex, bindData); //执行脚本
  8465. this.UpdataDataoffset(); //更新数据偏移
  8466. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  8467. this.Draw();
  8468. }
  8469. //切换api指标
  8470. this.ChangeAPIIndex=function(windowIndex,indexData)
  8471. {
  8472. this.DeleteIndexPaint(windowIndex, true);
  8473. //使用API挂接指标数据 API:{ Name:指标名字, Script:指标脚本可以为空, Args:参数可以为空, Url:指标执行地址 }
  8474. var apiItem=indexData.API;
  8475. this.WindowIndex[windowIndex]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,indexData);
  8476. var bindData=this.ChartPaint[0].Data;
  8477. this.BindIndexData(windowIndex,bindData); //执行脚本
  8478. this.UpdataDataoffset(); //更新数据偏移
  8479. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  8480. this.Draw();
  8481. }
  8482. this.ChangeIndex = function (windowIndex, indexName, option)
  8483. {
  8484. if (this.Frame.SubFrame.length < 3) return;
  8485. if (option && option.API)
  8486. return this.ChangeAPIIndex(windowIndex,option);
  8487. //查找系统指标
  8488. let scriptData = new JSCommonIndexScript.JSIndexScript();
  8489. let indexInfo = scriptData.Get(indexName);
  8490. if (!indexInfo) return;
  8491. if (windowIndex < 2) windowIndex = 2;
  8492. if (windowIndex >= this.Frame.SubFrame.length) windowIndex = 2;
  8493. if (option) JSIndexScript.ModifyAttribute(indexInfo, option);
  8494. return this.ChangeScriptIndex(windowIndex, indexInfo);
  8495. }
  8496. this.ChangeIndexTemplate=function(option) //切换指标模板 可以设置指标窗口个数 每个窗口的指标, 只能从第3个指标窗口开始设置,前面2个指标窗口固定无法设置
  8497. {
  8498. if (!Array.isArray(option.Windows)) return;
  8499. var count=option.Windows.length;
  8500. var currentLength=this.Frame.SubFrame.length;
  8501. var startWindowIndex=2;
  8502. count+=startWindowIndex;
  8503. var dayCount=null;
  8504. if (IFrameSplitOperator.IsNumber(option.DayCount) && option.DayCount!=this.DayCount) dayCount= option.DayCount; //天数
  8505. var bRefreshData= (dayCount!=null);
  8506. //清空所有的指标图型
  8507. for(var i=startWindowIndex;i<currentLength;++i)
  8508. {
  8509. this.DeleteIndexPaint(i);
  8510. var frame=this.Frame.SubFrame[i];
  8511. frame.YSpecificMaxMin=null;
  8512. frame.IsLocked=false;
  8513. frame.YSplitScale = null;
  8514. }
  8515. if (currentLength>count)
  8516. {
  8517. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME);
  8518. for(var i=currentLength-1;i>=count;--i)
  8519. {
  8520. if (event && event.Callback)
  8521. {
  8522. var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i };
  8523. event.Callback(event, sendData, this);
  8524. }
  8525. }
  8526. this.Frame.SubFrame.splice(count,currentLength-count);
  8527. this.WindowIndex.splice(count,currentLength-count);
  8528. this.TitlePaint.splice(count+1,currentLength-count);
  8529. }
  8530. else
  8531. {
  8532. for(var i=currentLength;i<count;++i) //创建新的指标窗口
  8533. {
  8534. var subFrame=this.CreateSubFrameItem(i);
  8535. this.Frame.SubFrame[i]=subFrame;
  8536. var titlePaint=new DynamicChartTitlePainting();
  8537. titlePaint.Frame=this.Frame.SubFrame[i].Frame;
  8538. titlePaint.Canvas=this.Canvas;
  8539. titlePaint.LanguageID=this.LanguageID;
  8540. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  8541. titlePaint.SelectedChart=this.SelectedChart;
  8542. this.TitlePaint[i+1]=titlePaint;
  8543. }
  8544. }
  8545. for(var i=0;i<count;++i)
  8546. {
  8547. var windowIndex=i;
  8548. var item=null,frameItem=null;
  8549. if (option.Frame && option.Frame.length>i) frameItem=option.Frame[windowIndex];
  8550. if (windowIndex>=startWindowIndex) item=option.Windows[windowIndex-startWindowIndex];
  8551. var titleIndex=windowIndex+1;
  8552. this.TitlePaint[titleIndex].Data=[];
  8553. this.TitlePaint[titleIndex].Title=null;
  8554. if (item)
  8555. {
  8556. if (item.Script) //自定义指标脚本
  8557. {
  8558. this.WindowIndex[windowIndex]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行
  8559. }
  8560. else if (item.API) //后台指标
  8561. {
  8562. var apiItem=item.API;
  8563. this.WindowIndex[windowIndex]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item);
  8564. }
  8565. else
  8566. {
  8567. var indexID=item.Index;
  8568. var indexItem=JSIndexMap.Get(indexID);
  8569. if (indexItem)
  8570. {
  8571. this.WindowIndex[windowIndex]=indexItem.Create();
  8572. this.CreateWindowIndex(windowIndex);
  8573. }
  8574. else
  8575. {
  8576. var systemScript = new JSIndexScript();
  8577. var indexInfo = systemScript.Get(indexID);
  8578. if (indexInfo)
  8579. {
  8580. JSIndexScript.ModifyAttribute(indexInfo, item)
  8581. this.WindowIndex[windowIndex]=new ScriptIndex(indexInfo.Name,indexInfo.Script, indexInfo.Args,indexInfo); //脚本执行
  8582. }
  8583. }
  8584. }
  8585. }
  8586. this.SetSubFrameAttribute(this.Frame.SubFrame[windowIndex], item, frameItem);
  8587. }
  8588. //清空叠加指标
  8589. for(var i=0;i<this.Frame.SubFrame.length;++i)
  8590. {
  8591. this.DeleteWindowsOverlayIndex(i);
  8592. }
  8593. //最后一个显示X轴坐标
  8594. for(var i=0;i<this.Frame.SubFrame.length;++i)
  8595. {
  8596. var item=this.Frame.SubFrame[i].Frame;
  8597. if (i==this.Frame.SubFrame.length-1) item.XSplitOperator.ShowText=true;
  8598. else item.XSplitOperator.ShowText=false;
  8599. }
  8600. //叠加指标
  8601. var aryOverlayIndex=[];
  8602. if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex))
  8603. {
  8604. for(var i=0;i<option.OverlayIndex.length;++i)
  8605. {
  8606. var item=option.OverlayIndex[i];
  8607. if (item.Index) item.IndexName=item.Index;
  8608. if (item.Windows>=0) item.WindowIndex=item.Windows;
  8609. var overlay=this.CreateOverlayWindowsIndex(item);
  8610. if (!overlay) continue;
  8611. aryOverlayIndex.push({ WindowsIndex:item.WindowIndex, Overlay:overlay });
  8612. }
  8613. }
  8614. this.Frame.SetSizeChage(true);
  8615. if (!bRefreshData)
  8616. {
  8617. var bindData=this.SourceData;
  8618. for(var i=0;i<count;++i)
  8619. {
  8620. this.BindIndexData(i,bindData);
  8621. }
  8622. for(var i=0;i<aryOverlayIndex.length;++i)
  8623. {
  8624. var item=aryOverlayIndex[i];
  8625. this.BindOverlayIndexData(item.Overlay,item.WindowsIndex,bindData);
  8626. }
  8627. this.UpdataDataoffset(); //更新数据偏移
  8628. if (this.UpdateXShowText) this.UpdateXShowText();
  8629. this.ResetFrameXYSplit();
  8630. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  8631. this.Draw();
  8632. }
  8633. else
  8634. {
  8635. //this.Frame.SetSizeChage(true);
  8636. if (dayCount!=null) this.ChangeDayCount(dayCount);
  8637. }
  8638. }
  8639. this.RemoveIndexWindow=function(id)
  8640. {
  8641. JSConsole.Chart.Log('[MinuteChartContainer::RemoveIndexWindow] remove id', id);
  8642. if (id<2) return;
  8643. if (!this.Frame.SubFrame) return;
  8644. if (id>=this.Frame.SubFrame.length) return;
  8645. var delFrame=this.Frame.SubFrame[id].Frame;
  8646. this.DeleteIndexPaint(id, true);
  8647. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME);
  8648. if (event && event.Callback)
  8649. {
  8650. var sendData={ SubFrame:this.Frame.SubFrame[id], WindowIndex:id };
  8651. event.Callback(event, sendData, this);
  8652. }
  8653. this.Frame.SubFrame.splice(id,1);
  8654. this.WindowIndex.splice(id,1);
  8655. this.TitlePaint.splice(id+1,1); //删除对应的动态标题
  8656. for(var i=0;i<this.Frame.SubFrame.length;++i)
  8657. {
  8658. var item=this.Frame.SubFrame[i].Frame;
  8659. if (i==this.Frame.SubFrame.length-1) item.XSplitOperator.ShowText=true;
  8660. else item.XSplitOperator.ShowText=false;
  8661. item.Identify=i;
  8662. }
  8663. this.Frame.SetSizeChage(true);
  8664. this.UpdateFrameMaxMin();
  8665. this.ResetFrameXYSplit();
  8666. this.Draw();
  8667. }
  8668. this.ClearIndexPaint=function()
  8669. {
  8670. if (this.Frame && this.Frame.SubFrame)
  8671. {
  8672. for(var i=2;i<this.Frame.SubFrame.length;++i)
  8673. {
  8674. if (i>=2) this.DeleteIndexPaint(i, true);
  8675. }
  8676. }
  8677. }
  8678. this.ResetDataStatus=function()
  8679. {
  8680. this.DataStatus.MultiDay=false;
  8681. this.DataStatus.LatestDay=false;
  8682. }
  8683. //切换股票代码
  8684. this.ChangeSymbol = function (symbol)
  8685. {
  8686. this.Symbol = symbol;
  8687. this.CancelAutoUpdate(); //先停止定时器
  8688. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  8689. this.ChartSplashPaint.EnableSplash(true);
  8690. this.ResetDataStatus();
  8691. this.ClearIndexPaint();
  8692. this.ResetOverlaySymbolStatus();
  8693. this.Frame.ClearYCoordinateMaxMin();
  8694. this.RequestData();
  8695. }
  8696. this.ChangeDayCount = function (count)
  8697. {
  8698. if (count < 0 || count > 10) return;
  8699. this.DayCount = count;
  8700. this.CancelAutoUpdate(); //先停止定时器
  8701. this.ResetDataStatus();
  8702. this.ClearIndexPaint();
  8703. this.ResetOverlaySymbolStatus();
  8704. this.Frame.ClearYCoordinateMaxMin();
  8705. this.RequestData();
  8706. }
  8707. //叠加股票 只支持日线数据
  8708. this.OverlaySymbol = function (symbol,option)
  8709. {
  8710. var arySymbol=null;
  8711. if (IFrameSplitOperator.IsString(symbol)) arySymbol=[symbol];
  8712. else if (Array.isArray(symbol)) arySymbol=symbol;
  8713. if (!IFrameSplitOperator.IsNonEmptyArray(arySymbol)) return false;
  8714. var aryNewSymbol=[];
  8715. for(var i=0, j=0;i<arySymbol.length;++i)
  8716. {
  8717. var strSymbol=arySymbol[i];
  8718. var bFind=false;
  8719. for(j=0;j<this.OverlayChartPaint.length; ++j)
  8720. {
  8721. var item=this.OverlayChartPaint[j];
  8722. if (item.Symbol==strSymbol)
  8723. {
  8724. bFind=true;
  8725. console.warn(`[MinuteChartContainer::OverlaySymbol] overlay symbol=${strSymbol} exist.`);
  8726. break;
  8727. }
  8728. }
  8729. if (!bFind) aryNewSymbol.push(strSymbol);
  8730. }
  8731. if (!IFrameSplitOperator.IsNonEmptyArray(aryNewSymbol)) return true;
  8732. for(var i=0;i<aryNewSymbol.length;++i)
  8733. {
  8734. var strSymbol=aryNewSymbol[i];
  8735. var paint=new ChartOverlayMinutePriceLine();
  8736. paint.Canvas=this.Canvas;
  8737. paint.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder;
  8738. paint.ChartFrame=this.Frame.SubFrame[0].Frame;
  8739. paint.Name="Overlay-Minute";
  8740. paint.Symbol=strSymbol;
  8741. paint.Identify=`Overlay-Minute-${strSymbol}`;
  8742. if (option && option.Color) paint.Color=option.Color; //外部设置颜色
  8743. else paint.Color=g_JSChartResource.OverlaySymbol.Color[g_JSChartResource.OverlaySymbol.Random%g_JSChartResource.OverlaySymbol.Color.length];
  8744. ++g_JSChartResource.OverlaySymbol.Random;
  8745. paint.MainData=this.SourceData; //绑定主图数据
  8746. if (paint.SetOption) paint.SetOption(option);
  8747. this.OverlayChartPaint.push(paint);
  8748. }
  8749. if (this.DayCount <= 1) this.RequestOverlayMinuteData(); //请求数据
  8750. else this.RequestOverlayHistoryMinuteData();
  8751. return true;
  8752. }
  8753. //删除一个叠加股票
  8754. this.DeleteOverlaySymbol=function(symbol)
  8755. {
  8756. for(var i=0;i<this.OverlayChartPaint.length; ++i)
  8757. {
  8758. var item=this.OverlayChartPaint[i];
  8759. if (item.Symbol===symbol)
  8760. {
  8761. item.IsDelete=true;
  8762. this.OverlayChartPaint.splice(i,1);
  8763. this.UpdateFrameMaxMin();
  8764. this.Draw();
  8765. return true;
  8766. }
  8767. }
  8768. console.warn(`[MinuteChartContainer::DeleteOverlaySymbol] overlay symbol=${symbol} not exist.`)
  8769. return false;
  8770. }
  8771. //取消叠加股票
  8772. this.ClearOverlaySymbol=function()
  8773. {
  8774. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  8775. {
  8776. var item=this.OverlayChartPaint[i];
  8777. item.IsDelete=true;
  8778. }
  8779. this.OverlayChartPaint=[];
  8780. this.Frame.SubFrame[0].Frame.YSplitOperator.OverlayChartPaint=this.OverlayChartPaint;
  8781. this.TitlePaint[0].OverlayChartPaint=this.OverlayChartPaint; //绑定叠加
  8782. this.UpdateFrameMaxMin();
  8783. this.Draw();
  8784. }
  8785. this.TryClickLock = function (x, y)
  8786. {
  8787. for (let i in this.Frame.SubFrame)
  8788. {
  8789. var item = this.Frame.SubFrame[i];
  8790. if (!item.Frame.IsLocked) continue;
  8791. if (!item.Frame.LockPaint) continue;
  8792. var tooltip = new TooltipData();
  8793. if (!item.Frame.LockPaint.GetTooltipData(x, y, tooltip)) continue;
  8794. tooltip.HQChart = this;
  8795. if (tooltip.Data.Callback) tooltip.Data.Callback(tooltip);
  8796. return true;
  8797. }
  8798. return false;
  8799. }
  8800. this.RequestData = function ()
  8801. {
  8802. if (this.DayCount <= 1) this.RequestMinuteData();
  8803. else this.RequestHistoryMinuteData(); //请求数据
  8804. }
  8805. this.RecvMinuteDataEvent = function ()
  8806. {
  8807. if (!this.mapEvent.has(JSCHART_EVENT_ID.RECV_MINUTE_DATA)) return;
  8808. var event = this.mapEvent.get(JSCHART_EVENT_ID.RECV_MINUTE_DATA);
  8809. var data = { MinuteData: this.SourceData, Stock: { Symbol: this.Symbol, Name: this.Name } }
  8810. event.Callback(event, data, this);
  8811. }
  8812. this.RequestHistoryMinuteData = function () //请求历史分钟数据
  8813. {
  8814. var self = this;
  8815. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  8816. this.ChartSplashPaint.EnableSplash(true);
  8817. this.Draw();
  8818. if (this.NetworkFilter)
  8819. {
  8820. var obj =
  8821. {
  8822. Name: 'MinuteChartContainer::RequestHistoryMinuteData', //类名::
  8823. Explain: '多日分时数据',
  8824. Request: { Url: self.HistoryMinuteApiUrl, Data: { daycount: self.DayCount, symbol: self.Symbol }, Type: 'POST' },
  8825. Self: this,
  8826. PreventDefault: false
  8827. };
  8828. this.NetworkFilter(obj, function (data) {
  8829. self.ChartSplashPaint.EnableSplash(false);
  8830. self.RecvHistoryMinuteData(data);
  8831. });
  8832. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  8833. }
  8834. JSNetwork.HttpRequest({
  8835. url: self.HistoryMinuteApiUrl,
  8836. data:
  8837. {
  8838. "symbol": self.Symbol,
  8839. "daycount": self.DayCount
  8840. },
  8841. method: "post",
  8842. dataType: "json",
  8843. success: function (data) {
  8844. self.ChartSplashPaint.EnableSplash(false);
  8845. self.RecvHistoryMinuteData(data);
  8846. }
  8847. });
  8848. }
  8849. this.RecvHistoryMinuteData = function (recvdata)
  8850. {
  8851. var data = recvdata.data;
  8852. if (data.code!=0)
  8853. {
  8854. JSConsole.Chart.Log('[MinuteChartContainer::RecvHistoryMinuteData] failed.',data);
  8855. return;
  8856. }
  8857. this.DayData = MinuteChartContainer.JsonDataToMinuteDataArray(data);;
  8858. this.Symbol = data.symbol;
  8859. this.Name = data.name;
  8860. this.DataStatus.MultiDay=true;
  8861. if (IFrameSplitOperator.IsNonEmptyArray(this.DayData))
  8862. {
  8863. this.CaclutateLimitPrice(this.DayData[0].YClose, data.data[0].limitprice); //计算涨停价格
  8864. }
  8865. this.UpdateHistoryMinuteUI();
  8866. this.RecvMinuteDataEvent();
  8867. this.RequestOverlayHistoryMinuteData();
  8868. this.BindAllOverlayIndexData(this.SourceData);
  8869. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistoryMinuteData', this);
  8870. this.AutoUpdate();
  8871. }
  8872. this.CaclutateLimitPrice=function(yClose, limitData)
  8873. {
  8874. this.LimitPrice=null;
  8875. //var limitData=data.stock[0].limitprice;
  8876. if (limitData && limitData.max>0 && limitData.min>0) //API里带涨停价格 直接使用
  8877. {
  8878. this.LimitPrice={ Max:limitData.max, Min:limitData.min };
  8879. return;
  8880. }
  8881. var range=MARKET_SUFFIX_NAME.GetLimitPriceRange(this.Symbol, this.Name); //通过规则获取涨停价格
  8882. if (!range)
  8883. {
  8884. JSConsole.Chart.Log(`[MinuteChartContainer::CaclutateLimitPrice] ${this.Symbol} no limit price.`)
  8885. return;
  8886. }
  8887. //var yClose=data.stock[0].yclose;
  8888. if (yClose<=0) return;
  8889. this.LimitPrice={ Max:yClose*(1+range.Max), Min:yClose*(1+range.Min) };
  8890. JSConsole.Chart.Log(`[MinuteChartContainer::CaclutateLimitPrice] ${this.Symbol} yClose:${yClose} max:${this.LimitPrice.Max} min:${this.LimitPrice.Min}`);
  8891. this.LimitPrice.Max=parseFloat(this.LimitPrice.Max.toFixed(2));
  8892. this.LimitPrice.Min=parseFloat(this.LimitPrice.Min.toFixed(2));
  8893. JSConsole.Chart.Log(`[MinuteChartContainer::CaclutateLimitPrice] ${this.Symbol} tofixed(2) max:${this.LimitPrice.Max} min:${this.LimitPrice.Min}`);
  8894. }
  8895. this.UpdateHistoryMinuteUI = function ()
  8896. {
  8897. var allMinuteData = this.HistoryMinuteDataToArray(this.DayData);
  8898. //原始数据
  8899. var sourceData = new ChartData();
  8900. sourceData.Data = allMinuteData;
  8901. this.SourceData = sourceData;
  8902. this.TradeDate = this.DayData[0].Date;
  8903. this.Frame.SetDayCount(this.DayData.length);
  8904. var upperSymbol=this.Symbol.toUpperCase();
  8905. var yClose=this.DayData[0].YClose;
  8906. var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol);
  8907. if (IFrameSplitOperator.IsNumber(this.DayData[0].YClearing) && isFutures) yClose=this.DayData[0].YClearing; //期货使用前结算价
  8908. this.BindMainData(sourceData, yClose);
  8909. //if (MARKET_SUFFIX_NAME.IsChinaFutures(this.Symbol)) this.ChartPaint[1].Data = null; //期货均线暂时不用
  8910. if (this.Frame.SubFrame.length > 2)
  8911. {
  8912. var bindData = new ChartData();
  8913. bindData.Data = allMinuteData;
  8914. for (var i = 2; i < this.Frame.SubFrame.length; ++i)
  8915. {
  8916. this.BindIndexData(i, bindData);
  8917. }
  8918. }
  8919. for (let i in this.Frame.SubFrame)
  8920. {
  8921. var item = this.Frame.SubFrame[i];
  8922. item.Frame.XSplitOperator.Symbol = this.Symbol;
  8923. item.Frame.XSplitOperator.DayCount = this.DayData.length;
  8924. item.Frame.XSplitOperator.DayData = this.DayData;
  8925. item.Frame.XSplitOperator.Operator(); //调整X轴个数
  8926. item.Frame.YSplitOperator.Symbol = this.Symbol;
  8927. }
  8928. this.ChartCorssCursor.StringFormatY.Symbol = this.Symbol;
  8929. this.ChartCorssCursor.StringFormatX.Symbol = this.Symbol;
  8930. this.TitlePaint[0].IsShowDate = true;
  8931. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  8932. this.Frame.SetSizeChage(true);
  8933. this.Draw();
  8934. }
  8935. this.HistoryMinuteDataToArray = function (data) //把多日分钟数据转化为单数组
  8936. {
  8937. var result = [];
  8938. for (var i = data.length - 1; i >= 0; --i) {
  8939. var item = data[i];
  8940. for (var j in item.Data) {
  8941. result.push(item.Data[j]);
  8942. }
  8943. }
  8944. return result;
  8945. }
  8946. this.UpdateLatestMinuteData = function (data, date) //更新最新交易日的分钟数据
  8947. {
  8948. for (var i in this.DayData) {
  8949. var item = this.DayData[i];
  8950. if (item.Date === date) {
  8951. item.Data = data;
  8952. break;
  8953. }
  8954. }
  8955. }
  8956. //请求分钟数据
  8957. this.RequestMinuteData = function ()
  8958. {
  8959. var self = this;
  8960. var fields =
  8961. [
  8962. "name", "symbol",
  8963. "yclose", "open", "price", "high", "low",
  8964. "vol", "amount",
  8965. "date", "time",
  8966. "minute", "minutecount"
  8967. ];
  8968. var upperSymbol = this.Symbol.toUpperCase();
  8969. if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)) //期货的需要加上结算价
  8970. {
  8971. fields.push("clearing");
  8972. fields.push("yclearing");
  8973. }
  8974. if (this.NetworkFilter)
  8975. {
  8976. var obj =
  8977. {
  8978. Name: 'MinuteChartContainer::RequestMinuteData', //类名::函数名
  8979. Explain: '最新分时数据',
  8980. Request: { Url: self.MinuteApiUrl, Data: { field: fields, symbol: [self.Symbol] }, Type: 'POST' },
  8981. Self: this,
  8982. PreventDefault: false
  8983. };
  8984. this.NetworkFilter(obj, function (data)
  8985. {
  8986. self.ChartSplashPaint.EnableSplash(false);
  8987. self.RecvMinuteData(data);
  8988. });
  8989. if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求
  8990. }
  8991. JSNetwork.HttpRequest({
  8992. url: this.MinuteApiUrl,
  8993. data:
  8994. {
  8995. "field": fields,
  8996. "symbol": [this.Symbol],
  8997. "start": -1
  8998. },
  8999. method: "post",
  9000. dataType: "json",
  9001. success: function (data) {
  9002. self.ChartSplashPaint.EnableSplash(false);
  9003. self.RecvMinuteData(data);
  9004. }
  9005. });
  9006. }
  9007. this.RecvMinuteData = function (data)
  9008. {
  9009. if (data.data && data.data.dataType===1) //增量更新数据模式
  9010. {
  9011. this.RecvUpdateMinuteData(data.data);
  9012. return;
  9013. }
  9014. var aryMinuteData = MinuteChartContainer.JsonDataToMinuteData(data.data);
  9015. this.DataStatus.LatestDay=true;
  9016. if (this.DayCount > 1) //多日走势图
  9017. {
  9018. this.UpdateLatestMinuteData(aryMinuteData, data.data.stock[0].date);
  9019. this.UpdateHistoryMinuteUI();
  9020. this.RecvMinuteDataEvent();
  9021. this.RequestOverlayMinuteData(); //更新最新叠加数据
  9022. this.BindAllOverlayIndexData(this.SourceData);
  9023. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this);
  9024. this.AutoUpdate();
  9025. return;
  9026. }
  9027. if (this.IsOnTouch==true) //正在操作中不更新数据
  9028. {
  9029. if (this.SourceData && IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data))
  9030. {
  9031. this.AutoUpdate();
  9032. return;
  9033. }
  9034. }
  9035. //原始数据
  9036. var sourceData = new ChartData();
  9037. sourceData.Data = aryMinuteData;
  9038. this.TradeDate = data.data.stock[0].date;
  9039. this.Frame.SetDayCount(1); //单日数据
  9040. this.SourceData = sourceData;
  9041. this.Symbol = data.data.stock[0].symbol;
  9042. this.Name = data.data.stock[0].name;
  9043. var yClose = data.data.stock[0].yclose;
  9044. var upperSymbol = this.Symbol.toUpperCase();
  9045. var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol);
  9046. if (data.data.stock[0].yclearing && isFutures) yClose = data.data.stock[0].yclearing; //期货使用前结算价
  9047. this.CaclutateLimitPrice(yClose, data.data.stock[0].limitprice); //计算涨停价格
  9048. var extendData = { High: data.data.stock[0].high, Low: data.data.stock[0].low };
  9049. this.BindMainData(sourceData, yClose, extendData);
  9050. for (let i in this.Frame.SubFrame) //把股票代码设置到X轴刻度类里
  9051. {
  9052. var item = this.Frame.SubFrame[i];
  9053. item.Frame.XSplitOperator.Symbol = this.Symbol;
  9054. item.Frame.XSplitOperator.DayCount = 1;
  9055. item.Frame.XSplitOperator.Operator(); //调整X轴个数
  9056. item.Frame.YSplitOperator.Symbol = this.Symbol;
  9057. }
  9058. //计算指标
  9059. if (this.Frame.SubFrame.length > 2)
  9060. {
  9061. var bindData = new ChartData();
  9062. bindData.Data = aryMinuteData;
  9063. for (var i = 2; i < this.Frame.SubFrame.length; ++i)
  9064. {
  9065. this.BindIndexData(i, bindData);
  9066. }
  9067. }
  9068. this.ChartCorssCursor.StringFormatY.Symbol = this.Symbol;
  9069. this.ChartCorssCursor.StringFormatX.Symbol = this.Symbol;
  9070. var chartInfo = this.GetChartMinuteInfo();
  9071. if (chartInfo) chartInfo.SourceData = this.SourceData; //数据绑定到信息地雷上
  9072. this.RecvMinuteDataEvent();
  9073. this.RequestMinuteInfoData();
  9074. this.RequestOverlayMinuteData();//请求叠加数据 (主数据下载完再下载)
  9075. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  9076. this.Frame.SetSizeChage(true);
  9077. this.Draw();
  9078. this.BindAllOverlayIndexData(this.SourceData);
  9079. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this);
  9080. this.AutoUpdate();
  9081. }
  9082. this.RecvUpdateMinuteData=function(data)
  9083. {
  9084. var minuteData=MinuteChartContainer.JsonDataToUpdateMinuteData(data);
  9085. if (this.DayCount > 1) //多日走势图
  9086. {
  9087. this.UpdateLatestMinuteDataV2(minuteData);
  9088. this.UpdateHistoryMinuteUI();
  9089. this.RecvMinuteDataEvent();
  9090. this.RequestOverlayMinuteData(); //更新最新叠加数据
  9091. this.BindAllOverlayIndexData(this.SourceData);
  9092. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this);
  9093. this.AutoUpdate();
  9094. return;
  9095. }
  9096. this.UpdateLatestMinuteDataV2(minuteData);
  9097. var sourceData=this.SourceData;
  9098. var aryMinuteData=this.SourceData.Data;
  9099. this.Frame.SetDayCount(1); //单日数据
  9100. var upperSymbol = this.Symbol.toUpperCase();
  9101. var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol);
  9102. var yClose=minuteData.YClose;
  9103. if (data.stock[0].yclearing && isFutures) yClose = data.stock[0].yclearing; //期货使用前结算价
  9104. this.CaclutateLimitPrice(yClose, data.stock[0].limitprice); //计算涨停价格
  9105. var extendData = { High: data.stock[0].high, Low: data.stock[0].low };
  9106. this.BindMainData(sourceData, yClose, extendData);
  9107. for (var i=0;i<this.Frame.SubFrame.length;++i) //把股票代码设置到X轴刻度类里
  9108. {
  9109. var item = this.Frame.SubFrame[i];
  9110. item.Frame.XSplitOperator.Symbol = this.Symbol;
  9111. item.Frame.XSplitOperator.DayCount = 1;
  9112. item.Frame.XSplitOperator.Operator(); //调整X轴个数
  9113. item.Frame.YSplitOperator.Symbol = this.Symbol;
  9114. }
  9115. //计算指标
  9116. if (this.Frame.SubFrame.length > 2)
  9117. {
  9118. var bindData = new ChartData();
  9119. bindData.Data = aryMinuteData;
  9120. for (var i = 2; i < this.Frame.SubFrame.length; ++i)
  9121. {
  9122. this.BindIndexData(i, bindData);
  9123. }
  9124. }
  9125. var chartInfo = this.GetChartMinuteInfo();
  9126. if (chartInfo) chartInfo.SourceData = this.SourceData; //数据绑定到信息地雷上
  9127. this.RecvMinuteDataEvent();
  9128. this.RequestMinuteInfoData();
  9129. this.RequestOverlayMinuteData();//请求叠加数据 (主数据下载完再下载)
  9130. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  9131. this.Frame.SetSizeChage(true);
  9132. this.Draw();
  9133. this.BindAllOverlayIndexData(this.SourceData);
  9134. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this);
  9135. this.AutoUpdate();
  9136. }
  9137. //更新最新的几条数据
  9138. this.UpdateLatestMinuteDataV2=function(minuteData)
  9139. {
  9140. if (this.DayCount>1)
  9141. {
  9142. if (!this.DayData) return;
  9143. var findItem=null;
  9144. for(var i=0; i<this.DayData.length; ++i)
  9145. {
  9146. var item=this.DayData[i];
  9147. if (item.Date===date)
  9148. {
  9149. findItem=item;
  9150. break;
  9151. }
  9152. }
  9153. if (!findItem) return;
  9154. var findIndex=-1;
  9155. var firstItem=minuteData.Data[0];
  9156. for(var i=0;i<findItem.Data.length;++i)
  9157. {
  9158. var item=findItem.Data[i];
  9159. if (item.Date==firstItem.Date && item.Time==firstItem.Time)
  9160. {
  9161. findIndex=i;
  9162. break;
  9163. }
  9164. }
  9165. if (findIndex<0) findIndex=findItem.Data.length;
  9166. for(var i=0, j=findIndex; i<minuteData.Data.length; ++i, ++j)
  9167. {
  9168. var item=minuteData.Data[i];
  9169. findItem.Data[j]=item;
  9170. }
  9171. }
  9172. else
  9173. {
  9174. if (!this.SourceData) return;
  9175. var findIndex=-1;
  9176. var firstItem=minuteData.Data[0];
  9177. for(var i=0;i<this.SourceData.Data.length;++i)
  9178. {
  9179. var item=this.SourceData.Data[i];
  9180. if (item.Date==firstItem.Date && item.Time==firstItem.Time)
  9181. {
  9182. findIndex=i;
  9183. break;
  9184. }
  9185. }
  9186. if (findIndex<0) findIndex=this.SourceData.Data.length;
  9187. for(var i=0, j=findIndex; i<minuteData.Data.length; ++i, ++j)
  9188. {
  9189. var item=minuteData.Data[i];
  9190. this.SourceData.Data[j]=item;
  9191. }
  9192. }
  9193. }
  9194. //请求叠加数据 (主数据下载完再下载))
  9195. this.RequestOverlayMinuteData = function ()
  9196. {
  9197. var self = this;
  9198. var date=this.TradeDate; //最后一个交易日期
  9199. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  9200. {
  9201. var item=this.OverlayChartPaint[i];
  9202. if (!item.MainData) continue;
  9203. if (item.Status!=OVERLAY_STATUS_ID.STATUS_NONE_ID) continue;
  9204. var symbol=item.Symbol;
  9205. if (!symbol) continue;
  9206. this.RequestSingleOverlayMinuteData(symbol, date, item);
  9207. }
  9208. }
  9209. this.RequestSingleOverlayMinuteData=function(symbol, date, item)
  9210. {
  9211. var self = this;
  9212. item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID;
  9213. if (this.NetworkFilter)
  9214. {
  9215. var obj=
  9216. {
  9217. Name:'MinuteChartContainer::RequestOverlayMinuteData', //类名::函数名
  9218. Explain:'叠加股票最新分时数据',
  9219. Request:{ Url:this.HistoryMinuteApiUrl, Data:{days:[date], symbol:symbol}, Type:'POST' },
  9220. Self:this,
  9221. PreventDefault:false
  9222. };
  9223. this.NetworkFilter(obj, function(data)
  9224. {
  9225. item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID;
  9226. self.RecvOverlayMinuteData(data,item);
  9227. });
  9228. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9229. }
  9230. //请求数据
  9231. JSNetwork.HttpRequest({
  9232. url: this.HistoryMinuteApiUrl,
  9233. data:
  9234. {
  9235. "symbol":symbol,
  9236. "days": [date],
  9237. },
  9238. type:"post",
  9239. dataType: "json",
  9240. async:true,
  9241. success: function (data)
  9242. {
  9243. item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID;
  9244. //self.RecvMultiOverlayMinuteData([data]);
  9245. self.RecvOverlayMinuteData(data,item);
  9246. }
  9247. });
  9248. }
  9249. this.RecvOverlayMinuteData = function (recvData, paint, option)
  9250. {
  9251. var data = recvData.data;
  9252. var aryMinuteData = MinuteChartContainer.JsonDataToMinuteDataArray(data);
  9253. var sourceData = null;
  9254. var yClose;
  9255. if (this.DayCount > 1) //多日数据
  9256. {
  9257. if (aryMinuteData.length <= 0) return;
  9258. var minuteData = aryMinuteData[0];
  9259. for (var i in this.OverlaySourceData)
  9260. {
  9261. var item = this.OverlaySourceData[i];
  9262. if (item.Date == minuteData.Date)
  9263. {
  9264. this.OverlaySourceData[i] = minuteData;
  9265. var allMinuteData = this.HistoryMinuteDataToArray(this.OverlaySourceData);
  9266. var sourceData = new ChartData();
  9267. sourceData.Data = allMinuteData;
  9268. yClose = minuteData.YClose;
  9269. break;
  9270. }
  9271. }
  9272. if (sourceData == null) return;
  9273. }
  9274. else
  9275. {
  9276. if (aryMinuteData.length > 0) sourceData = aryMinuteData[0];
  9277. else sourceData = new ChartData();
  9278. yClose = sourceData.YClose;
  9279. }
  9280. paint.Data=sourceData;
  9281. paint.Title=data.name;
  9282. paint.Symbol=data.symbol;
  9283. paint.YClose=yClose;
  9284. paint.Status=OVERLAY_STATUS_ID.STATUS_FINISHED_ID;
  9285. var bRedraw=true;
  9286. if (option && option.Redraw==false) bRedraw=false;
  9287. if (bRedraw)
  9288. {
  9289. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  9290. this.Frame.SetSizeChage(true);
  9291. this.Draw();
  9292. }
  9293. }
  9294. this.RequestOverlayHistoryMinuteData = function ()
  9295. {
  9296. if (!IFrameSplitOperator.IsNonEmptyArray(this.DayData)) return;
  9297. var self = this;
  9298. var days=[];
  9299. for(var i=0; i<this.DayData.length; ++i)
  9300. {
  9301. var item=this.DayData[i];
  9302. days.push(item.Date);
  9303. }
  9304. if (days.length<=0) return;
  9305. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  9306. {
  9307. var item=this.OverlayChartPaint[i]
  9308. var symbol=item.Symbol;
  9309. if (!symbol) continue;
  9310. if (item.Status!=OVERLAY_STATUS_ID.STATUS_NONE_ID) continue;
  9311. this.RequestSingleOverlayHistoryMinuteData(symbol, days, item);
  9312. }
  9313. }
  9314. this.RequestSingleOverlayHistoryMinuteData=function(symbol, days, item)
  9315. {
  9316. var self = this;
  9317. item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID;
  9318. if (this.NetworkFilter)
  9319. {
  9320. var obj=
  9321. {
  9322. Name:'MinuteChartContainer::RequestOverlayHistoryMinuteData', //类名::函数名
  9323. Explain:'叠加股票多日分时数据',
  9324. Request:{ Url:self.HistoryMinuteApiUrl, Data:{days:days, symbol:symbol}, Type:'POST' },
  9325. Self:this,
  9326. PreventDefault:false
  9327. };
  9328. this.NetworkFilter(obj, function(data)
  9329. {
  9330. item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID;
  9331. self.RecvOverlayHistoryMinuteData(data,item);
  9332. });
  9333. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  9334. }
  9335. JSNetwork.HttpRequest({
  9336. url: self.HistoryMinuteApiUrl,
  9337. data:{ "symbol": symbol, "days": days },
  9338. type:"post",
  9339. dataType: "json",
  9340. async:true,
  9341. success: function (data)
  9342. {
  9343. item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID;
  9344. self.RecvOverlayHistoryMinuteData(data,item);
  9345. }
  9346. });
  9347. }
  9348. this.RecvOverlayHistoryMinuteData = function (recvData, paint) //叠加历史的分钟数据
  9349. {
  9350. var data = recvData.data;
  9351. if (!IFrameSplitOperator.IsNonEmptyArray(this.DayData)) return;
  9352. var dayData=MinuteChartContainer.JsonDataToMinuteDataArray(data);
  9353. if (!IFrameSplitOperator.IsNonEmptyArray(dayData)) return;
  9354. var overlayDayData = [];
  9355. for (var i in this.DayData)
  9356. {
  9357. var item = this.DayData[i];
  9358. var bFind = false;
  9359. for (var j in dayData)
  9360. {
  9361. if (item.Date == dayData[j].Date)
  9362. {
  9363. overlayDayData.push(dayData[i]);
  9364. bFind = true;
  9365. break;
  9366. }
  9367. }
  9368. if (!bFind) //当天不存在叠加数据, 存空
  9369. {
  9370. var empytData = new ChartData();
  9371. empytData.Date=item.Date;
  9372. empytData.Data.length=item.Data.length;
  9373. overlayDayData.push(empytData);
  9374. }
  9375. }
  9376. paint.SourceData=overlayDayData;
  9377. var allMinuteData = this.HistoryMinuteDataToArray(overlayDayData);
  9378. var yClose=overlayDayData[0].YClose; //取最近一个交易日前收盘最为中轴线
  9379. //原始数据
  9380. var sourceData = new ChartData();
  9381. sourceData.Data = allMinuteData;
  9382. paint.Data=sourceData;
  9383. paint.Title=data.name;
  9384. paint.Symbol=data.symbol;
  9385. paint.YClose=yClose;
  9386. paint.Status=OVERLAY_STATUS_ID.STATUS_FINISHED_ID;
  9387. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  9388. this.Frame.SetSizeChage(true);
  9389. this.Draw();
  9390. }
  9391. this.CancelAutoUpdate = function () //关闭停止更新
  9392. {
  9393. if (this.AutoUpdateTimer)
  9394. {
  9395. clearTimeout(this.AutoUpdateTimer);
  9396. this.AutoUpdateTimer = null;
  9397. }
  9398. }
  9399. //数据自动更新
  9400. this.AutoUpdate = function ()
  9401. {
  9402. this.CancelAutoUpdate();
  9403. if (!this.IsAutoUpdate) return;
  9404. if (!this.Symbol) return;
  9405. if (this.IsDestroy) return;
  9406. var self = this;
  9407. var marketStatus = MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol);
  9408. if (marketStatus == 0 || marketStatus == 3) return; //闭市,盘后
  9409. var frequency = this.AutoUpdateFrequency;
  9410. if (marketStatus == 1) //盘前
  9411. {
  9412. this.AutoUpdateTimer=setTimeout(function () { self.AutoUpdate(); }, frequency);
  9413. }
  9414. else if (marketStatus == 2) //盘中
  9415. {
  9416. this.AutoUpdateTimer=setTimeout(function ()
  9417. {
  9418. //self.ResetOverlaySymbolStatus();
  9419. self.RequestMinuteData();
  9420. }, frequency);
  9421. }
  9422. }
  9423. this.StopAutoUpdate = function ()
  9424. {
  9425. this.CancelAutoUpdate();
  9426. this.IsAutoUpdate = false;
  9427. }
  9428. this.BindIndexData = function (windowIndex, hisData)
  9429. {
  9430. if (!this.WindowIndex[windowIndex]) return;
  9431. if (typeof (this.WindowIndex[windowIndex].RequestData) == "function") //数据需要另外下载的.
  9432. {
  9433. this.WindowIndex[windowIndex].RequestData(this, windowIndex, hisData);
  9434. return;
  9435. }
  9436. if (typeof (this.WindowIndex[windowIndex].ExecuteScript) == 'function')
  9437. {
  9438. this.WindowIndex[windowIndex].ExecuteScript(this, windowIndex, hisData);
  9439. return;
  9440. }
  9441. this.WindowIndex[windowIndex].BindData(this, windowIndex, hisData);
  9442. }
  9443. this.BindMainData = function (minuteData, yClose, extendData) //绑定分钟数据
  9444. {
  9445. //分钟数据
  9446. var bindData = new ChartData();
  9447. bindData.Data = minuteData.GetClose();
  9448. this.ChartPaint[0].Data = bindData;
  9449. this.ChartPaint[0].YClose = yClose;
  9450. this.ChartPaint[0].NotSupportMessage = null;
  9451. this.Frame.SubFrame[0].Frame.YSplitOperator.YClose = yClose;
  9452. this.Frame.SubFrame[0].Frame.YSplitOperator.Data = bindData;
  9453. this.Frame.Data=this.ChartPaint[0].Data;
  9454. this.Frame.SourceData=minuteData;
  9455. for(var i=0; i<this.Frame.SubFrame.length; ++i)
  9456. {
  9457. var item=this.Frame.SubFrame[i].Frame;
  9458. item.Data=minuteData; //每个子窗口都绑定下数据
  9459. }
  9460. //均线
  9461. bindData = new ChartData();
  9462. bindData.Data = minuteData.GetMinuteAvPrice();
  9463. this.ChartPaint[1].Data = bindData;
  9464. var upperSymbol=this.Symbol.toUpperCase();
  9465. if (MARKET_SUFFIX_NAME.IsForeignExchange(upperSymbol)) //外汇没有均线
  9466. this.ChartPaint[1].Data=null;
  9467. else if (MARKET_SUFFIX_NAME.IsShowAvPrice && !MARKET_SUFFIX_NAME.IsShowAvPrice(upperSymbol)) //外部控制是否显示均线
  9468. this.ChartPaint[1].Data=null;
  9469. this.Frame.SubFrame[0].Frame.YSplitOperator.AverageData = bindData;
  9470. this.Frame.SubFrame[0].Frame.YSplitOperator.OverlayChartPaint = this.OverlayChartPaint;
  9471. this.Frame.SubFrame[0].Frame.YSplitOperator.LimitPrice=this.LimitPrice;
  9472. if (extendData)
  9473. {
  9474. this.Frame.SubFrame[0].Frame.YSplitOperator.High = extendData.High;
  9475. this.Frame.SubFrame[0].Frame.YSplitOperator.Low = extendData.Low;
  9476. }
  9477. //成交量
  9478. this.ChartPaint[2].Data = minuteData;
  9479. this.ChartPaint[2].YClose = yClose;
  9480. var upperSymbol=this.Symbol.toUpperCase();
  9481. var bFutures=MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol);
  9482. var bSHO = MARKET_SUFFIX_NAME.IsSHO(upperSymbol);
  9483. var bSZO = MARKET_SUFFIX_NAME.IsSZO(upperSymbol); //深证股票期权
  9484. if (bFutures || bSHO || bSZO)
  9485. {
  9486. this.ChartPaint[3].Data.Data = minuteData.GetPosition();
  9487. }
  9488. else
  9489. {
  9490. this.ChartPaint[3].Data.Data=null;
  9491. }
  9492. this.TitlePaint[0].Data = this.SourceData; //动态标题
  9493. this.TitlePaint[0].Symbol = this.Symbol;
  9494. this.TitlePaint[0].Name = this.Name;
  9495. this.TitlePaint[0].YClose = yClose;
  9496. if (this.ChartCorssCursor)
  9497. {
  9498. if (this.ChartCorssCursor.StringFormatY)
  9499. {
  9500. this.ChartCorssCursor.StringFormatY.YClose=yClose;
  9501. this.ChartCorssCursor.StringFormatX.Data=this.ChartPaint[0].Data; //十字光标
  9502. }
  9503. }
  9504. if (this.ExtendChartPaint[0])
  9505. {
  9506. this.ExtendChartPaint[0].Symbol = this.Symbol;
  9507. this.ExtendChartPaint[0].Name = this.Name;
  9508. }
  9509. //叠加股票
  9510. for(var i=0; i<this.OverlayChartPaint.length; ++i)
  9511. {
  9512. var item=this.OverlayChartPaint[i];
  9513. item.MainData=minuteData; //绑定主图数据
  9514. }
  9515. }
  9516. //添加叠加指标
  9517. this.AddOverlayIndex=function(obj)
  9518. {
  9519. var overlay=this.CreateOverlayWindowsIndex(obj);
  9520. if (!overlay) return;
  9521. var bindData=this.SourceData;
  9522. this.BindOverlayIndexData(overlay,obj.WindowIndex,bindData);
  9523. this.UpdataDataoffset(); //更新数据偏移
  9524. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  9525. this.Draw();
  9526. }
  9527. //创建一个叠加指标
  9528. this.CreateOverlayWindowsIndex=function(obj) //{WindowIndex:, IndexName:, Identify:, ShowRightText:, API:}
  9529. {
  9530. let indexName=obj.IndexName;
  9531. let windowIndex=obj.WindowIndex;
  9532. var apiItem=null, indexInfo=null, indexCustom=null;
  9533. if (obj.API)
  9534. {
  9535. apiItem=obj.API;
  9536. }
  9537. else if (obj.Script) //动态执行脚本
  9538. {
  9539. indexInfo={ Script:obj.Script, ID:obj.indexName, Name:obj.indexName};
  9540. if (obj.Name) indexInfo.Name=obj.Name;
  9541. }
  9542. else
  9543. {
  9544. let scriptData = new JSCommonIndexScript.JSIndexScript();
  9545. indexInfo = scriptData.Get(indexName); //系统指标
  9546. if (!indexInfo)
  9547. {
  9548. indexCustom=JSIndexMap.Get(indexName); //定制指标
  9549. if (!indexCustom)
  9550. {
  9551. console.warn(`[MinuteChartContainer::CreateOverlayIndex] can not find index[${indexName}]`);
  9552. return null;
  9553. }
  9554. }
  9555. }
  9556. var subFrame=this.Frame.SubFrame[windowIndex];
  9557. subFrame.Interval=this.OverlayIndexFrameWidth;
  9558. var overlayFrame=new OverlayIndexItem();
  9559. if (obj.Identify) overlayFrame.Identify=obj.Identify; //由外部指定id
  9560. var frame=null;
  9561. if (this.ClassName=="MinuteChartContainer") frame=new OverlayMinuteFrame();
  9562. else frame=new OverlayMinuteHScreenFrame();
  9563. frame.Canvas=this.Canvas;
  9564. frame.MainFrame=subFrame.Frame;
  9565. frame.ChartBorder=subFrame.Frame.ChartBorder;
  9566. frame.GlobalOption=this.GlobalOption;
  9567. if (IFrameSplitOperator.IsBool(obj.ShowRightText)) frame.IsShow=obj.ShowRightText;
  9568. if (IFrameSplitOperator.IsBool(obj.IsShareY)) frame.IsShareY=true;
  9569. if (IFrameSplitOperator.IsBool(obj.IsCalculateYMaxMin)) frame.IsCalculateYMaxMin=obj.IsCalculateYMaxMin; //是否计算Y最大最小值
  9570. if (IFrameSplitOperator.IsNumber(obj.IsShowMainFrame)) frame.IsShowMainFrame=obj.IsShowMainFrame;
  9571. frame.YSplitOperator=new FrameSplitY();
  9572. frame.YSplitOperator.LanguageID=this.LanguageID;
  9573. frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double');
  9574. frame.YSplitOperator.Frame=frame;
  9575. frame.YSplitOperator.ChartBorder=frame.ChartBorder;
  9576. frame.YSplitOperator.SplitCount=subFrame.Frame.YSplitOperator.SplitCount;
  9577. frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); };
  9578. frame.YSplitOperator.HQChart=this;
  9579. frame.YSplitOperator.OverlayIdentify=overlayFrame.Identify;
  9580. if (obj.Frame)
  9581. {
  9582. var item=obj.Frame;
  9583. if (item.Custom) frame.YSplitOperator.Custom=item.Custom;
  9584. }
  9585. overlayFrame.Frame=frame;
  9586. if (apiItem)
  9587. {
  9588. var apiIndex=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,obj, true);
  9589. apiIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息
  9590. overlayFrame.Script=apiIndex;
  9591. }
  9592. else if (indexInfo)
  9593. {
  9594. let indexData = indexInfo;
  9595. if (obj.Args) indexData.Args=obj.Args; //外部可以设置参数
  9596. var scriptIndex=new OverlayScriptIndex(indexData.Name,indexData.Script,indexData.Args,indexData); //脚本执行
  9597. scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息
  9598. overlayFrame.Script=scriptIndex;
  9599. }
  9600. else
  9601. {
  9602. var scriptIndex=indexCustom.Create();
  9603. scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息
  9604. scriptIndex.Create(this,windowIndex);
  9605. overlayFrame.Script=scriptIndex;
  9606. }
  9607. subFrame.OverlayIndex.push(overlayFrame);
  9608. return overlayFrame;
  9609. }
  9610. //获取子窗口的所有画法
  9611. this.GetChartPaint = function (windowIndex)
  9612. {
  9613. var paint = new Array();
  9614. for (var i in this.ChartPaint)
  9615. {
  9616. if (i < 3) continue; //分钟 均线 成交量 3个线不能改
  9617. var item = this.ChartPaint[i];
  9618. if (item.ChartFrame == this.Frame.SubFrame[windowIndex].Frame)
  9619. paint.push(item);
  9620. }
  9621. return paint;
  9622. }
  9623. //创建指定窗口指标
  9624. this.CreateWindowIndex = function (windowIndex)
  9625. {
  9626. this.WindowIndex[windowIndex].Create(this, windowIndex);
  9627. }
  9628. this.CreateExtendChart = function (name, option) //创建扩展图形
  9629. {
  9630. var chart;
  9631. switch (name)
  9632. {
  9633. case 'MinuteTooltip':
  9634. if (option.Create && typeof(option.Create)=='function') chart=option.Create();
  9635. else chart = new MinuteTooltipPaint();
  9636. chart.Canvas = this.Canvas;
  9637. chart.ChartBorder = this.Frame.ChartBorder;
  9638. chart.ChartFrame = this.Frame;
  9639. chart.HQChart = this;
  9640. option.LanguageID = this.LanguageID;
  9641. chart.SetOption(option);
  9642. this.ExtendChartPaint.push(chart);
  9643. return chart;
  9644. default:
  9645. chart=g_ExtendChartPaintFactory.Create(name);
  9646. if (!chart) return null;
  9647. chart.Canvas=this.Canvas;
  9648. chart.ChartBorder=this.Frame.ChartBorder;
  9649. chart.ChartFrame=this.Frame;
  9650. chart.HQChart=this;
  9651. chart.SetOption(option);
  9652. this.ExtendChartPaint.push(chart);
  9653. return chart;
  9654. }
  9655. }
  9656. this.SetMinuteInfo = function (aryInfo, bUpdate)
  9657. {
  9658. this.ChartInfo = []; //先清空
  9659. for (var i in aryInfo)
  9660. {
  9661. var infoItem = JSMinuteInfoMap.Get(aryInfo[i]);
  9662. if (!infoItem) continue;
  9663. var item = infoItem.Create();
  9664. this.ChartInfo.push(item);
  9665. }
  9666. if (bUpdate == true) this.RequestMinuteInfoData();
  9667. }
  9668. this.GetChartMinuteInfo = function ()
  9669. {
  9670. return this.ChartInfoPaint;
  9671. }
  9672. this.CreateMinuteInfo = function (option) //在Create()以后 在调用
  9673. {
  9674. var chart = new ChartMinuteInfo();
  9675. chart.Canvas = this.Canvas;
  9676. chart.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  9677. chart.ChartFrame = this.Frame.SubFrame[0].Frame;
  9678. chart.ChartMinutePrice = this.ChartPaint[0];
  9679. if (option && chart.SetOption) chart.SetOption(option);
  9680. this.ChartInfoPaint = chart;
  9681. return chart;
  9682. }
  9683. //信息地雷数据请求
  9684. this.RequestMinuteInfoData = function ()
  9685. {
  9686. if (this.ChartInfo.length <= 0) return;
  9687. var chart = this.GetChartMinuteInfo();
  9688. if (!chart) chart = this.CreateMinuteInfo(null); //不存在就创建
  9689. chart.SourceData = this.SourceData;
  9690. //信息地雷信息
  9691. for (var i in this.ChartInfo) {
  9692. this.ChartInfo[i].RequestData(this);
  9693. }
  9694. }
  9695. //更新信息地雷
  9696. this.UpdataChartInfo = function ()
  9697. {
  9698. var chart = this.GetChartMinuteInfo();
  9699. if (!chart) return;
  9700. var infoMap = new Map();
  9701. for (var i in this.ChartInfo)
  9702. {
  9703. var infoData = this.ChartInfo[i].Data;
  9704. for (var j in infoData)
  9705. {
  9706. var item = infoData[j];
  9707. var dateTime = `${item.Date} ${item.Time}`;
  9708. if (infoMap.has(dateTime)) infoMap.get(dateTime).Data.push(item);
  9709. else infoMap.set(dateTime, { Data: new Array(item) });
  9710. }
  9711. }
  9712. chart.Data = infoMap;
  9713. }
  9714. this.TryClickIndexTitle=function(x,y)
  9715. {
  9716. for(var i=0; i<this.TitlePaint.length; ++i)
  9717. {
  9718. var item=this.TitlePaint[i];
  9719. if (!item.IsClickTitle) continue;
  9720. if (!item.IsClickTitle(x,y)) continue;
  9721. var data={ Point:{X:x, Y:y}, Title:item.Title, FrameID:item.Frame.Identify };
  9722. JSConsole.Chart.Log('[MinuteChartContainer::TryClickIndexTitle] click title ', data);
  9723. var event=this.GetEvent(JSCHART_EVENT_ID.ON_CLICK_INDEXTITLE);
  9724. if (event && event.Callback) event.Callback(event,data,this);
  9725. return true;
  9726. }
  9727. return false;
  9728. }
  9729. //接收到窗口指标数据 订阅模式
  9730. this.RecvWindowIndex=function(index, data)
  9731. {
  9732. if (index<2) return;
  9733. var indexItem=this.WindowIndex[index];
  9734. if (!indexItem) return;
  9735. if (typeof(indexItem.RecvSubscribeData)=="function")
  9736. {
  9737. var bindData=this.SourceData;
  9738. indexItem.RecvSubscribeData(data,this,index,bindData);
  9739. }
  9740. }
  9741. this.UpdateWindowIndex=function(index)
  9742. {
  9743. if (index<2) return;
  9744. var bindData=this.SourceData;
  9745. this.BindIndexData(index,bindData)
  9746. this.UpdataDataoffset(); //更新数据偏移
  9747. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  9748. this.Draw();
  9749. }
  9750. this.CreateChartDrawPicture=function(name, option, callback)
  9751. {
  9752. var drawPicture=null;
  9753. var item=IChartDrawPicture.GetDrawPictureByName(name);
  9754. if (item) drawPicture=item.Create();
  9755. if (!drawPicture) return false;
  9756. drawPicture.Canvas=this.Canvas;
  9757. drawPicture.Status=0;
  9758. drawPicture.Symbol=this.Symbol;
  9759. drawPicture.Period=888888888;
  9760. drawPicture.Option=this.ChartDrawOption;
  9761. drawPicture.PixelRatio=this.UIElement.PixelRatio;
  9762. if (callback) drawPicture.FinishedCallback=callback; //完成通知上层回调
  9763. if (option) drawPicture.SetOption(option);
  9764. var self=this;
  9765. drawPicture.Update=function() //更新回调函数
  9766. {
  9767. self.DrawDynamicInfo();
  9768. };
  9769. drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); }
  9770. this.CurrentChartDrawPicture=drawPicture;
  9771. JSConsole.Chart.Log("[MinuteChartContainer::CreateChartDrawPicture] ", name,this.CurrentChartDrawPicture);
  9772. return true;
  9773. }
  9774. }
  9775. //API 返回数据 转化为array[]
  9776. MinuteChartContainer.JsonDataToMinuteData = function (data)
  9777. {
  9778. var upperSymbol = data.stock[0].symbol.toUpperCase();
  9779. var isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  9780. var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol);
  9781. var isSHO = MARKET_SUFFIX_NAME.IsSHO(upperSymbol); //上海股票期权
  9782. var isSZO = MARKET_SUFFIX_NAME.IsSZO(upperSymbol); //深证股票期权
  9783. var preClose = data.stock[0].yclose; //前一个数据价格
  9784. var preAvPrice = data.stock[0].yclose; //前一个均价
  9785. var yClose = data.stock[0].yclose;
  9786. var yClearing=data.stock[0].yclearing;
  9787. if (isFutures && data.stock[0].yclearing) preClose = preAvPrice =yClearing ; //期货使用昨结算价
  9788. var date = data.stock[0].date;
  9789. var aryMinuteData = new Array();
  9790. for (var i in data.stock[0].minute)
  9791. {
  9792. var jsData = data.stock[0].minute[i];
  9793. var item = new MinuteData();
  9794. if (jsData.price) preClose = jsData.price;
  9795. if (jsData.avprice) preAvPrice = jsData.avprice;
  9796. item.YClearing=yClearing;
  9797. item.YClose=yClose;
  9798. item.Close = jsData.price;
  9799. item.Open = jsData.open;
  9800. item.High = jsData.high;
  9801. item.Low = jsData.low;
  9802. if (isSHSZ) item.Vol = jsData.vol / 100; //原始单位股
  9803. else item.Vol = jsData.vol;
  9804. item.Amount = jsData.amount;
  9805. item.Increase = jsData.increase;
  9806. item.Risefall = jsData.risefall;
  9807. item.AvPrice = jsData.avprice;
  9808. if (!item.Close) //当前没有价格 使用上一个价格填充
  9809. {
  9810. item.Close = preClose;
  9811. item.Open = item.High = item.Low = item.Close;
  9812. }
  9813. if (!item.AvPrice) item.AvPrice = preAvPrice;
  9814. if (jsData.date > 0) date = jsData.date; //分钟数据中有日期 优先使用
  9815. item.DateTime = date.toString() + " " + jsData.time.toString();
  9816. item.Date = date;
  9817. item.Time = jsData.time;
  9818. if (isFutures || isSHO || isSZO) item.Position = jsData.position; //期货 期权有持仓
  9819. if (yClose && item.Close) item.Increase = (item.Close - yClose) / yClose * 100; //涨幅 (最新价格-昨收)/昨收*100
  9820. if (isFutures && yClearing && item.Close) item.Increase = (item.Close - yClearing) / yClearing * 100; //涨幅 (最新价格-昨结算价)/昨结算价*100
  9821. if (jsData.ExtendData) item.ExtendData=jsData.ExtendData; //扩展数据
  9822. aryMinuteData[i] = item;
  9823. }
  9824. return aryMinuteData;
  9825. }
  9826. //多日日线数据API 转化成array[];
  9827. MinuteChartContainer.JsonDataToMinuteDataArray = function (data)
  9828. {
  9829. var upperSymbol = data.symbol.toUpperCase();
  9830. var isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  9831. var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol);
  9832. var isSHO = MARKET_SUFFIX_NAME.IsSHO(upperSymbol); //上海股票期权
  9833. var isSZO = MARKET_SUFFIX_NAME.IsSZO(upperSymbol); //深证股票期权
  9834. var result = [];
  9835. var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_MULTI_DAY_EXTENDDATA; //扩展数据序号
  9836. for (var i=0; i<data.data.length; ++i)
  9837. {
  9838. var minuteData = [];
  9839. var dayData = data.data[i];
  9840. var date = dayData.date;
  9841. var yClose = dayData.yclose; //前收盘 计算涨幅
  9842. var preClose = yClose; //前一个数据价格
  9843. var yClearing=dayData.yclearing; //昨结算价
  9844. var preAvPrice=null; //前一个均价
  9845. for (var j=0;j<dayData.minute.length; ++j)
  9846. {
  9847. var jsData = dayData.minute[j];
  9848. if (jsData[2]) preClose = jsData[2]; //保存上一个收盘数据
  9849. var item = new MinuteData();
  9850. item.YClose=yClose;
  9851. item.YClearing=yClearing;
  9852. item.Close = jsData[2];
  9853. item.Open = jsData[1];
  9854. item.High = jsData[3];
  9855. item.Low = jsData[4];
  9856. item.Increase = null;
  9857. if(isSHSZ) item.Vol = jsData[5] / 100; //原始单位股
  9858. else item.Vol = jsData[5];
  9859. item.Amount = jsData[6];
  9860. if (7 < jsData.length && jsData[7] > 0)
  9861. {
  9862. item.AvPrice = jsData[7]; //均价
  9863. preAvPrice = jsData[7];
  9864. }
  9865. if (!item.Close) //当前没有价格 使用上一个价格填充
  9866. {
  9867. item.Close = preClose;
  9868. item.Open = item.High = item.Low = item.Close;
  9869. }
  9870. if (!item.AvPrice && preAvPrice) item.AvPrice = preAvPrice;
  9871. if (item.Close && yClose) item.Increase = (item.Close - yClose) / yClose * 100;
  9872. if (isFutures && item.Close && yClearing) item.Increase = (item.Close - yClearing) / yClearing * 100;
  9873. item.DateTime = date.toString() + " " + jsData[0].toString();
  9874. item.Date = date;
  9875. item.Time = jsData[0];
  9876. if (8<jsData.length && jsData[8]>0)
  9877. {
  9878. item.Date=jsData[8]; //日期
  9879. item.DateTime=item.Date.toString()+" "+jsData[0].toString();
  9880. }
  9881. if ((isFutures || isSHO || isSZO) && 9 < jsData.length) item.Position = jsData[9]; //持仓
  9882. if (j == 0 )
  9883. {
  9884. //if (isSHSZ) item.DateTime = date.toString() + " 0925";//第1个数据 写死9:25
  9885. item.IsFristData = true;
  9886. }
  9887. if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex];
  9888. minuteData[j] = item;
  9889. }
  9890. var newData = new ChartData();
  9891. newData.Data = minuteData;
  9892. newData.YClose = yClose;
  9893. newData.Close = dayData.close;
  9894. newData.Date = date;
  9895. if (IFrameSplitOperator.IsNumber(yClearing)) newData.YClearing=yClearing;
  9896. result.push(newData);
  9897. }
  9898. return result;
  9899. }
  9900. //分钟增量数据 stock: [ { date:, yclose:, yclearing: , minute:[ [],]} 0=日期 1=时间 2=开 3=高 4=低 5=收 6=均价 7=量 8=金额 9=涨幅 10=涨跌 11=领先指标 ]
  9901. MinuteChartContainer.JsonDataToUpdateMinuteData=function(data)
  9902. {
  9903. if (!data || !data.stock) return null;
  9904. var stock=data.stock[0];
  9905. if (!IFrameSplitOperator.IsNumber(stock.date)) return null;
  9906. var symbol=data.stock[0].symbol;
  9907. var upperSymbol=symbol.toUpperCase();
  9908. var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol);
  9909. var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //国内期货, 纽约期货交易所
  9910. var minuteData={ Date:stock.date, Data:[] , Symbol:symbol, Name:stock.name };
  9911. var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_DAY_EXTENDDATA; //扩展数据序号
  9912. if (IFrameSplitOperator.IsNumber(stock.high)) minuteData.High=stock.high;
  9913. if (IFrameSplitOperator.IsNumber(stock.low)) minuteData.Low=stock.low;
  9914. if (IFrameSplitOperator.IsNumber(stock.yclose)) minuteData.YClose=stock.yclose;
  9915. if (IFrameSplitOperator.IsNumber(stock.YClearing)) minuteData.YClearing=stock.yclearing;
  9916. if (IFrameSplitOperator.IsNumber(stock.high)) minuteData.High=stock.high;
  9917. if (IFrameSplitOperator.IsNumber(stock.low)) minuteData.Low=stock.low;
  9918. if (IFrameSplitOperator.IsNumber(stock.yclose)) minuteData.YClose=stock.yclose;
  9919. if (IFrameSplitOperator.IsNumber(stock.YClearing)) minuteData.YClearing=stock.yclearing;
  9920. if (!IFrameSplitOperator.IsNonEmptyArray(stock.minute)) return minuteData;
  9921. for(var i=0;i<stock.minute.length;++i)
  9922. {
  9923. var jsData=stock.minute[i];
  9924. var item=new MinuteData();
  9925. item.YClearing=minuteData.YClearing;
  9926. item.YClose=minuteData.YClose;
  9927. item.Date=jsData[0];
  9928. item.Time=jsData[1];
  9929. item.Open=jsData[2];
  9930. item.High=jsData[3];
  9931. item.Low=jsData[4];
  9932. item.Close=jsData[5];
  9933. item.AvPrice=jsData[6];
  9934. item.Vol=jsData[7];
  9935. item.Amount=jsData[8];
  9936. if (IFrameSplitOperator.IsNumber(jsData[9])) item.Increase=jsData[9];
  9937. if (IFrameSplitOperator.IsNumber(jsData[10])) item.Risefall=jsData[10];
  9938. if (IFrameSplitOperator.IsNumber(jsData[11])) item.Lead=jsData[11];
  9939. if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex];
  9940. item.DateTime=item.Date.toString()+" "+item.Time.toString();
  9941. if (isSHSZ) item.Vol=item.Vol/100; //沪深股票原始单位股
  9942. if (IFrameSplitOperator.IsNumber(minuteData.YClose) && item.Close)
  9943. item.Increase=(item.Close-minuteData.YClose)/minuteData.YClose*100; //涨幅 (最新价格-昨收)/昨收*100;
  9944. if (isFutures && minuteData.YClearing && item.Close)
  9945. item.Increase=(item.Close-minuteData.YClearing)/minuteData.YClearing*100; //涨幅 (最新价格-昨结算价)/昨结算价*100;
  9946. minuteData.Data.push(item);
  9947. }
  9948. return minuteData;
  9949. }
  9950. /*
  9951. 历史分钟走势图
  9952. */
  9953. function HistoryMinuteChartContainer(uielement) {
  9954. this.newMethod = MinuteChartContainer; //派生
  9955. this.newMethod(uielement);
  9956. delete this.newMethod;
  9957. this.HistoryMinuteApiUrl = "http://127.0.0.1/cache/minuteday/day/";
  9958. //创建主图K线画法
  9959. this.CreateMainKLine = function () {
  9960. //分钟线
  9961. var minuteLine = new ChartMinutePriceLine();
  9962. minuteLine.Canvas = this.Canvas;
  9963. minuteLine.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  9964. minuteLine.ChartFrame = this.Frame.SubFrame[0].Frame;
  9965. minuteLine.Name = "Minute-Line";
  9966. minuteLine.Color = g_JSChartResource.Minute.PriceColor;
  9967. this.ChartPaint[0] = minuteLine;
  9968. //分钟线均线
  9969. var averageLine = new ChartLine();
  9970. averageLine.Canvas = this.Canvas;
  9971. averageLine.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  9972. averageLine.ChartFrame = this.Frame.SubFrame[0].Frame;
  9973. averageLine.Name = "Minute-Average-Line";
  9974. averageLine.Color = g_JSChartResource.Minute.AvPriceColor;
  9975. this.ChartPaint[1] = averageLine;
  9976. var averageLine = new ChartMinuteVolumBar();
  9977. averageLine.Color = g_JSChartResource.Minute.VolBarColor;
  9978. averageLine.Canvas = this.Canvas;
  9979. averageLine.ChartBorder = this.Frame.SubFrame[1].Frame.ChartBorder;
  9980. averageLine.ChartFrame = this.Frame.SubFrame[1].Frame;
  9981. averageLine.Name = "Minute-Vol-Bar";
  9982. this.ChartPaint[2] = averageLine;
  9983. this.TitlePaint[0] = new DynamicMinuteTitlePainting();
  9984. this.TitlePaint[0].Frame = this.Frame.SubFrame[0].Frame;
  9985. this.TitlePaint[0].Canvas = this.Canvas;
  9986. this.TitlePaint[0].IsShowDate = true;
  9987. /*
  9988. //主图叠加画法
  9989. var paint=new ChartOverlayKLine();
  9990. paint.Canvas=this.Canvas;
  9991. paint.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder;
  9992. paint.ChartFrame=this.Frame.SubFrame[0].Frame;
  9993. paint.Name="Overlay-KLine";
  9994. this.OverlayChartPaint[0]=paint;
  9995. */
  9996. }
  9997. //设置交易日期
  9998. this.ChangeTradeDate = function (trdateDate) {
  9999. if (!trdateDate) return;
  10000. this.TradeDate = trdateDate;
  10001. this.RequestData(); //更新数据
  10002. }
  10003. this.RequestData = function () {
  10004. var date = new Date();
  10005. var nowDate = date.getFullYear() * 10000 + (date.getMonth() + 1) * 100 + date.getDate();
  10006. if (nowDate == this.TradeDate) this.RequestMinuteData();
  10007. else this.RequestHistoryMinuteData();
  10008. }
  10009. //请求分钟数据
  10010. this.RequestHistoryMinuteData = function () {
  10011. var self = this;
  10012. var url = this.HistoryMinuteApiUrl + this.TradeDate.toString() + "/" + this.Symbol + ".json";
  10013. JSNetwork.HttpRequest({
  10014. url: url,
  10015. method: "get",
  10016. dataType: "json",
  10017. success: function (data) {
  10018. self.ChartSplashPaint.EnableSplash(false);
  10019. self.RecvHistoryMinuteData(data);
  10020. },
  10021. error: function (reqeust) {
  10022. self.ChartSplashPaint.EnableSplash(false);
  10023. self.RecvHistoryMinuteError(reqeust);
  10024. }
  10025. });
  10026. }
  10027. this.RecvHistoryMinuteError = function (reqeust) {
  10028. if (reqeust.status != 404) return;
  10029. var sourceData = new ChartData();
  10030. this.SourceData = sourceData;
  10031. for (var i in this.ChartPaint) {
  10032. this.ChartPaint[i].Data = sourceData;
  10033. if (i == 0) this.ChartPaint[i].NotSupportMessage = '没有权限访问!';
  10034. }
  10035. this.TitlePaint[0].Data = this.SourceData; //动态标题
  10036. this.TitlePaint[0].Symbol = this.Symbol;
  10037. this.TitlePaint[0].Name = null;
  10038. this.Draw();
  10039. }
  10040. this.RecvHistoryMinuteData = function (recvData) {
  10041. if (recvData.statusCode != 200) {
  10042. var sourceData = new ChartData();
  10043. this.SourceData = sourceData;
  10044. for (var i in this.ChartPaint) {
  10045. this.ChartPaint[i].Data = sourceData;
  10046. if (i == 0) this.ChartPaint[i].NotSupportMessage = '没有权限访问!';
  10047. }
  10048. this.TitlePaint[0].Data = this.SourceData; //动态标题
  10049. this.TitlePaint[0].Symbol = this.Symbol;
  10050. this.TitlePaint[0].Name = null;
  10051. this.Draw();
  10052. return;
  10053. }
  10054. var data = recvData.data;
  10055. var aryMinuteData = HistoryMinuteChartContainer.JsonDataToMinuteData(data);
  10056. //原始数据
  10057. var sourceData = new ChartData();
  10058. sourceData.Data = aryMinuteData;
  10059. this.TradeDate = data.date;
  10060. this.SourceData = sourceData;
  10061. this.Symbol = data.symbol;
  10062. this.Name = data.name;
  10063. this.BindMainData(sourceData, data.day.yclose);
  10064. if (this.Frame.SubFrame.length > 2) {
  10065. var bindData = new ChartData();
  10066. bindData.Data = aryMinuteData;
  10067. for (var i = 2; i < this.Frame.SubFrame.length; ++i) {
  10068. this.BindIndexData(i, bindData);
  10069. }
  10070. }
  10071. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  10072. this.Frame.SetSizeChage(true);
  10073. this.Draw();
  10074. //this.AutoUpdata();
  10075. }
  10076. }
  10077. //API 返回数据 转化为array[]
  10078. HistoryMinuteChartContainer.JsonDataToMinuteData = function (data)
  10079. {
  10080. var aryMinuteData = new Array();
  10081. for (var i in data.minute.time)
  10082. {
  10083. var item = new MinuteData();
  10084. if (data.minute.price[i] <= 0 && i > 0) //当前这一分钟价格为空,使用上一分钟的数据
  10085. {
  10086. item.Close = aryMinuteData[i - 1].Close;
  10087. item.Open = aryMinuteData[i - 1].Close;
  10088. item.High = item.Close;
  10089. item.Low = item.Close;
  10090. item.Vol = data.minute.vol[i] / 100; //原始单位股
  10091. item.Amount = data.minute.amount[i];
  10092. item.DateTime = data.date.toString() + " " + data.minute.time[i].toString();
  10093. item.Date = data.date;
  10094. item.Time = data.minute.time[i];
  10095. //item.Increate=jsData.increate;
  10096. //item.Risefall=jsData.risefall;
  10097. item.AvPrice = aryMinuteData[i - 1].AvPrice;
  10098. }
  10099. else
  10100. {
  10101. item.Close = data.minute.price[i];
  10102. item.Open = data.minute.open[i];
  10103. item.High = data.minute.high[i];
  10104. item.Low = data.minute.low[i];
  10105. item.Vol = data.minute.vol[i] / 100; //原始单位股
  10106. item.Amount = data.minute.amount[i];
  10107. item.DateTime = data.date.toString() + " " + data.minute.time[i].toString();
  10108. item.Date = data.date;
  10109. item.Time = data.minute.time[i];
  10110. //item.Increate=jsData.increate;
  10111. //item.Risefall=jsData.risefall;
  10112. item.AvPrice = data.minute.avprice[i];
  10113. }
  10114. //价格是0的 都用空
  10115. if (item.Open <= 0) item.Open = null;
  10116. if (item.Close <= 0) item.Close = null;
  10117. if (item.AvPrice <= 0) item.AvPrice = null;
  10118. if (item.High <= 0) item.High = null;
  10119. if (item.Low <= 0) item.Low = null;
  10120. aryMinuteData[i] = item;
  10121. }
  10122. return aryMinuteData;
  10123. }
  10124. /////////////////////////////////////////////////////////////////////////////
  10125. // 自定义指数
  10126. //
  10127. function CustomKLineChartContainer(uielement) {
  10128. this.newMethod = KLineChartContainer; //派生
  10129. this.newMethod(uielement);
  10130. delete this.newMethod;
  10131. this.ClassName = 'CustomKLineChartContainer';
  10132. this.ChangeRight = null; //没有复权设置
  10133. this.LoadDataSplashTitle = '计算指数数据';
  10134. this.CustomKLineApiUrl = g_JSChartResource.Domain + "/API/IndexCalculate"; //自定义指数计算地址
  10135. this.CustomStock; //成分
  10136. this.QueryDate = { Start: 20180101, End: 20180627 }; //计算时间区间
  10137. this.RequestHistoryData = function () {
  10138. var self = this;
  10139. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  10140. this.ChartSplashPaint.EnableSplash(true);
  10141. this.Draw();
  10142. JSNetwork.HttpRequest({
  10143. url: this.CustomKLineApiUrl,
  10144. data:
  10145. {
  10146. "stock": self.CustomStock,
  10147. "Name": self.Symbol,
  10148. "date": { "startdate": self.QueryDate.Start, "enddate": self.QueryDate.End }
  10149. },
  10150. method: 'POST',
  10151. dataType: "json",
  10152. async: true,
  10153. success: function (data) {
  10154. self.ChartSplashPaint.EnableSplash(false);
  10155. self.RecvHistoryData(data);
  10156. }
  10157. });
  10158. }
  10159. this.RecvHistoryData = function (recvData)
  10160. {
  10161. var data = recvData.data;
  10162. var aryDayData = KLineChartContainer.JsonDataToHistoryData(data);
  10163. //原始数据
  10164. var sourceData = new ChartData();
  10165. sourceData.Data = aryDayData;
  10166. sourceData.DataType = 0; //0=日线数据 1=分钟数据
  10167. sourceData.Symbol = data.symbol;
  10168. //显示的数据
  10169. var bindData = new ChartData();
  10170. bindData.Data = aryDayData;
  10171. bindData.Right = 0; //指数没有复权
  10172. bindData.Period = this.Period;
  10173. bindData.DataType = 0;
  10174. bindData.Symbol = data.symbol;
  10175. if (ChartData.IsDayPeriod(this.Period, false)) //周期数据
  10176. {
  10177. var periodData = sourceData.GetPeriodData(bindData.Period);
  10178. bindData.Data = periodData;
  10179. }
  10180. //绑定数据
  10181. this.SourceData = sourceData;
  10182. this.Name = data.name;
  10183. this.BindMainData(bindData, this.PageSize);
  10184. for (var i = 0; i < this.Frame.SubFrame.length; ++i)
  10185. {
  10186. this.BindIndexData(i, bindData);
  10187. }
  10188. //this.BindIndexData(0,hisData);
  10189. //this.BindIndexData(1,hisData);
  10190. //this.BindIndexData(2,hisData);
  10191. //刷新画图
  10192. this.UpdataDataoffset(); //更新数据偏移
  10193. this.UpdatePointByCursorIndex(); //更新十字光标位子
  10194. this.UpdateFrameMaxMin(); //调整坐标最大 最小值
  10195. this.Frame.SetSizeChage(true);
  10196. this.Draw();
  10197. if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistoryData', this);
  10198. }
  10199. }
  10200. ////////////////////////////////////////////////////////////////////////////////
  10201. // K线横屏显示
  10202. //
  10203. function KLineChartHScreenContainer(uielement)
  10204. {
  10205. this.newMethod = KLineChartContainer; //派生
  10206. this.newMethod(uielement);
  10207. delete this.newMethod;
  10208. this.ClassName = 'KLineChartHScreenContainer';
  10209. this.OnMouseMove = function (x, y, e)
  10210. {
  10211. this.LastPoint.X = x;
  10212. this.LastPoint.Y = y;
  10213. this.CursorIndex = this.Frame.GetXData(y);
  10214. this.DrawDynamicInfo();
  10215. }
  10216. //手机拖拽
  10217. this.ontouchstart = function (e)
  10218. {
  10219. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  10220. var jsChart = this;
  10221. if (jsChart.DragMode == 0) return;
  10222. this.IsPress=false;
  10223. this.IsOnTouch = true;
  10224. this.PhonePinch = null;
  10225. this.TouchDrawCount=0;
  10226. if (this.IsPhoneDragging(e))
  10227. {
  10228. if (jsChart.TryClickLock || this.TryClickIndexTitle)
  10229. {
  10230. var touches = this.GetToucheData(e);
  10231. var x = touches[0].clientX;
  10232. var y = touches[0].clientY;
  10233. if (jsChart.TryClickLock && jsChart.TryClickLock(x, y)) return;
  10234. if (jsChart.TryClickIndexTitle && jsChart.TryClickIndexTitle(x, y)) return;
  10235. }
  10236. //长按2秒,十字光标
  10237. if (this.TouchTimer != null) clearTimeout(this.TouchTimer);
  10238. var drag = { "Click": {}, "LastMove": {}, };//最后移动的位置
  10239. var touches = this.GetToucheData(e);
  10240. drag.Click.X = touches[0].clientX;
  10241. drag.Click.Y = touches[0].clientY;
  10242. drag.LastMove.X = touches[0].clientX;
  10243. drag.LastMove.Y = touches[0].clientY;
  10244. this.MouseDrag = drag;
  10245. this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } };
  10246. if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false;
  10247. this.SelectChartDrawPicture=null;
  10248. if (this.CurrentChartDrawPicture) //画图工具模式
  10249. {
  10250. var drawPicture=this.CurrentChartDrawPicture;
  10251. if (drawPicture.Status==2)
  10252. this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y,true);
  10253. else
  10254. {
  10255. this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true);
  10256. //只有1个点 直接完成
  10257. if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false});
  10258. }
  10259. return;
  10260. }
  10261. else
  10262. {
  10263. var drawPictrueData={X:touches[0].clientX, Y:touches[0].clientY, PixelRatio:this.UIElement.PixelRatio };
  10264. if (this.GetChartDrawPictureByPoint(drawPictrueData))
  10265. {
  10266. drawPictrueData.ChartDrawPicture.Status=20;
  10267. drawPictrueData.ChartDrawPicture.ValueToPoint();
  10268. drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex;
  10269. drawPictrueData.ChartDrawPicture.IsSelected=true;
  10270. this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture;
  10271. this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture;
  10272. let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件
  10273. if (event && event.Callback)
  10274. {
  10275. let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture };
  10276. event.Callback(event,sendData,this);
  10277. }
  10278. this.DrawDynamicInfo();
  10279. return;
  10280. }
  10281. }
  10282. if (this.ChartCorssCursor.IsShow == true)
  10283. {
  10284. this.TouchTimer = setTimeout(function () {
  10285. jsChart.IsPress=true;
  10286. if (drag.Click.X == drag.LastMove.X && drag.Click.Y == drag.LastMove.Y) //手指没有移动,出现十字光标
  10287. {
  10288. var mouseDrag = jsChart.MouseDrag;
  10289. jsChart.MouseDrag = null;
  10290. //移动十字光标
  10291. var x = drag.Click.X;
  10292. var y = drag.Click.Y;
  10293. jsChart.OnMouseMove(x, y, e);
  10294. }
  10295. }, jsChart.PressTime);
  10296. }
  10297. }
  10298. else if (this.IsPhonePinching(e))
  10299. {
  10300. var phonePinch = { "Start": {}, "Last": {}};
  10301. var touches = this.GetToucheData(e);
  10302. phonePinch.Start = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY };
  10303. phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY };
  10304. this.PhonePinch = phonePinch;
  10305. this.SelectChartDrawPicture=null;
  10306. }
  10307. this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e);
  10308. }
  10309. this.ontouchmove = function (e)
  10310. {
  10311. if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return;
  10312. var jsChart = this;
  10313. var touches = this.GetToucheData(e);
  10314. if (this.IsPhoneDragging(e))
  10315. {
  10316. var drag = jsChart.MouseDrag;
  10317. if (drag == null)
  10318. {
  10319. var x = touches[0].clientX;
  10320. var y = touches[0].clientY;
  10321. jsChart.OnMouseMove(x, y, e);
  10322. }
  10323. else
  10324. {
  10325. var moveSetp = Math.abs(drag.LastMove.Y - touches[0].clientY);
  10326. var moveUpDown=Math.abs(drag.LastMove.X-touches[0].clientX);
  10327. moveSetp = parseInt(moveSetp);
  10328. if (this.CurrentChartDrawPicture)
  10329. {
  10330. var drawPicture=this.CurrentChartDrawPicture;
  10331. if (drawPicture.Status==1 || drawPicture.Status==2)
  10332. {
  10333. if(moveSetp<5 && moveUpDown<5) return;
  10334. if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY))
  10335. {
  10336. this.DrawDynamicInfo();
  10337. }
  10338. }
  10339. else if (drawPicture.Status==3)
  10340. {
  10341. if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY))
  10342. {
  10343. this.DrawDynamicInfo();
  10344. }
  10345. }
  10346. else if (drawPicture.Status==20) //画图工具移动
  10347. {
  10348. if(moveSetp<5 && moveUpDown<5) return;
  10349. if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y))
  10350. {
  10351. this.DrawDynamicInfo();
  10352. }
  10353. }
  10354. drag.LastMove.X=touches[0].clientX;
  10355. drag.LastMove.Y=touches[0].clientY;
  10356. }
  10357. else if (jsChart.DragMode == 1) //数据左右拖拽
  10358. {
  10359. if (moveSetp < 5) return;
  10360. var isLeft = true;
  10361. if (drag.LastMove.Y < touches[0].clientY) isLeft = false;//右移数据
  10362. if (jsChart.DataMove(moveSetp, isLeft))
  10363. {
  10364. jsChart.UpdataDataoffset();
  10365. jsChart.UpdatePointByCursorIndex();
  10366. jsChart.UpdateFrameMaxMin();
  10367. jsChart.ResetFrameXYSplit();
  10368. jsChart.Draw();
  10369. }
  10370. else
  10371. {
  10372. if (jsChart.DragDownloadData) jsChart.DragDownloadData();
  10373. }
  10374. drag.LastMove.X = touches[0].clientX;
  10375. drag.LastMove.Y = touches[0].clientY;
  10376. }
  10377. }
  10378. if (this.PhoneTouchInfo)
  10379. {
  10380. this.PhoneTouchInfo.End.X=touches[0].clientX;
  10381. this.PhoneTouchInfo.End.Y=touches[0].clientY;
  10382. }
  10383. }
  10384. else if (this.IsPhonePinching(e))
  10385. {
  10386. var phonePinch = jsChart.PhonePinch;
  10387. if (!phonePinch) return;
  10388. if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return;
  10389. var yHeight = Math.abs(touches[0].pageX - touches[1].pageX);
  10390. var yLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2);
  10391. var yStep = yHeight - yLastHeight;
  10392. if (Math.abs(yStep) < 5) return;
  10393. if (yStep > 0) //放大
  10394. {
  10395. var cursorIndex = {};
  10396. cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0));
  10397. if (!jsChart.Frame.ZoomUp(cursorIndex)) return;
  10398. jsChart.CursorIndex = cursorIndex.Index;
  10399. jsChart.UpdatePointByCursorIndex();
  10400. jsChart.UpdataDataoffset();
  10401. jsChart.UpdateFrameMaxMin();
  10402. jsChart.ResetFrameXYSplit();
  10403. jsChart.Draw();
  10404. }
  10405. else //缩小
  10406. {
  10407. var cursorIndex = {};
  10408. cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0));
  10409. if (!jsChart.Frame.ZoomDown(cursorIndex)) return;
  10410. jsChart.CursorIndex = cursorIndex.Index;
  10411. jsChart.UpdataDataoffset();
  10412. jsChart.UpdatePointByCursorIndex();
  10413. jsChart.UpdateFrameMaxMin();
  10414. jsChart.ResetFrameXYSplit();
  10415. jsChart.Draw();
  10416. }
  10417. phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY };
  10418. }
  10419. }
  10420. uielement.onmousedown = function (e) //鼠标拖拽
  10421. {
  10422. if (!this.JSChartContainer) return;
  10423. if (this.JSChartContainer.DragMode == 0) return;
  10424. if (this.JSChartContainer.TryClickLock) {
  10425. var x = e.clientX - this.getBoundingClientRect().left;
  10426. var y = e.clientY - this.getBoundingClientRect().top;
  10427. if (this.JSChartContainer.TryClickLock(x, y)) return;
  10428. }
  10429. var drag =
  10430. {
  10431. "Click": {},
  10432. "LastMove": {}, //最后移动的位置
  10433. };
  10434. drag.Click.X = e.clientX;
  10435. drag.Click.Y = e.clientY;
  10436. drag.LastMove.X = e.clientX;
  10437. drag.LastMove.Y = e.clientY;
  10438. this.JSChartContainer.MouseDrag = drag;
  10439. document.JSChartContainer = this.JSChartContainer;
  10440. this.JSChartContainer.SelectChartDrawPicture = null;
  10441. uielement.ondblclick = function (e) {
  10442. var x = e.clientX - this.getBoundingClientRect().left;
  10443. var y = e.clientY - this.getBoundingClientRect().top;
  10444. if (this.JSChartContainer)
  10445. this.JSChartContainer.OnDoubleClick(x, y, e);
  10446. }
  10447. document.onmousemove = function (e) {
  10448. if (!this.JSChartContainer) return;
  10449. //加载数据中,禁用鼠标事件
  10450. if (this.JSChartContainer.ChartSplashPaint && this.JSChartContainer.ChartSplashPaint.IsEnableSplash == true) return;
  10451. var drag = this.JSChartContainer.MouseDrag;
  10452. if (!drag) return;
  10453. var moveSetp = Math.abs(drag.LastMove.Y - e.clientY);
  10454. if (this.JSChartContainer.DragMode == 1) //数据左右拖拽
  10455. {
  10456. if (moveSetp < 5) return;
  10457. var isLeft = true;
  10458. if (drag.LastMove.Y < e.clientY) isLeft = false;//右移数据
  10459. if (this.JSChartContainer.DataMove(moveSetp, isLeft)) {
  10460. this.JSChartContainer.UpdataDataoffset();
  10461. this.JSChartContainer.UpdatePointByCursorIndex();
  10462. this.JSChartContainer.UpdateFrameMaxMin();
  10463. this.JSChartContainer.ResetFrameXYSplit();
  10464. this.JSChartContainer.Draw();
  10465. }
  10466. drag.LastMove.X = e.clientX;
  10467. drag.LastMove.Y = e.clientY;
  10468. }
  10469. };
  10470. document.onmouseup = function (e) {
  10471. //清空事件
  10472. document.onmousemove = null;
  10473. document.onmouseup = null;
  10474. //清空数据
  10475. this.JSChartContainer.MouseDrag = null;
  10476. this.JSChartContainer.CurrentChartDrawPicture = null;
  10477. this.JSChartContainer = null;
  10478. }
  10479. }
  10480. //创建 windowCount 窗口个数
  10481. this.Create = function (windowCount)
  10482. {
  10483. this.UIElement.JSChartContainer = this;
  10484. //创建十字光标
  10485. this.ChartCorssCursor = new ChartCorssCursor();
  10486. this.ChartCorssCursor.Canvas = this.Canvas;
  10487. this.ChartCorssCursor.StringFormatX = g_DivTooltipDataForamt.Create("CorssCursor_XStringFormat");
  10488. this.ChartCorssCursor.StringFormatX.LanguageID=this.LanguageID;
  10489. this.ChartCorssCursor.StringFormatY = g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat");
  10490. this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID;
  10491. this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  10492. //创建等待提示
  10493. this.ChartSplashPaint = new ChartSplashPaint();
  10494. this.ChartSplashPaint.Canvas = this.Canvas;
  10495. this.ChartSplashPaint.HQChart=this;
  10496. //创建框架容器
  10497. this.Frame = new HQTradeHScreenFrame();
  10498. this.Frame.ChartBorder = new ChartBorder();
  10499. this.Frame.ChartBorder.UIElement = this.UIElement;
  10500. this.Frame.ChartBorder.Top = 30;
  10501. this.Frame.ChartBorder.Left = 5;
  10502. this.Frame.ChartBorder.Bottom = 20;
  10503. this.Frame.Canvas = this.Canvas;
  10504. this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架
  10505. this.ChartSplashPaint.Frame = this.Frame;
  10506. this.CreateChildWindow(windowCount);
  10507. this.CreateMainKLine();
  10508. //子窗口动态标题
  10509. for (var i in this.Frame.SubFrame)
  10510. {
  10511. var titlePaint = new DynamicChartTitlePainting();
  10512. titlePaint.Frame = this.Frame.SubFrame[i].Frame;
  10513. titlePaint.Canvas = this.Canvas;
  10514. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  10515. this.TitlePaint.push(titlePaint);
  10516. }
  10517. }
  10518. //创建子窗口
  10519. this.CreateChildWindow = function (windowCount)
  10520. {
  10521. for (var i = 0; i < windowCount; ++i)
  10522. {
  10523. var border = new ChartBorder();
  10524. border.UIElement = this.UIElement;
  10525. var frame = new KLineHScreenFrame();
  10526. frame.Canvas = this.Canvas;
  10527. frame.ChartBorder = border;
  10528. frame.Identify = i; //窗口序号
  10529. frame.RightSpaceCount = this.RightSpaceCount; //右边
  10530. if (this.ModifyIndexDialog) frame.ModifyIndexEvent = this.ModifyIndexDialog.DoModal; //绑定菜单事件
  10531. if (this.ChangeIndexDialog) frame.ChangeIndexEvent = this.ChangeIndexDialog.DoModal;
  10532. frame.HorizontalMax = 20;
  10533. frame.HorizontalMin = 10;
  10534. if (i == 0)
  10535. {
  10536. frame.YSplitOperator = new FrameSplitKLinePriceY();
  10537. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price');
  10538. frame.YSplitOperator.FrameSplitData2 = this.FrameSplitData.get('double');
  10539. //主图上下间距
  10540. border.TopSpace = 12;
  10541. border.BottomSpace = 12;
  10542. }
  10543. else
  10544. {
  10545. frame.YSplitOperator = new FrameSplitY();
  10546. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double');
  10547. //frame.IsLocked = true;
  10548. }
  10549. frame.YSplitOperator.Frame = frame;
  10550. frame.YSplitOperator.ChartBorder = border;
  10551. frame.XSplitOperator = new FrameSplitKLineX();
  10552. frame.XSplitOperator.Frame = frame;
  10553. frame.XSplitOperator.ChartBorder = border;
  10554. frame.XSplitOperator.GetEventCallback =(id)=> { return this.GetEventCallback(id); }
  10555. if (i != windowCount - 1) frame.XSplitOperator.ShowText = false;
  10556. for (var j = frame.HorizontalMin; j <= frame.HorizontalMax; j += 1)
  10557. {
  10558. frame.HorizontalInfo[j] = new CoordinateInfo();
  10559. frame.HorizontalInfo[j].Value = j;
  10560. if (i == 0 && j == frame.HorizontalMin) continue;
  10561. frame.HorizontalInfo[j].Message[1] = j.toString();
  10562. frame.HorizontalInfo[j].Font = "14px 微软雅黑";
  10563. }
  10564. var subFrame = new SubFrameItem();
  10565. frame.FrameData.SubFrameItem=subFrame;
  10566. subFrame.Frame = frame;
  10567. if (i == 0)
  10568. subFrame.Height = 20;
  10569. else
  10570. subFrame.Height = 10;
  10571. this.Frame.SubFrame[i] = subFrame;
  10572. }
  10573. }
  10574. }
  10575. ////////////////////////////////////////////////////////////////////////////////
  10576. // 走势图横屏显示
  10577. //
  10578. function MinuteChartHScreenContainer(uielement)
  10579. {
  10580. this.newMethod = MinuteChartContainer; //派生
  10581. this.newMethod(uielement);
  10582. delete this.newMethod;
  10583. this.ClassName = 'MinuteChartHScreenContainer';
  10584. this.OnMouseMove = function (x, y, e) {
  10585. this.LastPoint.X = x;
  10586. this.LastPoint.Y = y;
  10587. this.CursorIndex = this.Frame.GetXData(y);
  10588. this.DrawDynamicInfo();
  10589. }
  10590. //创建 windowCount 窗口个数
  10591. this.Create = function (windowCount)
  10592. {
  10593. this.UIElement.JSChartContainer = this;
  10594. //创建十字光标
  10595. this.ChartCorssCursor = new ChartCorssCursor();
  10596. this.ChartCorssCursor.Canvas = this.Canvas;
  10597. this.ChartCorssCursor.StringFormatX = new HQMinuteTimeStringFormat();
  10598. this.ChartCorssCursor.StringFormatY = new HQPriceStringFormat();
  10599. this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  10600. //创建等待提示
  10601. this.ChartSplashPaint = new ChartSplashPaint();
  10602. this.ChartSplashPaint.Canvas = this.Canvas;
  10603. this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle;
  10604. //创建框架容器
  10605. this.Frame = new HQTradeHScreenFrame();
  10606. this.Frame.ChartBorder = new ChartBorder();
  10607. this.Frame.ChartBorder.UIElement = this.UIElement;
  10608. this.Frame.ChartBorder.Top = 25;
  10609. this.Frame.ChartBorder.Left = 50;
  10610. this.Frame.ChartBorder.Bottom = 20;
  10611. this.Frame.Canvas = this.Canvas;
  10612. this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架
  10613. this.ChartSplashPaint.Frame = this.Frame;
  10614. this.CreateChildWindow(windowCount);
  10615. this.CreateMainKLine();
  10616. //子窗口动态标题
  10617. for (var i in this.Frame.SubFrame)
  10618. {
  10619. var titlePaint = new DynamicChartTitlePainting();
  10620. titlePaint.Frame = this.Frame.SubFrame[i].Frame;
  10621. titlePaint.Canvas = this.Canvas;
  10622. titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  10623. this.TitlePaint.push(titlePaint);
  10624. }
  10625. this.ChartCorssCursor.StringFormatX.Frame = this.Frame.SubFrame[0].Frame;
  10626. }
  10627. //创建子窗口
  10628. this.CreateChildWindow = function (windowCount)
  10629. {
  10630. for (var i = 0; i < windowCount; ++i)
  10631. {
  10632. var border = new ChartBorder();
  10633. border.UIElement = this.UIElement;
  10634. var frame = new MinuteHScreenFrame();
  10635. frame.Canvas = this.Canvas;
  10636. frame.ChartBorder = border;
  10637. if (i < 2) frame.ChartBorder.TitleHeight = 0;
  10638. frame.XPointCount = 243;
  10639. frame.Identify=i;
  10640. frame.HQChart=this;
  10641. frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  10642. var DEFAULT_HORIZONTAL = [9, 8, 7, 6, 5, 4, 3, 2, 1];
  10643. frame.HorizontalMax = DEFAULT_HORIZONTAL[0];
  10644. frame.HorizontalMin = DEFAULT_HORIZONTAL[DEFAULT_HORIZONTAL.length - 1];
  10645. if (i == 0)
  10646. {
  10647. frame.YSplitOperator = new FrameSplitMinutePriceY();
  10648. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price');
  10649. }
  10650. else
  10651. {
  10652. frame.YSplitOperator = new FrameSplitY();
  10653. frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double');
  10654. }
  10655. frame.YSplitOperator.Frame = frame;
  10656. frame.YSplitOperator.ChartBorder = border;
  10657. frame.XSplitOperator = new FrameSplitMinuteX();
  10658. frame.XSplitOperator.Frame = frame;
  10659. frame.XSplitOperator.ChartBorder = border;
  10660. frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  10661. if (i != windowCount - 1) frame.XSplitOperator.ShowText = false;
  10662. frame.XSplitOperator.Operator();
  10663. for (var j in DEFAULT_HORIZONTAL)
  10664. {
  10665. frame.HorizontalInfo[j] = new CoordinateInfo();
  10666. frame.HorizontalInfo[j].Value = DEFAULT_HORIZONTAL[j];
  10667. if (i == 0 && j == frame.HorizontalMin) continue;
  10668. frame.HorizontalInfo[j].Message[1] = DEFAULT_HORIZONTAL[j].toString();
  10669. frame.HorizontalInfo[j].Font = "14px 微软雅黑";
  10670. }
  10671. var subFrame = new SubFrameItem();
  10672. frame.FrameData.SubFrameItem=subFrame;
  10673. subFrame.Frame = frame;
  10674. if (i == 0)
  10675. subFrame.Height = 20;
  10676. else
  10677. subFrame.Height = 10;
  10678. this.Frame.SubFrame[i] = subFrame;
  10679. }
  10680. }
  10681. }
  10682. ////////////////////////////////////////////////////////////////////////////////
  10683. // K线训练,包含横屏
  10684. //
  10685. function KLineTrainChartContainer(uielement, bHScreen)
  10686. {
  10687. if (bHScreen === true)
  10688. {
  10689. this.newMethod = KLineChartHScreenContainer; //派生
  10690. this.newMethod(uielement);
  10691. delete this.newMethod;
  10692. }
  10693. else
  10694. {
  10695. this.newMethod = KLineChartContainer; //派生
  10696. this.newMethod(uielement);
  10697. delete this.newMethod;
  10698. }
  10699. this.ClassName2 = 'KLineTrainChartContainer';
  10700. this.BuySellPaint; //买卖点画法
  10701. this.TrainDataCount = 300; //训练数据个数
  10702. this.AutoRunTimer = null; //K线自动前进定时器
  10703. this.BuySellData = []; //模拟买卖数据 {Buy:{Price:价格,Date:日期,Time:时间} , Sell:{Price:价格,Date:日期,Time:时间}
  10704. this.TrainDataIndex; //当前训练的数据索引
  10705. this.TrainCallback; //训练回调 (K线每前进一次就调用一次)
  10706. this.DragMode = 1;
  10707. this.TrainStartEnd = {};
  10708. this.KLineSourceData; //原始K线数据 对应 SourceData
  10709. this.TrainInfo = { Start: {}, End: {} }; // Index:数据索引, Date:日期 Time:时间
  10710. this.CreateBuySellPaint = function () //在主窗口建立以后 创建买卖点
  10711. {
  10712. var chart = new ChartBuySell();
  10713. chart.Canvas = this.Canvas;
  10714. chart.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder;
  10715. chart.ChartFrame = this.Frame.SubFrame[0].Frame;
  10716. chart.Name = "KLine-Train-BuySell";
  10717. this.ChartPaintEx[0] = chart;
  10718. }
  10719. this.GetKDataIndexByDateTime = function (kData, dateTime)
  10720. {
  10721. if (!dateTime || !kData) return -1;
  10722. for (var i=0; i<kData.length; ++i)
  10723. {
  10724. var item = kData[i];
  10725. if (ChartData.IsMinutePeriod(this.Period, true))
  10726. {
  10727. if (IFrameSplitOperator.IsNumber(this.TrainStartDate.Time))
  10728. {
  10729. if (item.Date >= this.TrainStartDate.Date && item.Time >= this.TrainStartDate.Time)
  10730. return i;
  10731. }
  10732. else
  10733. {
  10734. if (item.Date >= this.TrainStartDate.Date)
  10735. return i;
  10736. }
  10737. }
  10738. else if (ChartData.IsDayPeriod(this.Period, true) || ChartData.IsTickPeriod(this.Period))
  10739. {
  10740. if (item.Date >= this.TrainStartDate.Date)
  10741. return i;
  10742. }
  10743. }
  10744. return -1;
  10745. }
  10746. this.AfterBindMainData = function (funcName)
  10747. {
  10748. if (!this.ChartPaintEx[0]) this.CreateBuySellPaint();
  10749. var hisData = this.ChartPaint[0].Data;
  10750. this.ChartPaintEx[0].Data = hisData;
  10751. var showItem = hisData.Data[hisData.Data.length - 1];
  10752. //最后一个显示数据
  10753. this.TrainInfo.LastShowData = showItem;
  10754. //最后一个原始数据
  10755. this.TrainInfo.LastData = this.SourceData.Data[this.SourceData.Data.length - 1];
  10756. if (funcName != 'Update')
  10757. this.UpdateTrainUICallback("开始");
  10758. }
  10759. this.BeforeBindMainData = function (funcName)
  10760. {
  10761. if (funcName == "Update") return;
  10762. //全量数据 需要过滤
  10763. this.KLineSourceData = new ChartData();
  10764. this.KLineSourceData.Data = this.SourceData.Data.slice(0);
  10765. var count = this.SourceData.Data.length;
  10766. var lEnd = count - this.TrainDataCount - 20;
  10767. var findIndex = this.GetKDataIndexByDateTime(this.SourceData.Data, this.TrainStartDate);
  10768. if (findIndex >= 0)
  10769. {
  10770. lEnd = findIndex + 1;
  10771. if (count - lEnd < this.TrainDataCount) this.TrainDataCount = count - lEnd;
  10772. }
  10773. //训练起始日期
  10774. var index = lEnd - 1;
  10775. var kItem = this.SourceData.Data[index];
  10776. this.TrainInfo.Start.Index = index;
  10777. this.TrainInfo.Start.Date = kItem.Date;
  10778. this.TrainInfo.Start.Time = kItem.Time;
  10779. //训练结束日期
  10780. this.TrainInfo.End.Index = index;
  10781. this.TrainInfo.End.Date = kItem.Date;
  10782. this.TrainInfo.End.Time = kItem.Time;
  10783. //最后一个数据
  10784. this.TrainInfo.LastData = kItem;
  10785. //修改数据个数
  10786. this.SourceData.Data.length = lEnd;
  10787. }
  10788. this.Run = function (option)
  10789. {
  10790. if (this.AutoRunTimer) return;
  10791. if (this.TrainDataCount <= 0) return;
  10792. var self = this;
  10793. this.AutoRunTimer = setInterval(function () {
  10794. if (!self.MoveNextKLineData(option)) clearInterval(self.AutoRunTimer);
  10795. }, 1000);
  10796. }
  10797. this.MoveNextKLineData = function (option) //{PageSize:, Step:}
  10798. {
  10799. if (this.TrainDataCount <= 0) return false;
  10800. var step = 1, moveStep=0;
  10801. if (option && option.Step > 1) step = option.Step;
  10802. for (var i = 0; i < step; ++i)
  10803. {
  10804. var index = this.TrainInfo.End.Index + 1;
  10805. if (index >= this.KLineSourceData.Data.length) break;
  10806. var kItem = this.KLineSourceData.Data[index];
  10807. this.SourceData.Data.push(kItem);
  10808. this.TrainInfo.End.Index = index;
  10809. this.TrainInfo.End.Date = kItem.Date;
  10810. this.TrainInfo.End.Time = kItem.Time;
  10811. --this.TrainDataCount;
  10812. ++moveStep;
  10813. if (this.TrainDataCount <= 0) break;
  10814. }
  10815. if (moveStep == 0) return false;
  10816. //使用当前页数据个数移动K线
  10817. var pageSize = this.Frame.GetCurrentPageSize();
  10818. if (IFrameSplitOperator.IsNumber(pageSize))
  10819. this.PageSize = pageSize - this.RightSpaceCount;
  10820. this.Update();
  10821. if (this.TrainDataCount <= 0)
  10822. {
  10823. this.FinishTrainData();
  10824. this.UpdateTrainUICallback("结束");
  10825. return false;
  10826. }
  10827. this.UpdateTrainUICallback("训练中");
  10828. return true;
  10829. }
  10830. this.UpdateTrainUICallback = function (description)
  10831. {
  10832. //新的监听事件
  10833. if (!this.mapEvent.has(JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP)) return;
  10834. var item = this.mapEvent.get(JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP);
  10835. if (!item.Callback) return;
  10836. var data =
  10837. {
  10838. TrainDataCount: this.TrainDataCount,
  10839. BuySellData: this.BuySellData,
  10840. KLine:
  10841. {
  10842. Start: { Index: this.TrainInfo.Start.Index, Date: this.TrainInfo.Start.Date },
  10843. End: { Index: this.TrainInfo.End.Index, Date: this.TrainInfo.End.Date }
  10844. },
  10845. LastData: this.TrainInfo.LastData,
  10846. LastShowData: this.TrainInfo.LastShowData
  10847. };
  10848. if (IFrameSplitOperator.IsNumber(this.TrainInfo.Start.Time)) data.KLine.Start.Time = this.TrainInfo.Start.Time;
  10849. if (IFrameSplitOperator.IsNumber(this.TrainInfo.End.Time)) data.KLine.End.Time = this.TrainInfo.End.Time;
  10850. if (description) data.Description = description
  10851. if (this.TrainDataCount <= 0)
  10852. {
  10853. data.Symbol = this.Symbol;
  10854. data.Name = this.Name;
  10855. }
  10856. item.Callback(item, data, this);
  10857. }
  10858. this.FinishTrainData = function ()
  10859. {
  10860. }
  10861. this.Stop = function ()
  10862. {
  10863. if (this.AutoRunTimer != null) clearInterval(this.AutoRunTimer);
  10864. this.AutoRunTimer = null;
  10865. }
  10866. this.BuyOrSell = function (obj, bDraw) //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 } bDraw是否立即绘制图标
  10867. {
  10868. var kItem = this.TrainInfo.LastShowData;
  10869. if (!kItem) return false;
  10870. var buySellPaint = this.ChartPaintEx[0];
  10871. if (!buySellPaint) return false;
  10872. var hisData = this.ChartPaint[0].Data;
  10873. if (!hisData || hisData.Data.length <= 0) return false;
  10874. var index = hisData.Data.length - 1; //数据索引
  10875. var buyItem = { Date: this.TrainInfo.End.Date, Time: this.TrainInfo.End.Time, Price: obj.Price, Vol: obj.Vol, Op: 0, ID: obj.ID };
  10876. if (obj.Op == 1) buyItem.Op = 1;
  10877. var key = index;
  10878. buyItem.Key = key;
  10879. this.BuySellData.push(buyItem);
  10880. buySellPaint.AddTradeItem(buyItem);
  10881. if (bDraw == true) this.Draw();
  10882. }
  10883. this.RestartTrain = function (option) // { Symbol:, Period:周期, Right:复权, Train:{ DataCount:, DateTime: } }
  10884. {
  10885. JSConsole.Chart.Log('[KLineTrainChartContainer::RestartTrain] option ', option);
  10886. this.TrainInfo = { Start: {}, End: {} };
  10887. this.BuySellData = [];
  10888. this.KLineSourceData = null;
  10889. var buySellPaint = this.ChartPaintEx[0];
  10890. if (buySellPaint)
  10891. {
  10892. buySellPaint.Data = null;
  10893. buySellPaint.ClearTradeData();
  10894. }
  10895. if (option.Symbol) this.Symbol = option.Symbol;
  10896. if (IFrameSplitOperator.IsNumber(option.Period)) this.Period = option.Period;
  10897. if (IFrameSplitOperator.IsNumber(option.Right)) this.Right = option.Right;
  10898. if (option.Train)
  10899. {
  10900. if (option.Train.DataCount > 1) this.TrainDataCount = option.Train.DataCount;
  10901. if (option.Train.DateTime) this.TrainStartDate = option.Train.DateTime;
  10902. }
  10903. var symbol = this.Symbol;
  10904. this.ChangeSymbol(symbol);
  10905. }
  10906. }
  10907. ///////////////////////////////////////////////////////////////////////////////////
  10908. // 简单的K线图, 只计算一次
  10909. //
  10910. //////////////////////////////////////////////////////////////////////////////////
  10911. function KLineTrainSimpleChartContainer(uielement, bHScreen)
  10912. {
  10913. this.newMethod=KLineTrainChartContainer; //派生
  10914. this.newMethod(uielement, bHScreen);
  10915. delete this.newMethod;
  10916. this.IsHScreen=bHScreen;
  10917. this.IsZoomLockRight=true;
  10918. this.RightSpaceCount=0;
  10919. this.RecvFlowCapitalData=function(data)
  10920. {
  10921. this.Super_RecvFlowCapitalData(data);
  10922. }
  10923. this.BeforeBindMainData=function(funcName)
  10924. {
  10925. }
  10926. this.UpdateLastDataIcon=function()
  10927. {
  10928. if (!this.ChartPaintEx[0]) return;
  10929. var chart=this.ChartPaintEx[0];
  10930. chart.LastDataIndex=this.TrainInfo.End.Index;
  10931. }
  10932. this.AfterBindMainData=function(funcName)
  10933. {
  10934. if (!this.ChartPaintEx[0])
  10935. {
  10936. this.CreateBuySellPaint();
  10937. this.ChartPaintEx[0].LastDataDrawType=1;
  10938. }
  10939. if (funcName!="Update")
  10940. {
  10941. var hisData=this.ChartOperator_Temp_GetHistroyData();
  10942. if (!hisData) return false;
  10943. var count=hisData.Data.length;
  10944. var lEnd=count-this.TrainDataCount-20;
  10945. var xPointcount=this.Frame.SubFrame[0].Frame.XPointCount;
  10946. var findIndex=this.GetKDataIndexByDateTime(hisData.Data, this.TrainStartDate);
  10947. if (findIndex>=0)
  10948. {
  10949. lEnd=findIndex+1;
  10950. if (count-lEnd<this.TrainDataCount) this.TrainDataCount=count-lEnd;
  10951. }
  10952. var xOffset=lEnd-xPointcount;
  10953. hisData.DataOffset=xOffset;
  10954. var index=lEnd-1;
  10955. var kItem=hisData.Data[index];
  10956. //最后一个显示数据
  10957. this.TrainInfo.LastShowData=kItem;
  10958. this.TrainInfo.LastData = kItem;
  10959. //训练起始日期
  10960. this.TrainInfo.Start.Index=index;
  10961. this.TrainInfo.Start.Date=kItem.Date;
  10962. this.TrainInfo.Start.Time=kItem.Time;
  10963. //训练结束日期
  10964. this.TrainInfo.End.Index=index;
  10965. this.TrainInfo.End.Date=kItem.Date;
  10966. this.TrainInfo.End.Time=kItem.Time;
  10967. this.UpdateLastDataIcon();
  10968. this.UpdateTrainUICallback("开始");
  10969. }
  10970. }
  10971. this.Super_UpdataDataoffset=this.UpdataDataoffset;
  10972. this.UpdataDataoffset=function()
  10973. {
  10974. this.Super_UpdataDataoffset();
  10975. var hisData=this.ChartPaint[0].Data;
  10976. this.ChartPaintEx[0].Data=hisData;
  10977. }
  10978. this.MoveNextKLineData=function(option) //{PageSize:, Step:}
  10979. {
  10980. if (this.TrainDataCount<=0) return false;
  10981. var hisData=this.ChartOperator_Temp_GetHistroyData();
  10982. if (!hisData) return false;
  10983. var step=1;
  10984. if (option && option.Step>1) step=option.Step;
  10985. var count=hisData.Data.length;
  10986. var moveStep=0;
  10987. for(var i=0; i<step; ++i)
  10988. {
  10989. var index=this.TrainInfo.End.Index+1;
  10990. if (index>=count) break;
  10991. var kItem=hisData.Data[index];
  10992. this.TrainInfo.End.Index=index;
  10993. this.TrainInfo.End.Date=kItem.Date;
  10994. this.TrainInfo.End.Time=kItem.Time;
  10995. --this.TrainDataCount;
  10996. ++moveStep;
  10997. if (this.TrainDataCount<=0) break;
  10998. }
  10999. if (moveStep==0) return false;
  11000. //最后一个显示数据
  11001. this.TrainInfo.LastShowData=kItem;
  11002. this.TrainInfo.LastData = kItem;
  11003. //调整x轴索引位置
  11004. var lEnd=this.TrainInfo.End.Index;
  11005. var xPointcount=this.Frame.SubFrame[0].Frame.XPointCount;
  11006. var xOffset=lEnd-xPointcount+1;
  11007. hisData.DataOffset=xOffset;
  11008. this.UpdateLastDataIcon();
  11009. this.UpdataDataoffset();
  11010. this.UpdateFrameMaxMin();
  11011. this.Draw();
  11012. if (this.TrainDataCount<=0)
  11013. {
  11014. this.FinishTrainData();
  11015. this.UpdateTrainUICallback("结束");
  11016. return false;
  11017. }
  11018. this.UpdateTrainUICallback("训练中");
  11019. return true;
  11020. }
  11021. this.BuyOrSell=function(obj, bDraw) //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 } bDraw是否立即绘制图标
  11022. {
  11023. var kItem=this.TrainInfo.LastShowData;
  11024. if (!kItem) return false;
  11025. var buySellPaint=this.ChartPaintEx[0];
  11026. if (!buySellPaint) return false;
  11027. var hisData=this.ChartPaint[0].Data;
  11028. if (!hisData || hisData.Data.length<=0) return false;
  11029. var index=this.TrainInfo.End.Index; //数据索引
  11030. var buyItem={ Date:this.TrainInfo.End.Date, Time:this.TrainInfo.End.Time, Price:obj.Price, Vol:obj.Vol, Op:0, ID:obj.ID };
  11031. if (obj.Op==1) buyItem.Op=1;
  11032. var key=index;
  11033. buyItem.Key=key;
  11034. this.BuySellData.push(buyItem);
  11035. buySellPaint.AddTradeItem(buyItem);
  11036. if (bDraw==true) this.Draw();
  11037. }
  11038. this.DataMove=function(step,isLeft)
  11039. {
  11040. step=parseInt(step/this.StepPixel);
  11041. if (step<=0) return false;
  11042. var data = this.ChartOperator_Temp_GetHistroyData();
  11043. if (!data) return false;
  11044. var xPointcount = 0;
  11045. if (this.Frame.XPointCount) xPointcount = this.Frame.XPointCount;
  11046. else xPointcount = this.Frame.SubFrame[0].Frame.XPointCount;
  11047. if (!xPointcount) return false;
  11048. if (isLeft) //-->
  11049. {
  11050. if (this.RightSpaceCount > 0)
  11051. {
  11052. //TODO: not support
  11053. if (xPointcount + data.DataOffset >= data.Data.length + this.RightSpaceCount - 1) return false;
  11054. data.DataOffset += step;
  11055. if (data.DataOffset + xPointcount >= data.Data.length + this.RightSpaceCount)
  11056. data.DataOffset = data.Data.length - (xPointcount - this.RightSpaceCount);
  11057. }
  11058. else
  11059. {
  11060. var end=this.TrainInfo.End.Index+1;
  11061. if (xPointcount + data.DataOffset >= end) return false;
  11062. data.DataOffset += step;
  11063. if (data.DataOffset + xPointcount >= end)
  11064. data.DataOffset = end - xPointcount;
  11065. }
  11066. return true;
  11067. }
  11068. else //<--
  11069. {
  11070. if (data.DataOffset <= 0) return false;
  11071. data.DataOffset -= step;
  11072. if (data.DataOffset < 0) data.DataOffset = 0;
  11073. return true;
  11074. }
  11075. }
  11076. //获取最后一个数据的相对于当前屏的索引
  11077. this.GetLastDataIndex=function()
  11078. {
  11079. if (!this.ChartPaint[0] || !this.ChartPaint[0].Data || !this.ChartPaint[0].Data.Data) return null;
  11080. var hisData=this.ChartPaint[0].Data;
  11081. var dataCount=this.TrainInfo.End.Index+1
  11082. if (dataCount>0) return (dataCount-1)-hisData.DataOffset;
  11083. return null;
  11084. }
  11085. }
  11086. /////////////////////////////////////////////////////////////////////////////////
  11087. // 深度图
  11088. //
  11089. function DepthChartContainer(uielement)
  11090. {
  11091. this.newMethod=JSChartContainer; //派生
  11092. this.newMethod(uielement);
  11093. delete this.newMethod;
  11094. this.ClassName="DepthChartContainer";
  11095. this.Symbol;
  11096. //数据
  11097. this.MapAsk=new Map();
  11098. this.MapBid=new Map();
  11099. this.IsAutoUpdate=false; //是否自动更新行情数据
  11100. this.AutoUpdateFrequency=30000; //30秒更新一次数据
  11101. this.AutoUpdateTimer=null;
  11102. this.DefaultZoom=0.8; //默认显示80%的盘口 (0 - 1)
  11103. this.MaxVolRate=1.1;
  11104. this.Create=function(option)
  11105. {
  11106. this.UIElement.JSChartContainer=this;
  11107. //创建十字光标
  11108. this.ChartCorssCursor=new DepthChartCorssCursor();
  11109. this.ChartCorssCursor.Canvas=this.Canvas;
  11110. this.ChartCorssCursor.HQChart=this;
  11111. //this.ChartCorssCursor.StringFormatX=g_DivTooltipDataForamt.Create("CorssCursor_XStringFormat");
  11112. //this.ChartCorssCursor.StringFormatX.LanguageID=this.LanguageID;
  11113. //this.ChartCorssCursor.StringFormatY=g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat");
  11114. //this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID;
  11115. //创建等待提示
  11116. this.ChartSplashPaint = new ChartSplashPaint();
  11117. this.ChartSplashPaint.Canvas = this.Canvas;
  11118. this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle;
  11119. //创建框架
  11120. this.Frame=new DepthChartFrame();
  11121. this.Frame.ChartBorder=new ChartBorder();
  11122. this.Frame.ChartBorder.UIElement=this.UIElement;
  11123. this.Frame.ChartBorder.Top=30;
  11124. this.Frame.ChartBorder.Left=5;
  11125. this.Frame.ChartBorder.Bottom=20;
  11126. this.Frame.ChartBorder.TitleHeight=0;
  11127. this.Frame.Canvas=this.Canvas;
  11128. this.Frame.Identify=0;
  11129. var ySplitOper=new FrameSplitY();
  11130. ySplitOper.FrameSplitData=this.FrameSplitData.get('double');
  11131. ySplitOper.LanguageID=this.LanguageID;
  11132. ySplitOper.Frame=this.Frame;
  11133. ySplitOper.SplitCount=5;
  11134. ySplitOper.IgnoreYValue=[0];
  11135. ySplitOper.LineType=3;
  11136. ySplitOper.ChartBorder=this.Frame.ChartBorder;
  11137. ySplitOper.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
  11138. this.Frame.YSplitOperator=ySplitOper;
  11139. var xSplitOper=new FrameSplitXDepth();
  11140. xSplitOper.Frame=this.Frame;;
  11141. xSplitOper.ChartBorder=this.Frame.ChartBorder;;
  11142. xSplitOper.LanguageID=this.LanguageID;
  11143. xSplitOper.LineType=3;
  11144. xSplitOper.GetEventCallback=(id)=> { return this.GetEventCallback(id); };
  11145. this.Frame.XSplitOperator=xSplitOper
  11146. if (this.ChartCorssCursor) this.ChartCorssCursor.Frame=this.Frame; //十字光标绑定框架
  11147. this.ChartSplashPaint.Frame = this.Frame;
  11148. var chartItem=new ChartOrderbookDepth();
  11149. chartItem.Canvas=this.Canvas;
  11150. chartItem.ChartBorder=this.Frame.ChartBorder;
  11151. chartItem.ChartFrame=this.Frame;
  11152. chartItem.Name="深度图"
  11153. this.ChartPaint.push(chartItem);
  11154. }
  11155. this.ontouchstart=function(e)
  11156. {
  11157. this.IsOnTouch=true;
  11158. this.TouchDrawCount=0;
  11159. this.PhonePinch=null;
  11160. var isSingleTouch=this.IsSingleTouch(e);
  11161. if (this.EnableScrollUpDown==false || !isSingleTouch) //多点触屏
  11162. {
  11163. }
  11164. if (this.IsPhoneDragging(e))
  11165. {
  11166. var drag=
  11167. {
  11168. "Click":{},
  11169. "LastMove":{} //最后移动的位置
  11170. };
  11171. var touches=this.GetToucheData(e,this.IsForceLandscape);
  11172. drag.Click.X=touches[0].clientX;
  11173. drag.Click.Y=touches[0].clientY;
  11174. drag.LastMove.X=touches[0].clientX;
  11175. drag.LastMove.Y=touches[0].clientY;
  11176. this.MouseDrag=drag;
  11177. var x = drag.Click.X;
  11178. var y = drag.Click.Y;
  11179. this.OnMouseMove(x, y, e);
  11180. }
  11181. else if (this.IsPhonePinching(e))
  11182. {
  11183. var phonePinch=
  11184. {
  11185. "Start":{},
  11186. "Last":{}
  11187. };
  11188. var touches=this.GetToucheData(e,this.IsForceLandscape);
  11189. phonePinch.Start={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY};
  11190. phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY};
  11191. this.PhonePinch=phonePinch;
  11192. }
  11193. }
  11194. this.ontouchmove=function(e)
  11195. {
  11196. var touches=this.GetToucheData(e,false);
  11197. if (this.IsPhoneDragging(e))
  11198. {
  11199. var drag=this.MouseDrag;
  11200. if (drag==null)
  11201. {
  11202. var x = touches[0].clientX;
  11203. var y = touches[0].clientY;
  11204. this.OnMouseMove(x,y,e);
  11205. }
  11206. else
  11207. {
  11208. this.MouseDrag=null;
  11209. var x = touches[0].clientX;
  11210. var y = touches[0].clientY;
  11211. this.OnMouseMove(x,y,e);
  11212. }
  11213. }
  11214. else if (this.IsPhonePinching(e))
  11215. {
  11216. var phonePinch=this.PhonePinch;
  11217. if (!phonePinch) return;
  11218. if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return;
  11219. var yHeight = Math.abs(touches[0].pageY - touches[1].pageY);
  11220. var yLastHeight = Math.abs(phonePinch.Last.Y - phonePinch.Last.Y2);
  11221. var yStep = yHeight - yLastHeight;
  11222. var xHeight = Math.abs(touches[0].pageX - touches[1].pageX);
  11223. var xLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2);
  11224. var xStep = xHeight - xLastHeight;
  11225. var minStep=this.ZoomStepPixel;
  11226. if (Math.abs(yStep) <minStep && Math.abs(xStep) < minStep) return;
  11227. var step = yStep;
  11228. if (Math.abs(yStep) < minStep) step = xStep;
  11229. if (step>0) //放大
  11230. {
  11231. if (!this.Frame.ZoomUp()) return;
  11232. this.UpdateFrameMaxMin();
  11233. this.Draw();
  11234. }
  11235. else //缩小
  11236. {
  11237. if (!this.Frame.ZoomDown()) return;
  11238. this.UpdateFrameMaxMin();
  11239. this.Draw();
  11240. }
  11241. phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY};
  11242. }
  11243. }
  11244. this.ontouchend=function(e)
  11245. {
  11246. JSConsole.Chart.Log('[DepthChartContainer::OnTouchEnd]',e);
  11247. this.IsOnTouch = false;
  11248. this.Draw();
  11249. this.TouchDrawCount=0;
  11250. }
  11251. this.OnMouseMove = function (x, y, e, bFullDraw)
  11252. {
  11253. var lastY = this.LastPoint.Y;
  11254. this.LastPoint.X = x;
  11255. this.LastPoint.Y = y;
  11256. this.FullDraw();
  11257. }
  11258. this.ChangeSymbol=function(symbol)
  11259. {
  11260. this.CancelAutoUpdate(); //先停止定时器
  11261. this.Symbol=symbol;
  11262. this.MapBid=new Map();
  11263. this.MapAsk=new Map();
  11264. this.Frame.VerticalRange.Differ=null;
  11265. this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle);
  11266. this.ChartSplashPaint.EnableSplash(true);
  11267. this.Draw();
  11268. this.RequestDepthData();
  11269. }
  11270. this.RequestDepthData=function() //全量历史数据
  11271. {
  11272. var self=this;
  11273. if (this.NetworkFilter)
  11274. {
  11275. var obj=
  11276. {
  11277. Name:'DepthChartContainer::RequestDepthData', //类名::
  11278. Explain:'深度图数据',
  11279. Request:{ Data: { symbol:self.Symbol } },
  11280. Self:this,
  11281. PreventDefault:false
  11282. };
  11283. this.NetworkFilter(obj, function(data)
  11284. {
  11285. self.ChartSplashPaint.EnableSplash(false);
  11286. self.RecvDepthData(data);
  11287. self.AutoUpdate();
  11288. });
  11289. if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
  11290. }
  11291. }
  11292. this.RecvDepthData=function(data)
  11293. {
  11294. this.UpdateAskAndBid(data);
  11295. var aryAsk=Array.from(this.MapAsk.values()); //卖 右边
  11296. aryAsk.sort((a,b)=> { return a.Price-b.Price; });
  11297. var sumVol=0;
  11298. for(var i in aryAsk)
  11299. {
  11300. var item=aryAsk[i];
  11301. sumVol+=item.Vol;
  11302. aryAsk[i]={Price:item.Price, Vol:sumVol };
  11303. }
  11304. var aryBid=Array.from(this.MapBid.values()); //买 左边
  11305. aryBid.sort((a,b)=> { return b.Price-a.Price; });
  11306. var sumVol=0;
  11307. for(var i in aryBid)
  11308. {
  11309. var item=aryBid[i];
  11310. sumVol+=item.Vol;
  11311. aryBid[i]={Price:item.Price, Vol:sumVol };
  11312. }
  11313. var drawData={ Asks:aryAsk, Bids:aryBid };
  11314. var chart=this.ChartPaint[0];
  11315. chart.Data=drawData;
  11316. this.Frame.XSplitOperator.Symbol=this.Symbol;
  11317. this.ChartCorssCursor.Data=drawData;
  11318. this.ChartCorssCursor.Symbol=this.Symbol;
  11319. this.UpdateFramePriceList();
  11320. this.UpdateFrameMaxMin();
  11321. this.Draw();
  11322. }
  11323. this.UpdateAskAndBid=function(data) //更新数据
  11324. {
  11325. if(data.datatype=="snapshot") //全量数据
  11326. {
  11327. this.MapBid=new Map();
  11328. this.MapAsk=new Map();
  11329. }
  11330. for(var i in data.asks)
  11331. {
  11332. var item=data.asks[i];
  11333. var price=parseFloat(item[0]);
  11334. var vol=parseFloat(item[1]);
  11335. if (this.MapAsk.has(price))
  11336. {
  11337. var value=this.MapAsk.get(price);
  11338. if (vol<=0) this.MapAsk.delete(price);
  11339. else value.Vol=vol;
  11340. }
  11341. else
  11342. {
  11343. if (vol>0) this.MapAsk.set(price, { Price:price, Vol:vol});
  11344. }
  11345. }
  11346. for(var i in data.bids)
  11347. {
  11348. var item=data.bids[i];
  11349. var price=parseFloat(item[0]);
  11350. var vol=parseFloat(item[1]);
  11351. if (this.MapBid.has(price))
  11352. {
  11353. var value=this.MapBid.get(price);
  11354. if (vol<=0) this.MapBid.delete(price);
  11355. else value.Vol=vol;
  11356. }
  11357. else
  11358. {
  11359. if (vol>0) this.MapBid.set(price, { Price:price, Vol:vol});
  11360. }
  11361. }
  11362. }
  11363. this.UpdateFramePriceList=function()
  11364. {
  11365. var aryAskPrice=Array.from(this.MapAsk.keys());
  11366. var aryBidPrice=Array.from(this.MapBid.keys());
  11367. aryAskPrice.sort((a,b)=> { return a-b; });
  11368. aryBidPrice.sort((a,b)=> { return a-b; });
  11369. if (aryAskPrice.length>1 && aryBidPrice.length>1)
  11370. {
  11371. var askMin=aryAskPrice[0], askMax=aryAskPrice[aryAskPrice.length-1];
  11372. var bidMin=aryBidPrice[0], bidMax=aryBidPrice[aryBidPrice.length-1];
  11373. var askDifference=askMax-askMin; //卖差值
  11374. var bidDifference=bidMax-bidMin; //买差值
  11375. var difference=Math.max(askDifference, bidDifference); //取最大的差值,2边调整
  11376. var ask={Min:askMin, Max:askMin+difference};
  11377. var bid={Max:bidMax, Min:bidMax-difference};
  11378. var range={ Max:ask.Max, Min:bid.Min };
  11379. }
  11380. this.Frame.SetPriceList(aryAskPrice,aryBidPrice);
  11381. var xRange=this.Frame.VerticalRange;
  11382. xRange.Max=range.Max;
  11383. xRange.Center=range.Min+(range.Max-range.Min)/2;
  11384. xRange.Min=range.Min;
  11385. xRange.MaxDiffer=difference; //差值
  11386. xRange.Ask=ask;
  11387. xRange.Bid=bid;
  11388. if (!IFrameSplitOperator.IsNumber(xRange.Differ))
  11389. xRange.Differ=difference*this.DefaultZoom;
  11390. xRange.Min=xRange.Center-xRange.Differ;
  11391. xRange.Max=xRange.Center+xRange.Differ;
  11392. }
  11393. this.UpdateFrameMaxMin=function()
  11394. {
  11395. var range=this.ChartPaint[0].GetMaxMin();
  11396. this.Frame.HorizontalMax=range.Max*this.MaxVolRate;
  11397. this.Frame.HorizontalMin=0;
  11398. this.Frame.XYSplit=true;
  11399. }
  11400. this.CancelAutoUpdate=function() //关闭停止更新
  11401. {
  11402. if (this.AutoUpdateTimer)
  11403. {
  11404. clearTimeout(this.AutoUpdateTimer);
  11405. this.AutoUpdateTimer = null;
  11406. }
  11407. }
  11408. this.StopAutoUpdate=function()
  11409. {
  11410. this.CancelAutoUpdate();
  11411. if (!this.IsAutoUpdate) return;
  11412. this.IsAutoUpdate=false;
  11413. }
  11414. this.AutoUpdate=function() //数据自动更新
  11415. {
  11416. this.CancelAutoUpdate();
  11417. if (!this.IsAutoUpdate) return;
  11418. if (!this.Symbol) return;
  11419. if (this.IsDestroy) return;
  11420. var self = this;
  11421. var marketStatus=MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol);
  11422. if (marketStatus==0 || marketStatus==3) return; //闭市,盘后
  11423. var frequency=this.AutoUpdateFrequency;
  11424. if (marketStatus==1) //盘前
  11425. {
  11426. this.AutoUpdateTimer=setTimeout(function()
  11427. {
  11428. self.AutoUpdate();
  11429. },frequency);
  11430. }
  11431. else if (marketStatus==2) //盘中
  11432. {
  11433. this.AutoUpdateTimer=setTimeout(function()
  11434. {
  11435. self.RequestDepthData();
  11436. },frequency);
  11437. }
  11438. }
  11439. }
  11440. //是否是指数代码
  11441. function IsIndexSymbol(symbol) {
  11442. var upperSymbol = symbol.toUpperCase();
  11443. if (upperSymbol.indexOf('.SH') > 0) {
  11444. upperSymbol = upperSymbol.replace('.SH', '');
  11445. if (upperSymbol.charAt(0) == '0' && parseInt(upperSymbol) <= 3000) return true;
  11446. }
  11447. else if (upperSymbol.indexOf('.SZ') > 0) {
  11448. upperSymbol = upperSymbol.replace('.SZ', '');
  11449. if (upperSymbol.charAt(0) == '3' && upperSymbol.charAt(1) == '9') return true;
  11450. }
  11451. else if (upperSymbol.indexOf('.CI') > 0) //自定义指数
  11452. {
  11453. return true;
  11454. }
  11455. return false;
  11456. }
  11457. //导出统一使用JSCommon命名空间名
  11458. var JSCommon=
  11459. {
  11460. JSCanvasElement: JSCanvasElement,
  11461. JSNetwork:JSNetwork,
  11462. JSChart: JSChart,
  11463. Guid: Guid,
  11464. IFrameSplitOperator: IFrameSplitOperator,
  11465. ChartData: ChartData,
  11466. DataPlus: DataPlus,
  11467. KLineTooltipPaint: KLineTooltipPaint,
  11468. MARKET_SUFFIX_NAME: MARKET_SUFFIX_NAME,
  11469. JSCommonCoordinateData:JSCommonCoordinateData,
  11470. FrameSplitKLineX:FrameSplitKLineX,
  11471. FrameSplitKLinePriceY:FrameSplitKLinePriceY,
  11472. JSCHART_EVENT_ID:JSCHART_EVENT_ID,
  11473. JSCHART_DATA_FIELD_ID:JSCHART_DATA_FIELD_ID,
  11474. JSCHART_OPERATOR_ID:JSCHART_OPERATOR_ID,
  11475. };
  11476. export
  11477. {
  11478. JSCommon
  11479. };
  11480. /*
  11481. module.exports =
  11482. {
  11483. JSCommon:
  11484. {
  11485. JSCanvasElement: JSCanvasElement,
  11486. JSChart: JSChart,
  11487. Guid: Guid,
  11488. IFrameSplitOperator: IFrameSplitOperator,
  11489. ChartData: ChartData,
  11490. DataPlus: DataPlus,
  11491. KLineTooltipPaint: KLineTooltipPaint,
  11492. MARKET_SUFFIX_NAME: MARKET_SUFFIX_NAME,
  11493. JSCommonCoordinateData:JSCommonCoordinateData,
  11494. FrameSplitKLineX:FrameSplitKLineX,
  11495. FrameSplitKLinePriceY:FrameSplitKLinePriceY,
  11496. JSCHART_EVENT_ID:JSCHART_EVENT_ID
  11497. },
  11498. };
  11499. */