import { IFrameSplitOperator, } from './umychart.framesplit.wechat.js' import { g_MinuteTimeStringData, } from "./umychart.coordinatedata.wechat.js"; import { g_JSChartResource, g_JSChartLocalization, } from './umychart.resource.wechat.js' import { JSConsole } from "./umychart.console.wechat.js"; function Guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } function Point() { this.X; this.Y; } //修正线段有毛刺 function ToFixedPoint(value) { return parseInt(value) + 0.5; } function ToFixedRect(value) { //return value; // With a bitwise or. //rounded = (0.5 + somenum) | 0; // A double bitwise not. //rounded = ~~ (0.5 + somenum); // Finally, a left bitwise shift. var rounded; return rounded = (0.5 + value) << 0; } function GetFontHeight(context, font, word) { if (!context) return null; if (font) context.font=font; var text='擎'; if (IFrameSplitOperator.IsString(word)) text=word; var fontInfo=context.measureText(text); var textHeight=fontInfo.width+2; return textHeight; } //画图工具 function IChartDrawPicture() { this.Frame; this.Canvas; this.Point=new Array() //画图的点 this.Value=new Array(); //XValue,YValue this.LinePoint=[]; this.PointCount=2; //画点的个数 this.Status=0; //0=开始画 1=完成第1个点 2=完成第2个点 3=完成第3个点 10=完成 20=移动 this.PointStatus=0; //2=第2个点完成 this.MovePointIndex=null; //移动哪个点 0-10 对应Point索引 100 整体移动 this.ClassName='IChartDrawPicture'; this.FinishedCallback; //画图完成回调通知 this.Guid=Guid(); //ID标识 this.Symbol; //对应的股票 this.Period; //对应的周期 this.Right; //对应的复权 this.IsSelected=false; //是否选中 this.Option; //全局配置 对应外部 ChartDrawOption this.EnableMove=true; //是否可以移动 this.EnableSave=true; //是否允许保存 this.EnableCtrlMove=false; //是否按住Ctrl才能移动 this.OnlyMoveXIndex=false; //只能在X轴刻度上移动 this.IsSupportMagnet=false; //是否支持磁吸 this.EnableMoveCheck=true; //允许移动时监测是否超出边界 this.IsDrawFirst=false; this.IsShowYCoordinate=false; //是否在Y轴显示点的刻度 this.IsShow=true; //是否显示 this.LineColor=g_JSChartResource.DrawPicture.LineColor[0]; //线段颜色 //this.LineColor="#1e90ff"; //线段颜色,input type="color" 不支持rgb和rgba 的格式 this.LineWidth=2; //线段宽度 this.BackupLineWidth=null; this.AreaColor='rgba(25,25,25,0.4)'; //面积颜色 this.PointColor=g_JSChartResource.DrawPicture.PointColor[0]; this.MoveOnPointColor=g_JSChartResource.DrawPicture.PointColor[1]; this.PointBGColor=g_JSChartResource.DrawPicture.PointColor[2]; this.PointRadius=5; //圆点半径 this.SquareSize=8; //方框点大小 this.PointType=g_JSChartResource.DrawPicture.PointType; // 0=圆点 1=方框 2= 空心圆 this.IsShowPoint=g_JSChartResource.DrawPicture.IsShowPoint; //是否始终显示点 this.LimitFrameID; //限制在指定窗口绘图 this.TouchConfig={ Point:{ Radius:15 }, Line:{ Width:10 } }, this.PixelRatio=null; //分辨率 //接口函数 this.SetLastPoint=null; //this.SetLastPoint=function(obj) obj={X:,Y:} this.Update=null; //更新数据回调 this.GetActiveDrawPicture=null; this.GetYCoordinatePoint=null; this.Draw=function() { } this.SetOption=function(option) { if (!option) return; if (option.LineColor) this.LineColor=option.LineColor; if (option.LineWidth>0) this.LineWidth=option.LineWidth; if (option.AreaColor) this.AreaColor=option.AreaColor; if (option.PointColor) this.PointColor=option.PointColor; if (option.MoveOnPointColor) this.SelectPointColor=option.PointColor; if (option.PointRadius) this.PointRadius=option.PointRadius; if (IFrameSplitOperator.IsNumber(option.SquareSize)) this.SquareSize=option.SquareSize; if (IFrameSplitOperator.IsBool(option.IsShowPoint)) this.IsShowPoint=option.IsShowPoint; if (IFrameSplitOperator.IsNumber(option.LimitFrameID)) this.LimitFrameID=option.LimitFrameID; if (IFrameSplitOperator.IsBool(option.EnableCtrlMove)) this.EnableCtrlMove=option.EnableCtrlMove; if (IFrameSplitOperator.IsBool(option.IsShowYCoordinate)) this.IsShowYCoordinate=option.IsShowYCoordinate; } this.ReloadResource=function(resource) { if (!resource) { this.PointColor=g_JSChartResource.DrawPicture.PointColor[0]; this.MoveOnPointColor=g_JSChartResource.DrawPicture.PointColor[1]; this.PointBGColor=g_JSChartResource.DrawPicture.PointColor[2]; } } this.SetLineWidth=function() { this.BackupLineWidth=null; if (this.LineWidth>0) { this.BackupLineWidth=this.Canvas.lineWidth; this.Canvas.lineWidth=this.LineWidth; } } this.GetFontHeight=function(font) { return GetFontHeight(this.Canvas, font, "擎"); } this.RestoreLineWidth=function() { if (this.BackupLineWidth!=null) { this.Canvas.lineWidth=this.BackupLineWidth; } } //磁吸K线 this.PointMagnetKLine=function() { if (!this.IsSupportMagnet) return false; if (!this.Frame) return false; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") return false; if (this.Frame.Identify!=0) return false; var pointIndex=-1; if (this.Status==2) pointIndex=1; else if (this.Status==1) pointIndex=0; else if (IFrameSplitOperator.IsNumber(this.MovePointIndex)) pointIndex=this.MovePointIndex; if (pointIndex<0) return false; if (this.Option && this.Option.Magnet && this.Option.Magnet.Enable) { var option= { IsFixedX:false, Magnet: { Enable:true, PointIndex:pointIndex, Distance:this.Option.Magnet.Distance, Type:this.Option.Magnet.Type } } return this.AdjustPoint(this.Point,option) } return false; } //Point => Value this.PointToValue=function() { if (!this.Frame) return false; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") { return this.PointToValue_Minute(); } else { return this.PointToValue_KLine(); } } this.PointToKLine=function(aryPoint) { if (!this.Frame) return null; var data=this.Frame.Data; if (!data) return null; var kLine=[]; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i in aryPoint) { var item=aryPoint[i]; var xValue=parseInt(this.Frame.GetXData(item.Y))+data.DataOffset; var yValue=this.Frame.GetYData(item.X); var valueItem={ XValue:xValue, YValue:yValue }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; kLine[i]=valueItem; } } else { for(var i in aryPoint) { var item=aryPoint[i]; var index=parseInt(this.Frame.GetXData(item.X,false)); var xValue=index+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) { xValue=data.Data.length-1; index=xValue-data.DataOffset; } var yValue=this.Frame.GetYData(item.Y,false); var valueItem={ XValue:xValue, YValue:yValue, XIndex:index }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; kLine[i]=valueItem; } } return kLine; } this.PointToValue_KLine=function() { if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i in this.Point) { var item=this.Point[i]; var xValue=parseInt(this.Frame.GetXData(item.Y,false))+data.DataOffset; var yValue=this.Frame.GetYData(item.X,false); var valueItem={ XValue:xValue, YValue:yValue }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; this.Value[i]=valueItem; } } else { for(var i in this.Point) { var item=this.Point[i]; var xValue=parseInt(this.Frame.GetXData(item.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var yValue=this.Frame.GetYData(item.Y,false); var valueItem={ XValue:xValue, YValue:yValue }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; this.Value[i]=valueItem; } } return true; } this.PointToValue_Minute=function() { if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i=0; i=data.Data.length) //超过当前数据,直接读固定时间 { var index=xValue%xDatetime.length; var dataIndex=data.Data.length-1; var valueItem={ XValue:xValue, YValue:yValue }; var minuteItem=data.Data[dataIndex]; var timeItem=xDatetime[index]; valueItem.DateTime={ Date:minuteItem.Date, Time:timeItem }; this.Value[i]=valueItem; } else { var valueItem={ XValue:xValue, YValue:yValue }; var minuteItem=data.Data[xValue]; valueItem.DateTime={ Date:minuteItem.Date, Time:minuteItem.Time }; this.Value[i]=valueItem; } } } return true; } this.IsPointIn=function(x, y, option) { return false; } //Value => Point this.ValueToPoint=function() { if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; //this.UpdateXValue(); var isHScreen=this.Frame.IsHScreen; this.Point=[]; for(var i=0; i=0) valueItem.XValue=findItem.Index; } } //xStep,yStep 移动的偏移量 this.Move=function(xStep,yStep) { if (this.Status!=20) return false; if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; if (this.MovePointIndex==null) return false; var index=parseInt(this.MovePointIndex); if (index===100) //整体移动 { if (this.IsMoveOutOfBounds(this.Point, xStep, yStep)) return false; for(var i in this.Point) { this.Point[i].X+=xStep; this.Point[i].Y+=yStep; } } else if (index===0 || index===1 || index===2 || index===3 || index===4 || index===5) { if (index0) { var xEnd=this.Frame.GetXFromIndex(endIndex-1,false); for(var i=0;ixEnd) return true; } } else if (xStep<0) { var xStart=this.Frame.GetXFromIndex(startIndex,false); for(var i=0;i=showCount) ++invaildX; var pt=new Point(); if (isHScreen) //横屏X,Y对调 { pt.Y=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false); pt.X=this.Frame.GetYFromData(item.YValue,false); } else { pt.X=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false); pt.Y=this.Frame.GetYFromData(item.YValue,false); } drawPoint.push(pt); } if (option && option.IsCheckX===true) { if (invaildX==this.Value.length) return null; } } else //移动中 { for(var i=0;i=0) { option.Magnet= { Enable:true, PointIndex:pointIndex, Distance:this.Option.Magnet.Distance, Type:this.Option.Magnet.Type } } } this.AdjustPoint(drawPoint,option) } } return drawPoint; } //修正X, Y轴坐标 this.AdjustPoint=function(aryPoint, option) { if (!this.Frame) return false; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") return false; return this.AdjustPoint_KLine(aryPoint, option); } this.AdjustPoint_KLine=function(aryPoint, option) { if (!option) return false; if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i=0; i=data.Data.length) xValue=data.Data.length-1; if (option.IsFixedX) { index=xValue-data.DataOffset; item.X=this.Frame.GetXFromIndex(index,false); } //磁吸 if (option.Magnet && option.Magnet.Enable && i==option.Magnet.PointIndex) { var kline=data.Data[xValue]; var aryKValue=[kline.Open, kline.High, kline.Low, kline.Close]; var yMinDistance=null, yKLine=null; for(var j=0; jvalue) { yMinDistance=value; yKLine=yPrice; } } if (option.Magnet.Type==1) //只能在K线上 { if (IFrameSplitOperator.IsNumber(yKLine)) item.Y=yKLine; } else { if (yMinDistancethis.Frame.HorizontalMax || yValue0) { var b2=bottom-ptStart.Y; var a2=a*b2/b; var pt=new Point(); pt.X=ptStart.X+a2; pt.Y=bottom; result.End=pt; var b2=ptEnd.Y-top; var a2=a*b2/b; var pt2=new Point(); pt2.Y=top; pt2.X=ptEnd.X-a2; result.Start=pt2; } else { var b2=bottom-ptStart.Y; var a2=Math.abs(a)*b2/b; var pt=new Point(); pt.X=ptStart.X-a2;; pt.Y=bottom; result.End=pt; var b2=ptEnd.Y-top; var a2=Math.abs(a)*b2/b; var pt2=new Point(); pt2.Y=top; pt2.X=ptEnd.X+a2; result.Start=pt2; } return result; } //计算2个点线的,点0->点1->延长线的点 this.CalculateExtendLineEndPoint=function(aryPoint) { var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); var bottom=this.Frame.ChartBorder.GetBottomEx(); var top=this.Frame.ChartBorder.GetTopEx(); var a=aryPoint[1].X-aryPoint[0].X; var b=aryPoint[1].Y-aryPoint[0].Y; if (a>0) { var a1=right-aryPoint[0].X; var b1=a1*b/a; var y=b1+aryPoint[0].Y; if (y>=top && y<=bottom) { var pt=new Point(); pt.X=right; pt.Y=y; return pt; } if (b>0) { var b2=bottom-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=bottom; return pt2; } else if (b==0) { var pt2=new Point(); pt2.X=right; pt2.Y=aryPoint[0].Y; return pt2; } else { var b2=top-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=top; return pt2; } } else { var a1=aryPoint[0].X-left; var b1=a1*b/Math.abs(a); var y=b1+aryPoint[0].Y; if (y>=top && y<=bottom) { var pt=new Point(); pt.X=left; pt.Y=y; return pt; } if (b>0) { var b2=bottom-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=bottom; return pt2; } else if (b==0) { var pt2=new Point(); pt2.X=left; pt2.Y=aryPoint[0].Y; return pt2; } else { var b2=top-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=top; return pt2; } } } //坐标是否在点上 返回在第几个点上 this.IsPointInXYValue=function(x, y, option) { if (!this.Frame) return -1; var data=this.Frame.Data; if (!data) return -1; if (!this.Value) return -1; var radius=this.TouchConfig.Point.Radius; if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom; else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom; var isHScreen=this.Frame.IsHScreen; for(var i=0;i=0) return value; value=this.IsPointInLine(x,y,option); if (value>=0) return 100; return -1; } this.DrawLine=function(ptStart,ptEnd,isDottedline) { if (isDottedline) this.Canvas.setLineDash([5,10]); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); if (isDottedline) this.Canvas.setLineDash([]); } this.CreateLineData=function(ptStart,ptEnd) { var line={Start:new Point(), End:new Point()}; line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=ptEnd.Y; line.End.X=ptEnd.X; return line; } //导出成存储格式 this.ExportStorageData=function() { var storageData= { ClassName:this.ClassName, Symbol:this.Symbol, Guid:this.Guid, Period:this.Period,Value:[] , FrameID:this.Frame.Identify, LineColor:this.LineColor, AreaColor:this.AreaColor, LineWidth:this.LineWidth, Right:this.Right, EnableSave:this.EnableSave, IsShowYCoordinate:this.IsShowYCoordinate }; for(var i=0; iaryPoint[i].X) xMin=aryPoint[i].X; if (yMaxaryPoint[i].Y) yMin=aryPoint[i].Y; aryData.push({X:aryPoint[i].X, Y:aryPoint[i].Y}); } var data= { X: { Max: { X:xMax }, Min: { X:xMin} }, Y: { Max: { Y:yMax}, Min: { Y:yMin} }, Points: aryData //所有的点 }; return data; } } this.GetXYCoordinate_default=function() { if (this.IsFrameMinSize()) return null; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); return this.PointRange(drawPoint); } this.GetXYCoordinate=function() { return null; } this.CopyData_default=function() { if (!this.Frame) return null; var data=this.ExportStorageData(); if (!data) return null; var dataOffset=0; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") { } else { var kData=this.Frame.Data; if (!kData) return null; dataOffset=kData.DataOffset; } var height=this.Frame.ChartBorder.GetHeight(); var yFirst=this.Frame.ChartBorder.GetBottomEx()-this.Point[0].Y; for(var i=0;i=text.length) { pos=text.length-1; count=pos-endPos; } var subText=text.slice(endPos,endPos+count); var textWidth=this.Canvas.measureText(subText).width; if (textWidth>maxWidth) { for(var i=count; i>=0 ;--i) { subText=text.slice(endPos, endPos+i); textWidth=this.Canvas.measureText(subText).width; if (textWidthmaxWidth) { subText=text.slice(endPos, endPos+i-1); aryText.push({Text:subText}); endPos+=i-1; bFind=true; break; } } if (!bFind) { aryText.push({Text:subText}); endPos=text.length-1; } } else { aryText.push({Text:subText}); endPos+=count; } } return { AryText:aryText }; } this.CloneArrayText=function(aryText) { if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return []; var aryValue=[]; for(var i=0;i y1) return 270; if (x2 > x1 && y2 == y1) return 0; if (x2 < x1 && y2 == y1) return 180; if (x2 > x1 && y2 > y1) //第四象限 return 360 - angle; if (x2 < x1 && y2 > y1) //第三象限 return 180 + angle; if (x2 < x1 && y2 < y1) //第二象限 return 180 - angle; return angle; } //复制 //this.CopyData=function() { } //this.PtInButtons=function(x, y) { } } IChartDrawPicture.ArrayDrawPricture= [ { Name:"线段", ClassName:'ChartDrawPictureLine', Create:function() { return new ChartDrawPictureLine(); } }, { Name:"射线", ClassName:'ChartDrawPictureHaflLine', Create:function() { return new ChartDrawPictureHaflLine(); } }, { Name:"箭头", ClassName:"ChartDrawArrowLine", Create:function() { return new ChartDrawArrowLine(); } }, { Name:"水平线", ClassName:'ChartDrawPictureHorizontalLine', Create:function() { return new ChartDrawPictureHorizontalLine(); }}, { Name:"标价线2", ClassName:"ChartDrawPriceLineV2", Create:function() { return new ChartDrawPriceLineV2(); } }, ]; IChartDrawPicture.GetDrawPictureByName=function(value) { for(var i=0; i=0) chartDraw.Period=obj.Period; if (obj.Right>=0) chartDraw.Right=obj.Right; if (obj.Guid) chartDraw.Guid=obj.Guid; if (obj.Symbol) chartDraw.Symbol=obj.Symbol; if (obj.Value) chartDraw.Value=obj.Value; if (obj.Text) chartDraw.Text=obj.Text; if (obj.LineColor) chartDraw.LineColor=obj.LineColor; if (obj.AreaColor) chartDraw.AreaColor=obj.AreaColor; if (obj.FontOption) chartDraw.FontOption=obj.FontOption; if (obj.Label) chartDraw.Label=obj.Label; if (obj.LineWidth>0) chartDraw.LineWidth=obj.LineWidth; if (obj.EnableMove===false) chartDraw.EnableMove=obj.EnableMove; if (IFrameSplitOperator.IsBool(obj.EnableSave)) chartDraw.EnableSave=obj.EnableSave; if (IFrameSplitOperator.IsNumber(obj.ChannelWidth)) chartDraw.ChannelWidth=obj.ChannelWidth; if (IFrameSplitOperator.IsBool(obj.IsShowYCoordinate)) chartDraw.IsShowYCoordinate=obj.IsShowYCoordinate; if (chartDraw.SetOption) chartDraw.SetOption(obj); return chartDraw; } //画图工具-线段 function ChartDrawPictureLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureLine'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.IsShowYCoordinate=false; this.CopyData=this.CopyData_default; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); this.RestoreLineWidth(); /* if (this.IsSelected) { this.Canvas.strokeStyle='rgba(255,0,0,0.5)'; this.Canvas.lineWidth=20 * GetDevicePixelRatio(); this.Canvas.stroke(); } */ var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.GetYCoordinatePoint=function() { if (this.IsFrameMinSize()) return null; if (this.Status<2) return null; if(!this.Point.length || !this.Frame) return null; if (this.Status!=10) return null; //完成 var aryPoint=[]; for(var i=0; i=0) return result; if (!this.FullLine) return result; var ptStart=this.FullLine.Start; var ptEnd=this.FullLine.End; var lineWidth=this.TouchConfig.Line.Width; this.Canvas.beginPath(); if (ptStart.X==ptEnd.X) //竖线 { this.Canvas.moveTo(ptStart.X-lineWidth,ptStart.Y); this.Canvas.lineTo(ptStart.X+lineWidth,ptStart.Y); this.Canvas.lineTo(ptEnd.X+lineWidth,ptEnd.Y); this.Canvas.lineTo(ptEnd.X-lineWidth,ptEnd.Y); } else { this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth); this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth); } this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) return 100; return result; } this.Draw=function() { this.LinePoint=[]; this.FullLine=null; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:false, IsCheckY:false}); if (!drawPoint || drawPoint.length!=2) return; var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.ClipFrame(); this.Canvas.strokeStyle=this.LineColor; this.SetLineWidth(); this.Canvas.beginPath(); this.Canvas.moveTo(drawPoint[0].X,drawPoint[0].Y); this.Canvas.lineTo(drawPoint[1].X,drawPoint[1].Y); var endPoint=this.CalculateExtendLineEndPoint(drawPoint); this.Canvas.lineTo(endPoint.X,endPoint.Y); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); this.FullLine={Start:drawPoint[0], End:endPoint}; } } //画图工具-箭头线 function ChartDrawArrowLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawArrowLine'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.ArrawLineWidth=5; this.ArrawLength=15; //三角斜边长度 this.ArrawAngle=35; //三角斜边一直线夹角 this.GetXYCoordinate=this.GetXYCoordinate_default; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; //计算箭头 var theta=this.ArrawAngle; //三角斜边一直线夹角 var headlen=this.ArrawLength; //三角斜边长度 var angle = Math.atan2(ptStart.Y - ptEnd.Y, ptStart.X - ptEnd.X) * 180 / Math.PI, angle1 = (angle + theta) * Math.PI / 180, angle2 = (angle - theta) * Math.PI / 180, topX = headlen * Math.cos(angle1), topY = headlen * Math.sin(angle1), botX = headlen * Math.cos(angle2), botY = headlen * Math.sin(angle2); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); this.Canvas.beginPath(); var arrowX = ptEnd.X + topX; var arrowY = ptEnd.Y + topY; this.Canvas.moveTo(arrowX,arrowY); this.Canvas.lineTo(ptEnd.X, ptEnd.Y); arrowX = ptEnd.X + botX; arrowY = ptEnd.Y + botY; this.Canvas.lineTo(arrowX,arrowY); this.Canvas.lineWidth=this.ArrawLineWidth; this.Canvas.stroke(); this.RestoreLineWidth(); /* if (this.IsSelected) { this.Canvas.strokeStyle='rgba(255,0,0,0.5)'; this.Canvas.lineWidth=20 * GetDevicePixelRatio(); this.Canvas.stroke(); } */ var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint([drawPoint[0]]); //画点 this.Canvas.restore(); } } // 画图工具-水平线 支持横屏 function ChartDrawPictureHorizontalLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.Super_SetOption=this.SetOption; //父类函数 this.Super_ExportStorageData=this.ExportStorageData; this.Label; //{Text:文本, Position: 0=左, 1=右 } this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.Label) this.Label=option.Label; } } this.ExportStorageData=function() { var storageData; if (this.Super_ExportStorageData) { storageData=this.Super_ExportStorageData(); if (this.Label) storageData.Label=this.Label; } return storageData; } this.PointCount=1; this.ClassName='ChartDrawPictureHorizontalLine'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.Font=16+"px 微软雅黑"; this.GetXYCoordinate=function() { if (this.IsFrameMinSize()) return null; var drawPoint=this.CalculateDrawPoint(); return this.PointRange(drawPoint); } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint || drawPoint.length!=1) return; if (!this.Frame) return; if (this.Value.length!=1) return; if (!this.IsYValueInFrame(this.Value[0].YValue)) return null; var isHScreen=this.Frame.IsHScreen; var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); if (isHScreen) { left=this.Frame.ChartBorder.GetTop(); right=this.Frame.ChartBorder.GetBottom(); } this.ClipFrame(); this.Canvas.strokeStyle=this.LineColor; this.SetLineWidth(); this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(drawPoint[0].X,left); this.Canvas.lineTo(drawPoint[0].X,right); } else { this.Canvas.moveTo(left,drawPoint[0].Y); this.Canvas.lineTo(right,drawPoint[0].Y); } this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:new Point(), End:new Point()}; if (isHScreen) { line.Start.X=drawPoint[0].X; line.Start.Y=left; line.End.X=drawPoint[0].X; line.End.Y=right; } else { line.Start.X=left; line.Start.Y=drawPoint[0].Y; line.End.X=right; line.End.Y=drawPoint[0].Y; } this.LinePoint.push(line); //画点 this.DrawPoint(drawPoint); //显示价格 this.LineText(drawPoint[0]) /* this.Canvas.fillStyle=this.LineColor; this.Canvas.font=this.Font; if (isHScreen) { this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; var xText=drawPoint[0].X; var yText=left; this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 var yValue=this.Frame.GetYData(drawPoint[0].X); var text=yValue.toFixed(2); if (this.Label) { if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; } this.Canvas.fillText(text,0,0); } else { this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; var yValue=this.Frame.GetYData(drawPoint[0].Y); var text=yValue.toFixed(2); if (this.Label) { if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; } this.Canvas.fillText(text,left,drawPoint[0].Y); } */ this.Canvas.restore(); } this.LineText=function(point) { if (!point) return; var isHScreen=this.Frame.IsHScreen; var left=this.Frame.ChartBorder.GetLeft(); this.Canvas.fillStyle=this.LineColor; this.Canvas.font=this.Font; if (isHScreen) { left=this.Frame.ChartBorder.GetTop(); this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; var xText=point.X; var yText=left; this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 var yValue=this.Frame.GetYData(point.X); var text=yValue.toFixed(2); if (this.Label) { if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; } this.Canvas.fillText(text,2,0); } else { this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; var yValue=this.Frame.GetYData(point.Y); var text=yValue.toFixed(2); if (this.Label) { if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; } this.Canvas.fillText(text,left,point.Y); } } } //画图工具-标价线2 支持横屏 function ChartDrawPriceLineV2() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPriceLineV2'; this.Font="12px 微软雅黑"; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.LineWidth=1; //this.IsDrawFirst=true; this.TextColor="rgb(255,255,255)"; this.Title; //标题 this.TextPosition=[null, 0]; //[0]=左侧(没有做) [1]=右侧 0=自动 1=内部 2=外部 this.Super_SetOption=this.SetOption; //父类函数 this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.TextColor) this.TextColor=option.TextColor; if (option.Title) this.Title=option.Title; if (IFrameSplitOperator.IsNonEmptyArray(option.TextPosition)) this.TextPosition=option.TextPosition.slice(); } } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:true } ); if (!drawPoint) return; if (drawPoint.length!=1) return; if (!this.IsYValueInFrame(this.Value[0].YValue)) return; this.IsHScreen=this.Frame.IsHScreen; var chartBorder=this.Frame.ChartBorder; var border=this.Frame.GetBorder(); if (this.IsHScreen) { var left=border.LeftEx; var right=border.RightEx; var bottom=border.Bottom; var top=border.Top; var ptStart={ X:drawPoint[0].X, Y:top }; if (ptStart.Xright) return; var ptEnd={X:drawPoint[0].X, Y:bottom }; var price=this.Frame.GetYData(ptStart.X, false); } else { var bottom=border.BottomEx; var top=border.TopTitle; var left=border.Left; var right=border.Right; var ptStart={ X:left, Y:drawPoint[0].Y }; if (ptStart.Ybottom) return; var ptEnd={ X:right, Y:drawPoint[0].Y }; var price=this.Frame.GetYData(ptStart.Y, false); } //this.ClipFrame(); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(ptStart.X),ToFixedPoint(ptStart.Y)); this.Canvas.lineTo(ToFixedPoint(ptEnd.X),ToFixedPoint(ptEnd.Y)); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); var pixelTatio =1; this.Canvas.font=this.Font; var offset=2*pixelTatio; var xText=ptEnd.X; var yText=ptEnd.Y; this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; var textHeight=this.GetFontHeight(); var text=price.toFixed(2); var textWidth=this.Canvas.measureText(text).width+2*offset; var centerPoint=null; if (this.IsHScreen) { var position=this.TextPosition[1]; var bDrawInside=false; //在内部绘制 if (position==0) bDrawInside=chartBorder.Bottom<=10; else if (position==1) bDrawInside=true; else if (position==2) bDrawInside=false; if (!bDrawInside) { var rtBG={ Left:(xText-textHeight/2), Top:yText , Width: textHeight, Height:textWidth }; } else //框架内部显示 { yText=yText-textWidth; var rtBG={ Left:(xText-textHeight/2), Top:yText , Width:textHeight, Height: textWidth}; } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.save(); this.Canvas.translate(xText,yText+1*pixelTatio); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,0,0); this.Canvas.restore(); if (this.Title) { var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio; if (!bDrawInside) { var rtTitle={ Left:rtBG.Left, Top:bottom-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth }; } else { var rtTitle={Left:rtBG.Left, Top:rtBG.Top-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth} } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtTitle.Left, rtTitle.Top, rtTitle.Width, rtTitle.Height); this.Canvas.save(); this.Canvas.translate(xText,rtTitle.Top+1*pixelTatio); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(this.Title,0,0); this.Canvas.restore(); } centerPoint={ X:ptStart.X, Y:ptStart.Y+(ptEnd.Y-ptStart.Y)/2 }; //中心点 } else { var position=this.TextPosition[1]; var bDrawInside=false; //在内部绘制 if (position==0) bDrawInside=chartBorder.Right<=10; else if (position==1) bDrawInside=true; else if (position==2) bDrawInside=false; if (!bDrawInside) { var rtBG={ Left:xText, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight}; if (rtBG.Left+rtBG.Width>border.ChartWidth) rtBG.Left=border.ChartWidth-rtBG.Width-2*pixelTatio; } else //框架内部显示 { var rtBG={ Left:xText-textWidth, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight}; } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text, rtBG.Left+offset, yText); if (this.Title) { var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio; if (!bDrawInside) { var rtTitle={ Left:right-textWidth-1*pixelTatio, Top:rtBG.Top, Width:textWidth, Height:textHeight }; if (rtBG.Left!=right) rtTitle.Left=rtBG.Left-textWidth-1*pixelTatio; } else { var rtTitle={Left:rtBG.Left-textWidth, Top:rtBG.Top, Width:textWidth, Height:textHeight} } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtTitle.Left, rtTitle.Top, rtTitle.Width, rtTitle.Height); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(this.Title, rtTitle.Left+1*pixelTatio, yText); } centerPoint={ X:ptStart.X+(ptEnd.X-ptStart.X)/2, Y:ptStart.Y }; //中心点 } if (centerPoint) this.DrawPoint([centerPoint]); } this.DrawPrice=function() { } } export { IChartDrawPicture, ChartDrawPictureLine, ChartDrawPictureHaflLine, ChartDrawArrowLine, ChartDrawPictureHorizontalLine, ChartDrawPriceLineV2, }