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

2078 lines
64 KiB

  1. import
  2. {
  3. IFrameSplitOperator,
  4. } from './umychart.framesplit.wechat.js'
  5. import
  6. {
  7. g_MinuteTimeStringData,
  8. } from "./umychart.coordinatedata.wechat.js";
  9. import
  10. {
  11. g_JSChartResource,
  12. g_JSChartLocalization,
  13. } from './umychart.resource.wechat.js'
  14. import { JSConsole } from "./umychart.console.wechat.js";
  15. function Guid()
  16. {
  17. function S4()
  18. {
  19. return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  20. }
  21. return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
  22. }
  23. function Point()
  24. {
  25. this.X;
  26. this.Y;
  27. }
  28. //修正线段有毛刺
  29. function ToFixedPoint(value)
  30. {
  31. return parseInt(value) + 0.5;
  32. }
  33. function ToFixedRect(value)
  34. {
  35. //return value;
  36. // With a bitwise or.
  37. //rounded = (0.5 + somenum) | 0;
  38. // A double bitwise not.
  39. //rounded = ~~ (0.5 + somenum);
  40. // Finally, a left bitwise shift.
  41. var rounded;
  42. return rounded = (0.5 + value) << 0;
  43. }
  44. function GetFontHeight(context, font, word)
  45. {
  46. if (!context) return null;
  47. if (font) context.font=font;
  48. var text='擎';
  49. if (IFrameSplitOperator.IsString(word)) text=word;
  50. var fontInfo=context.measureText(text);
  51. var textHeight=fontInfo.width+2;
  52. return textHeight;
  53. }
  54. //画图工具
  55. function IChartDrawPicture()
  56. {
  57. this.Frame;
  58. this.Canvas;
  59. this.Point=new Array() //画图的点
  60. this.Value=new Array(); //XValue,YValue
  61. this.LinePoint=[];
  62. this.PointCount=2; //画点的个数
  63. this.Status=0; //0=开始画 1=完成第1个点 2=完成第2个点 3=完成第3个点 10=完成 20=移动
  64. this.PointStatus=0; //2=第2个点完成
  65. this.MovePointIndex=null; //移动哪个点 0-10 对应Point索引 100 整体移动
  66. this.ClassName='IChartDrawPicture';
  67. this.FinishedCallback; //画图完成回调通知
  68. this.Guid=Guid(); //ID标识
  69. this.Symbol; //对应的股票
  70. this.Period; //对应的周期
  71. this.Right; //对应的复权
  72. this.IsSelected=false; //是否选中
  73. this.Option; //全局配置 对应外部 ChartDrawOption
  74. this.EnableMove=true; //是否可以移动
  75. this.EnableSave=true; //是否允许保存
  76. this.EnableCtrlMove=false; //是否按住Ctrl才能移动
  77. this.OnlyMoveXIndex=false; //只能在X轴刻度上移动
  78. this.IsSupportMagnet=false; //是否支持磁吸
  79. this.EnableMoveCheck=true; //允许移动时监测是否超出边界
  80. this.IsDrawFirst=false;
  81. this.IsShowYCoordinate=false; //是否在Y轴显示点的刻度
  82. this.IsShow=true; //是否显示
  83. this.LineColor=g_JSChartResource.DrawPicture.LineColor[0]; //线段颜色
  84. //this.LineColor="#1e90ff"; //线段颜色,input type="color" 不支持rgb和rgba 的格式
  85. this.LineWidth=2; //线段宽度
  86. this.BackupLineWidth=null;
  87. this.AreaColor='rgba(25,25,25,0.4)'; //面积颜色
  88. this.PointColor=g_JSChartResource.DrawPicture.PointColor[0];
  89. this.MoveOnPointColor=g_JSChartResource.DrawPicture.PointColor[1];
  90. this.PointBGColor=g_JSChartResource.DrawPicture.PointColor[2];
  91. this.PointRadius=5; //圆点半径
  92. this.SquareSize=8; //方框点大小
  93. this.PointType=g_JSChartResource.DrawPicture.PointType; // 0=圆点 1=方框 2= 空心圆
  94. this.IsShowPoint=g_JSChartResource.DrawPicture.IsShowPoint; //是否始终显示点
  95. this.LimitFrameID; //限制在指定窗口绘图
  96. this.TouchConfig={ Point:{ Radius:15 }, Line:{ Width:10 } },
  97. this.PixelRatio=null; //分辨率
  98. //接口函数
  99. this.SetLastPoint=null; //this.SetLastPoint=function(obj) obj={X:,Y:}
  100. this.Update=null; //更新数据回调
  101. this.GetActiveDrawPicture=null;
  102. this.GetYCoordinatePoint=null;
  103. this.Draw=function()
  104. {
  105. }
  106. this.SetOption=function(option)
  107. {
  108. if (!option) return;
  109. if (option.LineColor) this.LineColor=option.LineColor;
  110. if (option.LineWidth>0) this.LineWidth=option.LineWidth;
  111. if (option.AreaColor) this.AreaColor=option.AreaColor;
  112. if (option.PointColor) this.PointColor=option.PointColor;
  113. if (option.MoveOnPointColor) this.SelectPointColor=option.PointColor;
  114. if (option.PointRadius) this.PointRadius=option.PointRadius;
  115. if (IFrameSplitOperator.IsNumber(option.SquareSize)) this.SquareSize=option.SquareSize;
  116. if (IFrameSplitOperator.IsBool(option.IsShowPoint)) this.IsShowPoint=option.IsShowPoint;
  117. if (IFrameSplitOperator.IsNumber(option.LimitFrameID)) this.LimitFrameID=option.LimitFrameID;
  118. if (IFrameSplitOperator.IsBool(option.EnableCtrlMove)) this.EnableCtrlMove=option.EnableCtrlMove;
  119. if (IFrameSplitOperator.IsBool(option.IsShowYCoordinate)) this.IsShowYCoordinate=option.IsShowYCoordinate;
  120. }
  121. this.ReloadResource=function(resource)
  122. {
  123. if (!resource)
  124. {
  125. this.PointColor=g_JSChartResource.DrawPicture.PointColor[0];
  126. this.MoveOnPointColor=g_JSChartResource.DrawPicture.PointColor[1];
  127. this.PointBGColor=g_JSChartResource.DrawPicture.PointColor[2];
  128. }
  129. }
  130. this.SetLineWidth=function()
  131. {
  132. this.BackupLineWidth=null;
  133. if (this.LineWidth>0)
  134. {
  135. this.BackupLineWidth=this.Canvas.lineWidth;
  136. this.Canvas.lineWidth=this.LineWidth;
  137. }
  138. }
  139. this.GetFontHeight=function(font)
  140. {
  141. return GetFontHeight(this.Canvas, font, "擎");
  142. }
  143. this.RestoreLineWidth=function()
  144. {
  145. if (this.BackupLineWidth!=null)
  146. {
  147. this.Canvas.lineWidth=this.BackupLineWidth;
  148. }
  149. }
  150. //磁吸K线
  151. this.PointMagnetKLine=function()
  152. {
  153. if (!this.IsSupportMagnet) return false;
  154. if (!this.Frame) return false;
  155. if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") return false;
  156. if (this.Frame.Identify!=0) return false;
  157. var pointIndex=-1;
  158. if (this.Status==2) pointIndex=1;
  159. else if (this.Status==1) pointIndex=0;
  160. else if (IFrameSplitOperator.IsNumber(this.MovePointIndex)) pointIndex=this.MovePointIndex;
  161. if (pointIndex<0) return false;
  162. if (this.Option && this.Option.Magnet && this.Option.Magnet.Enable)
  163. {
  164. var option=
  165. {
  166. IsFixedX:false,
  167. Magnet:
  168. {
  169. Enable:true,
  170. PointIndex:pointIndex,
  171. Distance:this.Option.Magnet.Distance,
  172. Type:this.Option.Magnet.Type
  173. }
  174. }
  175. return this.AdjustPoint(this.Point,option)
  176. }
  177. return false;
  178. }
  179. //Point => Value
  180. this.PointToValue=function()
  181. {
  182. if (!this.Frame) return false;
  183. if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame")
  184. {
  185. return this.PointToValue_Minute();
  186. }
  187. else
  188. {
  189. return this.PointToValue_KLine();
  190. }
  191. }
  192. this.PointToKLine=function(aryPoint)
  193. {
  194. if (!this.Frame) return null;
  195. var data=this.Frame.Data;
  196. if (!data) return null;
  197. var kLine=[];
  198. var isHScreen=this.Frame.IsHScreen;
  199. if (isHScreen)
  200. {
  201. for(var i in aryPoint)
  202. {
  203. var item=aryPoint[i];
  204. var xValue=parseInt(this.Frame.GetXData(item.Y))+data.DataOffset;
  205. var yValue=this.Frame.GetYData(item.X);
  206. var valueItem={ XValue:xValue, YValue:yValue };
  207. var kline=data.Data[xValue];
  208. valueItem.DateTime={ Date:kline.Date };
  209. if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time;
  210. kLine[i]=valueItem;
  211. }
  212. }
  213. else
  214. {
  215. for(var i in aryPoint)
  216. {
  217. var item=aryPoint[i];
  218. var index=parseInt(this.Frame.GetXData(item.X,false));
  219. var xValue=index+data.DataOffset;
  220. if (xValue<0) xValue=0;
  221. else if (xValue>=data.Data.length)
  222. {
  223. xValue=data.Data.length-1;
  224. index=xValue-data.DataOffset;
  225. }
  226. var yValue=this.Frame.GetYData(item.Y,false);
  227. var valueItem={ XValue:xValue, YValue:yValue, XIndex:index };
  228. var kline=data.Data[xValue];
  229. valueItem.DateTime={ Date:kline.Date };
  230. if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time;
  231. kLine[i]=valueItem;
  232. }
  233. }
  234. return kLine;
  235. }
  236. this.PointToValue_KLine=function()
  237. {
  238. if (!this.Frame) return false;
  239. var data=this.Frame.Data;
  240. if (!data) return false;
  241. var isHScreen=this.Frame.IsHScreen;
  242. if (isHScreen)
  243. {
  244. for(var i in this.Point)
  245. {
  246. var item=this.Point[i];
  247. var xValue=parseInt(this.Frame.GetXData(item.Y,false))+data.DataOffset;
  248. var yValue=this.Frame.GetYData(item.X,false);
  249. var valueItem={ XValue:xValue, YValue:yValue };
  250. var kline=data.Data[xValue];
  251. valueItem.DateTime={ Date:kline.Date };
  252. if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time;
  253. this.Value[i]=valueItem;
  254. }
  255. }
  256. else
  257. {
  258. for(var i in this.Point)
  259. {
  260. var item=this.Point[i];
  261. var xValue=parseInt(this.Frame.GetXData(item.X,false))+data.DataOffset;
  262. if (xValue<0) xValue=0;
  263. else if (xValue>=data.Data.length) xValue=data.Data.length-1;
  264. var yValue=this.Frame.GetYData(item.Y,false);
  265. var valueItem={ XValue:xValue, YValue:yValue };
  266. var kline=data.Data[xValue];
  267. valueItem.DateTime={ Date:kline.Date };
  268. if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time;
  269. this.Value[i]=valueItem;
  270. }
  271. }
  272. return true;
  273. }
  274. this.PointToValue_Minute=function()
  275. {
  276. if (!this.Frame) return false;
  277. var data=this.Frame.Data;
  278. if (!data) return false;
  279. var isHScreen=this.Frame.IsHScreen;
  280. if (isHScreen)
  281. {
  282. for(var i=0; i<this.Point.length; ++i)
  283. {
  284. var item=this.Point[i];
  285. var xValue=parseInt(this.Frame.GetXData(item.Y));
  286. var yValue=this.Frame.GetYData(item.X);
  287. var valueItem={ XValue:xValue, YValue:yValue };
  288. var minuteItem=data.Data[xValue];
  289. valueItem.DateTime={ Date:minuteItem.Date ,Time:minuteItem.Time};
  290. this.Value[i]=valueItem;
  291. }
  292. }
  293. else
  294. {
  295. var xDatetime=g_MinuteTimeStringData.GetTimeData(this.Symbol);
  296. for(var i=0; i<this.Point.length; ++i)
  297. {
  298. var item=this.Point[i];
  299. var xValue=parseInt(this.Frame.GetXData(item.X));
  300. var yValue=this.Frame.GetYData(item.Y);
  301. if (xValue>=data.Data.length) //超过当前数据,直接读固定时间
  302. {
  303. var index=xValue%xDatetime.length;
  304. var dataIndex=data.Data.length-1;
  305. var valueItem={ XValue:xValue, YValue:yValue };
  306. var minuteItem=data.Data[dataIndex];
  307. var timeItem=xDatetime[index];
  308. valueItem.DateTime={ Date:minuteItem.Date, Time:timeItem };
  309. this.Value[i]=valueItem;
  310. }
  311. else
  312. {
  313. var valueItem={ XValue:xValue, YValue:yValue };
  314. var minuteItem=data.Data[xValue];
  315. valueItem.DateTime={ Date:minuteItem.Date, Time:minuteItem.Time };
  316. this.Value[i]=valueItem;
  317. }
  318. }
  319. }
  320. return true;
  321. }
  322. this.IsPointIn=function(x, y, option)
  323. {
  324. return false;
  325. }
  326. //Value => Point
  327. this.ValueToPoint=function()
  328. {
  329. if (!this.Frame) return false;
  330. var data=this.Frame.Data;
  331. if (!data) return false;
  332. //this.UpdateXValue();
  333. var isHScreen=this.Frame.IsHScreen;
  334. this.Point=[];
  335. for(var i=0; i<this.Value.length; ++i)
  336. {
  337. var item=this.Value[i];
  338. var pt=new Point();
  339. if (isHScreen)
  340. {
  341. pt.Y=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false);
  342. pt.X=this.Frame.GetYFromData(item.YValue,false);
  343. }
  344. else
  345. {
  346. pt.X=this.Frame.GetXFromIndex(item.XValue-data.DataOffset, false);
  347. pt.Y=this.Frame.GetYFromData(item.YValue,false);
  348. }
  349. this.Point[i]=pt;
  350. }
  351. }
  352. this.UpdateXValue=function() //通过datetime更新x的索引
  353. {
  354. if (!this.Frame) return false;
  355. var data=this.Frame.Data;
  356. if (!data) return false;
  357. var aryDateTime=[];
  358. for(var i=0; i<this.Value.length; ++i)
  359. {
  360. var item=this.Value[i];
  361. if (!item.DateTime) break;
  362. var dateTime={ Date:item.DateTime.Date };
  363. if (IFrameSplitOperator.IsNumber(item.DateTime.Time)) dateTime.Time=item.DateTime.Time;
  364. aryDateTime[i]=dateTime;
  365. }
  366. data.FindDataIndexByDateTime(aryDateTime);
  367. for(var i in aryDateTime)
  368. {
  369. var findItem=aryDateTime[i];
  370. var valueItem=this.Value[i];
  371. if (findItem.Index>=0) valueItem.XValue=findItem.Index;
  372. }
  373. }
  374. //xStep,yStep 移动的偏移量
  375. this.Move=function(xStep,yStep)
  376. {
  377. if (this.Status!=20) return false;
  378. if (!this.Frame) return false;
  379. var data=this.Frame.Data;
  380. if (!data) return false;
  381. if (this.MovePointIndex==null) return false;
  382. var index=parseInt(this.MovePointIndex);
  383. if (index===100) //整体移动
  384. {
  385. if (this.IsMoveOutOfBounds(this.Point, xStep, yStep)) return false;
  386. for(var i in this.Point)
  387. {
  388. this.Point[i].X+=xStep;
  389. this.Point[i].Y+=yStep;
  390. }
  391. }
  392. else if (index===0 || index===1 || index===2 || index===3 || index===4 || index===5)
  393. {
  394. if (index<this.Point.length)
  395. {
  396. this.Point[index].X+=xStep;
  397. this.Point[index].Y+=yStep;
  398. }
  399. }
  400. else
  401. {
  402. return false;
  403. }
  404. }
  405. //是否超出边界了
  406. this.IsMoveOutOfBounds=function(aryPoint,xStep,yStep)
  407. {
  408. if (!this.EnableMoveCheck) return false;
  409. if (!this.Frame) return false;
  410. if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame")
  411. return false;
  412. var data=this.Frame.Data;
  413. if (!data) return false;
  414. if (!IFrameSplitOperator.IsNonEmptyArray(data.Data)) return false;
  415. if (!IFrameSplitOperator.IsNonEmptyArray(aryPoint)) return false;
  416. var isHScreen=this.Frame.IsHScreen;
  417. if (isHScreen)
  418. {
  419. //TODO:横屏以后再做
  420. return false;
  421. }
  422. else
  423. {
  424. var offset=data.DataOffset;
  425. var startIndex=0-offset;
  426. var endIndex=data.Data.length-offset;
  427. if (xStep>0)
  428. {
  429. var xEnd=this.Frame.GetXFromIndex(endIndex-1,false);
  430. for(var i=0;i<aryPoint.length;++i)
  431. {
  432. var item=aryPoint[i];
  433. if (item.X+xStep>xEnd) return true;
  434. }
  435. }
  436. else if (xStep<0)
  437. {
  438. var xStart=this.Frame.GetXFromIndex(startIndex,false);
  439. for(var i=0;i<aryPoint.length;++i)
  440. {
  441. var item=aryPoint[i];
  442. if (item.X+xStep<xStart) return true;
  443. }
  444. }
  445. return false;
  446. }
  447. }
  448. this.ClipFrame=function()
  449. {
  450. if (this.Frame.IsHScreen)
  451. {
  452. var left=this.Frame.ChartBorder.GetLeftEx();
  453. var top=this.Frame.ChartBorder.GetTop();
  454. var width=this.Frame.ChartBorder.GetWidthEx();
  455. var height=this.Frame.ChartBorder.GetHeight();
  456. }
  457. else
  458. {
  459. var left=this.Frame.ChartBorder.GetLeft();
  460. var top=this.Frame.ChartBorder.GetTopEx();
  461. var width=this.Frame.ChartBorder.GetWidth();
  462. var height=this.Frame.ChartBorder.GetHeightEx();
  463. }
  464. this.Canvas.save();
  465. this.Canvas.beginPath();
  466. this.Canvas.rect(left,top,width,height);
  467. this.Canvas.clip();
  468. }
  469. //计算需要画的点的坐标option:{IsCheckX:是否检测X值, IsCheckY:是否检测Y值}
  470. this.CalculateDrawPoint=function(option)
  471. {
  472. if (this.Status<2) return null;
  473. if(!this.Point.length || !this.Frame) return null;
  474. var drawPoint=[];
  475. if (this.Status==10)
  476. {
  477. var data=this.Frame.Data;
  478. if (!data) return null;
  479. var showCount=this.Frame.XPointCount;
  480. var invaildX=0; //超出范围的x点个数
  481. var isHScreen=this.Frame.IsHScreen;
  482. for(var i=0; i<this.Value.length; ++i)
  483. {
  484. var item=this.Value[i];
  485. var dataIndex=item.XValue-data.DataOffset;
  486. if (dataIndex<0 || dataIndex>=showCount) ++invaildX;
  487. var pt=new Point();
  488. if (isHScreen) //横屏X,Y对调
  489. {
  490. pt.Y=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false);
  491. pt.X=this.Frame.GetYFromData(item.YValue,false);
  492. }
  493. else
  494. {
  495. pt.X=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false);
  496. pt.Y=this.Frame.GetYFromData(item.YValue,false);
  497. }
  498. drawPoint.push(pt);
  499. }
  500. if (option && option.IsCheckX===true)
  501. {
  502. if (invaildX==this.Value.length) return null;
  503. }
  504. }
  505. else //移动中
  506. {
  507. for(var i=0;i<this.Point.length;++i)
  508. {
  509. var item=this.Point[i];
  510. drawPoint.push({ X:item.X, Y:item.Y });
  511. }
  512. if (this.OnlyMoveXIndex)
  513. {
  514. var option= { IsFixedX:this.OnlyMoveXIndex };
  515. JSConsole.Chart.Log(`[IChartDrawPicture::CalculateDrawPoint] Status=${this.Status} MovePointIndex=${this.MovePointIndex} Identify=${this.Frame.Identify}`);
  516. //磁吸功能
  517. if (this.Option && this.Option.Magnet && this.Option.Magnet.Enable && this.IsSupportMagnet && this.Frame.Identify==0)
  518. {
  519. var pointIndex=-1;
  520. if (this.Status==2) pointIndex=1; //创建第2个点
  521. if (IFrameSplitOperator.IsNumber(this.MovePointIndex)) pointIndex=this.MovePointIndex;
  522. if (pointIndex>=0)
  523. {
  524. option.Magnet=
  525. {
  526. Enable:true,
  527. PointIndex:pointIndex,
  528. Distance:this.Option.Magnet.Distance,
  529. Type:this.Option.Magnet.Type
  530. }
  531. }
  532. }
  533. this.AdjustPoint(drawPoint,option)
  534. }
  535. }
  536. return drawPoint;
  537. }
  538. //修正X, Y轴坐标
  539. this.AdjustPoint=function(aryPoint, option)
  540. {
  541. if (!this.Frame) return false;
  542. if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame")
  543. return false;
  544. return this.AdjustPoint_KLine(aryPoint, option);
  545. }
  546. this.AdjustPoint_KLine=function(aryPoint, option)
  547. {
  548. if (!option) return false;
  549. if (!this.Frame) return false;
  550. var data=this.Frame.Data;
  551. if (!data) return false;
  552. var isHScreen=this.Frame.IsHScreen;
  553. if (isHScreen)
  554. {
  555. for(var i=0; i<aryPoint.length; ++i)
  556. {
  557. var item=aryPoint[i];
  558. var xValue=parseInt(this.Frame.GetXData(item.Y))+data.DataOffset;
  559. }
  560. }
  561. else
  562. {
  563. for(var i=0; i<aryPoint.length; ++i)
  564. {
  565. var item=aryPoint[i];
  566. var index=parseInt(this.Frame.GetXData(item.X,false));
  567. var xValue=index+data.DataOffset;
  568. if (xValue<0) xValue=0;
  569. else if (xValue>=data.Data.length) xValue=data.Data.length-1;
  570. if (option.IsFixedX)
  571. {
  572. index=xValue-data.DataOffset;
  573. item.X=this.Frame.GetXFromIndex(index,false);
  574. }
  575. //磁吸
  576. if (option.Magnet && option.Magnet.Enable && i==option.Magnet.PointIndex)
  577. {
  578. var kline=data.Data[xValue];
  579. var aryKValue=[kline.Open, kline.High, kline.Low, kline.Close];
  580. var yMinDistance=null, yKLine=null;
  581. for(var j=0; j<aryKValue.length; ++j)
  582. {
  583. var yPrice=this.Frame.GetYFromData(aryKValue[j]);
  584. var value=Math.abs(item.Y-yPrice);
  585. if (!IFrameSplitOperator.IsNumber(yMinDistance) || yMinDistance>value)
  586. {
  587. yMinDistance=value;
  588. yKLine=yPrice;
  589. }
  590. }
  591. if (option.Magnet.Type==1) //只能在K线上
  592. {
  593. if (IFrameSplitOperator.IsNumber(yKLine))
  594. item.Y=yKLine;
  595. }
  596. else
  597. {
  598. if (yMinDistance<option.Magnet.Distance && IFrameSplitOperator.IsNumber(yKLine))
  599. item.Y=yKLine;
  600. }
  601. }
  602. }
  603. }
  604. }
  605. this.IsYValueInFrame=function(yValue)
  606. {
  607. if (!this.Frame) return false;
  608. if (yValue>this.Frame.HorizontalMax || yValue<this.Frame.HorizontalMin) return false;
  609. return true;
  610. }
  611. this.DrawPoint=function(aryPoint)
  612. {
  613. if (!IFrameSplitOperator.IsNonEmptyArray(aryPoint)) return;
  614. var color=this.PointColor;
  615. var isMoveOn=false;
  616. if (this.IsShowPoint)
  617. {
  618. }
  619. else
  620. {
  621. if (this.GetActiveDrawPicture)
  622. {
  623. var active=this.GetActiveDrawPicture();
  624. if (active.Move.Guid!=this.Guid && active.Select.Guid!=this.Guid && active.MoveOn.Guid!=this.Guid)
  625. return;
  626. if (active.Select.Guid!=this.Guid && active.MoveOn.Guid==this.Guid)
  627. {
  628. isMoveOn=true;
  629. color=this.MoveOnPointColor;
  630. }
  631. }
  632. }
  633. //画点
  634. this.ClipFrame();
  635. var pixel=1;
  636. this.Canvas.fillStyle=color; //填充颜色
  637. if (this.PointType==2)
  638. {
  639. this.Canvas.fillStyle=this.PointBGColor; //背景填充颜色
  640. this.Canvas.strokeStyle=this.PointColor;
  641. if (isMoveOn) this.Canvas.lineWidth=1*pixel;
  642. else this.Canvas.lineWidth=2*pixel;
  643. }
  644. for(var i=0; i<aryPoint.length; ++i)
  645. {
  646. var item=aryPoint[i];
  647. if (this.PointType==1) //正方形
  648. {
  649. var value=this.SquareSize*pixel;
  650. var x=item.X-value/2;
  651. var y=item.Y-value/2;
  652. this.Canvas.fillRect(x,y,value,value); //画一个背景色, 不然是一个黑的背景
  653. }
  654. else if (this.PointType==2) //空心圆
  655. {
  656. var path=new Path2D();
  657. path.arc(item.X,item.Y,this.PointRadius*pixel,0,360,false);
  658. this.Canvas.fill(path);
  659. this.Canvas.stroke(path);
  660. }
  661. else //实心圆
  662. {
  663. this.Canvas.beginPath();
  664. this.Canvas.arc(item.X,item.Y,this.PointRadius*pixel,0,360,false);
  665. this.Canvas.fill(); //画实心圆
  666. this.Canvas.closePath();
  667. }
  668. }
  669. this.Canvas.restore();
  670. }
  671. this.DrawArrow=function(ptStart,ptEnd)
  672. {
  673. //计算箭头
  674. var theta=35; //三角斜边一直线夹角
  675. var headlen=10; //三角斜边长度
  676. var angle = Math.atan2(ptStart.Y - ptEnd.Y, ptStart.X - ptEnd.X) * 180 / Math.PI,
  677. angle1 = (angle + theta) * Math.PI / 180,
  678. angle2 = (angle - theta) * Math.PI / 180,
  679. topX = headlen * Math.cos(angle1),
  680. topY = headlen * Math.sin(angle1),
  681. botX = headlen * Math.cos(angle2),
  682. botY = headlen * Math.sin(angle2);
  683. this.Canvas.beginPath();
  684. var arrowX = ptEnd.X + topX;
  685. var arrowY = ptEnd.Y + topY;
  686. this.Canvas.moveTo(arrowX,arrowY);
  687. this.Canvas.lineTo(ptEnd.X, ptEnd.Y);
  688. arrowX = ptEnd.X + botX;
  689. arrowY = ptEnd.Y + botY;
  690. this.Canvas.lineTo(arrowX,arrowY);
  691. this.Canvas.stroke();
  692. }
  693. //计算2个点线的,左右的延长线的点
  694. this.CalculateExtendLinePoint=function(ptStart,ptEnd)
  695. {
  696. var result={};
  697. var left=this.Frame.ChartBorder.GetLeft();
  698. var right=this.Frame.ChartBorder.GetRight();
  699. var top=this.Frame.ChartBorder.GetTopEx();
  700. var bottom=this.Frame.ChartBorder.GetBottom();
  701. var a=ptEnd.X-ptStart.X;
  702. var b=ptEnd.Y-ptStart.Y;
  703. if (a>0)
  704. {
  705. var b2=bottom-ptStart.Y;
  706. var a2=a*b2/b;
  707. var pt=new Point();
  708. pt.X=ptStart.X+a2;
  709. pt.Y=bottom;
  710. result.End=pt;
  711. var b2=ptEnd.Y-top;
  712. var a2=a*b2/b;
  713. var pt2=new Point();
  714. pt2.Y=top;
  715. pt2.X=ptEnd.X-a2;
  716. result.Start=pt2;
  717. }
  718. else
  719. {
  720. var b2=bottom-ptStart.Y;
  721. var a2=Math.abs(a)*b2/b;
  722. var pt=new Point();
  723. pt.X=ptStart.X-a2;;
  724. pt.Y=bottom;
  725. result.End=pt;
  726. var b2=ptEnd.Y-top;
  727. var a2=Math.abs(a)*b2/b;
  728. var pt2=new Point();
  729. pt2.Y=top;
  730. pt2.X=ptEnd.X+a2;
  731. result.Start=pt2;
  732. }
  733. return result;
  734. }
  735. //计算2个点线的,点0->点1->延长线的点
  736. this.CalculateExtendLineEndPoint=function(aryPoint)
  737. {
  738. var left=this.Frame.ChartBorder.GetLeft();
  739. var right=this.Frame.ChartBorder.GetRight();
  740. var bottom=this.Frame.ChartBorder.GetBottomEx();
  741. var top=this.Frame.ChartBorder.GetTopEx();
  742. var a=aryPoint[1].X-aryPoint[0].X;
  743. var b=aryPoint[1].Y-aryPoint[0].Y;
  744. if (a>0)
  745. {
  746. var a1=right-aryPoint[0].X;
  747. var b1=a1*b/a;
  748. var y=b1+aryPoint[0].Y;
  749. if (y>=top && y<=bottom)
  750. {
  751. var pt=new Point();
  752. pt.X=right;
  753. pt.Y=y;
  754. return pt;
  755. }
  756. if (b>0)
  757. {
  758. var b2=bottom-aryPoint[0].Y;
  759. var a2=a*b2/b;
  760. var x=a2+aryPoint[0].X;
  761. var pt2=new Point();
  762. pt2.X=x;
  763. pt2.Y=bottom;
  764. return pt2;
  765. }
  766. else if (b==0)
  767. {
  768. var pt2=new Point();
  769. pt2.X=right;
  770. pt2.Y=aryPoint[0].Y;
  771. return pt2;
  772. }
  773. else
  774. {
  775. var b2=top-aryPoint[0].Y;
  776. var a2=a*b2/b;
  777. var x=a2+aryPoint[0].X;
  778. var pt2=new Point();
  779. pt2.X=x;
  780. pt2.Y=top;
  781. return pt2;
  782. }
  783. }
  784. else
  785. {
  786. var a1=aryPoint[0].X-left;
  787. var b1=a1*b/Math.abs(a);
  788. var y=b1+aryPoint[0].Y;
  789. if (y>=top && y<=bottom)
  790. {
  791. var pt=new Point();
  792. pt.X=left;
  793. pt.Y=y;
  794. return pt;
  795. }
  796. if (b>0)
  797. {
  798. var b2=bottom-aryPoint[0].Y;
  799. var a2=a*b2/b;
  800. var x=a2+aryPoint[0].X;
  801. var pt2=new Point();
  802. pt2.X=x;
  803. pt2.Y=bottom;
  804. return pt2;
  805. }
  806. else if (b==0)
  807. {
  808. var pt2=new Point();
  809. pt2.X=left;
  810. pt2.Y=aryPoint[0].Y;
  811. return pt2;
  812. }
  813. else
  814. {
  815. var b2=top-aryPoint[0].Y;
  816. var a2=a*b2/b;
  817. var x=a2+aryPoint[0].X;
  818. var pt2=new Point();
  819. pt2.X=x;
  820. pt2.Y=top;
  821. return pt2;
  822. }
  823. }
  824. }
  825. //坐标是否在点上 返回在第几个点上
  826. this.IsPointInXYValue=function(x, y, option)
  827. {
  828. if (!this.Frame) return -1;
  829. var data=this.Frame.Data;
  830. if (!data) return -1;
  831. if (!this.Value) return -1;
  832. var radius=this.TouchConfig.Point.Radius;
  833. if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom;
  834. else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom;
  835. var isHScreen=this.Frame.IsHScreen;
  836. for(var i=0;i<this.Value.length; ++i) //是否在点上
  837. {
  838. var item=this.Value[i];
  839. var pt=new Point();
  840. if (isHScreen)
  841. {
  842. pt.Y=this.Frame.GetXFromIndex(item.XValue-data.DataOffset);
  843. pt.X=this.Frame.GetYFromData(item.YValue);
  844. }
  845. else
  846. {
  847. pt.X=this.Frame.GetXFromIndex(item.XValue-data.DataOffset);
  848. pt.Y=this.Frame.GetYFromData(item.YValue);
  849. }
  850. this.Canvas.beginPath();
  851. this.Canvas.arc(pt.X,pt.Y,radius,0,360);
  852. if (this.Canvas.isPointInPath(x,y)) return i;
  853. }
  854. return -1;
  855. }
  856. //坐标是否在线段上 返回在第几个线段上
  857. this.IsPointInLine=function(x, y, option)
  858. {
  859. if (!this.LinePoint) return -1;
  860. var lineWidth=this.TouchConfig.Line.Width;
  861. if (IFrameSplitOperator.IsPlusNumber(this.PixelRatio)) lineWidth=this.PixelRatio*this.TouchConfig.Line.Width
  862. for(var i=0;i<this.LinePoint.length; ++i)
  863. {
  864. var item=this.LinePoint[i];
  865. var ptStart=item.Start;
  866. var ptEnd=item.End;
  867. this.Canvas.beginPath();
  868. if (ptStart.X==ptEnd.X) //竖线
  869. {
  870. this.Canvas.moveTo(ptStart.X-lineWidth,ptStart.Y);
  871. this.Canvas.lineTo(ptStart.X+lineWidth,ptStart.Y);
  872. this.Canvas.lineTo(ptEnd.X+lineWidth,ptEnd.Y);
  873. this.Canvas.lineTo(ptEnd.X-lineWidth,ptEnd.Y);
  874. }
  875. else
  876. {
  877. this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth);
  878. this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth);
  879. this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth);
  880. this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth);
  881. }
  882. this.Canvas.closePath();
  883. //for debug
  884. //this.Canvas.fillStyle='RGB(22,100,100)';
  885. //this.Canvas.fill();
  886. if (this.Canvas.isPointInPath(x,y))
  887. return i;
  888. }
  889. return -1;
  890. }
  891. //0-10 鼠标对应的点索引 100=鼠标在正个图形上 -1 鼠标不在图形上
  892. this.IsPointIn_XYValue_Line=function(x, y, option)
  893. {
  894. if (this.Status!=10) return -1;
  895. var value=this.IsPointInXYValue(x,y,option);
  896. if (value>=0) return value;
  897. value=this.IsPointInLine(x,y,option);
  898. if (value>=0) return 100;
  899. return -1;
  900. }
  901. this.DrawLine=function(ptStart,ptEnd,isDottedline)
  902. {
  903. if (isDottedline) this.Canvas.setLineDash([5,10]);
  904. this.Canvas.strokeStyle=this.LineColor;
  905. this.Canvas.beginPath();
  906. this.Canvas.moveTo(ptStart.X,ptStart.Y);
  907. this.Canvas.lineTo(ptEnd.X,ptEnd.Y);
  908. this.Canvas.stroke();
  909. if (isDottedline) this.Canvas.setLineDash([]);
  910. }
  911. this.CreateLineData=function(ptStart,ptEnd)
  912. {
  913. var line={Start:new Point(), End:new Point()};
  914. line.Start.Y=ptStart.Y;
  915. line.Start.X=ptStart.X;
  916. line.End.Y=ptEnd.Y;
  917. line.End.X=ptEnd.X;
  918. return line;
  919. }
  920. //导出成存储格式
  921. this.ExportStorageData=function()
  922. {
  923. var storageData=
  924. {
  925. ClassName:this.ClassName,
  926. Symbol:this.Symbol, Guid:this.Guid, Period:this.Period,Value:[] ,
  927. FrameID:this.Frame.Identify, LineColor:this.LineColor, AreaColor:this.AreaColor,
  928. LineWidth:this.LineWidth, Right:this.Right, EnableSave:this.EnableSave,
  929. IsShowYCoordinate:this.IsShowYCoordinate
  930. };
  931. for(var i=0; i<this.Value.length; ++i)
  932. {
  933. var item=this.Value[i];
  934. storageData.Value.push({ XValue:item.XValue, YValue:item.YValue, DateTime:item.DateTime });
  935. }
  936. if (this.Text) storageData.Text=this.Text; //如果有文本, 也导出
  937. if (this.FontOption) storageData.FontOption=this.FontOption; //字体也导出
  938. return storageData;
  939. }
  940. //导出基础的配置 不包含点
  941. this.ExportBaseData=function()
  942. {
  943. var data=
  944. {
  945. ClassName:this.ClassName, Guid:this.Guid, FrameID:this.Frame.Identify,
  946. Symbol:this.Symbol, Period:this.Period,Right:this.Right,
  947. LineColor:this.LineColor,
  948. LineWidth:this.LineWidth,
  949. EnableSave:this.EnableSave, IsShowYCoordinate:this.IsShowYCoordinate
  950. };
  951. if (this.AreaColor) data.AreaColor=this.AreaColor;
  952. if (this.Text) data.Text=this.Text; //如果有文本, 也导出
  953. if (this.FontOption)
  954. {
  955. data.FontOption={};
  956. this.SetFont(data.FontOption, this.FontOption); //字体也导出
  957. }
  958. return data;
  959. }
  960. this.IsFrameMinSize=function() //框架是否是最小化模式
  961. {
  962. return this.Frame && this.Frame.IsMinSize;
  963. }
  964. this.PointRange=function(aryPoint)
  965. {
  966. if (!IFrameSplitOperator.IsNonEmptyArray(aryPoint)) return null;
  967. if (aryPoint.length==1)
  968. {
  969. var data=
  970. {
  971. Points:[ { X:aryPoint[0].X, Y:aryPoint[0].Y } ]
  972. };
  973. return data;
  974. }
  975. else
  976. {
  977. var xMax=aryPoint[0].X;
  978. var xMin=xMax;
  979. var yMax=aryPoint[0].Y;
  980. var yMin=yMax;
  981. var aryData=[{ X:aryPoint[0].X, Y:aryPoint[0].Y }];
  982. for(var i=1;i<aryPoint.length;++i)
  983. {
  984. if (xMax<aryPoint[i].X) xMax=aryPoint[i].X;
  985. if (xMin>aryPoint[i].X) xMin=aryPoint[i].X;
  986. if (yMax<aryPoint[i].Y) yMax=aryPoint[i].Y;
  987. if (yMin>aryPoint[i].Y) yMin=aryPoint[i].Y;
  988. aryData.push({X:aryPoint[i].X, Y:aryPoint[i].Y});
  989. }
  990. var data=
  991. {
  992. X: { Max: { X:xMax }, Min: { X:xMin} },
  993. Y: { Max: { Y:yMax}, Min: { Y:yMin} },
  994. Points: aryData //所有的点
  995. };
  996. return data;
  997. }
  998. }
  999. this.GetXYCoordinate_default=function()
  1000. {
  1001. if (this.IsFrameMinSize()) return null;
  1002. var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} );
  1003. return this.PointRange(drawPoint);
  1004. }
  1005. this.GetXYCoordinate=function()
  1006. {
  1007. return null;
  1008. }
  1009. this.CopyData_default=function()
  1010. {
  1011. if (!this.Frame) return null;
  1012. var data=this.ExportStorageData();
  1013. if (!data) return null;
  1014. var dataOffset=0;
  1015. if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame")
  1016. {
  1017. }
  1018. else
  1019. {
  1020. var kData=this.Frame.Data;
  1021. if (!kData) return null;
  1022. dataOffset=kData.DataOffset;
  1023. }
  1024. var height=this.Frame.ChartBorder.GetHeight();
  1025. var yFirst=this.Frame.ChartBorder.GetBottomEx()-this.Point[0].Y;
  1026. for(var i=0;i<data.Value.length; ++i)
  1027. {
  1028. var item=data.Value[i];
  1029. var itemPoint=this.Point[i];
  1030. item.XIndex=item.XValue-dataOffset+1;
  1031. if (i==0)
  1032. {
  1033. item.XOffset=0;
  1034. item.YOffset=0;
  1035. }
  1036. else
  1037. {
  1038. var preItem=data.Value[i-1];
  1039. var prePoint=this.Point[i-1];
  1040. item.XOffset=item.XValue-preItem.XValue;
  1041. item.YOffset=itemPoint.Y-prePoint.Y;
  1042. }
  1043. }
  1044. data.DataOffset=dataOffset;
  1045. data.YFristScale=yFirst/height;
  1046. data.Height=height; //Y轴最大-最小差值
  1047. return data;
  1048. }
  1049. this.SetFont=function(destFont, srcFont)
  1050. {
  1051. if (!srcFont) return;
  1052. if (!destFont) return;
  1053. if (srcFont.Family) destFont.Family=srcFont.Family;
  1054. if (srcFont.Weight) destFont.Weight=srcFont.Weight;
  1055. if (srcFont.Style) destFont.Style=srcFont.Style;
  1056. if (IFrameSplitOperator.IsNumber(srcFont.Size)) destFont.Size=srcFont.Size;
  1057. }
  1058. this.GetFontString=function(fontOption)
  1059. {
  1060. const defaultFont="16px 微软雅黑";
  1061. if (!fontOption || !fontOption.Family || !IFrameSplitOperator.IsPlusNumber(fontOption.Size)) return defaultFont;
  1062. var font='';
  1063. if (fontOption.Color) font+=fontOption.Color+' ';
  1064. if (fontOption.Style) font+=fontOption.Style+' ';
  1065. if (fontOption.Weight) font+=fontOption.Weight+' ';
  1066. font+=fontOption.Size+'px ';
  1067. font+=fontOption.Family;
  1068. return font;
  1069. }
  1070. //获得多行文本
  1071. this.GetMultiLineText=function(text, maxWidth, font , option)
  1072. {
  1073. if (font) this.Canvas.font=font;
  1074. var textWidth=this.Canvas.measureText(text).width;
  1075. if (textWidth<=maxWidth) return { AryText:[{Text:text }] };
  1076. var singleWidth=this.Canvas.measureText("擎").width;
  1077. var estimateCount=parseInt(maxWidth/singleWidth); //预估个数
  1078. var endPos=0;
  1079. var aryText=[];
  1080. while(endPos<text.length-1)
  1081. {
  1082. var count=estimateCount;
  1083. var pos=endPos+count;
  1084. if (pos>=text.length)
  1085. {
  1086. pos=text.length-1;
  1087. count=pos-endPos;
  1088. }
  1089. var subText=text.slice(endPos,endPos+count);
  1090. var textWidth=this.Canvas.measureText(subText).width;
  1091. if (textWidth>maxWidth)
  1092. {
  1093. for(var i=count; i>=0 ;--i)
  1094. {
  1095. subText=text.slice(endPos, endPos+i);
  1096. textWidth=this.Canvas.measureText(subText).width;
  1097. if (textWidth<maxWidth)
  1098. {
  1099. aryText.push({Text:subText});
  1100. endPos+=i;
  1101. break;
  1102. }
  1103. }
  1104. }
  1105. else if (textWidth<maxWidth)
  1106. {
  1107. var bFind=false;
  1108. for(var i=count;(i+endPos)<=text.length;++i)
  1109. {
  1110. subText=text.slice(endPos, endPos+i);
  1111. textWidth=this.Canvas.measureText(subText).width;
  1112. if (textWidth>maxWidth)
  1113. {
  1114. subText=text.slice(endPos, endPos+i-1);
  1115. aryText.push({Text:subText});
  1116. endPos+=i-1;
  1117. bFind=true;
  1118. break;
  1119. }
  1120. }
  1121. if (!bFind)
  1122. {
  1123. aryText.push({Text:subText});
  1124. endPos=text.length-1;
  1125. }
  1126. }
  1127. else
  1128. {
  1129. aryText.push({Text:subText});
  1130. endPos+=count;
  1131. }
  1132. }
  1133. return { AryText:aryText };
  1134. }
  1135. this.CloneArrayText=function(aryText)
  1136. {
  1137. if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return [];
  1138. var aryValue=[];
  1139. for(var i=0;i<aryText.length;++i)
  1140. {
  1141. var item=aryText[i];
  1142. if (!item) continue;
  1143. aryValue.push({ Text:item.Text });
  1144. }
  1145. return aryValue;
  1146. }
  1147. //计算角度
  1148. this.CalculateAngle=function(x1, y1, x2,y2)
  1149. {
  1150. var x = Math.abs(x1 - x2);
  1151. var y = Math.abs(y1 - y2);
  1152. var z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
  1153. var cos = x / z;
  1154. var radina = Math.acos(cos); //用反三角函数求弧度
  1155. var angle = 180 / (Math.PI / radina);//将弧度转换成角度
  1156. if (x2 == x1 && y2 < y1)
  1157. return 90;
  1158. if (x2 == x1 && y2 > y1)
  1159. return 270;
  1160. if (x2 > x1 && y2 == y1)
  1161. return 0;
  1162. if (x2 < x1 && y2 == y1)
  1163. return 180;
  1164. if (x2 > x1 && y2 > y1) //第四象限
  1165. return 360 - angle;
  1166. if (x2 < x1 && y2 > y1) //第三象限
  1167. return 180 + angle;
  1168. if (x2 < x1 && y2 < y1) //第二象限
  1169. return 180 - angle;
  1170. return angle;
  1171. }
  1172. //复制
  1173. //this.CopyData=function() { }
  1174. //this.PtInButtons=function(x, y) { }
  1175. }
  1176. IChartDrawPicture.ArrayDrawPricture=
  1177. [
  1178. { Name:"线段", ClassName:'ChartDrawPictureLine', Create:function() { return new ChartDrawPictureLine(); } },
  1179. { Name:"射线", ClassName:'ChartDrawPictureHaflLine', Create:function() { return new ChartDrawPictureHaflLine(); } },
  1180. { Name:"箭头", ClassName:"ChartDrawArrowLine", Create:function() { return new ChartDrawArrowLine(); } },
  1181. { Name:"水平线", ClassName:'ChartDrawPictureHorizontalLine', Create:function() { return new ChartDrawPictureHorizontalLine(); }},
  1182. { Name:"标价线2", ClassName:"ChartDrawPriceLineV2", Create:function() { return new ChartDrawPriceLineV2(); } },
  1183. ];
  1184. IChartDrawPicture.GetDrawPictureByName=function(value)
  1185. {
  1186. for(var i=0; i<IChartDrawPicture.ArrayDrawPricture.length; ++i)
  1187. {
  1188. var item=IChartDrawPicture.ArrayDrawPricture[i];
  1189. if (item.Name==value) return item;
  1190. }
  1191. return null;
  1192. }
  1193. IChartDrawPicture.CreateChartDrawPicture=function(obj) //创建画图工具
  1194. {
  1195. var item=IChartDrawPicture.GetDrawPictureByClassName(obj.ClassName);
  1196. if (!item) return null;
  1197. var chartDraw=item.Create();
  1198. //TODO:后面都放到每一个SetOptin里面
  1199. if (obj.Period>=0) chartDraw.Period=obj.Period;
  1200. if (obj.Right>=0) chartDraw.Right=obj.Right;
  1201. if (obj.Guid) chartDraw.Guid=obj.Guid;
  1202. if (obj.Symbol) chartDraw.Symbol=obj.Symbol;
  1203. if (obj.Value) chartDraw.Value=obj.Value;
  1204. if (obj.Text) chartDraw.Text=obj.Text;
  1205. if (obj.LineColor) chartDraw.LineColor=obj.LineColor;
  1206. if (obj.AreaColor) chartDraw.AreaColor=obj.AreaColor;
  1207. if (obj.FontOption) chartDraw.FontOption=obj.FontOption;
  1208. if (obj.Label) chartDraw.Label=obj.Label;
  1209. if (obj.LineWidth>0) chartDraw.LineWidth=obj.LineWidth;
  1210. if (obj.EnableMove===false) chartDraw.EnableMove=obj.EnableMove;
  1211. if (IFrameSplitOperator.IsBool(obj.EnableSave)) chartDraw.EnableSave=obj.EnableSave;
  1212. if (IFrameSplitOperator.IsNumber(obj.ChannelWidth)) chartDraw.ChannelWidth=obj.ChannelWidth;
  1213. if (IFrameSplitOperator.IsBool(obj.IsShowYCoordinate)) chartDraw.IsShowYCoordinate=obj.IsShowYCoordinate;
  1214. if (chartDraw.SetOption) chartDraw.SetOption(obj);
  1215. return chartDraw;
  1216. }
  1217. //画图工具-线段
  1218. function ChartDrawPictureLine()
  1219. {
  1220. this.newMethod=IChartDrawPicture; //派生
  1221. this.newMethod();
  1222. delete this.newMethod;
  1223. this.ClassName='ChartDrawPictureLine';
  1224. this.IsPointIn=this.IsPointIn_XYValue_Line;
  1225. this.GetXYCoordinate=this.GetXYCoordinate_default;
  1226. this.IsShowYCoordinate=false;
  1227. this.CopyData=this.CopyData_default;
  1228. this.OnlyMoveXIndex=true;
  1229. this.IsSupportMagnet=true;
  1230. this.Draw=function()
  1231. {
  1232. this.LinePoint=[];
  1233. if (this.IsFrameMinSize()) return;
  1234. if (!this.IsShow) return;
  1235. var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} );
  1236. if (!drawPoint) return;
  1237. if (drawPoint.length!=2) return;
  1238. this.ClipFrame();
  1239. var ptStart=drawPoint[0];
  1240. var ptEnd=drawPoint[1];
  1241. this.SetLineWidth();
  1242. this.Canvas.strokeStyle=this.LineColor;
  1243. this.Canvas.beginPath();
  1244. this.Canvas.moveTo(ptStart.X,ptStart.Y);
  1245. this.Canvas.lineTo(ptEnd.X,ptEnd.Y);
  1246. this.Canvas.stroke();
  1247. this.RestoreLineWidth();
  1248. /*
  1249. if (this.IsSelected)
  1250. {
  1251. this.Canvas.strokeStyle='rgba(255,0,0,0.5)';
  1252. this.Canvas.lineWidth=20 * GetDevicePixelRatio();
  1253. this.Canvas.stroke();
  1254. }
  1255. */
  1256. var line={Start:ptStart, End:ptEnd};
  1257. this.LinePoint.push(line);
  1258. this.DrawPoint(drawPoint); //画点
  1259. this.Canvas.restore();
  1260. }
  1261. this.GetYCoordinatePoint=function()
  1262. {
  1263. if (this.IsFrameMinSize()) return null;
  1264. if (this.Status<2) return null;
  1265. if(!this.Point.length || !this.Frame) return null;
  1266. if (this.Status!=10) return null;
  1267. //完成
  1268. var aryPoint=[];
  1269. for(var i=0; i<this.Value.length; ++i)
  1270. {
  1271. var item=this.Value[i];
  1272. var y=this.Frame.GetYFromData(item.YValue,false);
  1273. aryPoint.push({ Y:y, YValue:item.YValue, Item:item, Color:this.PointColor });
  1274. }
  1275. return aryPoint;
  1276. }
  1277. }
  1278. //画图工具-射线
  1279. function ChartDrawPictureHaflLine()
  1280. {
  1281. this.newMethod=IChartDrawPicture; //派生
  1282. this.newMethod();
  1283. delete this.newMethod;
  1284. this.ClassName='ChartDrawPictureHaflLine';
  1285. this.GetXYCoordinate=this.GetXYCoordinate_default;
  1286. this.OnlyMoveXIndex=true;
  1287. this.IsSupportMagnet=true;
  1288. this.FullLine;
  1289. this.IsPointIn=function(x, y, option)
  1290. {
  1291. var result=this.IsPointIn_XYValue_Line(x,y,option);
  1292. if (result>=0) return result;
  1293. if (!this.FullLine) return result;
  1294. var ptStart=this.FullLine.Start;
  1295. var ptEnd=this.FullLine.End;
  1296. var lineWidth=this.TouchConfig.Line.Width;
  1297. this.Canvas.beginPath();
  1298. if (ptStart.X==ptEnd.X) //竖线
  1299. {
  1300. this.Canvas.moveTo(ptStart.X-lineWidth,ptStart.Y);
  1301. this.Canvas.lineTo(ptStart.X+lineWidth,ptStart.Y);
  1302. this.Canvas.lineTo(ptEnd.X+lineWidth,ptEnd.Y);
  1303. this.Canvas.lineTo(ptEnd.X-lineWidth,ptEnd.Y);
  1304. }
  1305. else
  1306. {
  1307. this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth);
  1308. this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth);
  1309. this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth);
  1310. this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth);
  1311. }
  1312. this.Canvas.closePath();
  1313. if (this.Canvas.isPointInPath(x,y))
  1314. return 100;
  1315. return result;
  1316. }
  1317. this.Draw=function()
  1318. {
  1319. this.LinePoint=[];
  1320. this.FullLine=null;
  1321. if (this.IsFrameMinSize()) return;
  1322. if (!this.IsShow) return;
  1323. var drawPoint=this.CalculateDrawPoint({IsCheckX:false, IsCheckY:false});
  1324. if (!drawPoint || drawPoint.length!=2) return;
  1325. var ptStart=drawPoint[0];
  1326. var ptEnd=drawPoint[1];
  1327. this.ClipFrame();
  1328. this.Canvas.strokeStyle=this.LineColor;
  1329. this.SetLineWidth();
  1330. this.Canvas.beginPath();
  1331. this.Canvas.moveTo(drawPoint[0].X,drawPoint[0].Y);
  1332. this.Canvas.lineTo(drawPoint[1].X,drawPoint[1].Y);
  1333. var endPoint=this.CalculateExtendLineEndPoint(drawPoint);
  1334. this.Canvas.lineTo(endPoint.X,endPoint.Y);
  1335. this.Canvas.stroke();
  1336. this.RestoreLineWidth();
  1337. var line={Start:ptStart, End:ptEnd};
  1338. this.LinePoint.push(line);
  1339. this.DrawPoint(drawPoint); //画点
  1340. this.Canvas.restore();
  1341. this.FullLine={Start:drawPoint[0], End:endPoint};
  1342. }
  1343. }
  1344. //画图工具-箭头线
  1345. function ChartDrawArrowLine()
  1346. {
  1347. this.newMethod=IChartDrawPicture; //派生
  1348. this.newMethod();
  1349. delete this.newMethod;
  1350. this.ClassName='ChartDrawArrowLine';
  1351. this.IsPointIn=this.IsPointIn_XYValue_Line;
  1352. this.ArrawLineWidth=5;
  1353. this.ArrawLength=15; //三角斜边长度
  1354. this.ArrawAngle=35; //三角斜边一直线夹角
  1355. this.GetXYCoordinate=this.GetXYCoordinate_default;
  1356. this.OnlyMoveXIndex=true;
  1357. this.IsSupportMagnet=true;
  1358. this.Draw=function()
  1359. {
  1360. this.LinePoint=[];
  1361. if (this.IsFrameMinSize()) return;
  1362. if (!this.IsShow) return;
  1363. var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} );
  1364. if (!drawPoint) return;
  1365. if (drawPoint.length!=2) return;
  1366. this.ClipFrame();
  1367. var ptStart=drawPoint[0];
  1368. var ptEnd=drawPoint[1];
  1369. //计算箭头
  1370. var theta=this.ArrawAngle; //三角斜边一直线夹角
  1371. var headlen=this.ArrawLength; //三角斜边长度
  1372. var angle = Math.atan2(ptStart.Y - ptEnd.Y, ptStart.X - ptEnd.X) * 180 / Math.PI,
  1373. angle1 = (angle + theta) * Math.PI / 180,
  1374. angle2 = (angle - theta) * Math.PI / 180,
  1375. topX = headlen * Math.cos(angle1),
  1376. topY = headlen * Math.sin(angle1),
  1377. botX = headlen * Math.cos(angle2),
  1378. botY = headlen * Math.sin(angle2);
  1379. this.SetLineWidth();
  1380. this.Canvas.strokeStyle=this.LineColor;
  1381. this.Canvas.beginPath();
  1382. this.Canvas.moveTo(ptStart.X,ptStart.Y);
  1383. this.Canvas.lineTo(ptEnd.X,ptEnd.Y);
  1384. this.Canvas.stroke();
  1385. this.Canvas.beginPath();
  1386. var arrowX = ptEnd.X + topX;
  1387. var arrowY = ptEnd.Y + topY;
  1388. this.Canvas.moveTo(arrowX,arrowY);
  1389. this.Canvas.lineTo(ptEnd.X, ptEnd.Y);
  1390. arrowX = ptEnd.X + botX;
  1391. arrowY = ptEnd.Y + botY;
  1392. this.Canvas.lineTo(arrowX,arrowY);
  1393. this.Canvas.lineWidth=this.ArrawLineWidth;
  1394. this.Canvas.stroke();
  1395. this.RestoreLineWidth();
  1396. /*
  1397. if (this.IsSelected)
  1398. {
  1399. this.Canvas.strokeStyle='rgba(255,0,0,0.5)';
  1400. this.Canvas.lineWidth=20 * GetDevicePixelRatio();
  1401. this.Canvas.stroke();
  1402. }
  1403. */
  1404. var line={Start:ptStart, End:ptEnd};
  1405. this.LinePoint.push(line);
  1406. this.DrawPoint([drawPoint[0]]); //画点
  1407. this.Canvas.restore();
  1408. }
  1409. }
  1410. // 画图工具-水平线 支持横屏
  1411. function ChartDrawPictureHorizontalLine()
  1412. {
  1413. this.newMethod=IChartDrawPicture; //派生
  1414. this.newMethod();
  1415. delete this.newMethod;
  1416. this.Super_SetOption=this.SetOption; //父类函数
  1417. this.Super_ExportStorageData=this.ExportStorageData;
  1418. this.Label; //{Text:文本, Position: 0=左, 1=右 }
  1419. this.SetOption=function(option)
  1420. {
  1421. if (this.Super_SetOption) this.Super_SetOption(option);
  1422. if (option)
  1423. {
  1424. if (option.Label) this.Label=option.Label;
  1425. }
  1426. }
  1427. this.ExportStorageData=function()
  1428. {
  1429. var storageData;
  1430. if (this.Super_ExportStorageData)
  1431. {
  1432. storageData=this.Super_ExportStorageData();
  1433. if (this.Label) storageData.Label=this.Label;
  1434. }
  1435. return storageData;
  1436. }
  1437. this.PointCount=1;
  1438. this.ClassName='ChartDrawPictureHorizontalLine';
  1439. this.IsPointIn=this.IsPointIn_XYValue_Line;
  1440. this.Font=16+"px 微软雅黑";
  1441. this.GetXYCoordinate=function()
  1442. {
  1443. if (this.IsFrameMinSize()) return null;
  1444. var drawPoint=this.CalculateDrawPoint();
  1445. return this.PointRange(drawPoint);
  1446. }
  1447. this.Draw=function()
  1448. {
  1449. this.LinePoint=[];
  1450. if (this.IsFrameMinSize()) return;
  1451. if (!this.IsShow) return;
  1452. var drawPoint=this.CalculateDrawPoint();
  1453. if (!drawPoint || drawPoint.length!=1) return;
  1454. if (!this.Frame) return;
  1455. if (this.Value.length!=1) return;
  1456. if (!this.IsYValueInFrame(this.Value[0].YValue)) return null;
  1457. var isHScreen=this.Frame.IsHScreen;
  1458. var left=this.Frame.ChartBorder.GetLeft();
  1459. var right=this.Frame.ChartBorder.GetRight();
  1460. if (isHScreen)
  1461. {
  1462. left=this.Frame.ChartBorder.GetTop();
  1463. right=this.Frame.ChartBorder.GetBottom();
  1464. }
  1465. this.ClipFrame();
  1466. this.Canvas.strokeStyle=this.LineColor;
  1467. this.SetLineWidth();
  1468. this.Canvas.beginPath();
  1469. if (isHScreen)
  1470. {
  1471. this.Canvas.moveTo(drawPoint[0].X,left);
  1472. this.Canvas.lineTo(drawPoint[0].X,right);
  1473. }
  1474. else
  1475. {
  1476. this.Canvas.moveTo(left,drawPoint[0].Y);
  1477. this.Canvas.lineTo(right,drawPoint[0].Y);
  1478. }
  1479. this.Canvas.stroke();
  1480. this.RestoreLineWidth();
  1481. var line={Start:new Point(), End:new Point()};
  1482. if (isHScreen)
  1483. {
  1484. line.Start.X=drawPoint[0].X;
  1485. line.Start.Y=left;
  1486. line.End.X=drawPoint[0].X;
  1487. line.End.Y=right;
  1488. }
  1489. else
  1490. {
  1491. line.Start.X=left;
  1492. line.Start.Y=drawPoint[0].Y;
  1493. line.End.X=right;
  1494. line.End.Y=drawPoint[0].Y;
  1495. }
  1496. this.LinePoint.push(line);
  1497. //画点
  1498. this.DrawPoint(drawPoint);
  1499. //显示价格
  1500. this.LineText(drawPoint[0])
  1501. /*
  1502. this.Canvas.fillStyle=this.LineColor;
  1503. this.Canvas.font=this.Font;
  1504. if (isHScreen)
  1505. {
  1506. this.Canvas.textAlign="left";
  1507. this.Canvas.textBaseline="bottom";
  1508. var xText=drawPoint[0].X;
  1509. var yText=left;
  1510. this.Canvas.translate(xText, yText);
  1511. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  1512. var yValue=this.Frame.GetYData(drawPoint[0].X);
  1513. var text=yValue.toFixed(2);
  1514. if (this.Label)
  1515. {
  1516. if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2);
  1517. else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text;
  1518. }
  1519. this.Canvas.fillText(text,0,0);
  1520. }
  1521. else
  1522. {
  1523. this.Canvas.textAlign="left";
  1524. this.Canvas.textBaseline="bottom";
  1525. var yValue=this.Frame.GetYData(drawPoint[0].Y);
  1526. var text=yValue.toFixed(2);
  1527. if (this.Label)
  1528. {
  1529. if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2);
  1530. else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text;
  1531. }
  1532. this.Canvas.fillText(text,left,drawPoint[0].Y);
  1533. }
  1534. */
  1535. this.Canvas.restore();
  1536. }
  1537. this.LineText=function(point)
  1538. {
  1539. if (!point) return;
  1540. var isHScreen=this.Frame.IsHScreen;
  1541. var left=this.Frame.ChartBorder.GetLeft();
  1542. this.Canvas.fillStyle=this.LineColor;
  1543. this.Canvas.font=this.Font;
  1544. if (isHScreen)
  1545. {
  1546. left=this.Frame.ChartBorder.GetTop();
  1547. this.Canvas.textAlign="left";
  1548. this.Canvas.textBaseline="bottom";
  1549. var xText=point.X;
  1550. var yText=left;
  1551. this.Canvas.translate(xText, yText);
  1552. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  1553. var yValue=this.Frame.GetYData(point.X);
  1554. var text=yValue.toFixed(2);
  1555. if (this.Label)
  1556. {
  1557. if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2);
  1558. else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text;
  1559. }
  1560. this.Canvas.fillText(text,2,0);
  1561. }
  1562. else
  1563. {
  1564. this.Canvas.textAlign="left";
  1565. this.Canvas.textBaseline="bottom";
  1566. var yValue=this.Frame.GetYData(point.Y);
  1567. var text=yValue.toFixed(2);
  1568. if (this.Label)
  1569. {
  1570. if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2);
  1571. else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text;
  1572. }
  1573. this.Canvas.fillText(text,left,point.Y);
  1574. }
  1575. }
  1576. }
  1577. //画图工具-标价线2 支持横屏
  1578. function ChartDrawPriceLineV2()
  1579. {
  1580. this.newMethod=IChartDrawPicture; //派生
  1581. this.newMethod();
  1582. delete this.newMethod;
  1583. this.ClassName='ChartDrawPriceLineV2';
  1584. this.Font="12px 微软雅黑";
  1585. this.PointCount=1;
  1586. this.IsPointIn=this.IsPointIn_XYValue_Line;
  1587. this.IsHScreen=false;
  1588. this.LineWidth=1;
  1589. //this.IsDrawFirst=true;
  1590. this.TextColor="rgb(255,255,255)";
  1591. this.Title; //标题
  1592. this.TextPosition=[null, 0]; //[0]=左侧(没有做) [1]=右侧 0=自动 1=内部 2=外部
  1593. this.Super_SetOption=this.SetOption; //父类函数
  1594. this.SetOption=function(option)
  1595. {
  1596. if (this.Super_SetOption) this.Super_SetOption(option);
  1597. if (option)
  1598. {
  1599. if (option.TextColor) this.TextColor=option.TextColor;
  1600. if (option.Title) this.Title=option.Title;
  1601. if (IFrameSplitOperator.IsNonEmptyArray(option.TextPosition)) this.TextPosition=option.TextPosition.slice();
  1602. }
  1603. }
  1604. this.Draw=function()
  1605. {
  1606. this.LinePoint=[];
  1607. if (this.IsFrameMinSize()) return;
  1608. if (!this.IsShow) return;
  1609. var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:true } );
  1610. if (!drawPoint) return;
  1611. if (drawPoint.length!=1) return;
  1612. if (!this.IsYValueInFrame(this.Value[0].YValue)) return;
  1613. this.IsHScreen=this.Frame.IsHScreen;
  1614. var chartBorder=this.Frame.ChartBorder;
  1615. var border=this.Frame.GetBorder();
  1616. if (this.IsHScreen)
  1617. {
  1618. var left=border.LeftEx;
  1619. var right=border.RightEx;
  1620. var bottom=border.Bottom;
  1621. var top=border.Top;
  1622. var ptStart={ X:drawPoint[0].X, Y:top };
  1623. if (ptStart.X<left || ptStart.X>right) return;
  1624. var ptEnd={X:drawPoint[0].X, Y:bottom };
  1625. var price=this.Frame.GetYData(ptStart.X, false);
  1626. }
  1627. else
  1628. {
  1629. var bottom=border.BottomEx;
  1630. var top=border.TopTitle;
  1631. var left=border.Left;
  1632. var right=border.Right;
  1633. var ptStart={ X:left, Y:drawPoint[0].Y };
  1634. if (ptStart.Y<top || ptStart.Y>bottom) return;
  1635. var ptEnd={ X:right, Y:drawPoint[0].Y };
  1636. var price=this.Frame.GetYData(ptStart.Y, false);
  1637. }
  1638. //this.ClipFrame();
  1639. this.SetLineWidth();
  1640. this.Canvas.strokeStyle=this.LineColor;
  1641. this.Canvas.beginPath();
  1642. this.Canvas.moveTo(ToFixedPoint(ptStart.X),ToFixedPoint(ptStart.Y));
  1643. this.Canvas.lineTo(ToFixedPoint(ptEnd.X),ToFixedPoint(ptEnd.Y));
  1644. this.Canvas.stroke();
  1645. this.RestoreLineWidth();
  1646. var line={Start:ptStart, End:ptEnd};
  1647. this.LinePoint.push(line);
  1648. var pixelTatio =1;
  1649. this.Canvas.font=this.Font;
  1650. var offset=2*pixelTatio;
  1651. var xText=ptEnd.X;
  1652. var yText=ptEnd.Y;
  1653. this.Canvas.textBaseline='middle';
  1654. this.Canvas.textAlign='left';
  1655. var textHeight=this.GetFontHeight();
  1656. var text=price.toFixed(2);
  1657. var textWidth=this.Canvas.measureText(text).width+2*offset;
  1658. var centerPoint=null;
  1659. if (this.IsHScreen)
  1660. {
  1661. var position=this.TextPosition[1];
  1662. var bDrawInside=false; //在内部绘制
  1663. if (position==0) bDrawInside=chartBorder.Bottom<=10;
  1664. else if (position==1) bDrawInside=true;
  1665. else if (position==2) bDrawInside=false;
  1666. if (!bDrawInside)
  1667. {
  1668. var rtBG={ Left:(xText-textHeight/2), Top:yText , Width: textHeight, Height:textWidth };
  1669. }
  1670. else //框架内部显示
  1671. {
  1672. yText=yText-textWidth;
  1673. var rtBG={ Left:(xText-textHeight/2), Top:yText , Width:textHeight, Height: textWidth};
  1674. }
  1675. this.Canvas.fillStyle=this.LineColor;
  1676. this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height);
  1677. this.Canvas.save();
  1678. this.Canvas.translate(xText,yText+1*pixelTatio);
  1679. this.Canvas.rotate(90 * Math.PI / 180);
  1680. this.Canvas.fillStyle=this.TextColor;
  1681. this.Canvas.fillText(text,0,0);
  1682. this.Canvas.restore();
  1683. if (this.Title)
  1684. {
  1685. var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio;
  1686. if (!bDrawInside)
  1687. {
  1688. var rtTitle={ Left:rtBG.Left, Top:bottom-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth };
  1689. }
  1690. else
  1691. {
  1692. var rtTitle={Left:rtBG.Left, Top:rtBG.Top-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth}
  1693. }
  1694. this.Canvas.fillStyle=this.LineColor;
  1695. this.Canvas.fillRect(rtTitle.Left, rtTitle.Top, rtTitle.Width, rtTitle.Height);
  1696. this.Canvas.save();
  1697. this.Canvas.translate(xText,rtTitle.Top+1*pixelTatio);
  1698. this.Canvas.rotate(90 * Math.PI / 180);
  1699. this.Canvas.fillStyle=this.TextColor;
  1700. this.Canvas.fillText(this.Title,0,0);
  1701. this.Canvas.restore();
  1702. }
  1703. centerPoint={ X:ptStart.X, Y:ptStart.Y+(ptEnd.Y-ptStart.Y)/2 }; //中心点
  1704. }
  1705. else
  1706. {
  1707. var position=this.TextPosition[1];
  1708. var bDrawInside=false; //在内部绘制
  1709. if (position==0) bDrawInside=chartBorder.Right<=10;
  1710. else if (position==1) bDrawInside=true;
  1711. else if (position==2) bDrawInside=false;
  1712. if (!bDrawInside)
  1713. {
  1714. var rtBG={ Left:xText, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight};
  1715. if (rtBG.Left+rtBG.Width>border.ChartWidth) rtBG.Left=border.ChartWidth-rtBG.Width-2*pixelTatio;
  1716. }
  1717. else //框架内部显示
  1718. {
  1719. var rtBG={ Left:xText-textWidth, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight};
  1720. }
  1721. this.Canvas.fillStyle=this.LineColor;
  1722. this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height);
  1723. this.Canvas.fillStyle=this.TextColor;
  1724. this.Canvas.fillText(text, rtBG.Left+offset, yText);
  1725. if (this.Title)
  1726. {
  1727. var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio;
  1728. if (!bDrawInside)
  1729. {
  1730. var rtTitle={ Left:right-textWidth-1*pixelTatio, Top:rtBG.Top, Width:textWidth, Height:textHeight };
  1731. if (rtBG.Left!=right) rtTitle.Left=rtBG.Left-textWidth-1*pixelTatio;
  1732. }
  1733. else
  1734. {
  1735. var rtTitle={Left:rtBG.Left-textWidth, Top:rtBG.Top, Width:textWidth, Height:textHeight}
  1736. }
  1737. this.Canvas.fillStyle=this.LineColor;
  1738. this.Canvas.fillRect(rtTitle.Left, rtTitle.Top, rtTitle.Width, rtTitle.Height);
  1739. this.Canvas.fillStyle=this.TextColor;
  1740. this.Canvas.fillText(this.Title, rtTitle.Left+1*pixelTatio, yText);
  1741. }
  1742. centerPoint={ X:ptStart.X+(ptEnd.X-ptStart.X)/2, Y:ptStart.Y }; //中心点
  1743. }
  1744. if (centerPoint) this.DrawPoint([centerPoint]);
  1745. }
  1746. this.DrawPrice=function()
  1747. {
  1748. }
  1749. }
  1750. export
  1751. {
  1752. IChartDrawPicture,
  1753. ChartDrawPictureLine,
  1754. ChartDrawPictureHaflLine,
  1755. ChartDrawArrowLine,
  1756. ChartDrawPictureHorizontalLine,
  1757. ChartDrawPriceLineV2,
  1758. }