umychart.extendchart.wechat.js 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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. //行情数据结构体 及涉及到的行情算法(复权,周期等)
  11. import
  12. {
  13. JSCommon_ChartData as ChartData, JSCommon_HistoryData as HistoryData,
  14. JSCommon_SingleData as SingleData, JSCommon_MinuteData as MinuteData,
  15. JSCommon_Guid as Guid,
  16. JSCommon_ToFixedPoint as ToFixedPoint,
  17. JSCommon_ToFixedRect as ToFixedRect,
  18. } from "./umychart.data.wechat.js";
  19. import
  20. {
  21. JSCommonCoordinateData as JSCommonCoordinateData,
  22. JSCommonCoordinateData_MARKET_SUFFIX_NAME as MARKET_SUFFIX_NAME
  23. } from "./umychart.coordinatedata.wechat.js";
  24. import
  25. {
  26. JSCommonResource_Global_JSChartResource as g_JSChartResource,
  27. JSCommonResource_JSCHART_LANGUAGE_ID as JSCHART_LANGUAGE_ID,
  28. JSCommonResource_Global_JSChartLocalization as g_JSChartLocalization,
  29. } from './umychart.resource.wechat.js'
  30. import
  31. {
  32. JSCommonSplit_IFrameSplitOperator as IFrameSplitOperator,
  33. } from './umychart.framesplit.wechat.js'
  34. function IExtendChartPainting()
  35. {
  36. this.Canvas; //画布
  37. this.ChartBorder; //边框信息
  38. this.ChartFrame; //框架画法
  39. this.Name; //名称
  40. this.Data; // = new ChartData(); //数据区
  41. this.ClassName = 'IExtendChartPainting';
  42. this.IsDynamic = false;
  43. this.IsEraseBG = false; //是否每次画的时候需要擦除K线图背景
  44. this.IsAnimation=false;
  45. this.DrawAfterTitle = false; //是否在动态标题画完以后再画,防止动态标题覆盖
  46. //上下左右间距
  47. this.Left = 5;
  48. this.Right = 5;
  49. this.Top = 5;
  50. this.Bottom = 5;
  51. this.Draw = function () { } //画图接口
  52. this.SetOption = function (option) { } //设置参数接口
  53. }
  54. //K线Tooltip, 显示在左边或右边
  55. function KLineTooltipPaint()
  56. {
  57. this.newMethod = IExtendChartPainting; //派生
  58. this.newMethod();
  59. delete this.newMethod;
  60. this.IsDynamic = true;
  61. this.IsEraseBG = true;
  62. this.DrawAfterTitle = true;
  63. this.ClassName = 'KLineTooltipPaint';
  64. this.LatestPoint; //手势位置
  65. this.ShowPosition=0; //显示位置 0=左 1=右
  66. this.BorderColor = g_JSChartResource.TooltipPaint.BorderColor; //边框颜色
  67. this.BGColor = g_JSChartResource.TooltipPaint.BGColor; //背景色
  68. this.TitleColor = g_JSChartResource.TooltipPaint.TitleColor; //标题颜色
  69. this.Font = [g_JSChartResource.TooltipPaint.TitleFont];
  70. this.Width = 50;
  71. this.Height = 100;
  72. this.LineHeight = 15; //行高
  73. this.Left = 1;
  74. this.Top = 0;
  75. this.HQChart;
  76. this.KLineTitlePaint;
  77. this.IsHScreen = false; //是否横屏
  78. this.LanguageID = JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
  79. this.GetLeft = function ()
  80. {
  81. if (this.IsHScreen)
  82. {
  83. return this.ChartBorder.GetRightEx()-this.Height-this.Top;
  84. }
  85. else
  86. {
  87. if (this.ShowPosition==0)
  88. return this.ChartBorder.GetLeft()+this.Left;
  89. else
  90. return this.ChartBorder.GetRight()-this.Width-this.Left;
  91. }
  92. }
  93. this.GetTop = function ()
  94. {
  95. if (this.IsHScreen)
  96. {
  97. if (this.ShowPosition==0)
  98. return this.ChartBorder.GetTop()+this.Left;
  99. else
  100. return this.ChartBorder.GetBottom()-this.Width-this.Left;
  101. }
  102. else
  103. {
  104. return this.ChartBorder.GetTopEx()+this.Top;
  105. }
  106. }
  107. this.Draw = function ()
  108. {
  109. if (!this.HQChart || !this.HQChart.TitlePaint || !this.HQChart.TitlePaint[0]) return;
  110. if (!this.HQChart.IsOnTouch) return;
  111. this.KLineTitlePaint = this.HQChart.TitlePaint[0];
  112. var klineData = this.KLineTitlePaint.GetCurrentKLineData();
  113. if (!klineData) return;
  114. var upperSymbol;
  115. if (this.HQChart.Symbol) upperSymbol = this.HQChart.Symbol.toUpperCase();
  116. var isFutures=MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)?true:false;
  117. var lineCount = 8; //显示函数
  118. if (this.ClassName === 'MinuteTooltipPaint')
  119. {
  120. lineCount=7;
  121. if (isFutures && IFrameSplitOperator.IsNumber(klineData.Position)) ++lineCount; //期货多一个持仓量
  122. }
  123. else
  124. {
  125. if (IFrameSplitOperator.IsNumber(klineData.Time)) ++lineCount; //分钟K线多一列时间
  126. if (isFutures && IFrameSplitOperator.IsNumber(klineData.Position)) ++lineCount; //持仓量
  127. }
  128. this.IsHScreen = this.ChartFrame.IsHScreen === true;
  129. this.Canvas.font = this.Font[0];
  130. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.HQChart.Symbol);//价格小数位数
  131. var maxText = ' 擎: 9999.99亿 ';
  132. if (defaultfloatPrecision >= 5) maxText = ` 擎: ${99.99.toFixed(defaultfloatPrecision)} `; //小数位数太多了
  133. this.Width = this.Canvas.measureText(maxText).width;
  134. this.Height = this.LineHeight * lineCount + 2 * 2;
  135. if (klineData && klineData.High>0)
  136. {
  137. maxText=` 擎: ${klineData.High.toFixed(defaultfloatPrecision)} `;
  138. var textWidth=this.Canvas.measureText(maxText).width;
  139. if (textWidth>this.Width) this.Width=textWidth;
  140. }
  141. this.CalculateShowPosition();
  142. this.DrawBG();
  143. this.DrawTooltipData(klineData);
  144. this.DrawBorder();
  145. }
  146. //判断显示位置
  147. this.CalculateShowPosition=function()
  148. {
  149. this.ShowPosition=0;
  150. if (!this.LatestPoint) return;
  151. if(this.IsHScreen)
  152. {
  153. var top=this.ChartBorder.GetTop();
  154. var height=this.ChartBorder.GetHeight();
  155. var yCenter=top+height/2;
  156. if (this.LatestPoint.Y<yCenter) this.ShowPosition=1;
  157. }
  158. else
  159. {
  160. var left=this.ChartBorder.GetLeft();
  161. var width=this.ChartBorder.GetWidth();
  162. var xCenter=left+width/2;
  163. if (this.LatestPoint.X<xCenter) this.ShowPosition=1;
  164. }
  165. }
  166. this.DrawBorder = function ()
  167. {
  168. var isHScreen = (this.ChartFrame.IsHScreen === true);
  169. var left = this.GetLeft();
  170. var top = this.GetTop();
  171. this.Canvas.setStrokeStyle(this.BorderColor);
  172. if (isHScreen)
  173. {
  174. this.Canvas.strokeRect(this.HQChart.ToFixedPoint(left), this.HQChart.ToFixedPoint(top),
  175. this.HQChart.ToFixedRect(this.Height), this.HQChart.ToFixedRect(this.Width));
  176. }
  177. else
  178. {
  179. this.Canvas.strokeRect(this.HQChart.ToFixedPoint(left), this.HQChart.ToFixedPoint(top),
  180. this.HQChart.ToFixedRect(this.Width), this.HQChart.ToFixedRect(this.Height));
  181. }
  182. }
  183. this.DrawBG = function ()
  184. {
  185. var isHScreen = (this.ChartFrame.IsHScreen === true);
  186. var left = this.GetLeft();
  187. var top = this.GetTop();
  188. this.Canvas.setFillStyle(this.BGColor);
  189. if (isHScreen) this.Canvas.fillRect(left, top, this.Height, this.Width);
  190. else this.Canvas.fillRect(left, top, this.Width, this.Height);
  191. }
  192. this.DrawTooltipData = function (item)
  193. {
  194. //console.log('[KLineTooltipPaint::DrawKLineData] ', item);
  195. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.HQChart.Symbol);//价格小数位数
  196. var left = this.GetLeft() + 2;
  197. var top = this.GetTop() + 3;
  198. // #ifdef MP-TOUTIAO
  199. var top = this.GetTop() + 15;
  200. // #endif
  201. if (this.IsHScreen)
  202. {
  203. this.Canvas.save();
  204. var x = this.GetLeft() + this.Height, y = this.GetTop();
  205. this.Canvas.translate(x, y);
  206. this.Canvas.rotate(90 * Math.PI / 180);
  207. //x, y 作为原点
  208. left = 2;
  209. top = 3;
  210. }
  211. this.Canvas.textBaseline = "top";
  212. this.Canvas.textAlign = "left";
  213. this.Canvas.font = this.Font[0];
  214. var labelWidth = this.Canvas.measureText('擎: ').width;
  215. var text = this.HQChart.FormatDateString(item.Date);
  216. this.Canvas.setFillStyle(this.TitleColor);
  217. this.Canvas.fillText(text, left, top);
  218. var period = this.HQChart.Period;
  219. if (ChartData.IsMinutePeriod(period, true) && IFrameSplitOperator.IsNumber(item.Time))
  220. {
  221. top += this.LineHeight;
  222. text = this.HQChart.FormatTimeString(item.Time);
  223. this.Canvas.fillText(text, left, top);
  224. }
  225. else if (ChartData.IsSecondPeriod(period) && IFrameSplitOperator.IsNumber(item.Time))
  226. {
  227. top += this.LineHeight;
  228. text = this.HQChart.FormatTimeString(item.Time,"HH:MM:SS");
  229. this.Canvas.fillText(text, left, top);
  230. }
  231. top += this.LineHeight;
  232. this.Canvas.setFillStyle(this.TitleColor);
  233. text = g_JSChartLocalization.GetText('Tooltip-Open', this.LanguageID);
  234. this.Canvas.fillText(text, left, top);
  235. var color = this.KLineTitlePaint.GetColor(item.Open, item.YClose);
  236. text = item.Open.toFixed(defaultfloatPrecision);
  237. this.Canvas.setFillStyle(color);
  238. this.Canvas.fillText(text, left + labelWidth, top);
  239. top += this.LineHeight;
  240. this.Canvas.setFillStyle(this.TitleColor);
  241. text = g_JSChartLocalization.GetText('Tooltip-High', this.LanguageID);
  242. this.Canvas.fillText(text, left, top);
  243. var color = this.KLineTitlePaint.GetColor(item.High, item.YClose);
  244. var text = item.High.toFixed(defaultfloatPrecision);
  245. this.Canvas.setFillStyle(color);
  246. this.Canvas.fillText(text, left + labelWidth, top);
  247. top += this.LineHeight;
  248. this.Canvas.setFillStyle(this.TitleColor);
  249. text = g_JSChartLocalization.GetText('Tooltip-Low', this.LanguageID);
  250. this.Canvas.fillText(text, left, top);
  251. var color = this.KLineTitlePaint.GetColor(item.Low, item.YClose);
  252. var text = item.Low.toFixed(defaultfloatPrecision);
  253. this.Canvas.setFillStyle(color);
  254. this.Canvas.fillText(text, left + labelWidth, top);
  255. top += this.LineHeight;
  256. this.Canvas.setFillStyle(this.TitleColor);
  257. text = g_JSChartLocalization.GetText('Tooltip-Close', this.LanguageID);
  258. this.Canvas.fillText(text, left, top);
  259. var color = this.KLineTitlePaint.GetColor(item.Close, item.YClose);
  260. var text = item.Close.toFixed(defaultfloatPrecision);
  261. this.Canvas.setFillStyle(color);
  262. this.Canvas.fillText(text, left + labelWidth, top);
  263. top += this.LineHeight;
  264. this.Canvas.setFillStyle(this.TitleColor);
  265. text = g_JSChartLocalization.GetText('Tooltip-Increase', this.LanguageID);
  266. this.Canvas.fillText(text, left, top);
  267. if (item.YClose>0)
  268. {
  269. var value = (item.Close - item.YClose) / item.YClose * 100;
  270. var color = this.KLineTitlePaint.GetColor(value, 0);
  271. var text = value.toFixed(2) + '%';
  272. }
  273. else
  274. {
  275. var text='--.--';
  276. var color = this.KLineTitlePaint.GetColor(0, 0);
  277. }
  278. this.Canvas.setFillStyle(color);
  279. this.Canvas.fillText(text, left + labelWidth, top);
  280. this.Canvas.setFillStyle(this.TitleColor);
  281. if (IFrameSplitOperator.IsNumber(item.Vol))
  282. {
  283. top += this.LineHeight;
  284. text = g_JSChartLocalization.GetText('Tooltip-Vol', this.LanguageID);
  285. this.Canvas.fillText(text, left, top);
  286. var text = this.HQChart.FormatValueString(item.Vol, 2, this.LanguageID);
  287. this.Canvas.fillText(text, left + labelWidth, top);
  288. }
  289. if (IFrameSplitOperator.IsNumber(item.Amount))
  290. {
  291. top += this.LineHeight;
  292. text = g_JSChartLocalization.GetText('Tooltip-Amount',this.LanguageID);
  293. this.Canvas.fillText(text, left, top);
  294. var text = this.HQChart.FormatValueString(item.Amount, 2, this.LanguageID);
  295. this.Canvas.fillText(text, left + labelWidth, top);
  296. }
  297. //持仓量
  298. var upperSymbol;
  299. if (this.HQChart.Symbol) upperSymbol = this.HQChart.Symbol.toUpperCase();
  300. if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
  301. {
  302. this.Canvas.setFillStyle(this.TitleColor);
  303. top += this.LineHeight;
  304. text = g_JSChartLocalization.GetText('Tooltip-Position', this.LanguageID);
  305. this.Canvas.fillText(text, left, top);
  306. var text = IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
  307. this.Canvas.fillText(text, left + labelWidth, top);
  308. }
  309. if (this.IsHScreen) this.Canvas.restore();
  310. }
  311. //设置参数接口
  312. this.SetOption = function (option)
  313. {
  314. if (option.LineHeight > 0) this.LineHeight = option.LineHeight;
  315. if (option.BGColor) this.BGColor = option.BGColor;
  316. if (option.LanguageID > 0) this.LanguageID = option.LanguageID;
  317. }
  318. }
  319. function MinuteTooltipPaint()
  320. {
  321. this.newMethod = KLineTooltipPaint; //派生
  322. this.newMethod();
  323. delete this.newMethod;
  324. this.ClassName = 'MinuteTooltipPaint';
  325. this.IsShowAveragePrice=true;
  326. this.GetTop=function()
  327. {
  328. if (this.IsHScreen)
  329. {
  330. if (this.ShowPosition==0)
  331. return this.ChartBorder.GetTop()+this.Left;
  332. else
  333. return this.ChartBorder.GetBottom()-this.Width-this.Left;
  334. }
  335. else
  336. {
  337. return this.ChartBorder.GetTop()+this.Top;
  338. }
  339. }
  340. this.GetLeft=function()
  341. {
  342. if (this.IsHScreen)
  343. {
  344. return this.ChartBorder.GetRight()-this.Height-this.Top;
  345. }
  346. else
  347. {
  348. if (this.ShowPosition==0)
  349. return this.ChartBorder.GetLeft()+this.Left;
  350. else
  351. return this.ChartBorder.GetRight()-this.Width-this.Left;
  352. }
  353. }
  354. this.DrawTooltipData = function (item)
  355. {
  356. //console.log('[KLineTooltipPaint::DrawKLineData] ', item);
  357. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.HQChart.Symbol);//价格小数位数
  358. var left = this.GetLeft() + 2;
  359. var top = this.GetTop() + 3;
  360. this.YClose = this.KLineTitlePaint.YClose;
  361. if (this.IsHScreen)
  362. {
  363. this.Canvas.save();
  364. var x = this.GetLeft() + this.Height, y = this.GetTop();
  365. this.Canvas.translate(x, y);
  366. this.Canvas.rotate(90 * Math.PI / 180);
  367. //x, y 作为原点
  368. left = 2;
  369. top = 3;
  370. }
  371. this.Canvas.textBaseline = "top";
  372. this.Canvas.textAlign = "left";
  373. this.Canvas.font = this.Font[0];
  374. var labelWidth = this.Canvas.measureText('擎: ').width;
  375. var aryDateTime = item.DateTime.split(' ');
  376. if (aryDateTime && aryDateTime.length == 2)
  377. {
  378. var text = this.HQChart.FormatDateString(aryDateTime[0]);
  379. this.Canvas.setFillStyle(this.TitleColor);
  380. this.Canvas.fillText(text, left, top);
  381. top += this.LineHeight;
  382. text = this.HQChart.FormatTimeString(aryDateTime[1]);
  383. this.Canvas.fillText(text, left, top);
  384. }
  385. top += this.LineHeight;
  386. this.Canvas.setFillStyle(this.TitleColor);
  387. text = g_JSChartLocalization.GetText('Tooltip-Price', this.LanguageID);
  388. this.Canvas.fillText(text, left, top);
  389. var color = this.KLineTitlePaint.GetColor(item.Close, this.YClose);
  390. text = item.Close.toFixed(defaultfloatPrecision);
  391. this.Canvas.setFillStyle(color);
  392. this.Canvas.fillText(text, left + labelWidth, top);
  393. if (IFrameSplitOperator.IsNumber(item.AvPrice) && this.IsShowAveragePrice==true)
  394. {
  395. top += this.LineHeight;
  396. this.Canvas.setFillStyle(this.TitleColor);
  397. text = g_JSChartLocalization.GetText('Tooltip-AvPrice', this.LanguageID);
  398. this.Canvas.fillText(text, left, top);
  399. var color = this.KLineTitlePaint.GetColor(item.AvPrice, this.YClose);
  400. var text = item.AvPrice.toFixed(defaultfloatPrecision);
  401. this.Canvas.setFillStyle(color);
  402. this.Canvas.fillText(text, left + labelWidth, top);
  403. }
  404. top += this.LineHeight;
  405. this.Canvas.setFillStyle(this.TitleColor);
  406. text = g_JSChartLocalization.GetText('Tooltip-Increase', this.LanguageID);
  407. this.Canvas.fillText(text, left, top);
  408. var value = (item.Close - this.YClose) / this.YClose * 100;
  409. var color = this.KLineTitlePaint.GetColor(value, 0);
  410. var text = value.toFixed(2) + '%';
  411. this.Canvas.setFillStyle(color);
  412. this.Canvas.fillText(text, left + labelWidth, top);
  413. if (IFrameSplitOperator.IsNumber(item.Vol))
  414. {
  415. this.Canvas.setFillStyle(this.TitleColor);
  416. top += this.LineHeight;
  417. text = g_JSChartLocalization.GetText('Tooltip-Vol', this.LanguageID);
  418. this.Canvas.fillText(text, left, top);
  419. var text = this.HQChart.FormatValueString(item.Vol, 2, this.LanguageID);
  420. this.Canvas.fillText(text, left + labelWidth, top);
  421. }
  422. if (IFrameSplitOperator.IsNumber(item.Amount))
  423. {
  424. top += this.LineHeight;
  425. text = g_JSChartLocalization.GetText('Tooltip-Amount', this.LanguageID);
  426. this.Canvas.fillText(text, left, top);
  427. var text = this.HQChart.FormatValueString(item.Amount, 2, this.LanguageID);
  428. this.Canvas.fillText(text, left + labelWidth, top);
  429. }
  430. //持仓量
  431. var upperSymbol;
  432. if (this.HQChart.Symbol) upperSymbol = this.HQChart.Symbol.toUpperCase();
  433. if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
  434. {
  435. this.Canvas.setFillStyle(this.TitleColor);
  436. top += this.LineHeight;
  437. text = g_JSChartLocalization.GetText('Tooltip-Position', this.LanguageID);
  438. this.Canvas.fillText(text, left, top);
  439. var text = IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
  440. this.Canvas.fillText(text, left + labelWidth, top);
  441. }
  442. if (this.IsHScreen) this.Canvas.restore();
  443. }
  444. }
  445. //////////////////////////////////////////////////////////////////////////////
  446. // 弹幕
  447. //弹幕数据 { X:X偏移, Y:Y偏移, Text:内容, Color:颜色 }
  448. function BarrageList()
  449. {
  450. this.PlayList = []; //正在播放队列
  451. this.Cache = []; //没有播放的弹幕数据
  452. this.MinLineHeight = 40;
  453. this.Height; //高度
  454. this.Step = 1;
  455. //{Canves:画布, Right:右边坐标, Left:左边坐标, Font:默认字体 }
  456. this.GetPlayList = function (obj)
  457. {
  458. var canves = obj.Canves;
  459. var right = obj.Right;
  460. var left = obj.Left;
  461. var width = right - left;
  462. var isMoveStep = obj.IsMoveStep;
  463. var list = [];
  464. var yOffset = 0;
  465. for (var i = 0; i < this.PlayList.length; ++i)
  466. {
  467. var ary = this.PlayList[i];
  468. var lineHeight = this.MinLineHeight;
  469. if (ary.Height > this.MinLineHeight) lineHeight = ary.Height;
  470. var bAddNewItem = true; //是否需要加入新弹幕
  471. var bRemoveFirst = false; //是否删除第1个数据
  472. for (var j = 0; j < ary.Data.length; ++j)
  473. {
  474. var item = ary.Data[j];
  475. var playItem = { X: item.X, Y: yOffset, Text: item.Text, Color: item.Color, Height: lineHeight, Font: item.Font, Info: item.Info };
  476. list.push(playItem);
  477. if (!isMoveStep) continue;
  478. if (j == ary.Data.length - 1 && this.Cache.length > 0) //最后一个数据了 判断是否需要增加弹幕
  479. {
  480. bAddNewItem = false;
  481. if (!item.TextWidth)
  482. {
  483. if (item.Font && item.Font.Name) canves.font = item.Font.Name;
  484. else canves.font = obj.Font;
  485. item.TextWidth = canves.measureText(playItem.Text + '擎擎').width;
  486. }
  487. if (item.X >= item.TextWidth)
  488. bAddNewItem = true;
  489. }
  490. else if (j == 0)
  491. {
  492. bRemoveFirst = false;
  493. if (!item.TextWidth)
  494. {
  495. if (item.Font && item.Font.Name) canves.font = item.Font.Name;
  496. else canves.font = obj.Font;
  497. item.TextWidth = canves.measureText(playItem.Text + '擎擎').width;
  498. }
  499. if (item.X > width + item.TextWidth) bRemoveFirst = true;
  500. }
  501. item.X += this.Step;
  502. }
  503. if (isMoveStep && bAddNewItem && this.Cache.length > 0) //最后一个数据了 判断是否需要增加弹幕
  504. {
  505. var cacheItem = this.Cache.shift();
  506. var newItem = { X: 0, Text: cacheItem.Text, Color: cacheItem.Color, Font: cacheItem.Font, Info: cacheItem.Info };
  507. ary.Data.push(newItem);
  508. }
  509. if (isMoveStep && bRemoveFirst && ary.Data.length > 0)
  510. {
  511. var removeItem = ary.Data.shift();
  512. this.OnItemPlayEnd(obj.HQChart, removeItem);
  513. }
  514. yOffset += lineHeight;
  515. }
  516. return list;
  517. }
  518. //根据高度计算播放队列个数
  519. this.CacluatePlayLine = function (height)
  520. {
  521. this.Height = height;
  522. var lineCount = parseInt(height / this.MinLineHeight);
  523. if (this.PlayList.length < lineCount)
  524. {
  525. var addCount = lineCount - this.PlayList.length;
  526. for (var i = 0; i < addCount; ++i)
  527. {
  528. this.PlayList.push({ Data: [] });
  529. }
  530. }
  531. else if (this.PlayList.length > lineCount)
  532. {
  533. var removeCount = this.PlayList.length - lineCount;
  534. for (var i = 0; i < removeCount; ++i)
  535. {
  536. var ary = this.PlayList.pop();
  537. for (var j = 0; j < ary.Data.length; ++j)
  538. {
  539. var item = ary.Data[j];
  540. var cacheItem = { Text: item.Text, Color: item.Color, Font: item.Font, Info: item.Info };
  541. this.Cache.unshift(cacheItem);
  542. }
  543. }
  544. }
  545. JSConsole.Chart.Log(`[BarrageList::CacluatePlayLine] LineCount=${this.PlayList.length} Height=${this.Height}`)
  546. }
  547. //添加弹幕
  548. this.AddBarrage = function (barrageData)
  549. {
  550. for (var i in barrageData) {
  551. var item = barrageData[i];
  552. this.Cache.push(item);
  553. }
  554. }
  555. this.OnItemPlayEnd = function (hqChart, item) //单挑弹幕播放完毕
  556. {
  557. //监听事件
  558. var event = hqChart.GetBarrageEvent();
  559. if (!event || !event.Callback) return;
  560. event.Callback(event, item, this);
  561. }
  562. this.Count = function () { return this.Cache.length; } //未播放的弹幕个数
  563. }
  564. //背景图 支持横屏
  565. function BackgroundPaint()
  566. {
  567. this.newMethod = IExtendChartPainting; //派生
  568. this.newMethod();
  569. delete this.newMethod;
  570. this.ClassName = 'BackgroundPaint';
  571. this.IsDynamic = false;
  572. this.IsCallbackDraw = true; //在回调函数里绘制, 不在Draw()中绘制
  573. this.FrameID = 0;
  574. this.Data; //背景数据 { Start:, End:, Color:[] }
  575. this.ID = Guid(); //唯一的ID
  576. /*
  577. this.Data=
  578. [
  579. { Start:{ Date:20181201 }, End:{ Date:20181230 }, Color:'rgb(44,55,44)' } ,
  580. { Start:{ Date:20190308 }, End:{ Date:20190404 }, Color:['rgb(44,55,255)','rgb(200,55,255)'] }
  581. ]
  582. */
  583. this.ChartSubFrame;
  584. this.ChartBorder;
  585. this.KData;
  586. this.Period;
  587. this.XPointCount = 0;
  588. this.SetOption = function (option) //设置
  589. {
  590. if (option.FrameID > 0) this.FrameID = option.FrameID;
  591. if (IFrameSplitOperator.IsObjectExist(option.ID)) this.ID = option.ID;
  592. }
  593. this.Draw = function ()
  594. {
  595. if (!this.Data || !this.HQChart) return;
  596. if (!this.ChartFrame || !this.ChartFrame.SubFrame || this.ChartFrame.SubFrame.length <= this.FrameID) return;
  597. var klineChart = this.HQChart.ChartPaint[0];
  598. if (!klineChart || !klineChart.Data) return;
  599. this.ChartSubFrame = this.ChartFrame.SubFrame[this.FrameID].Frame;
  600. this.ChartBorder = this.ChartSubFrame.ChartBorder;
  601. this.KData = klineChart.Data;
  602. this.Period = this.HQChart.Period;
  603. if (!this.KData || this.KData.Data.length <= 0) return;
  604. var isHScreen = (this.ChartSubFrame.IsHScreen === true);
  605. this.XPointCount = this.ChartSubFrame.XPointCount;
  606. var xPointCount = this.ChartSubFrame.XPointCount;
  607. var firstKItem = this.KData.Data[this.KData.DataOffset];
  608. var endIndex = this.KData.DataOffset + xPointCount - 1;
  609. if (endIndex >= this.KData.Data.length) endIndex = this.KData.Data.length - 1;
  610. var endKItem = this.KData.Data[endIndex];
  611. var showData = this.GetShowData(firstKItem, endKItem);
  612. if (!showData || showData.length <= 0) return;
  613. var kLineMap = this.BuildKLineMap();
  614. var bottom = this.ChartBorder.GetBottomEx();
  615. var top = this.ChartBorder.GetTopEx();
  616. var height = this.ChartBorder.GetHeightEx();
  617. if (isHScreen)
  618. {
  619. top = this.ChartBorder.GetRightEx();
  620. bottom = this.ChartBorder.GetLeftEx();
  621. height = this.ChartBorder.GetWidthEx();
  622. }
  623. for (var i in showData)
  624. {
  625. var item = showData[i];
  626. var rt = this.GetBGCoordinate(item, kLineMap);
  627. if (!rt) continue;
  628. if (Array.isArray(item.Color))
  629. {
  630. var gradient;
  631. if (isHScreen) gradient = this.Canvas.createLinearGradient(bottom, rt.Left, top, rt.Left);
  632. else gradient = this.Canvas.createLinearGradient(rt.Left, top, rt.Left, bottom);
  633. var offset = 1 / item.Color.length;
  634. for (var i in item.Color)
  635. {
  636. gradient.addColorStop(i * offset, item.Color[i]);
  637. }
  638. this.Canvas.setFillStyle(gradient);
  639. }
  640. else
  641. {
  642. this.Canvas.setFillStyle(item.Color);
  643. }
  644. if (isHScreen) this.Canvas.fillRect(ToFixedRect(bottom), ToFixedRect(rt.Left), ToFixedRect(height), ToFixedRect(rt.Width));
  645. else this.Canvas.fillRect(ToFixedRect(rt.Left), ToFixedRect(top), ToFixedRect(rt.Width), ToFixedRect(height));
  646. }
  647. }
  648. this.GetShowData = function (first, end)
  649. {
  650. var aryData = [];
  651. for (var i in this.Data) {
  652. var item = this.Data[i];
  653. var showItem = {};
  654. if (item.Start.Date >= first.Date && item.Start.Date <= end.Date) showItem.Start = item.Start;
  655. if (item.End.Date >= first.Date && item.End.Date <= end.Date) showItem.End = item.End;
  656. if (showItem.Start || showItem.End)
  657. {
  658. showItem.Color = item.Color;
  659. aryData.push(showItem);
  660. }
  661. }
  662. return aryData;
  663. }
  664. this.BuildKLineMap = function ()
  665. {
  666. var isHScreen = (this.ChartSubFrame.IsHScreen === true);
  667. var dataWidth = this.ChartSubFrame.DataWidth;
  668. var distanceWidth = this.ChartSubFrame.DistanceWidth;
  669. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
  670. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
  671. var chartright = this.ChartBorder.GetRight();
  672. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  673. var mapKLine = { Data: new Map() }; //Key: date / date time, Value:索引
  674. for (var i = this.KData.DataOffset, j = 0; i < this.KData.Data.length && j < this.XPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  675. {
  676. var kItem = this.KData.Data[i];
  677. var left = xOffset;
  678. var right = xOffset + dataWidth;
  679. if (right > chartright) break;
  680. var x = left + (right - left) / 2;
  681. if (j == 0) mapKLine.XLeft = left;
  682. mapKLine.XRight = right;
  683. var value = { Index: i, ShowIndex: j, X: x, Right: right, Left: left, Date: kItem.Date };
  684. if (ChartData.IsMinutePeriod(this.Period, true))
  685. {
  686. var key = `Date:${kItem.Date} Time:${kItem.Time}`;
  687. value.Time = kItem.Time;
  688. }
  689. else
  690. {
  691. var key = `Date:${kItem.Date}`;
  692. }
  693. mapKLine.Data.set(key, value);
  694. }
  695. return mapKLine;
  696. }
  697. this.GetBGCoordinate = function (item, kLineMap)
  698. {
  699. var xLeft = null, xRight = null;
  700. if (item.Start)
  701. {
  702. if (ChartData.IsMinutePeriod(this.Period, true))
  703. var key = `Date:${item.Start.Date} Time:${item.Start.Time}`;
  704. else
  705. var key = `Date:${item.Start.Date}`;
  706. if (kLineMap.Data.has(key))
  707. {
  708. var findItem = kLineMap.Data.get(key);
  709. xLeft = findItem.Left;
  710. }
  711. else
  712. {
  713. for (var kItem of kLineMap.Data)
  714. {
  715. var value = kItem[1];
  716. if (value.Date > item.Start.Date)
  717. {
  718. xLeft = value.Left;
  719. break;
  720. }
  721. }
  722. }
  723. }
  724. else
  725. {
  726. xLeft = kLineMap.XLeft;
  727. }
  728. if (item.End)
  729. {
  730. if (ChartData.IsMinutePeriod(this.Period, true))
  731. var key = `Date:${item.End.Date} Time:${item.End.Time}`;
  732. else
  733. var key = `Date:${item.End.Date}`;
  734. if (kLineMap.Data.has(key))
  735. {
  736. var findItem = kLineMap.Data.get(key);
  737. xRight = findItem.Right;
  738. }
  739. else
  740. {
  741. var previousX = null;
  742. for (var kItem of kLineMap.Data)
  743. {
  744. var value = kItem[1];
  745. if (value.Date > item.End.Date)
  746. {
  747. xRight = previousX;
  748. break;
  749. }
  750. previousX = value.Right;
  751. }
  752. }
  753. }
  754. else
  755. {
  756. xRight = kLineMap.XRight;
  757. }
  758. if (xLeft == null || xRight == null) return null;
  759. return { Left: xLeft, Right: xRight, Width: xRight - xLeft };
  760. }
  761. }
  762. //弹幕
  763. function BarragePaint()
  764. {
  765. this.newMethod = IExtendChartPainting; //派生
  766. this.newMethod();
  767. delete this.newMethod;
  768. this.ClassName = 'BarragePaint';
  769. this.IsAnimation = true;
  770. this.IsEraseBG = true;
  771. this.HQChart;
  772. this.Font = g_JSChartResource.Barrage.Font;
  773. this.TextColor = g_JSChartResource.Barrage.Color;
  774. this.FontHeight = g_JSChartResource.Barrage.Height;
  775. this.BarrageList = new BarrageList(); //字幕列表
  776. this.IsMoveStep = false;
  777. this.SetOption = function (option) //设置参数接口
  778. {
  779. if (option)
  780. {
  781. if (option.Step > 0) this.BarrageList.Step = option.Step;
  782. if (option.MinLineHeight) this.Barrage.MinLineHeight = option.MinLineHeight;
  783. }
  784. }
  785. this.DrawHScreen = function ()
  786. {
  787. var height = this.ChartBorder.GetWidth();
  788. var left = this.ChartBorder.GetTop();
  789. var right = this.ChartBorder.GetBottom();
  790. var top = this.ChartBorder.GetRightEx();
  791. var wdith = this.ChartBorder.GetChartWidth();
  792. if (height != this.BarrageList.Height)
  793. this.BarrageList.CacluatePlayLine(height);
  794. this.Canvas.textBaseline = "middle";
  795. this.Canvas.textAlign = "left";
  796. var play = this.BarrageList.GetPlayList({ Canves: this.Canvas, Right: right, Left: left, Font: this.Font, IsMoveStep: this.IsMoveStep, HQChart: this.HQChart });
  797. this.IsMoveStep = false;
  798. if (!play) return;
  799. this.Canvas.save();
  800. this.Canvas.translate(this.ChartBorder.GetChartHeight(), 0);
  801. this.Canvas.rotate(90 * Math.PI / 180);
  802. for (var i = 0; i < play.length; ++i)
  803. {
  804. var item = play[i];
  805. if (item.Color) this.Canvas.setFillStyle(item.Color);
  806. else this.Canvas.setFillStyle(this.TextColor);
  807. if (item.Font) this.Canvas.font = item.Font.Name;
  808. else this.Canvas.font = this.Font;
  809. var fontHeight = this.FontHeight;
  810. if (item.Font && item.Font.Height > 0) fontHeight = item.Font.Height;
  811. var yOffset = item.Y + parseInt((item.Height - fontHeight) / 2);
  812. this.Canvas.fillText(item.Text, right - item.X, top + yOffset);
  813. }
  814. this.Canvas.restore();
  815. }
  816. this.Draw = function ()
  817. {
  818. if (this.ChartFrame.IsHScreen)
  819. {
  820. this.DrawHScreen();
  821. return;
  822. }
  823. var left = this.ChartBorder.GetLeft();
  824. var right = this.ChartBorder.GetRight();
  825. var top = this.ChartBorder.GetTopEx();
  826. var height = this.ChartBorder.GetHeight();
  827. if (height != this.BarrageList.Height)
  828. this.BarrageList.CacluatePlayLine(height);
  829. this.Canvas.textBaseline = "middle";
  830. this.Canvas.textAlign = "left";
  831. var play = this.BarrageList.GetPlayList({ Canves: this.Canvas, Right: right, Left: left, Font: this.Font, IsMoveStep: this.IsMoveStep, HQChart: this.HQChart });
  832. this.IsMoveStep = false;
  833. if (!play) return;
  834. for (var i = 0; i < play.length; ++i)
  835. {
  836. var item = play[i];
  837. if (item.Color) this.Canvas.setFillStyle(item.Color);
  838. else this.Canvas.setFillStyle(this.TextColor);
  839. if (item.Font) this.Canvas.font = item.Font.Name;
  840. else this.Canvas.font = this.Font;
  841. var fontHeight = this.FontHeight;
  842. if (item.Font && item.Font.Height > 0) fontHeight = item.Font.Height;
  843. var yOffset = item.Y + parseInt((item.Height - fontHeight) / 2);
  844. this.Canvas.fillText(item.Text, right - item.X, top + yOffset);
  845. }
  846. }
  847. }
  848. //导出统一使用JSCommon命名空间名
  849. module.exports =
  850. {
  851. JSCommonExtendChartPaint:
  852. {
  853. IExtendChartPainting: IExtendChartPainting,
  854. KLineTooltipPaint: KLineTooltipPaint,
  855. BarragePaint: BarragePaint,
  856. MinuteTooltipPaint: MinuteTooltipPaint,
  857. BackgroundPaint: BackgroundPaint,
  858. },
  859. //单个类导出
  860. JSCommonExtendChartPaint_IExtendChartPainting: IExtendChartPainting,
  861. JSCommonExtendChartPaint_KLineTooltipPaint: KLineTooltipPaint,
  862. JSCommonExtendChartPaint_BarragePaint: BarragePaint,
  863. JSCommonExtendChartPaint_MinuteTooltipPaint: MinuteTooltipPaint,
  864. JSCommonExtendChartPaint_BackgroundPaint: BackgroundPaint,
  865. };