umychart.charttitle.wechat.js 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  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. import
  9. {
  10. g_JSChartResource,
  11. JSCHART_LANGUAGE_ID,
  12. g_JSChartLocalization,
  13. } from './umychart.resource.wechat.js'
  14. import
  15. {
  16. ChartData, HistoryData,
  17. SingleData, MinuteData,
  18. CUSTOM_DAY_PERIOD_START,
  19. CUSTOM_DAY_PERIOD_END,
  20. CUSTOM_MINUTE_PERIOD_START,
  21. CUSTOM_MINUTE_PERIOD_END,
  22. CUSTOM_SECOND_PERIOD_START,
  23. CUSTOM_SECOND_PERIOD_END,
  24. JSCHART_EVENT_ID,
  25. CloneData
  26. } from "./umychart.data.wechat.js";
  27. import
  28. {
  29. JSCommonCoordinateData
  30. } from "./umychart.coordinatedata.wechat.js";
  31. import
  32. {
  33. KLINE_INFO_TYPE,
  34. } from "./umychart.klineinfo.wechat.js";
  35. import
  36. {
  37. IFrameSplitOperator,
  38. } from './umychart.framesplit.wechat.js'
  39. var MARKET_SUFFIX_NAME = JSCommonCoordinateData.MARKET_SUFFIX_NAME;
  40. function ToFixedPoint(value)
  41. {
  42. //return value;
  43. return parseInt(value) + 0.5;
  44. }
  45. function ToFixedRect(value)
  46. {
  47. var rounded;
  48. return rounded = (0.5 + value) << 0;
  49. }
  50. //标题画法基类
  51. function IChartTitlePainting()
  52. {
  53. this.Frame;
  54. this.Data = new Array();
  55. this.Canvas; //画布
  56. this.IsDynamic = false; //是否是动态标题
  57. this.Position = 0; //标题显示位置 0 框架里的标题 1 框架上面
  58. this.CursorIndex; //数据索引
  59. this.Font = g_JSChartResource.DynamicTitleFont;//"12px 微软雅黑";
  60. this.Title; //固定标题(可以为空)
  61. this.TitleColor = g_JSChartResource.DefaultTextColor;
  62. this.LanguageID = JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID;
  63. this.UpdateUICallback; //通知外面更新标题(老接口废弃)
  64. this.OnDrawEvent; //外部事件通知
  65. this.GetEventCallback; //事件回调,新的版本同意都用这个
  66. }
  67. var PERIOD_NAME = ["日线", "周线", "月线", "年线", "1分", "5分", "15分", "30分", "60分", "季线", "分笔", "2小时", "4小时", "", ""];
  68. var RIGHT_NAME = ['不复权', '前复权', '后复权'];
  69. //K线标题
  70. function DynamicKLineTitlePainting()
  71. {
  72. this.newMethod = IChartTitlePainting; //派生
  73. this.newMethod();
  74. delete this.newMethod;
  75. this.ClassName ='DynamicKLineTitlePainting';
  76. this.IsDynamic = true;
  77. this.IsShow = true; //是否显示
  78. this.LineCount = 1; //默认显示1行
  79. this.ColumnCount=4; //列, 多行才使用
  80. this.SpaceWidth = 1; //空格宽度
  81. this.TextSpace=-1; //文字之间的间距
  82. this.DateTimeSpace=2; //日期时间向后间距
  83. this.PeriodSpace=1; //周期向后间距
  84. this.NameSpace=1; //名字向后间距
  85. this.Period; //周期
  86. this.UpColor = g_JSChartResource.UpTextColor;
  87. this.DownColor = g_JSChartResource.DownTextColor;
  88. this.UnchagneColor = g_JSChartResource.UnchagneTextColor;
  89. this.VolColor=g_JSChartResource.Title.VolColor;
  90. this.AmountColor=g_JSChartResource.Title.AmountColor;
  91. this.DateTimeColor=g_JSChartResource.Title.DateTimeColor;
  92. this.NameColor = g_JSChartResource.Title.NameColor;
  93. this.SettingColor=g_JSChartResource.Title.SettingColor; //周期 复权
  94. this.PositionColor=g_JSChartResource.Title.PositionColor; //持仓
  95. this.ShowPositionConfig={ Margin:{ Bottom:2 } }; //显示位置高级配置 { Type:1 左对齐, Margin:{ Left, Right, Bottom } }
  96. this.Symbol;
  97. this.UpperSymbol;
  98. this.Name;
  99. this.InfoData;
  100. this.InfoTextHeight = 15;
  101. this.InfoTextColor = g_JSChartResource.KLine.Info.TextColor;
  102. this.InfoTextBGColor = g_JSChartResource.KLine.Info.TextBGColor;
  103. this.IsShowName = true; //是否显示股票名称
  104. this.IsShowSettingInfo = true; //是否显示设置信息(周期 复权)
  105. this.IsShowDateTime=true;
  106. this.HQChart;
  107. this.GetVolUnit=function()
  108. {
  109. var upperSymbol;
  110. if (this.Symbol) upperSymbol=this.Symbol.toUpperCase();
  111. var unit=MARKET_SUFFIX_NAME.GetVolUnit(upperSymbol);
  112. return unit;
  113. }
  114. this.GetCurrentKLineData = function () //获取当天鼠标位置所在的K线数据
  115. {
  116. if (this.CursorIndex == null || !this.Data) return null;
  117. if (this.Data.length <= 0) return null;
  118. var index = this.CursorIndex;
  119. index = parseInt(index.toFixed(0));
  120. var dataIndex = this.Data.DataOffset + index;
  121. if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
  122. if (dataIndex < 0) return null;
  123. var item = this.Data.Data[dataIndex];
  124. return item;
  125. }
  126. this.GetDataIndex=function()
  127. {
  128. if (this.CursorIndex == null || !this.Data) return null;
  129. if (this.Data.length <= 0) return null;
  130. var index = this.CursorIndex;
  131. index = parseInt(index.toFixed(0));
  132. var dataIndex = this.Data.DataOffset + index;
  133. if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
  134. if (dataIndex < 0) return null;
  135. return dataIndex;
  136. }
  137. this.SendUpdateUIMessage = function (funcName) //通知外面 标题变了
  138. {
  139. if (!this.UpdateUICallback) return;
  140. var sendData = {
  141. TitleName: 'K线标题', CallFunction: funcName, Stock: { Name: this.Name, Symbol: this.Symbol, },
  142. Rect:
  143. {
  144. Left: this.Frame.ChartBorder.GetLeft(), Right: this.Frame.ChartBorder.GetRight(),
  145. Top: 0, Bottom: this.Frame.ChartBorder.GetTop(),
  146. }
  147. };
  148. //有数据
  149. if (this.Data && this.Data.Data && this.Data.Data.length > 0) {
  150. let index = this.Data.Data.length - 1; //默认最后一天的数据
  151. if (this.CursorIndex) {
  152. let cursorIndex = Math.abs(this.CursorIndex - 0.5);
  153. cursorIndex = parseInt(cursorIndex.toFixed(0));
  154. index = this.Data.DataOffset + cursorIndex;
  155. if (index >= this.Data.Data.length) index = this.Data.Data.length - 1;
  156. }
  157. if (index >= 0) {
  158. let item = this.Data.Data[index];
  159. sendData.Stock.Data =
  160. {
  161. Date: item.Date,
  162. YClose: item.YClose, Open: item.Open, High: item.High, Low: item.Low, Close: item.Close,
  163. Vol: item.Vol, Amount: item.Amount
  164. }
  165. if (item.Time) sendData.Stock.Time = item.Time; //分钟K线才有时间
  166. }
  167. if (this.Data.Period != null) sendData.Stock.PeriodName = this.GetPeriodName(this.Data.Period); //周期名字
  168. if (this.Data.Right != null) sendData.Stock.RightName = RIGHT_NAME[this.Data.Right]; //复权名字
  169. }
  170. //console.log('[DynamicKLineTitlePainting::SendUpdateUIMessage', sendData);
  171. this.UpdateUICallback(sendData);
  172. }
  173. this.GetPeriodName = function (period)
  174. {
  175. var name = '';
  176. if (period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END)
  177. name = (period - CUSTOM_MINUTE_PERIOD_START) + g_JSChartLocalization.GetText('自定义分钟', this.LanguageID);
  178. else if (period > CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END)
  179. name = (period - CUSTOM_DAY_PERIOD_START) + g_JSChartLocalization.GetText('自定义日线',this.LanguageID);
  180. else if (period > CUSTOM_SECOND_PERIOD_START && period <= CUSTOM_SECOND_PERIOD_END)
  181. name = (period - CUSTOM_SECOND_PERIOD_START) + g_JSChartLocalization.GetText('自定义秒', this.LanguageID);
  182. else
  183. name = g_JSChartLocalization.GetText(ChartData.GetPeriodName(period), this.LanguageID);
  184. return name;
  185. }
  186. this.GetRightName = function (rightID, periodID)
  187. {
  188. if (!MARKET_SUFFIX_NAME.IsEnableRight(periodID, this.Symbol, this.HQChart.RightFormula)) return null;
  189. var rightName = RIGHT_NAME[rightID];
  190. return rightName
  191. }
  192. this.FullDraw=function()
  193. {
  194. if (!this.IsShow) return;
  195. this.UpperSymbol=this.Symbol ? this.Symbol.toUpperCase():'';
  196. if (this.CursorIndex == null || !this.Data || this.Data.length <= 0)
  197. {
  198. this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::FullDraw');
  199. return;
  200. }
  201. if (this.TextSpace>=0)
  202. {
  203. this.SpaceWidth=this.TextSpace;
  204. }
  205. else
  206. {
  207. this.Canvas.font = this.Font;
  208. this.SpaceWidth = this.Canvas.measureText(' ').width;
  209. }
  210. var index = this.CursorIndex;
  211. index = parseInt(index.toFixed(0));
  212. var dataIndex = this.Data.DataOffset + index;
  213. if (dataIndex >= this.Data.Data.length) dataIndex=-1;
  214. if (dataIndex < 0)
  215. {
  216. this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::FullDraw');
  217. return;
  218. }
  219. var item = this.Data.Data[dataIndex];
  220. this.OnDrawEventCallback(item, 'DynamicKLineTitlePainting::FullDraw');
  221. //console.log('[FullDraw]', item);
  222. if (this.Frame.IsHScreen === true)
  223. {
  224. this.Canvas.save();
  225. if (this.LineCount > 1) this.DrawMulitLine(item);
  226. else this.DrawSingleLine(item,true);
  227. this.Canvas.restore();
  228. if (!item.Time && item.Date && this.InfoData) this.HSCreenKLineInfoDraw(item.Date);
  229. }
  230. else
  231. {
  232. if (this.LineCount > 1) this.DrawMulitLine(item);
  233. else this.DrawSingleLine(item, true);
  234. if (!item.Time && item.Date && this.InfoData) this.KLineInfoDraw(item.Date);
  235. }
  236. }
  237. this.DrawTitle = function ()
  238. {
  239. this.UpperSymbol=this.Symbol ? this.Symbol.toUpperCase():'';
  240. this.SendUpdateUIMessage('DrawTitle');
  241. this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::DrawTitle');
  242. if (!this.IsShow) return;
  243. if (!this.IsShowName && !this.IsShowSettingInfo) return;
  244. if (this.LineCount > 1) return;
  245. if (this.Frame.IsHScreen === true)
  246. {
  247. this.Canvas.save();
  248. this.HScreenDrawTitle();
  249. this.Canvas.restore();
  250. return;
  251. }
  252. var left = this.Frame.ChartBorder.GetLeft();
  253. var bottom = this.Frame.ChartBorder.GetTop();
  254. var right = this.Frame.ChartBorder.GetRight();
  255. if (bottom < 5) return;
  256. this.Canvas.textAlign = "left";
  257. this.Canvas.textBaseline = "bottom";
  258. this.Canvas.font = this.Font;
  259. var position = { Left: left, Bottom: bottom, IsHScreen: false };
  260. if (this.IsShowName && this.Name)
  261. {
  262. if (!this.DrawKLineText(this.Name, this.NameColor, position)) return;
  263. }
  264. if (this.IsShowSettingInfo && this.Data.Period != null && this.Data.Right != null)
  265. {
  266. var periodName = this.GetPeriodName(this.Data.Period);
  267. var rightName = this.GetRightName(this.Data.Right,this.Data.Period);
  268. var text = "(" + periodName + ")";
  269. if (rightName) text = "(" + periodName + " " + rightName + ")";
  270. if (!this.DrawKLineText(text, this.SettingColor, position)) return;
  271. }
  272. }
  273. this.HScreenDrawTitle = function ()
  274. {
  275. var xText = this.Frame.ChartBorder.GetRight();
  276. var yText = this.Frame.ChartBorder.GetTop();
  277. var right = this.Frame.ChartBorder.GetHeight();
  278. if (this.Frame.ChartBorder.Right < 10) return;
  279. this.Canvas.translate(xText, yText);
  280. this.Canvas.rotate(90 * Math.PI / 180);
  281. this.Canvas.textAlign = "left";
  282. this.Canvas.textBaseline = "bottom";
  283. this.Canvas.font = this.Font;
  284. var left = 2;
  285. var bottom = -2;
  286. var position = { Left: left, Bottom: bottom, IsHScreen: false };
  287. if (this.IsShowName && this.Name)
  288. {
  289. if (!this.DrawKLineText(this.Name, this.NameColor, position)) return;
  290. }
  291. if (this.IsShowSettingInfo && this.Data.Period != null && this.Data.Right != null)
  292. {
  293. var periodName = this.GetPeriodName(this.Data.Period);
  294. var rightName = this.GetRightName(this.Data.Right,this.Data.Period);
  295. var text = "(" + periodName + ")";
  296. if (rightName) text = "(" + periodName + " " + rightName + ")";
  297. if (!this.DrawKLineText(text, this.SettingColor, position)) return;
  298. }
  299. }
  300. this.DrawMulitLine = function (item) //画多行
  301. {
  302. var isHScreen = this.Frame.IsHScreen === true;
  303. var left=this.GetLeft(isHScreen);
  304. var right=this.GetRight(isHScreen);
  305. var width = right-left;
  306. var top=this.GetTop(isHScreen);
  307. var bottom=this.GetBottom(isHScreen);
  308. var height = bottom-top;
  309. var itemHeight = height / this.LineCount;
  310. var itemWidth = width / this.ColumnCount;
  311. if (isHScreen)
  312. {
  313. var yText=left, xText=top+itemHeight;
  314. this.Canvas.translate(xText, yText);
  315. this.Canvas.rotate(90 * Math.PI / 180);
  316. xText=0,yText=0;
  317. }
  318. else
  319. {
  320. var yText=itemHeight, xText=left;
  321. }
  322. this.Canvas.textAlign = "left";
  323. this.Canvas.textBaseline = "bottom";
  324. this.Canvas.font = this.Font;
  325. var titleData=this.GetFormatMulitLineTitle({ Data:item });
  326. if (titleData && IFrameSplitOperator.IsNonEmptyArray(titleData.AryText))
  327. {
  328. var cellCount= this.LineCount *this.ColumnCount;
  329. for(var i=0;i<titleData.AryText.length && i<cellCount;++i)
  330. {
  331. var item=titleData.AryText[i];
  332. if (i%this.ColumnCount==0 && i>0) //换行
  333. {
  334. if (isHScreen)
  335. {
  336. xText=0;
  337. yText -= itemHeight;
  338. }
  339. else
  340. {
  341. yText += itemHeight;
  342. xText=left;
  343. }
  344. }
  345. if (item.Text)
  346. {
  347. this.Canvas.fillStyle = item.Color;
  348. this.Canvas.fillText(item.Text, xText, yText, itemWidth);
  349. }
  350. xText += itemWidth;
  351. }
  352. }
  353. }
  354. this.FormatPrice=function(price, yClose, defaultfloatPrecision, TitleID)
  355. {
  356. var item={ Text:'--', Color:this.UnchagneColor };
  357. if (!IFrameSplitOperator.IsNumber(price)) return item;
  358. item.Color = this.GetColor(price, yClose);
  359. item.Text = `${g_JSChartLocalization.GetText(TitleID, this.LanguageID)}${price.toFixed(defaultfloatPrecision)}`;
  360. return item;
  361. }
  362. this.FormatVol=function(vol, TitleID)
  363. {
  364. var item={ Text:'--', Color:this.VolColor };
  365. if (!IFrameSplitOperator.IsNumber(vol)) return item;
  366. item.Text = `${g_JSChartLocalization.GetText(TitleID, this.LanguageID)}${IFrameSplitOperator.FormatValueString(vol, 2, this.LanguageID)}`;
  367. return item;
  368. }
  369. this.FormatAmount=function(value, TitleID)
  370. {
  371. var item={ Text:'--', Color:this.AmountColor };
  372. if (!IFrameSplitOperator.IsNumber(value)) return item;
  373. item.Text = `${g_JSChartLocalization.GetText(TitleID, this.LanguageID)}${IFrameSplitOperator.FormatValueString(value, 2, this.LanguageID)}`;
  374. return item;
  375. }
  376. this.FormatIncrease=function(price, yClose, TitleID)
  377. {
  378. var item={ Text:'--', Color:this.UnchagneColor };
  379. if (!IFrameSplitOperator.IsNumber(price) || !IFrameSplitOperator.IsNumber(yClose) || yClose===0) return item;
  380. var value=(price-yClose)/yClose;
  381. item.Color=this.GetColor(value,0);
  382. item.Text=`${g_JSChartLocalization.GetText(TitleID, this.LanguageID)}${(value*100).toFixed(2)}%`;
  383. return item;
  384. }
  385. this.ForamtTime=function(time, TitleID)
  386. {
  387. var item={ Text:null, Color:this.DateTimeColor };
  388. if (!IFrameSplitOperator.IsNumber(time)) return item;
  389. if (ChartData.IsMinutePeriod(this.Period, true))
  390. item.Text = IFrameSplitOperator.FormatTimeString(time,"HH:MM");
  391. else if (ChartData.IsSecondPeriod(this.Period) )
  392. item.Text = IFrameSplitOperator.FormatTimeString(time, "HH:MM:SS");
  393. return item;
  394. }
  395. this.GetFormatMulitLineTitle=function(data)
  396. {
  397. if (!data || !data.Data) return null;
  398. var unit=this.GetVolUnit();
  399. var aryText=[];
  400. var item=data.Data;
  401. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);//价格小数位数
  402. aryText.push({Text:IFrameSplitOperator.FormatDateString(item.Date), Color:this.DateTimeColor }); //日期
  403. aryText.push(this.FormatPrice(item.Close, item.YClose,defaultfloatPrecision, 'KTitle-Close')); //收
  404. //aryText.push(this.FormatPrice(item.Open, item.YClose,defaultfloatPrecision, 'KTitle-Open')); //开
  405. aryText.push(this.FormatPrice(item.High, item.YClose,defaultfloatPrecision, 'KTitle-High')); //高
  406. aryText.push(this.FormatPrice(item.Low, item.YClose,defaultfloatPrecision, 'KTitle-Low')); //低
  407. aryText.push(this.ForamtTime(item.Time)); //时间 分钟K线才有
  408. aryText.push(this.FormatIncrease(item.Close, item.YClose, "KTitle-Increase")); //涨幅
  409. aryText.push(this.FormatVol(item.Vol/unit, "KTitle-Vol")); //量
  410. aryText.push(this.FormatAmount(item.Amount,"KTitle-Amount")); //额
  411. /*
  412. if (MARKET_SUFFIX_NAME.IsChinaFutures(this.UpperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
  413. {
  414. var text = g_JSChartLocalization.GetText('KTitle-Position', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
  415. aryText.push({Text:text, Color:this.PositionColor});
  416. }
  417. */
  418. return { AryText:aryText };
  419. }
  420. this.GetFormatTitle=function(data)
  421. {
  422. if (!data || !data.Data) return null;
  423. var unit=this.GetVolUnit();
  424. var aryText=[];
  425. var item=data.Data;
  426. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);//价格小数位数
  427. if (this.IsShowName) //名称
  428. aryText.push({Text:this.Name, Color:this.NameColor, LeftSpace:this.NameSpace});
  429. if (this.IsShowSettingInfo) //周期 复权信息
  430. {
  431. var periodName = this.GetPeriodName(this.Data.Period);
  432. var rightName = this.GetRightName(this.Data.Right,this.Data.Period);
  433. var text = "(" + periodName + ")";
  434. if (rightName) text = "(" + periodName + " " + rightName + ")";
  435. aryText.push({Text:text, Color:this.SettingColor, LeftSpace:this.PeriodSpace});
  436. }
  437. if (this.IsShowDateTime) //日期 时间
  438. {
  439. var text = IFrameSplitOperator.FormatDateString(item.Date); //日期
  440. if (ChartData.IsDayPeriod(this.Period, true))
  441. {
  442. aryText.push({Text:text, Color:this.DateTimeColor, LeftSpace:this.DateTimeSpace});
  443. }
  444. else if (ChartData.IsMinutePeriod(this.Period, true))
  445. {
  446. if (IFrameSplitOperator.IsNumber(item.Time))
  447. {
  448. var timeText = IFrameSplitOperator.FormatTimeString(item.Time,"HH:MM");
  449. text=`${text} ${timeText}`;
  450. }
  451. aryText.push({Text:text, Color:this.DateTimeColor, LeftSpace:this.DateTimeSpace});
  452. }
  453. else if (ChartData.IsSecondPeriod(this.Period) )
  454. {
  455. if (IFrameSplitOperator.IsNumber(item.Time))
  456. {
  457. var timeText = IFrameSplitOperator.FormatTimeString(item.Time, "HH:MM:SS");
  458. text=`${text} ${timeText}`;
  459. }
  460. aryText.push({Text:text, Color:this.DateTimeColor, LeftSpace:this.DateTimeSpace});
  461. }
  462. }
  463. //开
  464. if (IFrameSplitOperator.IsNumber(item.Open))
  465. {
  466. var color = this.GetColor(item.Open, item.YClose);
  467. var text = g_JSChartLocalization.GetText('KTitle-Open', this.LanguageID) + item.Open.toFixed(defaultfloatPrecision);
  468. aryText.push({Text:text, Color:color});
  469. }
  470. //高
  471. if (IFrameSplitOperator.IsNumber(item.High))
  472. {
  473. var color = this.GetColor(item.High, item.YClose);
  474. var text = g_JSChartLocalization.GetText('KTitle-High', this.LanguageID) + item.High.toFixed(defaultfloatPrecision);
  475. aryText.push({Text:text, Color:color});
  476. }
  477. //低
  478. if (IFrameSplitOperator.IsNumber(item.Low))
  479. {
  480. var color = this.GetColor(item.Low, item.YClose);
  481. var text = g_JSChartLocalization.GetText('KTitle-Low', this.LanguageID) + item.Low.toFixed(defaultfloatPrecision);
  482. aryText.push({Text:text, Color:color});
  483. }
  484. //收
  485. if (IFrameSplitOperator.IsNumber(item.Close))
  486. {
  487. var color = this.GetColor(item.Close, item.YClose);
  488. var text = g_JSChartLocalization.GetText('KTitle-Close', this.LanguageID) + item.Close.toFixed(defaultfloatPrecision);
  489. aryText.push({Text:text, Color:color});
  490. }
  491. if (IFrameSplitOperator.IsNumber(item.Vol))
  492. {
  493. var text = g_JSChartLocalization.GetText('KTitle-Vol', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Vol/unit, 2, this.LanguageID);
  494. aryText.push({Text:text, Color:this.VolColor});
  495. }
  496. if (IFrameSplitOperator.IsNumber(item.Amount))
  497. {
  498. var text = g_JSChartLocalization.GetText('KTitle-Amount', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Amount, 2, this.LanguageID);
  499. aryText.push({Text:text, Color:this.AmountColor});
  500. }
  501. if (MARKET_SUFFIX_NAME.IsChinaFutures(this.UpperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
  502. {
  503. var text = g_JSChartLocalization.GetText('KTitle-Position', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
  504. aryText.push({Text:text, Color:this.PositionColor});
  505. }
  506. return { AryText:aryText };
  507. }
  508. this.GetLeft=function(isHScreen)
  509. {
  510. if (isHScreen)
  511. {
  512. var left=this.Frame.ChartBorder.GetTop();
  513. if (this.ShowPositionConfig)
  514. {
  515. var item=this.ShowPositionConfig;
  516. if (item.Type===1) left=0;
  517. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Left)) left+=item.Margin.Left;
  518. }
  519. return left;
  520. }
  521. else
  522. {
  523. var left=this.Frame.ChartBorder.GetLeft();
  524. if (this.ShowPositionConfig)
  525. {
  526. var item=this.ShowPositionConfig;
  527. if (item.Type===1) left=0;
  528. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Left)) left+=item.Margin.Left;
  529. }
  530. return left;
  531. }
  532. }
  533. this.GetRight=function(isHScreen)
  534. {
  535. if (isHScreen)
  536. {
  537. var right = this.Frame.ChartBorder.GetHeight();
  538. if (this.ShowPositionConfig)
  539. {
  540. var item=this.ShowPositionConfig;
  541. if (item.Type===1) right=this.Frame.ChartBorder.GetChartHeight();
  542. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Right)) right-=item.Margin.Right;
  543. }
  544. return right;
  545. }
  546. else
  547. {
  548. var right = this.Frame.ChartBorder.GetRight();
  549. if (this.ShowPositionConfig)
  550. {
  551. var item=this.ShowPositionConfig;
  552. if (item.Type===1) right=this.Frame.ChartBorder.GetChartWidth();
  553. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Right)) right-=item.Margin.Right;
  554. }
  555. return right;
  556. }
  557. }
  558. this.GetBottom=function(isHScreen)
  559. {
  560. if (isHScreen)
  561. {
  562. var bottom=this.Frame.ChartBorder.GetRight();
  563. if (this.ShowPositionConfig)
  564. {
  565. var item=this.ShowPositionConfig;
  566. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Bottom)) bottom+=item.Margin.Bottom;
  567. }
  568. return bottom;
  569. }
  570. else
  571. {
  572. var bottom = this.Frame.ChartBorder.GetTop();
  573. if (this.ShowPositionConfig)
  574. {
  575. var item=this.ShowPositionConfig;
  576. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Bottom)) bottom-=item.Margin.Bottom;
  577. }
  578. return bottom;
  579. }
  580. }
  581. this.GetTop=function(isHScreen)
  582. {
  583. if (isHScreen)
  584. {
  585. var top=this.Frame.ChartBorder.GetChartWidth();
  586. if (this.ShowPositionConfig)
  587. {
  588. var item=this.ShowPositionConfig;
  589. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Top)) top-=item.Margin.Top;
  590. }
  591. return top;
  592. }
  593. else
  594. {
  595. var top = 0;
  596. if (this.ShowPositionConfig)
  597. {
  598. var item=this.ShowPositionConfig;
  599. if (item.Margin && IFrameSplitOperator.IsNumber(item.Margin.Top)) top+=item.Margin.Top;
  600. }
  601. return top;
  602. }
  603. }
  604. this.DrawSingleLine = function (item,bDrawTitle) //画单行
  605. {
  606. var isHScreen = this.Frame.IsHScreen === true;
  607. var left=this.GetLeft(isHScreen);
  608. var right=this.GetRight(isHScreen);
  609. var bottom =this.GetBottom(isHScreen);
  610. if (isHScreen)
  611. {
  612. if (this.Frame.ChartBorder.Right < 5) return;
  613. var xText = bottom;
  614. var yText = left;
  615. this.Canvas.translate(xText, yText);
  616. this.Canvas.rotate(90 * Math.PI / 180);
  617. left = bottom=0;
  618. }
  619. else
  620. {
  621. if (this.Frame.ChartBorder.Top<5) return;
  622. }
  623. this.Canvas.textAlign = "left";
  624. this.Canvas.textBaseline = "bottom";
  625. this.Canvas.font = this.Font;
  626. var position = { Left: left, MaxRight:right, Bottom: bottom, IsHScreen: isHScreen };
  627. var titleData=this.GetFormatTitle({ Data:item });
  628. if (titleData && IFrameSplitOperator.IsNonEmptyArray(titleData.AryText))
  629. {
  630. for(var i=0;i<titleData.AryText.length;++i)
  631. {
  632. var item=titleData.AryText[i];
  633. if (!this.DrawText(item.Text, item.Color, position, bDrawTitle==true)) break;
  634. if (IFrameSplitOperator.IsNumber(item.LeftSpace)) position.Left+=item.LeftSpace;
  635. }
  636. }
  637. }
  638. this.OnDrawEventCallback = function (drawData, explain)
  639. {
  640. if (!this.OnDrawEvent || !this.OnDrawEvent.Callback) return;
  641. var data = { Draw: drawData, Name: this.ClassName, Explain: explain };
  642. if (this.Data && this.Data.Data)
  643. {
  644. if (IFrameSplitOperator.IsNumber(this.CursorIndex))
  645. {
  646. var index = this.CursorIndex;
  647. index = parseInt(index.toFixed(0));
  648. var dataIndex = this.Data.DataOffset + index;
  649. }
  650. else
  651. {
  652. dataIndex=this.Data.Data.length-1;
  653. }
  654. var dataCount=this.Data.Data.length;
  655. data.DataIndex=dataIndex;
  656. data.DataCount=dataCount;
  657. }
  658. this.OnDrawEvent.Callback(this.OnDrawEvent, data, this);
  659. }
  660. this.Draw = function ()
  661. {
  662. this.UpperSymbol = this.Symbol ? this.Symbol.toUpperCase() : '';
  663. this.SendUpdateUIMessage('Draw');
  664. if (!this.IsShow) return;
  665. if (this.CursorIndex == null || !this.Data || this.Data.length <= 0)
  666. {
  667. this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::Draw');
  668. return;
  669. }
  670. this.SpaceWidth = this.Canvas.measureText(' ').width;
  671. var index = this.CursorIndex;
  672. index = parseInt(index.toFixed(0));
  673. var dataIndex = this.Data.DataOffset + index;
  674. if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
  675. if (dataIndex < 0)
  676. {
  677. this.OnDrawEventCallback(null, 'DynamicKLineTitlePainting::Draw');
  678. return;
  679. }
  680. var item = this.Data.Data[dataIndex];
  681. this.OnDrawEventCallback(item, 'DynamicKLineTitlePainting::Draw');
  682. if (this.Frame.IsHScreen === true)
  683. {
  684. this.Canvas.save();
  685. if (this.LineCount > 1) this.DrawMulitLine(item);
  686. else this.DrawSingleLine(item);
  687. this.Canvas.restore();
  688. if (!item.Time && item.Date && this.InfoData) this.HSCreenKLineInfoDraw(item.Date);
  689. }
  690. else
  691. {
  692. if (this.LineCount > 1) this.DrawMulitLine(item);
  693. else this.DrawSingleLine(item);
  694. if (!item.Time && item.Date && this.InfoData) this.KLineInfoDraw(item.Date);
  695. }
  696. }
  697. this.KLineInfoDraw = function (date) {
  698. var info = this.InfoData.get(date.toString());
  699. if (!info) return;
  700. var invesotrCount = 0; //互动易统计
  701. var researchCouunt = 0;
  702. var reportCount = 0;
  703. var blockTradeCount = 0; //大宗交易次数
  704. var tradeDetailCount = 0; //龙虎榜上榜次数
  705. var policyData = null;
  706. var reportTitle = null, pforecastTitle = null;
  707. //console.log(info);
  708. for (var i in info.Data) {
  709. var item = info.Data[i];
  710. switch (item.InfoType) {
  711. case KLINE_INFO_TYPE.INVESTOR:
  712. ++invesotrCount;
  713. break;
  714. case KLINE_INFO_TYPE.PFORECAST:
  715. pforecastTitle = item.Title;
  716. break;
  717. case KLINE_INFO_TYPE.ANNOUNCEMENT:
  718. ++reportCount;
  719. break;
  720. case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_1:
  721. case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_2:
  722. case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_3:
  723. case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_4:
  724. reportTitle = item.Title;
  725. break;
  726. case KLINE_INFO_TYPE.RESEARCH:
  727. ++researchCouunt;
  728. break;
  729. case KLINE_INFO_TYPE.BLOCKTRADING:
  730. ++blockTradeCount;
  731. break;
  732. case KLINE_INFO_TYPE.TRADEDETAIL:
  733. ++tradeDetailCount;
  734. break;
  735. case KLINE_INFO_TYPE.POLICY:
  736. policyData = item;
  737. break;
  738. }
  739. }
  740. var isHScreen = (this.Frame.IsHScreen === true);
  741. var right = this.Frame.ChartBorder.GetRight() - 4;
  742. var top = this.Frame.ChartBorder.GetTopEx();
  743. if (isHScreen) {
  744. right = this.Frame.ChartBorder.GetBottom() - 4;
  745. top = this.Frame.ChartBorder.GetRightEx();
  746. this.Canvas.translate(top, right);
  747. this.Canvas.rotate(90 * Math.PI / 180);
  748. right = 0; top = 0;
  749. }
  750. this.Canvas.font = this.Font;
  751. var aryTitle = [];
  752. var position = { Top: top, Right: right, IsHScreen: isHScreen };
  753. aryTitle.push(IFrameSplitOperator.FormatDateString(date));
  754. if (reportTitle) aryTitle.push(reportTitle); //季报
  755. if (pforecastTitle) aryTitle.push(pforecastTitle); //业绩预告
  756. if (reportCount > 0) aryTitle.push('公告数量:' + reportCount);
  757. if (researchCouunt > 0) aryTitle.push('机构调研次数:' + researchCouunt);
  758. if (tradeDetailCount > 0) aryTitle.push('龙虎榜上榜次数:' + tradeDetailCount);
  759. if (invesotrCount > 0) aryTitle.push('互动易数量:' + invesotrCount);
  760. if (blockTradeCount > 0) aryTitle.push('大宗交易次数:' + blockTradeCount);
  761. if (policyData) //策略选股
  762. {
  763. for (let i in policyData.ExtendData) //显示满足的策略
  764. {
  765. aryTitle.push(policyData.ExtendData[i].Name);
  766. }
  767. }
  768. var maxWidth = 0, textBGHeight = 0;
  769. for (let i in aryTitle) {
  770. var item = aryTitle[i];
  771. var textWidth = this.Canvas.measureText(item).width + 2; //后空2个像素
  772. if (maxWidth < textWidth) maxWidth = textWidth;
  773. textBGHeight += this.InfoTextHeight;
  774. }
  775. this.Canvas.fillStyle = this.InfoTextBGColor;
  776. if (isHScreen) this.Canvas.fillRect(position.Right - maxWidth, position.Top, maxWidth + 2, textBGHeight + 2);
  777. else this.Canvas.fillRect(position.Right - maxWidth, position.Top, maxWidth + 2, textBGHeight + 2);
  778. for (let i in aryTitle) {
  779. var item = aryTitle[i];
  780. this.DrawInfoText(item, position);
  781. }
  782. }
  783. this.HSCreenKLineInfoDraw = function (date) {
  784. this.Canvas.save();
  785. this.KLineInfoDraw(date);
  786. this.Canvas.restore();
  787. }
  788. this.GetColor = function (price, yclse) {
  789. if (price > yclse) return this.UpColor;
  790. else if (price < yclse) return this.DownColor;
  791. else return this.UnchagneColor;
  792. }
  793. this.DrawInfoText = function (title, position) {
  794. if (!title) return true;
  795. this.Canvas.textAlign = "right";
  796. this.Canvas.textBaseline = "top";
  797. this.Canvas.fillStyle = this.InfoTextColor;
  798. this.Canvas.fillText(title, position.Right, position.Top);
  799. position.Top += this.InfoTextHeight;
  800. return true;
  801. }
  802. this.DrawKLineText = function (title, color, position, isShow)
  803. {
  804. if (!title) return true;
  805. var isHScreen = this.Frame.IsHScreen === true;
  806. var right = this.Frame.ChartBorder.GetRight();
  807. if (isHScreen) right = this.Frame.ChartBorder.GetHeight();
  808. this.Canvas.fillStyle = color;
  809. var textWidth = this.Canvas.measureText(title).width;
  810. if (position.Left + textWidth > right) return false;
  811. if (!(isShow === false)) this.Canvas.fillText(title, position.Left, position.Bottom, textWidth);
  812. position.Left += textWidth + this.SpaceWidth;
  813. return true;
  814. }
  815. this.DrawText=function(title,color, position, isShow)
  816. {
  817. if (!title) return true;
  818. var isHScreen = this.Frame.IsHScreen === true;
  819. var right = this.Frame.ChartBorder.GetRight();
  820. if (isHScreen) right = this.Frame.ChartBorder.GetHeight();
  821. if (IFrameSplitOperator.IsNumber(position.MaxRight)) right=position.MaxRight;
  822. this.Canvas.fillStyle = color;
  823. var textWidth = this.Canvas.measureText(title).width;
  824. if (position.Left + textWidth > right) return false;
  825. if (!(isShow === false)) this.Canvas.fillText(title, position.Left, position.Bottom, textWidth);
  826. position.Left += textWidth + this.SpaceWidth;
  827. return true;
  828. }
  829. }
  830. //分时图标题
  831. function DynamicMinuteTitlePainting()
  832. {
  833. this.newMethod = DynamicKLineTitlePainting; //派生
  834. this.newMethod();
  835. delete this.newMethod;
  836. this.YClose;
  837. this.IsShowDate = false; //标题是否显示日期
  838. this.IsShowName = true; //标题是否显示股票名字
  839. this.Symbol;
  840. this.UpperSymbol;
  841. this.LastShowData; //保存最后显示的数据 给tooltip用
  842. this.ClassName ='DynamicMinuteTitlePainting';
  843. this.SpaceWidth = 2;
  844. this.IsShowAveragePrice=true; //是否显示均线价格
  845. this.GetCurrentKLineData = function () //获取当天鼠标位置所在的K线数据
  846. {
  847. if (this.LastShowData) return this.LastShowData;
  848. if (this.CursorIndex == null || !this.Data) return null;
  849. if (this.Data.length <= 0) return null;
  850. var index = Math.abs(this.CursorIndex);
  851. index = parseInt(index.toFixed(0));
  852. var dataIndex = this.Data.DataOffset + index;
  853. if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
  854. if (dataIndex < 0) return null;
  855. var item = this.Data.Data[dataIndex];
  856. return item;
  857. }
  858. this.SendUpdateUIMessage = function (funcName) //通知外面 标题变了
  859. {
  860. if (!this.UpdateUICallback) return;
  861. var sendData =
  862. {
  863. TitleName: '分钟标题', CallFunction: funcName, Stock: { Name: this.Name, Symbol: this.Symbol, },
  864. Rect:
  865. {
  866. Left: this.Frame.ChartBorder.GetLeft(), Right: this.Frame.ChartBorder.GetRight(),
  867. Top: 0, Bottom: this.Frame.ChartBorder.GetTop(),
  868. }
  869. };
  870. //有数据
  871. if (this.Data && this.Data.Data && this.Data.Data.length > 0) {
  872. let index = this.Data.Data.length - 1; //默认最后1分钟的数据
  873. if (this.CursorIndex) {
  874. let cursorIndex = Math.abs(this.CursorIndex - 0.5);
  875. cursorIndex = parseInt(cursorIndex.toFixed(0));
  876. index = this.Data.DataOffset + cursorIndex;
  877. if (index >= this.Data.Data.length) index = this.Data.Data.length - 1;
  878. }
  879. if (index >= 0) {
  880. let item = this.Data.Data[index];
  881. this.LastShowData = item;
  882. sendData.Stock.Data =
  883. {
  884. Time: item.Time, Close: item.Close, AvPrice: item.AvPrice,
  885. Vol: item.Vol, Amount: item.Amount
  886. }
  887. if (item.Time) sendData.Stock.Time = item.Time; //分钟K线才有时间
  888. }
  889. }
  890. this.UpdateUICallback(sendData);
  891. }
  892. this.DrawTitle = function ()
  893. {
  894. this.UpperSymbol = this.Symbol ? this.Symbol.toUpperCase() : '';
  895. this.SendUpdateUIMessage('DrawTitle');
  896. this.OnDrawEventCallback(null, "DynamicMinuteTitlePainting::DrawTitle");
  897. }
  898. this.GetDecimal = function (symbol)
  899. {
  900. return JSCommonCoordinateData.GetfloatPrecision(symbol);//价格小数位数
  901. }
  902. this.GetFormatMulitLineTitle=function(data)
  903. {
  904. if (!data || !data.Data) return null;
  905. var unit=this.GetVolUnit();
  906. var aryText=[];
  907. var item=data.Data;
  908. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);//价格小数位数
  909. aryText.push({Text:IFrameSplitOperator.FormatDateString(item.Date), Color:this.DateTimeColor }); //日期
  910. aryText.push(this.FormatPrice(item.Close, item.YClose,defaultfloatPrecision, 'KTitle-Close')); //收
  911. aryText.push(this.FormatPrice(item.High, item.YClose,defaultfloatPrecision, 'KTitle-High')); //高
  912. aryText.push(this.FormatPrice(item.Low, item.YClose,defaultfloatPrecision, 'KTitle-Low')); //低
  913. aryText.push({Text:IFrameSplitOperator.FormatDateTimeString(item.DateTime, 'HH-MM'), Color:this.DateTimeColor }); //时间
  914. aryText.push(this.FormatIncrease(item.Close, item.YClose, "KTitle-Increase")); //涨幅
  915. aryText.push(this.FormatVol(item.Vol/unit, "KTitle-Vol")); //量
  916. aryText.push(this.FormatAmount(item.Amount,"KTitle-Amount")); //额
  917. return { AryText:aryText };
  918. }
  919. this.GetFormatTitle=function(data)
  920. {
  921. if (!data || !data.Data) return null;
  922. var item=data.Data;
  923. var defaultfloatPrecision = this.GetDecimal(this.Symbol); //价格小数位数
  924. var upperSymbol=this.Symbol.toUpperCase();
  925. var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //期货
  926. var unit=this.GetVolUnit();
  927. var aryText=[];
  928. var yClose=item.YClose;
  929. if (isFutures && IFrameSplitOperator.IsNumber(item.YClearing)) yClose=item.YClearing;
  930. if (this.IsShowName) aryText.push({ Text:this.Name, Color:this.NameColor });
  931. var text = IFrameSplitOperator.FormatDateTimeString(item.DateTime, this.IsShowDate ? 'YYYY-MM-DD HH-MM' : 'HH-MM');
  932. aryText.push({ Text:text, Color:this.DateTimeColor });
  933. if (IFrameSplitOperator.IsNumber(item.Close))
  934. {
  935. var color = this.GetColor(item.Close, yClose);
  936. var text = g_JSChartLocalization.GetText('MTitle-Close', this.LanguageID) + item.Close.toFixed(defaultfloatPrecision);
  937. aryText.push({ Text:text, Color:color });
  938. }
  939. if (IFrameSplitOperator.IsNumber(item.Increase))
  940. {
  941. var color = this.GetColor(item.Increase, 0);
  942. var text = g_JSChartLocalization.GetText('MTitle-Increase', this.LanguageID) + item.Increase.toFixed(2) + '%';
  943. aryText.push({ Text:text, Color:color });
  944. }
  945. if (IFrameSplitOperator.IsNumber(item.AvPrice) && this.IsShowAveragePrice==true)
  946. {
  947. var color = this.GetColor(item.AvPrice, yClose);
  948. var text = g_JSChartLocalization.GetText('MTitle-AvPrice', this.LanguageID) + item.AvPrice.toFixed(defaultfloatPrecision);
  949. aryText.push({ Text:text, Color:color });
  950. }
  951. if (IFrameSplitOperator.IsNumber(item.Vol))
  952. {
  953. var text = g_JSChartLocalization.GetText('MTitle-Vol', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Vol/unit, 2, this.LanguageID);
  954. aryText.push({ Text:text, Color:this.VolColor });
  955. }
  956. if (IFrameSplitOperator.IsNumber(item.Amount))
  957. {
  958. var text = g_JSChartLocalization.GetText('MTitle-Amount', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Amount, 2, this.LanguageID);
  959. aryText.push({ Text:text, Color:this.AmountColor });
  960. }
  961. if (MARKET_SUFFIX_NAME.IsChinaFutures(this.UpperSymbol) && IFrameSplitOperator.IsNumber(item.Position))
  962. {
  963. var text = g_JSChartLocalization.GetText('MTitle-Position', this.LanguageID) + IFrameSplitOperator.FormatValueString(item.Position, 2, this.LanguageID);
  964. aryText.push({ Text:text, Color:this.VolColor });
  965. }
  966. return { AryText:aryText };
  967. }
  968. this.DrawItem = function (item)
  969. {
  970. var isHScreen = this.Frame.IsHScreen === true;
  971. var left=this.GetLeft(isHScreen);
  972. var right=this.GetRight(isHScreen);
  973. var bottom =this.GetBottom(isHScreen);
  974. if (isHScreen)
  975. {
  976. if (this.Frame.ChartBorder.Right < 5) return;
  977. var xText = bottom;
  978. var yText = left;
  979. this.Canvas.translate(xText, yText);
  980. this.Canvas.rotate(90 * Math.PI / 180);
  981. left=bottom=0;
  982. }
  983. else
  984. {
  985. if (this.Frame.ChartBorder.Top<5) return;
  986. }
  987. this.Canvas.textAlign = "left";
  988. this.Canvas.textBaseline = "bottom";
  989. this.Canvas.font = this.Font;
  990. var position = { Left: left, MaxRight:right, Bottom: bottom, IsHScreen: isHScreen };
  991. var titleData=this.GetFormatTitle({ Data:item });
  992. if (titleData && IFrameSplitOperator.IsNonEmptyArray(titleData.AryText))
  993. {
  994. for(var i=0;i<titleData.AryText.length;++i)
  995. {
  996. var item=titleData.AryText[i];
  997. if (!this.DrawText(item.Text, item.Color, position, true)) break;
  998. if (IFrameSplitOperator.IsNumber(item.LeftSpace)) position.Left+=item.LeftSpace;
  999. }
  1000. }
  1001. }
  1002. this.FullDraw=function()
  1003. {
  1004. this.Draw();
  1005. }
  1006. this.Draw = function ()
  1007. {
  1008. this.UpperSymbol = this.Symbol ? this.Symbol.toUpperCase() : '';
  1009. this.LastShowData = null;
  1010. this.SendUpdateUIMessage('Draw');
  1011. if (!this.IsShow) return;
  1012. if (this.CursorIndex == null || !this.Data || !this.Data.Data || this.Data.Data.length <= 0)
  1013. {
  1014. this.OnDrawEventCallback(null,"DynamicMinuteTitlePainting::Draw");
  1015. return;
  1016. }
  1017. if (this.TextSpace>=0)
  1018. {
  1019. this.SpaceWidth=this.TextSpace;
  1020. }
  1021. else
  1022. {
  1023. this.Canvas.font = this.Font;
  1024. this.SpaceWidth = this.Canvas.measureText(' ').width;
  1025. }
  1026. var index = this.CursorIndex;
  1027. index = parseInt(index.toFixed(0));
  1028. var dataIndex = index + this.Data.DataOffset;
  1029. if (dataIndex >= this.Data.Data.length) dataIndex = this.Data.Data.length - 1;
  1030. var item = this.Data.Data[dataIndex];
  1031. this.LastShowData = item;
  1032. this.OnDrawEventCallback(item, "DynamicMinuteTitlePainting::Draw");
  1033. if (this.Frame.IsHScreen === true)
  1034. {
  1035. this.Canvas.save();
  1036. if (this.LineCount > 1) this.DrawMulitLine(item);
  1037. else this.DrawSingleLine(item, true);
  1038. this.Canvas.restore();
  1039. if (!item.Time && item.Date && this.InfoData) this.HSCreenKLineInfoDraw(item.Date);
  1040. }
  1041. else
  1042. {
  1043. if (this.LineCount > 1) this.DrawMulitLine(item);
  1044. else this.DrawSingleLine(item, true);
  1045. if (!item.Time && item.Date && this.InfoData) this.KLineInfoDraw(item.Date);
  1046. }
  1047. }
  1048. this.DrawMinuteText = function (title, color, position, isShow)
  1049. {
  1050. if (!title) return true;
  1051. var isHScreen = this.Frame.IsHScreen === true;
  1052. var right = this.Frame.ChartBorder.GetRight();
  1053. if (isHScreen) right = this.Frame.ChartBorder.GetHeight();
  1054. this.Canvas.fillStyle = color;
  1055. var textWidth = this.Canvas.measureText(title).width;
  1056. if (position.Left + textWidth > right) return false;
  1057. if (!(isShow === false)) this.Canvas.fillText(title, position.Left, position.Bottom, textWidth);
  1058. position.Left += textWidth + this.SpaceWidth;
  1059. return true;
  1060. }
  1061. }
  1062. //字符串输出格式
  1063. var STRING_FORMAT_TYPE =
  1064. {
  1065. DEFAULT: 1, //默认 2位小数 单位自动转化 (万 亿)
  1066. ORIGINAL: 2, //原始数据
  1067. THOUSANDS: 21, //千分位分割
  1068. };
  1069. function DynamicTitleData(data, name, color) //指标标题数据
  1070. {
  1071. this.Data = data;
  1072. this.Name = name;
  1073. this.Color = color; //字体颜色
  1074. this.DataType; //数据类型
  1075. this.ChartClassName;
  1076. this.StringFormat = STRING_FORMAT_TYPE.DEFAULT; //字符串格式
  1077. this.FloatPrecision = 2; //小数位数
  1078. this.GetTextCallback; //自定义数据转文本回调
  1079. this.IsShow=true;
  1080. }
  1081. //指标标题
  1082. function DynamicChartTitlePainting()
  1083. {
  1084. this.newMethod = IChartTitlePainting; //派生
  1085. this.newMethod();
  1086. delete this.newMethod;
  1087. this.IsDynamic = true;
  1088. this.Data = new Array();
  1089. this.Explain;
  1090. this.TitleBG; //标题背景色
  1091. this.TitleBGHeight = 20; //标题背景色高度
  1092. this.TitleAlign = 'middle';//对其方式
  1093. this.TitleBottomDistance = 1; //标题靠底部输出的时候 字体和底部的间距
  1094. this.Text = new Array(); //副标题 Text:'文本', Color:'颜色'
  1095. this.EraseRect;
  1096. this.EraseColor = g_JSChartResource.BGColor; //用来擦出的背景色
  1097. this.TitleRect; //指标名字显示区域
  1098. this.IsDrawTitleBG=false; //是否绘制指标名字背景色
  1099. this.BGColor=g_JSChartResource.IndexTitleBGColor; //指标名字背景颜色
  1100. this.BGBorderColor=g_JSChartResource.IndexTitleBorderColor;
  1101. this.TitleButtonConfig=
  1102. {
  1103. Mergin:
  1104. {
  1105. Left:g_JSChartResource.IndexTitleButton.Mergin.Left, Top:g_JSChartResource.IndexTitleButton.Mergin.Top,
  1106. Bottom:g_JSChartResource.IndexTitleButton.Mergin.Bottom, Right:g_JSChartResource.IndexTitleButton.Mergin.Right
  1107. },
  1108. Font:g_JSChartResource.IndexTitleButton.Font,
  1109. RightSpace:g_JSChartResource.IndexTitleButton.RightSpace
  1110. };
  1111. this.TitleColor = g_JSChartResource.IndexTitleColor; //指标名字颜色
  1112. this.ArgumentsText; //参数信息
  1113. this.IsShowIndexName = true; //是否显示指标名字
  1114. this.IsShowNameArrow=false;
  1115. this.IsSinlgeLine=false; //主图指标标题是否单行显示
  1116. this.NameArrowConfig=CloneData(g_JSChartResource.IndexTitle.NameArrow);
  1117. this.ParamSpace = 2; //参数显示的间距
  1118. this.TitleSpace=2; //指标名字和参数之间的间距
  1119. this.OutName=null; //动态标题
  1120. this.IsFullDraw=true; //手势离开屏幕以后是否显示最后的价格
  1121. this.IsShowUpDownArrow=true; //指标数据是否显示 上涨下跌箭头
  1122. this.TitleArrowType=0; //指标数据上涨下跌箭头类型 0=独立颜色 1=跟指标颜色一致
  1123. this.OverlayIndex=new Map(); //叠加指标 key=Identify value={ Data:数据, Title:标题, Identify:标识}
  1124. this.IsShowOverlayIndexName=true;
  1125. this.OverlayIndexType={ LineSpace:1, BGColor:g_JSChartResource.OverlayIndexTitleBGColor }; //Position 0=主图指标后面显示 1=叠加指标单行显示
  1126. this.DynamicTitle={ OutName:null, OutValue:null };
  1127. this.OverlayDynamicTitle=new Map(); //key , value={ OutName, OutValue }
  1128. this.IsShowMainIndexTitle=true; //是否显示主图指标标题
  1129. this.IsKLineFrame=false; //是否是K线框架标题
  1130. this.IsMinuteFrame=false;
  1131. this.IsLocked=false; //上锁的指标区域
  1132. this.UpDownArrowConfig=
  1133. {
  1134. UpColor:g_JSChartResource.IndexTitle.UpDownArrow.UpColor,
  1135. DownColor:g_JSChartResource.IndexTitle.UpDownArrow.DownColor,
  1136. UnchangeColor:g_JSChartResource.IndexTitle.UpDownArrow.UnchangeColor
  1137. };
  1138. this.ReloadResource=function()
  1139. {
  1140. this.BGColor=g_JSChartResource.IndexTitleBGColor; //指标名字背景颜色
  1141. this.BGBorderColor=g_JSChartResource.IndexTitleBorderColor;
  1142. this.TitleColor = g_JSChartResource.IndexTitleColor; //指标名字颜色
  1143. }
  1144. this.SetDynamicTitleData=function(outName, args, data)
  1145. {
  1146. if (!data.OutName) data.OutName=new Map();
  1147. else data.OutName.clear();
  1148. if (!data.OutValue) data.OutValue=new Map();
  1149. else data.OutValue.clear();
  1150. var mapArgs=new Map();
  1151. for(var i in args)
  1152. {
  1153. var item=args[i];
  1154. mapArgs.set(`{${item.Name}}`, item);
  1155. }
  1156. for(var i in outName)
  1157. {
  1158. var item=outName[i];
  1159. if (item.DynamicName)
  1160. {
  1161. var aryFond = item.DynamicName.match(/{\w*}/i);
  1162. if (!aryFond || aryFond.length<=0)
  1163. {
  1164. data.OutName.set(item.Name, item.DynamicName);
  1165. }
  1166. else
  1167. {
  1168. var dyName=item.DynamicName;
  1169. var bFind=true;
  1170. for(var j=0;j<aryFond.length;++j)
  1171. {
  1172. var findItem=aryFond[j];
  1173. if (mapArgs.has(findItem))
  1174. {
  1175. var value=mapArgs.get(findItem).Value;
  1176. dyName=dyName.replace(findItem,value.toString());
  1177. }
  1178. else
  1179. {
  1180. bFind=false;
  1181. break;
  1182. }
  1183. }
  1184. if (bFind) data.OutName.set(item.Name, dyName);
  1185. }
  1186. }
  1187. if (item.DynamicValue)
  1188. {
  1189. data.OutValue.set(item.Name, item.DynamicValue);
  1190. }
  1191. }
  1192. }
  1193. this.SetDynamicTitle=function(outName, args, overlayID)
  1194. {
  1195. if (IFrameSplitOperator.IsString(overlayID))
  1196. {
  1197. var dynamicTitle=null;
  1198. if (this.OverlayDynamicTitle.has(overlayID))
  1199. {
  1200. dynamicTitle=this.OverlayDynamicTitle.get(overlayID);
  1201. }
  1202. else
  1203. {
  1204. dynamicTitle={ OutName:null, OutValue:null };
  1205. this.OverlayDynamicTitle.set(overlayID, dynamicTitle);
  1206. }
  1207. this.SetDynamicTitleData(outName, args, dynamicTitle);
  1208. }
  1209. else
  1210. {
  1211. this.SetDynamicTitleData(outName, args, this.DynamicTitle);
  1212. }
  1213. }
  1214. this.GetDynamicOutName=function(key, overlayID)
  1215. {
  1216. if (IFrameSplitOperator.IsString(overlayID))
  1217. {
  1218. if (!this.OverlayDynamicTitle.has(overlayID)) return null;
  1219. var dynamicTitle=this.OverlayDynamicTitle.get(overlayID);
  1220. var outName=dynamicTitle.OutName;
  1221. }
  1222. else
  1223. {
  1224. var outName=this.DynamicTitle.OutName;
  1225. }
  1226. if (!outName || outName.size<=0) return null;
  1227. if (!outName.has(key)) return null;
  1228. return outName.get(key);
  1229. }
  1230. this.IsClickTitle=function(x,y) //是否点击了指标标题
  1231. {
  1232. if (!this.TitleRect) return false;
  1233. if (x>this.TitleRect.Left && x<this.TitleRect.Left+this.TitleRect.Width && y>this.TitleRect.Top && y<this.TitleRect.Top+this.TitleRect.Height)
  1234. {
  1235. return true;
  1236. }
  1237. return false;
  1238. }
  1239. this.FormatValue = function (value, item)
  1240. {
  1241. if (item.StringFormat == STRING_FORMAT_TYPE.DEFAULT)
  1242. return IFrameSplitOperator.FormatValueString(value, item.FloatPrecision, this.LanguageID);
  1243. else if (item.StringFormat == STRING_FORMAT_TYPE.THOUSANDS)
  1244. return IFrameSplitOperator.FormatValueThousandsString(value, item.FloatPrecision);
  1245. else if (item.StringFormat == STRING_FORMAT_TYPE.ORIGINAL)
  1246. return value.toFixed(item.FloatPrecision).toString();
  1247. }
  1248. this.FormatMultiReport = function (data, format)
  1249. {
  1250. if (!IFrameSplitOperator.IsNonEmptyArray(data)) return null;
  1251. var text = "";
  1252. for(var i=0; i<data.length; ++i)
  1253. {
  1254. var item = data[i];
  1255. let quarter = item.Quarter;
  1256. let year = item.Year;
  1257. let value = item.Value;
  1258. if (text.length > 0) text += ',';
  1259. text += year.toString();
  1260. switch (quarter) {
  1261. case 1:
  1262. text += '一季报 ';
  1263. break;
  1264. case 2:
  1265. text += '半年报 ';
  1266. break;
  1267. case 3:
  1268. text += '三季报 ';
  1269. break;
  1270. case 4:
  1271. text += '年报 ';
  1272. break;
  1273. }
  1274. text += this.FormatValue(value, format);
  1275. }
  1276. return text;
  1277. }
  1278. //多变量输出
  1279. this.FormatStackedBarTitle=function(aryBar, dataInfo)
  1280. {
  1281. if (!IFrameSplitOperator.IsNonEmptyArray(aryBar)) return null;
  1282. if (!IFrameSplitOperator.IsNonEmptyArray(dataInfo.Color)) return null;
  1283. var aryText=[];
  1284. for(var i=0;i<aryBar.length;++i)
  1285. {
  1286. var value=aryBar[i];
  1287. if (!IFrameSplitOperator.IsNumber(value)) continue;
  1288. var item={ Text:value.toFixed(2) };
  1289. if (dataInfo.Name && dataInfo.Name[i]) item.Name=dataInfo.Name[i];
  1290. item.Color=dataInfo.Color[i];
  1291. aryText.push(item);
  1292. }
  1293. if (aryText.length<=0) return null;
  1294. return aryText;
  1295. }
  1296. this.SendUpdateUIMessage = function (funcName) //通知外面 标题变了
  1297. {
  1298. if (!this.UpdateUICallback) return;
  1299. var sendData = {
  1300. TitleName: '指标标题', CallFunction: funcName,
  1301. TitleData: { Title: this.Title, Identify: this.Frame.Identify, Data: [] },
  1302. Rect: //标题的位置
  1303. {
  1304. Top: this.Frame.ChartBorder.GetTop(), Left: this.Frame.ChartBorder.GetLeft(),
  1305. Right: this.Frame.ChartBorder.GetRight(), Bottom: this.Frame.ChartBorder.GetBottom()
  1306. }
  1307. };
  1308. for (var i in this.Data) {
  1309. var item = this.Data[i];
  1310. if (!item || !item.Data || !item.Data.Data) continue;
  1311. if (item.Data.Data.length <= 0) continue;
  1312. var titleItem = { Name: item.Name, Color: item.Color };
  1313. if (item.DataType) titleItem.DataType = item.DataType;
  1314. if (item.DataType == "StraightLine") //直线只有1个数据
  1315. {
  1316. titleItem.Value = item.Data.Data[0];
  1317. }
  1318. else {
  1319. var index = item.Data.Data.length - 1;
  1320. if (this.CursorIndex != null) {
  1321. var cursorIndex = Math.abs(this.CursorIndex - 0.5);
  1322. cursorIndex = parseInt(cursorIndex.toFixed(0));
  1323. index = item.Data.DataOffset + cursorIndex
  1324. }
  1325. if (index >= item.Data.Data.length) index = item.Data.Data.length - 1;
  1326. titleItem.Value = item.Data.Data[index];
  1327. }
  1328. sendData.TitleData.Data.push(titleItem);
  1329. }
  1330. //console.log('[DynamicChartTitlePainting::SendUpdateUIMessage', sendData);
  1331. this.UpdateUICallback(sendData);
  1332. }
  1333. this.FullDraw=function()
  1334. {
  1335. this.EraseRect = null;
  1336. this.TitleRect=null;
  1337. this.IsLocked=false;
  1338. if (this.Frame.IsMinSize) return;
  1339. this.IsKLineFrame= this.Frame.IsKLineFrame(false);
  1340. this.IsMinuteFrame=this.Frame.IsMinuteFrame(false);
  1341. this.OnDrawTitleEvent();
  1342. if (this.Frame.ChartBorder.TitleHeight < 5) return;
  1343. if (this.Frame.IsShowTitle == false) return;
  1344. this.IsDrawTitleBG=this.Frame.IsDrawTitleBG;
  1345. this.IsShowIndexName = this.Frame.IsShowIndexName;
  1346. this.IsShowNameArrow=this.Frame.IsShowNameArrow;
  1347. this.IsSinlgeLine=this.Frame.IsSinlgeLine;
  1348. this.ParamSpace = this.Frame.IndexParamSpace;
  1349. this.TitleSpace=this.Frame.IndexTitleSpace;
  1350. this.IsShowUpDownArrow=this.Frame.IsShowTitleArrow;
  1351. this.TitleArrowType=this.Frame.TitleArrowType;
  1352. if (this.Frame.IsHScreen === true)
  1353. {
  1354. var rtText={ };
  1355. this.Canvas.save();
  1356. this.DrawItem(true,true,rtText);
  1357. if (!this.IsLocked) this.DrawOverlayIndexSingleLine();
  1358. this.Canvas.restore();
  1359. /*
  1360. //测试用
  1361. if (this.TitleRect)
  1362. {
  1363. this.Canvas.strokeStyle='rgba(200,0,50,1)';
  1364. this.Canvas.strokeRect(ToFixedPoint(this.TitleRect.Left),ToFixedPoint(this.TitleRect.Top),ToFixedRect(this.TitleRect.Width),ToFixedRect(this.TitleRect.Height));
  1365. }
  1366. */
  1367. return;
  1368. }
  1369. var rtText={ };
  1370. this.DrawItem(true,true,rtText);
  1371. if (!this.IsLocked) this.DrawOverlayIndexSingleLine(rtText);
  1372. }
  1373. this.DrawTitle = function ()
  1374. {
  1375. this.IsDrawTitleBG=this.Frame.IsDrawTitleBG;
  1376. this.EraseRect = null;
  1377. this.TitleRect=null;
  1378. this.SendUpdateUIMessage('DrawTitle');
  1379. if (this.Frame.ChartBorder.TitleHeight < 5) return;
  1380. if (this.Frame.IsShowTitle == false) return;
  1381. this.IsShowIndexName = this.Frame.IsShowIndexName;
  1382. this.ParamSpace = this.Frame.IndexParamSpace;
  1383. if (this.Frame.IsHScreen === true)
  1384. {
  1385. this.Canvas.save();
  1386. this.DrawItem(true,false);
  1387. this.Canvas.restore();
  1388. return;
  1389. }
  1390. this.DrawItem(true,false);
  1391. }
  1392. this.EraseTitle = function ()
  1393. {
  1394. if (!this.EraseRect) return;
  1395. this.Canvas.fillStyle = this.EraseColor;
  1396. this.Canvas.fillRect(this.EraseRect.Left, this.EraseRect.Top, this.EraseRect.Width, this.EraseRect.Height);
  1397. }
  1398. this.Draw = function ()
  1399. {
  1400. this.TitleRect=null;
  1401. this.SendUpdateUIMessage('Draw');
  1402. if (this.CursorIndex == null) return;
  1403. if (!this.Data) return;
  1404. if (this.Frame.ChartBorder.TitleHeight < 5) return;
  1405. if (this.Frame.IsShowTitle == false) return;
  1406. this.IsShowIndexName = this.Frame.IsShowIndexName;
  1407. this.IsShowNameArrow=this.Frame.IsShowNameArrow;
  1408. this.ParamSpace = this.Frame.IndexParamSpace;
  1409. this.TitleSpace=this.Frame.IndexTitleSpace;
  1410. if (this.Frame.IsHScreen === true)
  1411. {
  1412. this.Canvas.save();
  1413. this.DrawItem(false,true);
  1414. this.Canvas.restore();
  1415. return;
  1416. }
  1417. this.DrawItem(false,true);
  1418. }
  1419. this.GetTitleItem=function(item, isShowLastData, titleIndex)
  1420. {
  1421. if (!item || !item.Data || !item.Data.Data) return null;
  1422. if (item.Data.Data.length <= 0) return null;
  1423. if (item.IsShow==false) return null;
  1424. var valueText = null;
  1425. var aryText=null;
  1426. var value = null;
  1427. var dataIndex=-1;
  1428. if (item.DataType == "StraightLine") //直线只有1个数据
  1429. {
  1430. value = item.Data.Data[0];
  1431. valueText = this.FormatValue(value, item);
  1432. }
  1433. else
  1434. {
  1435. var index = this.CursorIndex - 0.5;
  1436. if (index<0) index=0;
  1437. index = parseInt(index.toFixed(0));
  1438. var dataIndex=item.Data.DataOffset+index;
  1439. if (dataIndex >= item.Data.Data.length) return null;
  1440. if (dataIndex>=0 && item.Data && IFrameSplitOperator.IsNonEmptyArray(item.Data.Data)) value=item.Data.Data[dataIndex];
  1441. if (this.GetEventCallback)
  1442. {
  1443. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_INDEX_OUT_TEXT);
  1444. if (event)
  1445. {
  1446. var sendData=
  1447. {
  1448. Item:item, Index:titleIndex, Data:this.Data, FrameID:this.Frame.Identify,
  1449. DataIndex:dataIndex, Value:value, PreventDefault:false, Out:null
  1450. };
  1451. event.Callback(event,sendData,this);
  1452. if (sendData.Out) return sendData.Out;
  1453. if (sendData.PreventDefault) return sendData.Out;
  1454. }
  1455. }
  1456. if (item.DataType == "MultiReport")
  1457. {
  1458. valueText = this.FormatMultiReport(value, item);
  1459. if (!valueText) return;
  1460. }
  1461. else if (item.DataType=="ChartStackedBar")
  1462. {
  1463. aryText=this.FormatStackedBarTitle(value, item);
  1464. if (!aryText) return null;
  1465. }
  1466. else
  1467. {
  1468. if (value == null) return null;
  1469. var arrowSuper=null; //独立颜色
  1470. if (this.IsShowUpDownArrow)
  1471. {
  1472. var preValue=null;
  1473. if (dataIndex-1>=0) preValue=item.Data.Data[dataIndex-1];
  1474. if (IFrameSplitOperator.IsNumber(preValue))
  1475. {
  1476. if (preValue>value) arrowSuper={ Text:'↓', TextColor:this.UpDownArrowConfig.DownColor };
  1477. else if (preValue<value) arrowSuper={ Text:'↑', TextColor:this.UpDownArrowConfig.UpColor};
  1478. else arrowSuper={ Text:'→', TextColor:this.UpDownArrowConfig.UnchangeColor };
  1479. if (this.TitleArrowType==1) arrowSuper.TextColor=item.Color;
  1480. }
  1481. }
  1482. if (item.GetTextCallback) valueText = item.GetTextCallback(value, item);
  1483. else valueText = this.FormatValue(value, item);
  1484. if (arrowSuper)
  1485. {
  1486. var outItem={ Name:null, Text:valueText, Color:item.Color, TextEx:[arrowSuper] };
  1487. if (item.Name)
  1488. {
  1489. var text=item.Name;
  1490. var dyTitle=this.GetDynamicOutName(item.Name); //动态标题
  1491. if (dyTitle) text=dyTitle;
  1492. outItem.Name=text;
  1493. }
  1494. //outItem.BG='rgb(100,100,100)';
  1495. aryText=[outItem];
  1496. valueText=null;
  1497. }
  1498. }
  1499. }
  1500. if (!valueText && !aryText) return null;
  1501. return { Text:valueText, ArrayText:aryText };
  1502. }
  1503. this.DrawItem=function(bDrawTitle, bDrawValue, rtText)
  1504. {
  1505. var bHScreen=(this.Frame.IsHScreen === true);
  1506. var left = this.Frame.ChartBorder.GetLeft() + 1;
  1507. var bottom = this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.TitleHeight / 2; //上下居中显示
  1508. if (this.TitleAlign == 'bottom') bottom = this.Frame.ChartBorder.GetTopEx() - this.TitleBottomDistance;
  1509. var right = this.Frame.ChartBorder.GetRight();
  1510. var lineHeight=this.Canvas.measureText("擎").width+2;
  1511. var textWidth;
  1512. if (bHScreen)
  1513. {
  1514. let xText = this.Frame.ChartBorder.GetRightTitle();
  1515. let yText = this.Frame.ChartBorder.GetTop();
  1516. this.Canvas.translate(xText, yText);
  1517. this.Canvas.rotate(90 * Math.PI / 180);
  1518. left = 1;
  1519. bottom = -(this.Frame.ChartBorder.TitleHeight / 2); //上下居中显示
  1520. if (this.TitleAlign == 'bottom') bottom = -this.TitleBottomDistance;
  1521. right = this.Frame.ChartBorder.GetHeight();
  1522. }
  1523. this.EraseTitle();
  1524. this.Canvas.textAlign = "left";
  1525. this.Canvas.textBaseline = this.TitleAlign;
  1526. this.Canvas.font = this.Font;
  1527. if (this.TitleBG && this.Title && this.IsShowMainIndexTitle) //指标名称
  1528. {
  1529. textWidth = this.Canvas.measureText(this.Title).width + 2;
  1530. let height = this.Frame.ChartBorder.TitleHeight;
  1531. let top = this.Frame.ChartBorder.GetTop();
  1532. if (height > 20)
  1533. {
  1534. top += (height - 20) / 2 + (height - 45) / 2;
  1535. height = 20;
  1536. }
  1537. if (this.TitleAlign == 'bottom') //底部输出文字
  1538. {
  1539. top = this.Frame.ChartBorder.GetTopEx() - 20;
  1540. if (top < 0) top = 0;
  1541. }
  1542. if (bDrawTitle)
  1543. {
  1544. this.Canvas.fillStyle = this.TitleBG;
  1545. this.Canvas.fillRect(left, top, textWidth, height);
  1546. }
  1547. }
  1548. if (this.Title && this.IsShowIndexName && this.IsShowMainIndexTitle) //指标参数
  1549. {
  1550. const metrics = this.Canvas.measureText(this.Title);
  1551. textWidth = metrics.width + 2;
  1552. if (bDrawTitle)
  1553. {
  1554. if (this.IsDrawTitleBG) //绘制指标名背景色
  1555. {
  1556. if (this.TitleButtonConfig.Font) this.Canvas.font=this.TitleButtonConfig.Font;
  1557. var title=this.Title;
  1558. var textWidth=this.Canvas.measureText(title).width;
  1559. var titleWidth=textWidth+this.TitleButtonConfig.Mergin.Left+this.TitleButtonConfig.Mergin.Right;
  1560. var arrowWidth=0;
  1561. if (this.IsShowNameArrow && this.NameArrowConfig)
  1562. {
  1563. arrowWidth=this.Canvas.measureText(this.NameArrowConfig.Symbol).width;
  1564. titleWidth+=arrowWidth;
  1565. if (IFrameSplitOperator.IsNumber(this.NameArrowConfig.Space)) titleWidth+=this.NameArrowConfig.Space;
  1566. }
  1567. var textHeight=this.Canvas.measureText("擎").width;
  1568. var bgHeight=textHeight+this.TitleButtonConfig.Mergin.Top+this.TitleButtonConfig.Mergin.Bottom;
  1569. var bgWidth=titleWidth;
  1570. this.Canvas.fillStyle=this.BGColor;
  1571. if (bHScreen)
  1572. {
  1573. this.TitleRect=
  1574. {
  1575. Top:this.Frame.ChartBorder.GetTop(),
  1576. Left:this.Frame.ChartBorder.GetRightTitle()+this.Frame.ChartBorder.TitleHeight/2-bgHeight/2,
  1577. Width:bgHeight ,Height:bgWidth
  1578. }; //保存下标题的坐标
  1579. let drawRect={Left:left, Top:-bgHeight-2, Width:bgWidth, Height:bgHeight};
  1580. this.Canvas.fillRect(drawRect.Left,drawRect.Top,drawRect.Width,drawRect.Height);
  1581. if (this.BGBorderColor)
  1582. {
  1583. this.Canvas.strokeStyle=this.BGBorderColor;
  1584. this.Canvas.strokeRect(ToFixedPoint(drawRect.Left),ToFixedPoint(drawRect.Top),ToFixedRect(drawRect.Width),ToFixedRect(drawRect.Height));
  1585. }
  1586. }
  1587. else
  1588. {
  1589. this.TitleRect={ Left:left, Top:bottom-textHeight/2-this.TitleButtonConfig.Mergin.Top, Width:bgWidth, Height:bgHeight }; //保存下标题的坐标
  1590. this.Canvas.fillRect(this.TitleRect.Left,this.TitleRect.Top,this.TitleRect.Width,this.TitleRect.Height);
  1591. if (this.BGBorderColor)
  1592. {
  1593. this.Canvas.strokeStyle=this.BGBorderColor;
  1594. this.Canvas.strokeRect(ToFixedPoint(this.TitleRect.Left),ToFixedPoint(this.TitleRect.Top),ToFixedRect(this.TitleRect.Width),ToFixedRect(this.TitleRect.Height));
  1595. }
  1596. }
  1597. var xText= left+this.TitleButtonConfig.Mergin.Left;
  1598. var yText=bottom-this.TitleButtonConfig.Mergin.Bottom;
  1599. this.Canvas.fillStyle = this.TitleColor;
  1600. this.Canvas.fillText(title, xText, yText, textWidth);
  1601. xText+=textWidth;
  1602. if (this.IsShowNameArrow && this.NameArrowConfig)
  1603. {
  1604. if (IFrameSplitOperator.IsNumber(this.NameArrowConfig.Space)) xText+=this.NameArrowConfig.Space;
  1605. this.Canvas.fillStyle=this.NameArrowConfig.Color;
  1606. this.Canvas.fillText(this.NameArrowConfig.Symbol,xText,yText,arrowWidth);
  1607. }
  1608. textWidth=bgWidth+this.TitleButtonConfig.RightSpace;
  1609. this.Canvas.font=this.Font;
  1610. }
  1611. else
  1612. {
  1613. this.Canvas.fillStyle = this.TitleColor;
  1614. this.Canvas.fillText(this.Title, left, bottom, textWidth);
  1615. }
  1616. }
  1617. left += textWidth;
  1618. left+=this.TitleSpace;
  1619. }
  1620. //指标参数
  1621. if (this.ArgumentsText && this.IsShowIndexName && this.IsShowMainIndexTitle)
  1622. {
  1623. var textWidth=this.Canvas.measureText(this.ArgumentsText).width+2;
  1624. this.Canvas.fillStyle=this.TitleColor;
  1625. this.Canvas.fillText(this.ArgumentsText, left, bottom, textWidth);
  1626. left += textWidth;
  1627. left+=this.TitleSpace;
  1628. }
  1629. if (this.Text && this.Text.length > 0)
  1630. {
  1631. for (let i in this.Text)
  1632. {
  1633. let item = this.Text[i];
  1634. this.Canvas.fillStyle = item.Color;
  1635. textWidth = this.Canvas.measureText(item.Text).width + 2;
  1636. this.Canvas.fillText(item.Text, left, bottom, textWidth);
  1637. left += textWidth;
  1638. }
  1639. }
  1640. var lockRect=this.Frame.GetLockRect();
  1641. if (lockRect) //指标上锁区域不显示动态标题
  1642. {
  1643. var index=Math.abs(this.CursorIndex);
  1644. if (this.IsKLineFrame) index=this.CursorIndex;
  1645. var x=this.Frame.GetXFromIndex(index.toFixed(0));
  1646. if (bHScreen)
  1647. {
  1648. if (x>=lockRect.Top) this.IsLocked=true;
  1649. }
  1650. else
  1651. {
  1652. if (x>=lockRect.Left) this.IsLocked=true;
  1653. }
  1654. if (this.IsLocked) return;
  1655. }
  1656. if (bDrawValue)
  1657. {
  1658. for (var i=0; i<this.Data.length && this.IsShowMainIndexTitle; ++i)
  1659. {
  1660. var item = this.Data[i];
  1661. var outText=this.GetTitleItem(item, false, i);
  1662. if (!outText) continue;
  1663. var valueText=outText.Text;
  1664. var aryText=outText.ArrayText;
  1665. if (aryText)
  1666. {
  1667. var text;
  1668. for(var k=0;k<aryText.length;++k)
  1669. {
  1670. var titleItem=aryText[k];
  1671. if (titleItem.Name) text=titleItem.Name+":"+titleItem.Text;
  1672. else text=titleItem.Text;
  1673. var textWidth=this.Canvas.measureText(text).width
  1674. if ((left+textWidth)>right) //换行
  1675. {
  1676. if (this.IsSinlgeLine) break;
  1677. left=this.Frame.ChartBorder.GetLeft() + 3;
  1678. bottom+=lineHeight;
  1679. }
  1680. this.Canvas.fillStyle=titleItem.Color;
  1681. this.Canvas.fillText(text,left,bottom,textWidth);
  1682. left+=textWidth;
  1683. if (IFrameSplitOperator.IsNonEmptyArray(titleItem.TextEx))
  1684. {
  1685. for(var n=0; n<titleItem.TextEx.length; ++n)
  1686. {
  1687. var outItem=titleItem.TextEx[n];
  1688. this.Canvas.fillStyle=outItem.TextColor;
  1689. outItem.Width=this.Canvas.measureText(outItem.Text).width+2;
  1690. if ((left+outItem.Width)>right) break;
  1691. this.Canvas.fillText(outItem.Text,left,bottom,outItem.Width);
  1692. left+=outItem.Width;
  1693. }
  1694. }
  1695. left+=this.ParamSpace;
  1696. }
  1697. }
  1698. else
  1699. {
  1700. var text=valueText;
  1701. if (item.Name)
  1702. {
  1703. var dyTitle=this.GetDynamicOutName(item.Name);
  1704. if (dyTitle) text=dyTitle+ ":" + valueText;
  1705. else text = item.Name + ":" + valueText;
  1706. }
  1707. textWidth = this.Canvas.measureText(text).width + this.ParamSpace; //后空2个像素
  1708. if (textWidth+left>right) //换行
  1709. {
  1710. if (this.IsSinlgeLine) break;
  1711. left=this.Frame.ChartBorder.GetLeft() + 3;
  1712. bottom+=lineHeight;
  1713. }
  1714. this.Canvas.fillStyle = item.Color;
  1715. this.Canvas.fillText(text, left, bottom, textWidth);
  1716. left += textWidth;
  1717. }
  1718. }
  1719. }
  1720. else
  1721. {
  1722. left += 4;
  1723. var eraseRight = left, eraseLeft = left;
  1724. for (var i in this.Data)
  1725. {
  1726. var item = this.Data[i];
  1727. if (!item || !item.Data || !item.Data.Data) continue;
  1728. if (item.Data.Data.length <= 0) continue;
  1729. var indexName = '●' + item.Name;
  1730. this.Canvas.fillStyle = item.Color;
  1731. textWidth = this.Canvas.measureText(indexName).width + this.ParamSpace;
  1732. if (left + textWidth >= right) break;
  1733. this.Canvas.fillText(indexName, left, bottom, textWidth);
  1734. left += textWidth;
  1735. eraseRight = left;
  1736. }
  1737. if (eraseRight > eraseLeft)
  1738. {
  1739. if (bHScreen)
  1740. {
  1741. this.EraseRect =
  1742. {
  1743. Left: eraseLeft, Right: eraseRight, Top: -(this.Frame.ChartBorder.TitleHeight - 1),
  1744. Width: eraseRight - eraseLeft, Height: this.Frame.ChartBorder.TitleHeight - 2
  1745. };
  1746. }
  1747. else
  1748. {
  1749. this.EraseRect =
  1750. {
  1751. Left: eraseLeft, Right: eraseRight, Top: (this.Frame.ChartBorder.GetTop() + 1),
  1752. Width: eraseRight - eraseLeft, Height: this.Frame.ChartBorder.TitleHeight - 2
  1753. };
  1754. }
  1755. }
  1756. }
  1757. if (rtText)
  1758. {
  1759. if (this.TitleAlign=="middle") rtText.Bottom=bottom+lineHeight/2+1;
  1760. else rtText.Bottom=bottom+1;
  1761. }
  1762. }
  1763. this.OnDrawTitleEvent=function()
  1764. {
  1765. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_INDEXTITLE_DRAW);
  1766. if (!event) return;
  1767. var data={ Index:null, Data:this.Data ,Title:this.Title, FrameID:this.Frame.Identify };
  1768. if (IFrameSplitOperator.IsNumber(this.CursorIndex))
  1769. {
  1770. var index=Math.abs(this.CursorIndex);
  1771. index=parseInt(index.toFixed(0));
  1772. data.Index=index; //当前屏数据索引
  1773. }
  1774. var border=this.Frame.GetBorder();
  1775. data.Left=border.LeftEx;
  1776. data.Top=border.Top;
  1777. data.Right=border.RightEx;
  1778. event.Callback(event,data,this);
  1779. }
  1780. this.DrawOverlayIndexSingleLine=function(rtText) //叠加指标1个指标一行
  1781. {
  1782. if (this.OverlayIndex.size<=0) return;
  1783. var isHScreen=(this.Frame.IsHScreen === true);
  1784. var border=this.Frame.GetBorder();
  1785. var lineSpace=this.OverlayIndexType.LineSpace;
  1786. this.Canvas.textAlign="left";
  1787. this.Canvas.textBaseline="middle";
  1788. this.Canvas.font=this.Font;
  1789. var fontHeight=this.Canvas.measureText("擎").width;
  1790. if (isHScreen)
  1791. {
  1792. var left = 1;
  1793. var top = lineSpace; //上下居中显示
  1794. if (!this.IsShowMainIndexTitle) top-=this.Frame.ChartBorder.TitleHeight;
  1795. var right = this.Frame.ChartBorder.GetHeight();
  1796. }
  1797. else
  1798. {
  1799. var top=border.TopTitle+2;
  1800. if (rtText && IFrameSplitOperator.IsNumber(rtText.Bottom) && rtText.Bottom>top) top=rtText.Bottom;
  1801. if (!this.IsShowMainIndexTitle) top=this.Frame.ChartBorder.GetTop()+2;
  1802. var left=border.Left+1;
  1803. var right=border.Right;
  1804. var bottom=border.Bottom;
  1805. }
  1806. var x=left, y=top;
  1807. y=top+fontHeight/2;
  1808. for(var item of this.OverlayIndex)
  1809. {
  1810. var overlayItem=item[1];
  1811. var overlayID=item[0];
  1812. x=left;
  1813. if (!overlayItem.IsShowIndexTitle) continue;
  1814. if (overlayItem.Title && this.IsShowOverlayIndexName)
  1815. {
  1816. var textWidth=this.Canvas.measureText(overlayItem.Title).width+2;
  1817. if ((x+textWidth)<right)
  1818. {
  1819. if (this.OverlayIndexType.BGColor)
  1820. {
  1821. this.Canvas.fillStyle=this.OverlayIndexType.BGColor;
  1822. var rtBG={Left:x, Top:y-fontHeight/2, Width:textWidth, Height: fontHeight+lineSpace }; //保存下标题的坐标
  1823. this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height);
  1824. }
  1825. this.Canvas.fillStyle=this.TitleColor;
  1826. this.Canvas.fillText(overlayItem.Title,x,y,textWidth);
  1827. }
  1828. x+=textWidth;
  1829. }
  1830. for(var i=0; i<overlayItem.Data.length; ++i)
  1831. {
  1832. var item=overlayItem.Data[i];
  1833. var outText=this.GetTitleItem(item, false);
  1834. if (!outText) continue;
  1835. var valueText=outText.Text;
  1836. var aryText=outText.ArrayText;
  1837. if (aryText)
  1838. {
  1839. var text;
  1840. for(var k=0;k<aryText.length;++k)
  1841. {
  1842. var titleItem=aryText[k];
  1843. if (titleItem.Name) text=titleItem.Name+":"+titleItem.Text;
  1844. else text=titleItem.Text;
  1845. var textWidth=this.Canvas.measureText(text).width+this.ParamSpace;
  1846. if ((left+textWidth)>right) break;
  1847. this.Canvas.fillStyle=titleItem.Color;
  1848. this.Canvas.fillText(text,x,y,textWidth);
  1849. x+=textWidth;
  1850. }
  1851. }
  1852. else
  1853. {
  1854. var text=valueText;
  1855. if (item.Name)
  1856. {
  1857. var dyTitle=this.GetDynamicOutName(item.Name);
  1858. if (dyTitle) text=dyTitle+ ":" + valueText;
  1859. else text = item.Name + ":" + valueText;
  1860. }
  1861. textWidth = this.Canvas.measureText(text).width + this.ParamSpace; //后空2个像素
  1862. if (textWidth+left>right) break; //画不下了就不画了
  1863. if (this.OverlayIndexType.BGColor)
  1864. {
  1865. this.Canvas.fillStyle=this.OverlayIndexType.BGColor;
  1866. var rtBG={Left:x, Top:y-fontHeight/2, Width:textWidth, Height: fontHeight+lineSpace }; //保存下标题的坐标
  1867. this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height);
  1868. }
  1869. this.Canvas.fillStyle = item.Color;
  1870. this.Canvas.fillText(text, x, y, textWidth);
  1871. x += textWidth;
  1872. }
  1873. }
  1874. y+=fontHeight+lineSpace;
  1875. }
  1876. }
  1877. }
  1878. //导出统一使用JSCommon命名空间名
  1879. export
  1880. {
  1881. IChartTitlePainting,
  1882. DynamicKLineTitlePainting,
  1883. DynamicMinuteTitlePainting,
  1884. DynamicChartTitlePainting,
  1885. DynamicTitleData,
  1886. STRING_FORMAT_TYPE,
  1887. };
  1888. /*
  1889. module.exports =
  1890. {
  1891. JSCommonChartTitle:
  1892. {
  1893. IChartTitlePainting: IChartTitlePainting,
  1894. DynamicKLineTitlePainting: DynamicKLineTitlePainting,
  1895. DynamicMinuteTitlePainting: DynamicMinuteTitlePainting,
  1896. DynamicChartTitlePainting: DynamicChartTitlePainting,
  1897. DynamicTitleData: DynamicTitleData,
  1898. STRING_FORMAT_TYPE: STRING_FORMAT_TYPE,
  1899. },
  1900. //单个类导出
  1901. JSCommonChartTitle_IChartTitlePainting: IChartTitlePainting,
  1902. JSCommonChartTitle_DynamicKLineTitlePainting: DynamicKLineTitlePainting,
  1903. JSCommonChartTitle_DynamicMinuteTitlePainting: DynamicMinuteTitlePainting,
  1904. JSCommonChartTitle_DynamicChartTitlePainting: DynamicChartTitlePainting,
  1905. JSCommonChartTitle_DynamicTitleData: DynamicTitleData,
  1906. JSCommonChartTitle_STRING_FORMAT_TYPE: STRING_FORMAT_TYPE,
  1907. };
  1908. */