/* copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 指标窗口 */ //日志 import { JSConsole } from "./umychart.console.wechat.js" import { g_JSChartResource, JSCHART_LANGUAGE_ID, g_JSChartLocalization, } from './umychart.resource.wechat.js' import { Guid, JSCHART_EVENT_ID, ToFixedPoint, ToFixedRect, CloneData, } from "./umychart.data.wechat.js"; import { CoordinateInfo, IFrameSplitOperator, FrameSplitKLinePriceY, FrameSplitY, FrameSplitKLineX, FrameSplitMinutePriceY, FrameSplitMinuteX, FrameSplitXData, SplitData, PriceSplitData, FrameSplitXDepth, IChangeStringFormat, HQPriceStringFormat, HQDateStringFormat, HQMinuteTimeStringFormat, g_DivTooltipDataForamt, } from './umychart.framesplit.wechat.js' import { g_MinuteTimeStringData } from "./umychart.coordinatedata.wechat.js"; function IChartFramePainting() { this.HorizontalInfo = new Array(); //Y轴 this.VerticalInfo = new Array(); //X轴 this.ClassName='IChartFramePainting'; this.Canvas; //画布 this.Identify; //窗口标识 this.Guid=Guid(); //内部窗口唯一标识 this.ChartBorder; this.PenBorder = g_JSChartResource.FrameBorderPen; //边框颜色 this.TitleBGColor = g_JSChartResource.FrameTitleBGColor; //标题背景色 this.IsShow = true; //是否显示 this.SizeChange = true; //大小是否改变 this.XYSplit = true; //XY轴坐标信息改变 this.XSplit=true; //X轴坐标信息改变 this.YCustomSplit=true; //Y轴自定刻度 this.HorizontalMax; //Y轴最大值 this.HorizontalMin; //Y轴最小值 this.XPointCount = 10; //X轴数据个数 this.YMaxMin={ Max:null, Min:null }; //Y轴原始的最大值 最小值 this.YSplitOperator; //Y轴分割 this.XSplitOperator; //X轴分割 this.Data; //主数据 this.YSpecificMaxMin = null; //指定Y轴最大最小值 this.YSplitScale=null; //固定分割刻度数组 [2,5,8] this.IsShowBorder = true; //是否显示边框 this.IsShowIndexName = true; //是否显示指标名字 this.IndexParamSpace = 2; //指标参数数值显示间距 this.IndexTitleSpace=0; //指标标题到参数之间的间距 this.IsShowTitleArrow=g_JSChartResource.IndexTitle.EnableIndexArrow; //是否显示指标信息上涨下跌箭头 this.TitleArrowType=g_JSChartResource.IndexTitle.ArrowType; //指标信息上涨下跌箭头类型 0=独立颜色 1=跟指标名字颜色一致 //上锁信息 this.IsLocked = false; //是否上锁 this.LockPaint = null; this.BorderLine=null; //1=上 2=下 4=左 8=右 this.IsMinSize=false; //窗口是否最小化 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; this.Draw = function () { this.DrawFrame(); this.DrawBorder(); this.SizeChange = false; this.XYSplit = false; this.XSplit=false; this.YCustomSplit=false; } this.DrawFrame = function () { } this.GetBorder=function() { if (this.IsHScreen) return this.ChartBorder.GetHScreenBorder(); else return this.ChartBorder.GetBorder(); } this.ClearCoordinateText=function(option) { if (IFrameSplitOperator.IsNonEmptyArray(this.HorizontalInfo)) { for(var i=0;i0) //上 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(right,top); } if ((this.BorderLine&2)>0) //下 { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } if ((this.BorderLine&4)>0) //左 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(left,bottom); } if ((this.BorderLine&8)>0) //右 { this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); } this.Canvas.stroke(); } } //左右刻度文字宽度 this.GetScaleTextWidth=function() { } //画标题背景色 this.DrawTitleBG = function () { /* 指标信息背景色不画,画了感觉框架变小了 if (this.ChartBorder.TitleHeight<=0) return; var left=ToFixedPoint(this.ChartBorder.GetLeft()); var top=ToFixedPoint(this.ChartBorder.GetTop()); var right=ToFixedPoint(this.ChartBorder.GetRight()); var bottom=ToFixedPoint(this.ChartBorder.GetTopEx()); var width=right-left; var height=bottom-top; this.Canvas.fillStyle=this.TitleBGColor; this.Canvas.fillRect(left,top,width,height); */ } this.DrawLock = function () { if (this.IsLocked) { if (this.LockPaint == null) this.LockPaint = new ChartLock(); this.LockPaint.Canvas = this.Canvas; this.LockPaint.ChartBorder = this.ChartBorder; this.LockPaint.ChartFrame = this; this.LockPaint.Draw(); } } this.DrawLogo=function() { var border=this.GetBorder(); var text=g_JSChartResource.FrameLogo.Text; if (!text) return; this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.font=this.LogoTextFont; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; if (this.IsHScreen) { var x=border.Left+5; var y=border.Top+5; this.Canvas.save(); this.Canvas.translate(x,y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,0,0); this.Canvas.restore(); } else { var x=border.Left+5; var y=border.Bottom-5; this.Canvas.fillText(text,x,y); } } //设施上锁 this.SetLock = function (lockData) { if (!lockData) //空数据不上锁 { this.IsLocked = false; return; } this.IsLocked = true; if (!this.LockPaint) this.LockPaint = new ChartLock(); //创建锁 if (lockData.Callback) this.LockPaint.Callback = lockData.Callback; //回调 if (lockData.IndexName) this.LockPaint.IndexName = lockData.IndexName; //指标名字 if (lockData.ID) this.LockPaint.LockID = lockData.ID; //锁ID if (lockData.BG) this.LockPaint.BGColor = lockData.BG; //背景色 if (lockData.Text) this.LockPaint.Title = lockData.Text; if (lockData.TextColor) this.LockPaint.TextColor = lockData.TextColor; if (lockData.Font) this.LockPaint.Font = lockData.Font; if (lockData.Count) this.LockPaint.LockCount = lockData.Count; } this.GetLockRect=function() { if (!this.IsLocked) return null; if (!this.LockPaint) return null; return this.LockPaint.LockRect; } this.GetFontHeight=function(font) { if (font) this.Canvas.font=font; return this.Canvas.measureText("擎").width; } } //空框架只画边框 function NoneFrame() { this.newMethod = IChartFramePainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='NoneFrame'; this.Snapshot = function () { } this.DrawInsideHorizontal = function () { } this.SetSizeChage = function (sizeChange) { this.SizeChange = sizeChange; //画布的位置 this.Position = { X: this.ChartBorder.UIElement.offsetLeft, Y: this.ChartBorder.UIElement.offsetTop, W: this.ChartBorder.UIElement.clientWidth, H: this.ChartBorder.UIElement.clientHeight }; } } function AverageWidthFrame() { this.newMethod = IChartFramePainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='AverageWidthFrame'; this.DataWidth = 50; this.DistanceWidth = 10; this.MinXDistance = 30; //X轴刻度最小间距 this.MinYDistance=10; this.XMessageAlign = 'top'; //X轴刻度文字上下对齐方式 this.IsShowTitle = true; //是否显示动态标题 this.IsShowYText = [true, true]; //是否显示Y轴坐标坐标 [0=左侧] [1=右侧] this.XBottomOffset = g_JSChartResource.Frame.XBottomOffset; //X轴文字显示向下偏移 this.YTextTopOffset=g_JSChartResource.Frame.YTopOffset; //Y轴顶部文字向下偏移 this.YTextPosition=[0,0], //是坐标否强制画在内部 [0=左侧] [1=右侧] 1=OUT" , 2=INSIDE this.YTextPadding=[g_JSChartResource.Frame.YTextPadding[0], g_JSChartResource.Frame.YTextPadding[1]], //Y轴文字和边框间距 [0=左侧] [1=右侧] this.IsShowXLine=true; //是否显示X轴刻度线 this.IsShowYLine=true; this.YTextBaseline=0; //0=居中 1=上部 (目前就支持内部刻度) this.ShortYLineLength=5; this.ShortXLineLength=5; this.DrawOtherChart; //其他画法调用 this.GetEventCallback; //事件回调 this.FrameData={ SubFrameItem:null }; //窗口框架信息 this.DrawFrame = function () { if (this.XPointCount > 0) { this.DistanceWidth = this.ChartBorder.GetWidth() / (4 * this.XPointCount); this.DataWidth = 2 * this.DistanceWidth; } this.DrawHorizontal(); this.DrawVertical(); } this.GetYFromData = function (value) { if (value <= this.HorizontalMin) return this.ChartBorder.GetBottomEx(); if (value >= this.HorizontalMax) return this.ChartBorder.GetTopEx(); var height = this.ChartBorder.GetHeightEx() * (value - this.HorizontalMin) / (this.HorizontalMax - this.HorizontalMin); return this.ChartBorder.GetBottomEx() - height; } //Y刻度画在内部 this.DrawInsideHorizontal = function () { if (this.IsHScreen === true) return; //横屏不画 if (this.IsMinSize) return; if (this.IsShowYText[0] === false && this.IsShowYText[1] === false) return; var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRight(); var bottom = this.ChartBorder.GetBottom(); var top = this.ChartBorder.GetTopTitle(); var borderRight = this.ChartBorder.Right; var borderLeft = this.ChartBorder.Left; var titleHeight = this.ChartBorder.TitleHeight; if (borderLeft >= 10 && borderRight>=10) return; if ((borderLeft < 10 && this.IsShowYText[0] === true) || (borderRight < 10 && this.IsShowYText[1] === true)) { var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; if (!item) continue; var y = this.GetYFromData(item.Value); if (y != null && yPrev !=null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 //坐标信息 左边 间距小于10 画在内部 if (item.Message[0] != null && borderLeft < 10 && this.IsShowYText[0] === true) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; var textHeight=this.Canvas.measureText('擎').width; var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if (y-textHeight/2 <= top) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { if (this.YTextBaseline==1) this.Canvas.textBaseline = "bottom"; else this.Canvas.textBaseline = "middle"; } var textObj = { X: left, Y: yText, Text: { BaseLine: this.Canvas.textBaseline, Font: this.Canvas.font, Value: item.Message[0] } }; if (!this.IsOverlayMaxMin || !this.IsOverlayMaxMin(textObj)) this.Canvas.fillText(item.Message[0], left + 1, yText); } if (item.Message[1] != null && borderRight < 10 && this.IsShowYText[1] === true) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; var textHeight=this.Canvas.measureText('擎').width; var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if (y-textHeight/2 <= top) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { if (this.YTextBaseline==1) this.Canvas.textBaseline = "bottom"; else this.Canvas.textBaseline = "middle"; } var textWidth = this.Canvas.measureText(item.Message[1]).width; var textObj = { X: right - textWidth, Y: yText, Text: { BaseLine: this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font: this.Canvas.font, Value: item.Message[1] } }; if (!this.IsOverlayMaxMin || !this.IsOverlayMaxMin(textObj)) this.Canvas.fillText(item.Message[1], right - 1, yText); } yPrev = y; } } } //画Y轴 this.DrawHorizontal = function () { var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRight(); var bottom = this.ChartBorder.GetBottom(); var top = this.ChartBorder.GetTopTitle(); var borderRight = this.ChartBorder.Right; var borderLeft = this.ChartBorder.Left; var titleHeight = this.ChartBorder.TitleHeight; this.Canvas.save(); var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev != null && Math.abs(y - yPrev) 0) { this.Canvas.strokeStyle = item.LineColor; if(g_JSChartResource.FrameYLineDash) { this.Canvas.setLineDash(g_JSChartResource.FrameYLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(left, yFixed); this.Canvas.lineTo(right, yFixed); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.beginPath(); this.Canvas.moveTo(left, yFixed); this.Canvas.lineTo(right, yFixed); this.Canvas.stroke(); } } } var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if (y <= top + 2) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { this.Canvas.textBaseline = "middle"; } //坐标信息 左边 间距小于10 不画坐标 this.Canvas.fillStyle = item.TextColor; this.Canvas.strokeStyle = item.TextColor; if (item.Message[0] != null && borderLeft > 10 && this.IsShowYText[0] === true) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.textAlign = "right"; this.Canvas.fillText(item.Message[0], left - this.YTextPadding[0], yText); } //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1] != null && borderRight > 10 && this.IsShowYText[1] === true) { if (item.Font != null) this.Canvas.font = item.Font; var xText=right; if (item.LineType==3) { var lineLength=this.ShortYLineLength; this.Canvas.beginPath(); this.Canvas.moveTo(xText,yFixed); this.Canvas.lineTo(xText+lineLength,yFixed); this.Canvas.stroke(); xText+=lineLength; } this.Canvas.textAlign = "left"; this.Canvas.fillText(item.Message[1], xText + this.YTextPadding[1], yText); } yPrev = y; } this.Canvas.restore(); } this.GetXFromIndex = function (index) { var count = this.XPointCount; if (count == 1) { if (index == 0) return this.ChartBorder.GetLeft(); else return this.ChartBorder.GetRight(); } else if (count <= 0) { return this.ChartBorder.GetLeft(); } else if (index >= count) { return this.ChartBorder.GetRight(); } else { var offset = this.ChartBorder.GetLeft() + this.ChartBorder.GetWidth() * index / count; return offset; } } //画X轴 this.DrawVertical = function () { var top = this.ChartBorder.GetTopTitle(); var bottom = this.ChartBorder.GetBottom(); var right = this.ChartBorder.GetRight(); var yText = bottom; if (this.XMessageAlign == 'bottom') yText = this.ChartBorder.GetChartHeight(); else this.XMessageAlign = 'top'; var xPrev = null; //上一个坐标x的值 let xPrevTextRight = null; for (var i in this.VerticalInfo) { var x = this.GetXFromIndex(this.VerticalInfo[i].Value); if (x > right) break; if (xPrev != null && Math.abs(x - xPrev) < this.MinXDistance) continue; var item=this.VerticalInfo[i]; var xFixed=ToFixedPoint(x); if (this.IsShowXLine && item.LineType > 0) { if (item.LineType==2) { this.Canvas.strokeStyle = item.LineColor; if (item.LineDash) this.Canvas.setLineDash(item.LineDash); else this.Canvas.setLineDash([5,5]); this.Canvas.beginPath(); this.Canvas.moveTo(xFixed, top); this.Canvas.lineTo(xFixed, bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else if (item.LineType==3) { } else if (item.LineType>0) { if(g_JSChartResource.FrameXLineDash) { this.Canvas.strokeStyle = item.LineColor; this.Canvas.beginPath(); this.Canvas.setLineDash(g_JSChartResource.FrameXLineDash); this.Canvas.moveTo(xFixed, top); this.Canvas.lineTo(xFixed, bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.strokeStyle = item.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed, top); this.Canvas.lineTo(xFixed, bottom); this.Canvas.stroke(); } } } if (this.VerticalInfo[i].Message[0] != null && this.ChartBorder.Bottom > 5) { let xTextRight = null; let xTextLeft = null; if (this.VerticalInfo[i].Font != null) this.Canvas.font = this.VerticalInfo[i].Font; this.Canvas.fillStyle=item.TextColor; this.Canvas.strokeStyle=item.TextColor; var testWidth = this.Canvas.measureText(this.VerticalInfo[i].Message[0]).width; if (x < testWidth / 2) { this.Canvas.textAlign = "left"; this.Canvas.textBaseline = this.XMessageAlign; xTextRight = x + testWidth; xTextLeft = x; } else if ((x + testWidth / 2) >= this.ChartBorder.GetChartWidth()) { this.Canvas.textAlign = "right"; this.Canvas.textBaseline = this.XMessageAlign; xTextRight = x + testWidth; xTextLeft = x; } else { this.Canvas.textAlign = "center"; this.Canvas.textBaseline = this.XMessageAlign; xTextRight = x + testWidth / 2; xTextLeft = x - testWidth / 2; } if (xPrevTextRight != null && xPrevTextRight > xTextLeft) continue; var yText=bottom; if (item.LineType==3) { var lineLength=this.ShortXLineLength; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,yText); this.Canvas.lineTo(xFixed,yText+lineLength); this.Canvas.stroke(); yText+=lineLength+2; } this.Canvas.fillText(this.VerticalInfo[i].Message[0], x, yText + this.XBottomOffset); xPrevTextRight = xTextRight; } xPrev = x; } } this.GetYData = function (y) //Y坐标转y轴数值 { if (y < this.ChartBorder.GetTopEx()) return this.HorizontalMax; if (y > this.ChartBorder.GetBottomEx()) return this.HorizontalMin; return (this.ChartBorder.GetBottomEx() - y) / this.ChartBorder.GetHeightEx() * (this.HorizontalMax - this.HorizontalMin) + this.HorizontalMin; } this.GetXData = function (x) //X坐标转x轴数值 { if (x <= this.ChartBorder.GetLeft()) return 0; if (x >= this.ChartBorder.GetRight()) return this.XPointCount; return (x - this.ChartBorder.GetLeft()) * (this.XPointCount * 1.0 / this.ChartBorder.GetWidth()); } this.DrawCustomItem = function (item) //显示自定义刻度 { //if (this.IsHScreen === true) return; //横屏不画 if (!item.Message[1] && !item.Message[0]) return; if (item.Value > this.HorizontalMax || item.Value < this.HorizontalMin) { if (item.CountDown===true) this.SendDrawCountDownEvent( { IsShow:false } ); return; } var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRight(); var bottom = this.ChartBorder.GetBottom(); var top = this.ChartBorder.GetTopTitle(); var borderRight = this.ChartBorder.Right; var borderLeft = this.ChartBorder.Left; var titleHeight = this.ChartBorder.TitleHeight; if (this.IsHScreen) { borderLeft = this.ChartBorder.Top; borderRight = this.ChartBorder.Bottom; top = this.ChartBorder.GetTop(); bottom = this.ChartBorder.GetBottom(); } var defaultTextHeight=16 var textHeight = defaultTextHeight; var y = this.GetYFromData(item.Value); var position=0; if (item.ExtendData && item.ExtendData.Custom) { var customItem=item.ExtendData.Custom; if (IFrameSplitOperator.IsNumber(customItem.Position)) position=customItem.Position; } if (item.Message[0]) { if (borderLeft < 10 || position==1) //左边 { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; var textInfo=this.GetCustomItemTextInfo(item,true); var textWidth = textInfo.MaxWidth; var fontHeight=this.GetFontHeight(); textHeight=fontHeight>defaultTextHeight? fontHeight:defaultTextHeight; var bgColor = item.LineColor; var rgb = this.RGBToStruct(item.LineColor); if (rgb) bgColor = `rgba(${rgb.R}, ${rgb.G}, ${rgb.B}, ${g_JSChartResource.FrameLatestPrice.BGAlpha})`; //内部刻度 背景增加透明度 var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var bgColor = item.LineColor; var rgb = this.RGBToStruct(item.LineColor); if (rgb) bgColor = `rgba(${rgb.R}, ${rgb.G}, ${rgb.B}, ${g_JSChartResource.FrameLatestPrice.BGAlpha})`; //内部刻度 背景增加透明度 var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var yText=y; for(var i=0;iwidth) width=value; aryText.push({Text:item.Text, Width:value+3}); } } if (width>0) width+=3; } else { width=this.Canvas.measureText(text).width+3; aryText.push( {Text:text, Width:width} ); } return { MaxWidth:width, Text:aryText }; } this.SendDrawCountDownEvent=function(sendData) { if (!this.GetEventCallback) return false; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_COUNTDOWN); if (!event || !event.Callback) return false; event.Callback(event,sendData,this); return true; } this.DrawLine=function(left, right, y, color, lineType) { if (lineType==-1) return; if (lineType==0) { this.Canvas.strokeStyle = color; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(ToFixedPoint(y), left); this.Canvas.lineTo(ToFixedPoint(y), right); } else { this.Canvas.moveTo(left, ToFixedPoint(y)); this.Canvas.lineTo(right, ToFixedPoint(y)); } this.Canvas.stroke(); } else { this.DrawDotLine(left, right, y, color); } } this.DrawDotLine = function (left, right, y, color) { this.Canvas.save(); this.Canvas.strokeStyle = color; this.Canvas.setLineDash([5, 5]); //虚线 this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(ToFixedPoint(y), left); this.Canvas.lineTo(ToFixedPoint(y), right); } else { this.Canvas.moveTo(left, ToFixedPoint(y)); this.Canvas.lineTo(right, ToFixedPoint(y)); } this.Canvas.stroke(); this.Canvas.restore(); } this.RGBToStruct = function (rgb) { if (/^(rgb|RGB)/.test(rgb)) { var aColor = rgb.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); var result = {}; if (aColor.length != 3) return null; result.R = Number(aColor[0]); result.G = Number(aColor[1]); result.B = Number(aColor[2]); return result; } return null; } this.DrawHScreenText = function (center, data) { this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = data.Color; this.Canvas.save(); this.Canvas.translate(center.X, center.Y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(data.Text, data.XOffset, data.YOffset); this.Canvas.restore(); } this.GetScaleTextWidth=function() { var border=this.ChartBorder.GetBorder(); if (this.IsHScreen) { var borderTop = this.ChartBorder.Top; var borderBottom = this.ChartBorder.Bottom; var isDrawLeft=borderTop>10 && this.IsShowYText[0]===true; var isDrawRight=borderBottom>10 && this.IsShowYText[1]===true; } else { var borderRight=this.ChartBorder.Right; var borderLeft=this.ChartBorder.Left; var isDrawLeft=borderLeft>10 && this.IsShowYText[0]===true; var isDrawRight=borderRight>10 && this.IsShowYText[1]===true; } var width={ Left:null, Right:null }; if (!isDrawRight && !isDrawLeft) return width; for(var i=0;i= count) { return this.ChartBorder.GetRight(); } else { var offset = this.ChartBorder.GetLeft() + this.ChartBorder.GetWidth() * index / count; return offset; } } //X坐标转x轴数值 this.GetXData = function (x) { if (x <= this.ChartBorder.GetLeft()) return 0; if (x >= this.ChartBorder.GetRight()) return this.XPointCount; return (x - this.ChartBorder.GetLeft()) * (this.XPointCount * 1.0 / this.ChartBorder.GetWidth()); } this.DrawCustomHorizontal = function () //Y轴刻度定制显示 { if (this.IsMinSize) return; for (var i in this.CustomHorizontalInfo) { var item = this.CustomHorizontalInfo[i]; switch (item.Type) { case 0: case 1: this.DrawCustomItem(item); //自定义刻度 break; } } } } function MinuteHScreenFrame() { this.newMethod = MinuteFrame; //派生 this.newMethod(); delete this.newMethod; this.ClassName='MinuteHScreenFrame'; this.IsHScreen = true; //是否是横屏 //画标题背景色 this.DrawTitleBG = function () { /* if (this.ChartBorder.TitleHeight <= 0) return; var left = ToFixedPoint(this.ChartBorder.GetRightEx()); var top = ToFixedPoint(this.ChartBorder.GetTop()); var bottom = ToFixedPoint(this.ChartBorder.GetBottom()); var width = this.ChartBorder.TitleHeight; var height = bottom - top; this.Canvas.fillStyle = this.TitleBGColor; this.Canvas.fillRect(left, top, width, height); */ } this.DrawInsideHorizontal = function () { if (this.IsMinSize) return; if (this.IsShowYText[0] === false && this.IsShowYText[1] === false) return; var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRightEx(); var top = this.ChartBorder.GetTop(); var bottom = this.ChartBorder.GetBottom(); var borderTop = this.ChartBorder.Top; var borderBottom = this.ChartBorder.Bottom; var titleHeight = this.ChartBorder.TitleHeight; var pixelTatio = 1; var isDrawLeft = (borderTop < 10 * pixelTatio || this.YTextPosition[0] == 2) && this.IsShowYText[0] === true; var isDrawRight = (borderBottom < 10 * pixelTatio || this.YTextPosition[1] == 2) && this.IsShowYText[1] === true; if (isDrawLeft || isDrawRight) { var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev != null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 //坐标信息 左边 间距小于10 画在内部 if (item.Message[0] != null && isDrawLeft) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textObj = { X: left, Y: y, Text: { BaseLine: this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font: this.Canvas.font, Value: item.Message[0] } }; var xText = y, yText = top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], 2, 0); this.Canvas.restore(); } if (item.Message[1] != null && isDrawRight) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textWidth = this.Canvas.measureText(item.Message[1]).width; var textObj = { X: right - textWidth, Y: y, Text: { BaseLine: this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font: this.Canvas.font, Value: item.Message[1] } }; var xText = y, yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[1], -2, 0); this.Canvas.restore(); } yPrev = y; } } } //Y坐标转y轴数值 this.GetYData = function (x) { if (x < this.ChartBorder.GetLeftEx()) return this.HorizontalMin; if (x > this.ChartBorder.GetRightEx()) return this.HorizontalMax; return (x - this.ChartBorder.GetLeftEx()) / this.ChartBorder.GetWidthEx() * (this.HorizontalMax - this.HorizontalMin) + this.HorizontalMin; } //X坐标转x轴数值 this.GetXData = function (y) { if (y <= this.ChartBorder.GetTop()) return 0; if (y >= this.ChartBorder.GetBottom()) return this.XPointCount; var count=this.XPointCount-1; return (y - this.ChartBorder.GetTop()) * (count * 1.0 / this.ChartBorder.GetHeight()); } this.GetXFromIndex = function (index) { var count = this.XPointCount - 1; if (count == 1) { if (index == 0) return this.ChartBorder.GetTop(); else return this.ChartBorder.GetBottom(); } else if (count <= 0) { return this.ChartBorder.GetTop(); } else if (index >= count) { return this.ChartBorder.GetBottom(); } else { var offset = this.ChartBorder.GetTop() + this.ChartBorder.GetHeight() * index / count; return offset; } } this.GetYFromData = function (value) { if (value <= this.HorizontalMin) return this.ChartBorder.GetLeftEx(); if (value >= this.HorizontalMax) return this.ChartBorder.GetRightEx(); var width = this.ChartBorder.GetWidthEx() * (value - this.HorizontalMin) / (this.HorizontalMax - this.HorizontalMin); return this.ChartBorder.GetLeftEx() + width; } //画Y轴 this.DrawHorizontal = function () { var top = this.ChartBorder.GetTop(); var bottom = this.ChartBorder.GetBottom(); var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var borderTop = this.ChartBorder.Top; var borderBottom = this.ChartBorder.Bottom; var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从左往右画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 this.Canvas.strokeStyle = item.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(y), top); this.Canvas.lineTo(ToFixedPoint(y), bottom); this.Canvas.stroke(); if (y >= right - 2) { this.Canvas.textBaseline = 'top'; y = right; } else if (y <= left + 2) { this.Canvas.textBaseline = 'bottom'; y=left; if (y != null && Math.abs(y - yPrev) < 2*this.MinYDistance) continue; //两个坐标在近了 就不画了 } else { this.Canvas.textBaseline = "middle"; } //坐标信息 左边 间距小于10 不画坐标 if (item.Message[0] != null && borderTop > 10) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; //this.Canvas.textBaseline = "middle"; var xText = y, yText = top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], -2, 0); this.Canvas.restore(); } //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1] != null && borderBottom > 10) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; //this.Canvas.textBaseline = "middle"; var xText = y, yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[1], 2, 0); this.Canvas.restore(); } yPrev = y; } } //画X轴 this.DrawVertical = function () { var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRightEx(); var bottom = this.ChartBorder.GetBottom(); var xPrev = null; //上一个坐标x的值 for (var i in this.VerticalInfo) { var x = this.GetXFromIndex(this.VerticalInfo[i].Value); if (x > bottom) break; if (xPrev != null && Math.abs(x - xPrev) < this.MinXDistance) continue; this.Canvas.strokeStyle = this.VerticalInfo[i].LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(left, ToFixedPoint(x)); this.Canvas.lineTo(right, ToFixedPoint(x)); this.Canvas.stroke(); if (this.VerticalInfo[i].Message[0] != null) { if (this.VerticalInfo[i].Font != null) this.Canvas.font = this.VerticalInfo[i].Font; this.Canvas.fillStyle = this.VerticalInfo[i].TextColor; var testWidth = this.Canvas.measureText(this.VerticalInfo[i].Message[0]).width; if (x < testWidth / 2) { this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "top"; } else if ((x + testWidth / 2) >= this.ChartBorder.GetChartHeight()) { this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "top"; } else { this.Canvas.textAlign = "center"; this.Canvas.textBaseline = "top"; } var xText = left, yText = x; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(this.VerticalInfo[i].Message[0], 0, 0); this.Canvas.restore(); } xPrev = x; } } this.DrawNightDayBG=function() { if (this.DayCount!=1) return; if (!this.HQChart) return; if (!this.HQChart.EnableNightDayBG) return; var symbol=this.HQChart.Symbol; if (!symbol) return; var xIndex=-1; //获取夜盘和日期的分界线X索引位置 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_MINUTE_NIGHT_DAY_X_INDEX) if (!event || !event.Callback) return; var sendData={ Symbol:symbol, XIndex:xIndex, MinuteTimeStringData:g_MinuteTimeStringData }; event.Callback(event,sendData,this); xIndex=sendData.XIndex; if (xIndex<0) return; var border=this.ChartBorder.GetHScreenBorder(); var y=this.GetXFromIndex(xIndex); var rtNight={ Left: border.Left, Top:border.Top, Right:border.RightEx, Bottom:y }; rtNight.Width=rtNight.Right-rtNight.Left; rtNight.Height=rtNight.Bottom-rtNight.Top; this.Canvas.fillStyle = this.NightDayConfig.NightBGColor; this.Canvas.fillRect(rtNight.Left, rtNight.Top, rtNight.Width, rtNight.Height); if (this.Identify!=0) return; //显示 日盘夜盘文字 this.Canvas.font=this.NightDayConfig.Font; this.Canvas.textBaseline = "bottom"; this.Canvas.textAlign = 'left'; var aryTitle=[{ Title:"夜盘", Position:1, Config:this.NightDayConfig.Night }, { Title:"日盘", Position:0,Config:this.NightDayConfig.Day }]; var textHeight= this.Canvas.measureText("擎").width; for(var i=0;i this.xPointCount - 1) index = this.xPointCount - 1; var offset = this.ChartBorder.GetLeft() + g_JSChartResource.FrameLeftMargin + this.DistanceWidth / 2 + this.DataWidth / 2; for (var i = 1; i <= index; ++i) { offset += this.DistanceWidth + this.DataWidth; } return offset; } //X坐标转x轴数值 this.GetXData = function (x) { if (x <= this.ChartBorder.GetLeft()) return 0; if (x >= this.ChartBorder.GetRight()) return this.XPointCount-1; var left=this.ChartBorder.GetLeft()+g_JSChartResource.FrameLeftMargin; var right=this.ChartBorder.GetRight()-g_JSChartResource.FrameRightMargin; var distanceWidth = this.DistanceWidth; var dataWidth = this.DataWidth; var index = 0; var xPoint = left + distanceWidth/2 + dataWidth + distanceWidth; while (xPoint < right && index < 10000 && index+1 x) break; xPoint += (dataWidth + distanceWidth); ++index; } //var test=(x-this.ChartBorder.GetLeft())*(this.XPointCount*1.0/this.ChartBorder.GetWidth()); return index; } this.DrawCustomHorizontal = function () //Y轴刻度定制显示 { if (this.IsMinSize) return; for (var i=0; i=0 && this.LastCalculateStatus.Width==width && this.LastCalculateStatus.XPointCount==this.XPointCount) //宽度没变 尝试使用原来的柱子宽度 { var caclWidth=(this.DistanceWidth/2+g_JSChartResource.FrameLeftMargin)+(this.DataWidth + this.DistanceWidth)*(this.XPointCount-1); var caclWidth2=(this.DataWidth + this.DistanceWidth) * this.XPointCount; if (caclWidth<= width) //当前的柱子宽度够用 就不调整了 return; } this.LastCalculateStatus.Width=width; this.LastCalculateStatus.XPointCount=this.XPointCount; for (var i = 0; i < ZOOM_SEED.length; ++i) { let barWidth = ZOOM_SEED[i][0]; //数据宽度 let distanceWidth = ZOOM_SEED[i][1]; //间距宽度 if ((ZOOM_SEED[i][0] + ZOOM_SEED[i][1]) * this.XPointCount < width) { this.ZoomIndex = i; this.DataWidth = ZOOM_SEED[i][0]; this.DistanceWidth = ZOOM_SEED[i][1]; this.TrimKLineDataWidth(width); JSConsole.Chart.Log(`[KLineFrame::CalculateDataWidth] ZoomIndex=${this.ZoomIndex} DataWidth=${this.DataWidth} DistanceWidth=${this.DistanceWidth}` ); return; } } //太多了 就平均分了 this.ZoomIndex = ZOOM_SEED.length - 1; this.DataWidth = width / this.XPointCount; this.DistanceWidth = 0; } this.OnSize=function(obj) { var width=this.GetFrameWidth()-g_JSChartResource.FrameMargin; var xPointCount=0; var y=this.DistanceWidth/2+g_JSChartResource.FrameLeftMargin+(this.DataWidth+this.DistanceWidth); for(;y width) { this.DistanceWidth -= 0.01; break; } this.DistanceWidth += 0.01; } /* if (zoom[0]<4) //最后2个缩放,调整间距不调整数据宽度, 数据都是画竖线的 { while (true) { if ((this.DistanceWidth + this.DataWidth) * this.XPointCount + this.DistanceWidth > width) { this.DistanceWidth -= 0.01; break; } this.DistanceWidth += 0.01; } } else { while (true) { if ((this.DistanceWidth + this.DataWidth) * this.XPointCount + this.DistanceWidth > width) { this.DataWidth -= 0.01; break; } this.DataWidth += 0.01; } } */ } this.IsOverlayMaxMin = function (obj) //当前坐标信息 是否覆盖最大 最小值输出 { if (!this.ChartKLine) return false; if (!this.ChartKLine.Max || !this.ChartKLine.Min) return false; var textWidth = this.Canvas.measureText(obj.Text.Value).width + 4; //刻度文字宽度 var max = this.ChartKLine.Max, min = this.ChartKLine.Min; var isOverlayMax = false, isOverlayMin = false; const textHeight = 20; //字体高度 if (max.X >= obj.X && max.X <= obj.X + textWidth) { var y1 = max.Y + textHeight, y2 = max.Y - textHeight; if ((y1 >= obj.Y - textHeight && y1 <= obj.Y + textHeight) || (y2 >= obj.Y - textHeight && y2 <= obj.Y + textHeight)) isOverlayMax = true; } if (isOverlayMax == true) return true; if (min.X >= obj.X && min.X <= obj.X + textWidth) //最小值X 坐标不在 刻度文字范围内 { var y1 = min.Y + textHeight, y2 = min.Y - textHeight; if ((y1 >= obj.Y - textHeight && y1 <= obj.Y + textHeight) || (y2 >= obj.Y - textHeight && y2 <= obj.Y + textHeight)) isOverlayMin = true; } return isOverlayMax || isOverlayMin; } //分割x,y轴坐标信息 this.SplitXYCoordinate = function () { if (this.XYSplit == false) { if (this.XSplit) { if (this.XSplitOperator) this.XSplitOperator.Operator(); } if (this.YCustomSplit) { if (this.YSplitOperator && this.YSplitOperator.CustomCoordinate) this.YSplitOperator.CustomCoordinate(); } return; } if (this.YSplitOperator != null) this.YSplitOperator.Operator(); if (this.XSplitOperator != null) this.XSplitOperator.Operator(); } this.CalculateCount = function (zoomIndex) { var width = this.GetFrameWidth() - g_JSChartResource.FrameMargin; return parseInt(width / (ZOOM_SEED[zoomIndex][0] + ZOOM_SEED[zoomIndex][1])); } this.ZoomUp = function (cursorIndex) { if (this.ZoomIndex <= 0) return false; if (this.Data.DataOffset < 0) return false; var dataCount = this.Data.Data.length; var maxDataCount = dataCount + this.RightSpaceCount; var rightSpaceCount = 0; var lastDataIndex = this.Data.DataOffset + this.XPointCount - 1; //最右边的数据索引 var lastCursorIndex = this.Data.DataOffset + cursorIndex.Index; if (lastDataIndex >= dataCount) { rightSpaceCount = lastDataIndex - (this.Data.Data.length - 1); //计算右边预留空间 lastDataIndex = this.Data.Data.length - 1; if (rightSpaceCount > this.RightSpaceCount) rightSpaceCount = this.RightSpaceCount; } var xPointCount = this.CalculateCount(this.ZoomIndex-1); --this.ZoomIndex; this.XPointCount = xPointCount; if (cursorIndex.IsLockRight==true) //固定右边 { var rightDataIndex=this.Data.DataOffset + this.XPointCount; //最右边的数据索引 if (xPointCount>rightDataIndex) { xPointCount=rightDataIndex; this.XPointCount=xPointCount; this.Data.DataOffset=0; } else { var dataOffset=lastDataIndex - (xPointCount-rightSpaceCount)+1; this.XPointCount=xPointCount; this.Data.DataOffset=dataOffset; if (this.Data.DataOffset<0) this.Data.DataOffset=0; } } else if (xPointCount >= maxDataCount) { xPointCount = maxDataCount; this.XPointCount = xPointCount; this.Data.DataOffset = 0; } else { this.XPointCount = xPointCount; this.Data.DataOffset = lastDataIndex - (this.XPointCount - rightSpaceCount) + 1; if (this.Data.DataOffset<0) { JSConsole.Chart.Log(`[KLineFrame::ZoomDown] this.Data.DataOffset=${this.Data.DataOffset}, reset this.Data.DataOffset=0`); this.Data.DataOffset=0; } } this.DataWidth = ZOOM_SEED[this.ZoomIndex][0]; this.DistanceWidth = ZOOM_SEED[this.ZoomIndex][1]; var width = this.GetFrameWidth() - g_JSChartResource.FrameMargin; this.TrimKLineDataWidth(width); this.LastCalculateStatus.XPointCount = this.XPointCount; cursorIndex.Index = lastCursorIndex - this.Data.DataOffset; return true; } this.ZoomDown = function (cursorIndex) { if (this.ZoomIndex + 1 >= ZOOM_SEED.length) return false; if (this.Data.DataOffset < 0) return false; if (this.Data.DataOffset<=0 && cursorIndex.IsLockRight==true) return false; var dataCount = this.Data.Data.length; var maxDataCount = dataCount + this.RightSpaceCount; //if (this.XPointCount >= dataCount) return false; var rightSpaceCount = 0; var lastDataIndex = this.Data.DataOffset + this.XPointCount - 1; //最右边的数据索引 if (lastDataIndex >= this.Data.Data.length) { rightSpaceCount = lastDataIndex - (this.Data.Data.length - 1); //计算右边预留空间 lastDataIndex = this.Data.Data.length - 1; if (rightSpaceCount > this.RightSpaceCount) rightSpaceCount = this.RightSpaceCount; } var xPointCount = this.CalculateCount(this.ZoomIndex + 1); var lastCursorIndex = this.Data.DataOffset + cursorIndex.Index; ++this.ZoomIndex; if (cursorIndex.IsLockRight==true) //固定右边 { var rightDataIndex=this.Data.DataOffset + this.XPointCount; //最右边的数据索引 if (xPointCount>rightDataIndex) { xPointCount=rightDataIndex; this.XPointCount=xPointCount; this.Data.DataOffset=0; } else { var dataOffset=lastDataIndex - (xPointCount-rightSpaceCount)+1; this.XPointCount=xPointCount; this.Data.DataOffset=dataOffset; if (this.Data.DataOffset<0) this.Data.DataOffset=0; } } else if (xPointCount >= maxDataCount) { //xPointCount = maxDataCount; this.XPointCount = xPointCount; this.Data.DataOffset = 0; } else { this.XPointCount = xPointCount; this.Data.DataOffset = lastDataIndex - (this.XPointCount - rightSpaceCount) + 1; if (this.Data.DataOffset<0) { JSConsole.Chart.Log(`[KLineFrame::ZoomDown] this.Data.DataOffset=${this.Data.DataOffset}, reset this.Data.DataOffset=0`); this.Data.DataOffset=0; } } this.DataWidth = ZOOM_SEED[this.ZoomIndex][0]; this.DistanceWidth = ZOOM_SEED[this.ZoomIndex][1]; var width = this.GetFrameWidth() - g_JSChartResource.FrameMargin; this.TrimKLineDataWidth(width); this.LastCalculateStatus.XPointCount = this.XPointCount; cursorIndex.Index = lastCursorIndex - this.Data.DataOffset; return true; } this.GetFrameWidth = function () { if (this.IsHScreen) return this.ChartBorder.GetHeight(); return this.ChartBorder.GetWidth(); } this.SetXShowCount=function(showCount) { var index=-1; var width=this.GetFrameWidth()-g_JSChartResource.FrameMargin; for(var i=0; i=showCount) { index=i; this.XPointCount=showCount; this.ZoomIndex=index; this.DataWidth=dataWidth; this.DistanceWidth=distanceWidth; if (dataWidth==1 && distanceWidth==0) this.DataWidth=width/this.XPointCount; this.LastCalculateStatus.XPointCount=this.XPointCount; this.LastCalculateStatus.Width=width; return; } } //太多了 就平均分了 this.XPointCount=showCount; this.ZoomIndex=ZOOM_SEED.length-1; this.DataWidth=width/this.XPointCount; this.DistanceWidth=0; this.LastCalculateStatus.XPointCount=this.XPointCount; this.LastCalculateStatus.Width=width; } //画标题背景色 this.DrawTitleBG=function() { if (!this.TitleBorderLine || !this.TitleBorderLine.Color) return; var border=this.GetBorder(); if (this.ChartBorder.TopSpace<5) return; this.Canvas.save(); this.Canvas.strokeStyle=this.TitleBorderLine.Color; if (this.TitleBorderLine.Dash) this.Canvas.setLineDash(this.TitleBorderLine.Dash); //虚线 var x=ToFixedPoint(border.TopTitle); this.Canvas.beginPath(); this.Canvas.moveTo(border.Left,x); this.Canvas.lineTo(border.Right,x); this.Canvas.stroke(); this.Canvas.restore(); } } //K线横屏框架 function KLineHScreenFrame() { this.newMethod = KLineFrame; //派生 this.newMethod(); delete this.newMethod; this.ClassName='KLineHScreenFrame'; this.IsHScreen = true; //是否是横屏 this.DrawInsideHorizontal = function () { if (this.IsMinSize) return; if (this.IsShowYText[0] === false && this.IsShowYText[1] === false) return; var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRightEx(); var top = this.ChartBorder.GetTop(); var bottom = this.ChartBorder.GetBottom(); var borderTop = this.ChartBorder.Top; var borderBottom = this.ChartBorder.Bottom; var titleHeight = this.ChartBorder.TitleHeight; var pixelTatio = 1; var isDrawLeft = (borderTop < 10 * pixelTatio || this.YTextPosition[0] == 2) && this.IsShowYText[0] === true; var isDrawRight = (borderBottom < 10 * pixelTatio || this.YTextPosition[1] == 2) && this.IsShowYText[1] === true; if (isDrawLeft || isDrawRight) { var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev != null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 //坐标信息 左边 间距小于10 画在内部 if (item.Message[0] != null && isDrawLeft) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textObj = { X: left, Y: y, Text: { BaseLine: this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font: this.Canvas.font, Value: item.Message[0] } }; var xText = y, yText = top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], 2, 0); this.Canvas.restore(); } if (item.Message[1] != null && isDrawRight) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textWidth = this.Canvas.measureText(item.Message[1]).width; var textObj = { X: right - textWidth, Y: y, Text: { BaseLine: this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font: this.Canvas.font, Value: item.Message[1] } }; var xText = y, yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[1], -2, 0); this.Canvas.restore(); } yPrev = y; } } } //画标题背景色 this.DrawTitleBG = function () { /* if (this.ChartBorder.TitleHeight <= 0) return; var left = ToFixedPoint(this.ChartBorder.GetRightEx()); var top = ToFixedPoint(this.ChartBorder.GetTop()); var bottom = ToFixedPoint(this.ChartBorder.GetBottom()); var width = this.ChartBorder.TitleHeight; var height = bottom - top; this.Canvas.fillStyle = this.TitleBGColor; this.Canvas.fillRect(left, top, width, height); */ } this.GetYFromData = function (value) { if (value <= this.HorizontalMin) return this.ChartBorder.GetLeftEx(); if (value >= this.HorizontalMax) return this.ChartBorder.GetRightEx(); var width = this.ChartBorder.GetWidthEx() * (value - this.HorizontalMin) / (this.HorizontalMax - this.HorizontalMin); return this.ChartBorder.GetLeftEx() + width; } //画Y轴 this.DrawHorizontal = function () { var top = this.ChartBorder.GetTop(); var bottom = this.ChartBorder.GetBottom(); var borderTop = this.ChartBorder.Top; var borderBottom = this.ChartBorder.Bottom; var left=this.ChartBorder.GetLeft(); var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从左往右画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && Math.abs(y - yPrev) < 15) continue; //两个坐标在近了 就不画了 if (y!=left) { if (item.LineType==2) { this.Canvas.strokeStyle = item.LineColor; this.Canvas.setLineDash([5,5]); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(y),top); this.Canvas.lineTo(ToFixedPoint(y),bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else if (item.LineType>0) { this.Canvas.strokeStyle = item.LineColor; if (g_JSChartResource.FrameYLineDash) { this.Canvas.setLineDash(g_JSChartResource.FrameYLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(y),top); this.Canvas.lineTo(ToFixedPoint(y),bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(y), top); this.Canvas.lineTo(ToFixedPoint(y), bottom); this.Canvas.stroke(); } } } //坐标信息 左边 间距小于10 不画坐标 if (item.Message[0] != null && borderTop > 10 && this.IsShowYText[0] === true) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "middle"; var xText = y, yText = top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], -2, 0); this.Canvas.restore(); } //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1] != null && borderBottom > 10 && this.IsShowYText[1] === true) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; var xText = y, yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[1], 2, 0); this.Canvas.restore(); } yPrev = y; } } this.GetXFromIndex = function (index) { if (index < 0) index = 0; if (index > this.xPointCount - 1) index = this.xPointCount - 1; var offset = this.ChartBorder.GetTop() + g_JSChartResource.FrameLeftMargin + this.DistanceWidth / 2 + this.DataWidth / 2; for (var i = 1; i <= index; ++i) { offset += this.DistanceWidth + this.DataWidth; } return offset; } //画X轴 this.DrawVertical = function () { var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRightTitle(); var bottom = this.ChartBorder.GetBottom(); var xPrev = null; //上一个坐标x的值 for (var i in this.VerticalInfo) { var x = this.GetXFromIndex(this.VerticalInfo[i].Value); if (x >= bottom) break; if (xPrev != null && Math.abs(x - xPrev) < 80) continue; var item=this.VerticalInfo[i]; if (item.LineType==2) { this.Canvas.setLineDash([5,5]); this.Canvas.beginPath(); this.Canvas.moveTo(left, ToFixedPoint(x)); this.Canvas.lineTo(right, ToFixedPoint(x)); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else if (item.LineType>0) { this.Canvas.strokeStyle = item.LineColor; if (g_JSChartResource.FrameXLineDash) { this.Canvas.setLineDash(g_JSChartResource.FrameXLineDash); this.Canvas.beginPath(); this.Canvas.moveTo(left, ToFixedPoint(x)); this.Canvas.lineTo(right, ToFixedPoint(x)); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.beginPath(); this.Canvas.moveTo(left, ToFixedPoint(x)); this.Canvas.lineTo(right, ToFixedPoint(x)); this.Canvas.stroke(); } } if (this.VerticalInfo[i].Message[0] != null) { if (this.VerticalInfo[i].Font != null) this.Canvas.font = this.VerticalInfo[i].Font; this.Canvas.fillStyle = this.VerticalInfo[i].TextColor; var testWidth = this.Canvas.measureText(this.VerticalInfo[i].Message[0]).width; if (x < testWidth / 2) { this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "top"; } else { this.Canvas.textAlign = "center"; this.Canvas.textBaseline = "top"; } var xText = left, yText = x; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(this.VerticalInfo[i].Message[0], 0, this.XBottomOffset); this.Canvas.restore(); } xPrev = x; } } //Y坐标转y轴数值 this.GetYData = function (x) { if (x < this.ChartBorder.GetLeftEx()) return this.HorizontalMin; if (x > this.ChartBorder.GetRightEx()) return this.HorizontalMax; return (x - this.ChartBorder.GetLeftEx()) / this.ChartBorder.GetWidthEx() * (this.HorizontalMax - this.HorizontalMin) + this.HorizontalMin; } //X坐标转x轴数值 this.GetXData = function (y) { if (y <= this.ChartBorder.GetTop()) return 0; if (y >= this.ChartBorder.GetBottom()) return this.XPointCount-1; var distanceWidth=this.DistanceWidth; var dataWidth=this.DataWidth; var left=this.ChartBorder.GetTop()+g_JSChartResource.FrameLeftMargin; var right=this.ChartBorder.GetBottom()-g_JSChartResource.FrameRightMargin; var index=0; var xPoint=left+distanceWidth/2+dataWidth+distanceWidth; while(xPoint=y) break; xPoint+=(dataWidth+distanceWidth); ++index; } return index; } } function OverlayKLineFrame() { this.newMethod=KLineFrame; //派生 this.newMethod(); delete this.newMethod; this.ClassName='OverlayKLineFrame'; this.MainFrame=null; //主框架 this.IsShareY=false; //使用和主框架公用Y轴 this.IsShowMainFrame=0; //是否显示在主框架坐标上 1=左边 2=右边 this.IsCalculateYMaxMin=true; //是否计算Y最大最小值 this.RightOffset=50; this.PenBorder=g_JSChartResource.OverlayFrame.BolderPen; //'rgb(0,0,0)' this.IsShow=false; //坐标是否显示 this.IsShowToolbar=true; //是否显示工具条 this.Title=null; this.TitleColor=g_JSChartResource.OverlayFrame.TitleColor; this.TitleFont=g_JSChartResource.OverlayFrame.TitleFont; this.KLineFrame_ReloadResource=this.ReloadResource; this.ReloadResource=function(resource) { this.KLineFrame_ReloadResource(resource); if (!resource) { this.PenBorder=g_JSChartResource.OverlayFrame.BolderPen; //'rgb(0,0,0)' this.TitleColor=g_JSChartResource.OverlayFrame.TitleColor; this.TitleFont=g_JSChartResource.OverlayFrame.TitleFont; } } this.Draw=function() { this.Buttons=[]; if (this.ChartBorder.IsShowTitleOnly) return; this.SplitXYCoordinate(); if (this.IsShow) { this.DrawVertical(); this.DrawHorizontal(); } this.SizeChange=false; this.XYSplit=false; } this.GetScaleTextWidth=function() { return { TextWidth:0 }; } //分割x,y轴坐标信息 this.SplitXYCoordinate=function() { if (this.XYSplit==false) return; if (this.IsShareY) //和主图指标共享Y轴坐标 { this.HorizontalMax=this.MainFrame.HorizontalMax; this.HorizontalMin=this.MainFrame.HorizontalMin; this.HorizontalInfo=[]; for(var i in this.MainFrame.HorizontalInfo) { var item=this.MainFrame.HorizontalInfo[i]; this.HorizontalInfo.push(item); } this.CoordinateType=this.MainFrame.CoordinateType; } else //独立Y轴坐标 { if (this.YSplitOperator!=null) this.YSplitOperator.Operator(); } } //画Y轴 this.DrawHorizontal=function() { var border=this.ChartBorder.GetBorder(); var left=border.Left; var right=border.Right; var bottom = border.Bottom; var top = this.ChartBorder.GetTopTitle(); var borderRight=this.ChartBorder.Right; right+=this.RightOffset; var yPrev=null; //上一个坐标y的值 for(var i=this.HorizontalInfo.length-1; i>=0; --i) //从上往下画分割线 { var item=this.HorizontalInfo[i]; var y=this.GetYFromData(item.Value); if (y!=null && Math.abs(y-yPrev)= bottom - 2) this.Canvas.textBaseline = 'bottom'; else if (y <= top + 2) this.Canvas.textBaseline = 'top'; else this.Canvas.textBaseline = "middle"; this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(right-2,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); this.Canvas.stroke(); //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1]!=null && borderRight>10) { if (item.Font!=null) this.Canvas.font=item.Font; var text=item.Message[1]; if (Array.isArray(item.Message[1])) text=item.Message[1][0]; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="left"; this.Canvas.fillText(text,right+2,y); } yPrev=y; } } //画X轴 this.DrawVertical=function() { var border=this.ChartBorder.GetBorder(); var top=border.TopEx; //var left=this.ChartBorder.GetLeft(); var right=border.Right; var bottom=border.BottomEx; right+=this.RightOffset; this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(right),ToFixedPoint(top)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(bottom)); this.Canvas.stroke(); } } function OverlayKLineHScreenFrame() { this.newMethod=KLineHScreenFrame; //派生 this.newMethod(); delete this.newMethod; this.ClassName='OverlayKLineHScreenFrame'; this.MainFrame=null; //主框架 this.IsShareY=false; //使用和主框架公用Y轴 this.IsCalculateYMaxMin=true; //是否计算Y最大最小值 this.RightOffset=50; this.PenBorder=g_JSChartResource.OverlayFrame.BolderPen; //'rgb(0,0,0)' this.IsShow=true; //坐标是否显示 this.Title=null; this.TitleColor=g_JSChartResource.OverlayFrame.TitleColor; this.TitleFont=g_JSChartResource.OverlayFrame.TitleFont; this.Draw=function() { this.SplitXYCoordinate(); if (this.IsShow) { this.DrawVertical(); this.DrawHorizontal(); } this.SizeChange=false; this.XYSplit=false; } //分割x,y轴坐标信息 this.SplitXYCoordinate=function() { if (this.XYSplit==false) return; if (this.IsShareY) //和主图指标共享Y轴坐标 { this.HorizontalMax=this.MainFrame.HorizontalMax; this.HorizontalMin=this.MainFrame.HorizontalMin; this.HorizontalInfo=[]; for(var i=0; i0) { var minPrice=this.BidPrice[0]; if (price0) { var maxPrice=this.AskPrice[this.AskPrice.length-1]; if (price>maxPrice) { isAskPrice=true; find=maxPrice; } } } if (find==null) return null; var x=this.GetXFromIndex(find); return { X:x, Price:find, IsAsk:isAskPrice }; } this.GetPrice=function(aryPrice, price) { if (!aryPrice || !Array.isArray(aryPrice) || aryPrice.length<=0) return null; if (pricearyPrice[aryPrice.length-1]) return null; var lastPrice=null; for(var i in aryPrice) { var item=aryPrice[i]; if (price==item) { return item; } if (pricexRange.MaxDiffer) differ=xRange.MaxDiffer; xRange.Differ=differ; xRange.Min=xRange.Center-xRange.Differ; xRange.Max=xRange.Center+xRange.Differ; return true; } } //导出统一使用JSCommon命名空间名 export { IChartFramePainting, AverageWidthFrame, MinuteFrame, MinuteHScreenFrame, OverlayMinuteFrame, OverlayMinuteHScreenFrame, OverlayKLineFrame, OverlayKLineHScreenFrame, ZOOM_SEED, KLineFrame, KLineHScreenFrame, DepthChartFrame, };