/* copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 小程序图形库 */ //行情数据结构体 及涉及到的行情算法(复权,周期等) import { ChartData, HistoryData, SingleData, MinuteData, Rect, JSCHART_EVENT_ID, OVERLAY_STATUS_ID, } from "./umychart.data.wechat.js"; import { g_JSChartResource, g_JSChartLocalization, JSChartResource, } from './umychart.resource.wechat.js' import { IFrameSplitOperator, } from './umychart.framesplit.wechat.js' import { JSCommonCoordinateData, MARKET_SUFFIX_NAME } from "./umychart.coordinatedata.wechat.js"; import { JSConsole } from "./umychart.console.wechat.js"; //配色 function JSChartPaintResource() { //指标不支持信息 this.Index= { NotSupport : { Font: "14px 微软雅黑", TextColor: "rgb(52,52,52)" } } } var g_JSChartPaintResource = new JSChartPaintResource(); 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.fontBoundingBoxAscent + fontInfo.fontBoundingBoxDescent; var textHeight=fontInfo.width+2; return textHeight; } function ColorToRGBA(color,opacity) { var reg = /^(rgb|RGB)/; if (reg.test(color)) { var strHex = "#"; var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); // 把RGB的3个数值变成数组 // 转成16进制 for (var i = 0; i < colorArr.length; i++) { var hex = Number(colorArr[i]).toString(16); if (hex === "0") hex += hex; strHex += hex; } color=strHex; } return "rgba(" + parseInt("0x" + color.slice(1, 3)) + "," + parseInt("0x" + color.slice(3, 5)) + "," + parseInt("0x" + color.slice(5, 7)) + "," + opacity + ")"; } //图新画法接口类 function IChartPainting() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName = 'IChartPainting'; //类名 this.Data = new ChartData(); //数据区 this.Script; //图形对应的指标脚本 (只有指标图形才有) this.NotSupportMessage = null; this.MessageFont = g_JSChartPaintResource.Index.NotSupport.Font; this.MessageColor = g_JSChartPaintResource.Index.NotSupport.TextColor; this.IsDrawFirst = false; //是否比K线先画 this.IsShow = true; //是否显示 this.IsVisible=true; //是否显示 (预留给外部单独设置线段显隐) this.GetEventCallback; this.Draw = function () { } this.GetYFromData=function(value,isLimit) { return this.ChartFrame.GetYFromData(value,isLimit); } this.IsMinuteFrame=function() { var isMinute=(this.ChartFrame.ClassName=="MinuteFrame" || this.ChartFrame.ClassName=="MinuteHScreenFrame" || this.ChartFrame.ClassName=="OverlayMinuteFrame" || this.ChartFrame.ClassName=="OverlayMinuteHScreenFrame"); return isMinute } //是否隐藏指标 this.IsHideScriptIndex=function() { if (this.Script && this.Script.IsShow==false) return true; return false; } this.DrawNotSupportmessage = function () { this.Canvas.font = this.MessageFont; this.Canvas.fillStyle = this.MessageColor; var left = this.ChartBorder.GetLeft(); var width = this.ChartBorder.GetWidth(); var top = this.ChartBorder.GetTopEx(); var height = this.ChartBorder.GetHeightEx(); var x = left + width / 2; var y = top + height / 2; this.Canvas.textAlign = "center"; this.Canvas.textBaseline = "middle"; this.Canvas.fillText(this.NotSupportMessage, x, y); } this.GetTooltipData = function (x, y, tooltip) { return false; } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; if (!this.Data || !this.Data.Data) return range; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null || isNaN(value)) continue; if (range.Max == null) range.Max = value; if (range.Min == null) range.Min = value; if (range.Max < value) range.Max = value; if (range.Min > value) range.Min = value; } return range; } this.GetDynamicFont = function (dataWidth) //根据宽度自动获取对应字体 { var font; if (dataWidth < 5) font = '4px Arial'; //字体根据数据宽度动态调整 else if (dataWidth < 7) font = '6px Arial'; else if (dataWidth < 9) font = '8px Arial'; else if (dataWidth < 11) font = '10px Arial'; else if (dataWidth < 13) font = '12px Arial'; else if (dataWidth < 15) font = '14px Arial'; else font = '16px Arial'; return font; } this.GetDynamicFontEx=function(dataWidth, distanceWidth, maxSize, minSize, zoom, fontname) //根据宽度自动获取对应字体 { if (maxSize==minSize) { var font=`${maxSize.toFixed(0)}px ${fontname}` ; return font; } var fontSize=(dataWidth+distanceWidth); if (zoom) { if (zoom.Type==0) { if (zoom.Value>0) fontSize=(dataWidth*zoom.Value); } else if (zoom.Type==1) { if (zoom.Value>0) fontSize=(dataWidth+distanceWidth)*zoom.Value; } else if (zoom.Type==2) { if (IFrameSplitOperator.IsNumber(zoom.Value)) fontSize=(dataWidth+distanceWidth) + (2*zoom.Value); } } if (fontSizemaxSize) fontSize=maxSize; var font=`${fontSize.toFixed(0)}px ${fontname}` ; return font; } this.SetFillStyle = function (color, x0, y0, x1, y1) { if (Array.isArray(color)) { let gradient = this.Canvas.createLinearGradient(x0, y0, x1, y1); var offset = 1 / (color.length-1); for (var i=0;i0 UpColor 其他 DownColor this.TradeData; //交易系统 包含买卖数据{Buy:, Sell:} this.IsShowMaxMinPrice = true; //是否显示最大最小值 this.TextFont = g_JSChartResource.KLine.MaxMin.Font; this.TextColor = g_JSChartResource.KLine.MaxMin.Color; this.InfoPointColor = g_JSChartResource.KLine.Info.Color; this.InfoPointColor2 = g_JSChartResource.KLine.Info.Color2; this.InfoDrawType = 0; //0=在底部画远点 1=在最低价画三角 this.PtMax; //最大值的位置 this.PtMin; //最小值的位置 this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度 this.MinColorBarWidth=g_JSChartResource.MinColorKBarWidth; this.CustomKLine; //自定义K线, key=date*1000000+time, key={ Color:, DrawType: } //当前屏显示K线信息 this.ShowRange={ }; //K线显示范围 { Start:, End:, DataCount:, ShowCount: } this.DrawKRange={ Start:null, End:null }; //当前屏K线的索引{ Start: , End:} //未回补的价格缺口 this.PriceGap={ Enable:false, Count:1 }; this.PriceGapStyple= { Line:{ Color:g_JSChartResource.PriceGapStyple.Line.Color }, Text:{ Color:g_JSChartResource.PriceGapStyple.Text.Color, Font: g_JSChartResource.PriceGapStyple.Text.Font } }; this.AryPriceGapCache=[]; //缺口数据 { } this.OneLimitBarType=0; //一字板颜色类型 4个价格全部都在同一个价位上 0=使用平盘颜色 1=跟昨收比较 this.DrawAKLine = function () //美国线 { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin; if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) { eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR); } var upColor=this.UpColor; var downColor=this.DownColor; var unchagneColor=this.UnchagneColor; var ptMax = { X: null, Y: null, Value: null, Align: 'left' }; var ptMin = { X: null, Y: null, Value: null, Align: 'left' }; var preKItemInfo=null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yLow = this.ChartFrame.GetYFromData(data.Low); var yHigh = this.ChartFrame.GetYFromData(data.High); var yOpen = this.ChartFrame.GetYFromData(data.Open); var yClose = this.ChartFrame.GetYFromData(data.Close); this.DrawKRange.End=i; var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right } }; if (ptMax.Value == null || ptMax.Value < data.High) //求最大值 { ptMax.X = x; ptMax.Y = yHigh; ptMax.Value = data.High; ptMax.Align = j < xPointCount / 2 ? 'left' : 'right'; } if (ptMin.Value == null || ptMin.Value > data.Low) //求最小值 { ptMin.X = x; ptMin.Y = yLow; ptMin.Value = data.Low; ptMin.Align = j < xPointCount / 2 ? 'left' : 'right'; } if (data.Open < data.Close) { this.Canvas.strokeStyle =upColor; //阳线 } else if (data.Open > data.Close) { this.Canvas.strokeStyle = downColor; //阴线 } else { if (eventUnchangeKLine && eventUnchangeKLine.Callback) { var sendData={ KItem:data, DataIndex:i, DefaultColor:unchagneColor, BarColor:null }; eventUnchangeKLine.Callback(eventUnchangeKLine, sendData, this); if (sendData.BarColor) unchagneColor=sendData.BarColor; } this.Canvas.strokeStyle =unchagneColor; //平线 } this.Canvas.beginPath(); //最高-最低 if (isHScreen) { if (data.High==data.Low && dataWidth < this.MinBarWidth) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow-1, ToFixedPoint(x)); } else { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } } else { if (data.High==data.Low && dataWidth < this.MinBarWidth) { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow+1); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } } this.Canvas.stroke(); if (dataWidth >= this.MinBarWidth) { this.Canvas.beginPath(); //开盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen), left); this.Canvas.lineTo(ToFixedPoint(yOpen), x); } else { this.Canvas.moveTo(left, ToFixedPoint(yOpen)); this.Canvas.lineTo(x, ToFixedPoint(yOpen)); } this.Canvas.stroke(); this.Canvas.beginPath(); //收盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yClose), right); this.Canvas.lineTo(ToFixedPoint(yClose), x); } else { this.Canvas.moveTo(right, ToFixedPoint(yClose)); this.Canvas.lineTo(x, ToFixedPoint(yClose)); } this.Canvas.stroke(); } if (this.Data.DataType == 0 && ChartData.IsDayPeriod(this.Data.Period,true)) //信息地雷 { var infoItem = { X: x, Xleft: left, XRight: right, YMax: yHigh, YMin: yLow, DayData: data, Index: j }; this.DrawInfoDiv(infoItem); } if (this.PriceGap.Enable && preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } this.PtMax = ptMax; this.PtMin = ptMin; } this.DrawCloseLine = function () //收盘价线 { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var bFirstPoint = true; this.Canvas.beginPath(); this.Canvas.strokeStyle = this.CloseLineColor; var preKItemInfo=null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yClose = this.ChartFrame.GetYFromData(data.Close); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) this.Canvas.moveTo(yClose, x); else this.Canvas.moveTo(x, yClose); bFirstPoint = false; } else { if (isHScreen) this.Canvas.lineTo(yClose, x); else this.Canvas.lineTo(x, yClose); } if (this.PriceGap.Enable ) { var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; if (preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } } if (bFirstPoint == false) this.Canvas.stroke(); } this.DrawCloseArea = function () //收盘价面积 { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xPointCount = this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var borderLeft=border.TopEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var borderLeft=border.LeftEx; } var bFirstPoint = true; var firstPoint = null; this.Canvas.beginPath(); this.Canvas.strokeStyle = this.CloseLineColor; var ptLast=null; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; if (this.Data.DataOffset>0) //把最左边的一个点连上 { var data=this.Data.Data[this.Data.DataOffset-1]; if (data && IFrameSplitOperator.IsNumber(data.Close)) { var x=borderLeft; var yClose=this.GetYFromData(data.Close,false); if (isHScreen) { this.Canvas.moveTo(yClose,x); firstPoint={ X:yClose, Y:x }; } else { this.Canvas.moveTo(x,yClose); firstPoint={ X:x, Y:yClose }; } bFirstPoint=false; } } var preKItemInfo=null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yClose = this.ChartFrame.GetYFromData(data.Close); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) { this.Canvas.moveTo(yClose, x); firstPoint = { X: yClose, Y: x }; } else { this.Canvas.moveTo(x, yClose); firstPoint = { X: x, Y: yClose }; } bFirstPoint = false; } else { if (isHScreen) this.Canvas.lineTo(yClose, x); else this.Canvas.lineTo(x, yClose); } if (i==this.Data.Data.length-1) { ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright }; } if (this.PriceGap.Enable ) { var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; if (preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } } this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点 if (bFirstPoint) return; this.Canvas.stroke(); //画面积 if (isHScreen) { this.Canvas.lineTo(this.ChartBorder.GetLeft(), x); this.Canvas.lineTo(this.ChartBorder.GetLeft(), firstPoint.Y); } else { this.Canvas.lineTo(x, this.ChartBorder.GetBottom()); this.Canvas.lineTo(firstPoint.X, this.ChartBorder.GetBottom()); } this.Canvas.closePath(); if (Array.isArray(this.CloseLineAreaColor)) { if (isHScreen) { let gradient = this.Canvas.createLinearGradient(this.ChartBorder.GetRightEx(), this.ChartBorder.GetTop(), this.ChartBorder.GetLeft(), this.ChartBorder.GetTop()); gradient.addColorStop(0, this.CloseLineAreaColor[0]); gradient.addColorStop(1, this.CloseLineAreaColor[1]); this.Canvas.fillStyle = gradient; } else { let gradient = this.Canvas.createLinearGradient(firstPoint.X, this.ChartBorder.GetTopEx(), firstPoint.X, this.ChartBorder.GetBottom()); gradient.addColorStop(0, this.CloseLineAreaColor[0]); gradient.addColorStop(1, this.CloseLineAreaColor[1]); this.Canvas.fillStyle = gradient; } } else { this.Canvas.fillStyle = this.CloseLineAreaColor; } this.Canvas.fill(); } this.DrawKBar = function () { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; var border=this.ChartBorder.GetBorder(); if (isHScreen) { xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; chartright = this.ChartBorder.GetBottom(); } var ptMax = { X: null, Y: null, Value: null, Align: 'left' }; var ptMin = { X: null, Y: null, Value: null, Align: 'left' }; var upColor = this.UpColor; var downColor = this.DownColor; var unchagneColor = this.UnchagneColor; var ptLast=null; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) { eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR); } var preKItemInfo=null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth), ++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; this.DrawKRange.End=i; var x = left + (right - left) / 2; var yLow = this.ChartFrame.GetYFromData(data.Low); var yHigh = this.ChartFrame.GetYFromData(data.High); var yOpen = this.ChartFrame.GetYFromData(data.Open); var yClose = this.ChartFrame.GetYFromData(data.Close); var y = yHigh; var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; if (ptMax.Value == null || ptMax.Value < data.High) //求最大值 { ptMax.X = x; ptMax.Y = yHigh; ptMax.Value = data.High; ptMax.Align = j < xPointCount / 2 ? 'left' : 'right'; } if (ptMin.Value == null || ptMin.Value > data.Low) //求最小值 { ptMin.X = x; ptMin.Y = yLow; ptMin.Value = data.Low; ptMin.Align = j < xPointCount / 2 ? 'left' : 'right'; } if (this.ColorData) ///五彩K线颜色设置 { if (i < this.ColorData.length) upColor = downColor = unchagneColor = (this.ColorData[i] > 0 ? this.UpColor : this.DownColor); else upColor = downColor = unchagneColor = this.DownColor; } var kLineOption=this.GetCustomKLine(data); if (kLineOption) { var barColor=kLineOption.Color; if (!barColor) { if (data.Opendata.Close) barColor=downColor; else barColor=unchagneColor; } var drawType=this.DrawType; if (IFrameSplitOperator.IsNumber(kLineOption.DrawType)) drawType=kLineOption.DrawType; this.DrawKBar_Custom(data, dataWidth, barColor, drawType, kLineOption, x, y, left, right, yLow, yHigh, yOpen, yClose, border, isHScreen); } else if (this.DrawType==9 && data.ColorData) { this.DrawColorKBar(data, data.ColorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } else if (data.Open < data.Close) //阳线 { this.DrawKBar_Up(data, dataWidth, upColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } else if (data.Open > data.Close) //阴线 { this.DrawKBar_Down(data, dataWidth, downColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } else // 平线 { var barColor=unchagneColor; if (eventUnchangeKLine && eventUnchangeKLine.Callback) { var sendData={ KItem:data, DataIndex:i, DefaultColor:barColor, BarColor:null }; eventUnchangeKLine.Callback(eventUnchangeKLine, sendData, this); if (sendData.BarColor) barColor=sendData.BarColor; } this.DrawKBar_Unchagne(data, dataWidth, barColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } if (this.Data.DataType == 0 && ChartData.IsDayPeriod(this.Data.Period,true)) //信息地雷 { var infoItem = { X: x, Xleft: left, XRight: right, YMax: yHigh, YMin: yLow, DayData: data, Index: j }; this.DrawInfoDiv(infoItem); } if (i==this.Data.Data.length-1) { ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright }; } if (this.PriceGap.Enable && preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点 this.PtMax = ptMax; this.PtMin = ptMin; } this.DrawKBar_Up = function(data, dataWidth, upColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //阳线 { var isEmptyBar=(drawType==3 || drawType==6); if (dataWidth >= this.MinBarWidth) { if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } this.Canvas.strokeStyle = upColor; if (data.High > data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : yClose), ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen))); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yClose)); } } this.Canvas.stroke(); y = yClose; } else { y = yClose; } this.Canvas.fillStyle = upColor; if (isHScreen) { if (Math.abs(yOpen - y) < 1) { this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { //宽度是负数竟然不会画, h5就可以 //this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth)); this.Canvas.fillRect(ToFixedRect(Math.min(yOpen, y)), ToFixedRect(left), ToFixedRect(Math.abs(yOpen - y)), ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen - y) < 1) { this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y)); } } } if (data.Open > data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen))); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow)); } } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } this.Canvas.strokeStyle = upColor; this.Canvas.stroke(); } } this.DrawKBar_Down=function(data, dataWidth, downColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //阴线 { var isEmptyBar=(drawType==6); if (dataWidth >= this.MinBarWidth) { if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } this.Canvas.strokeStyle = downColor; if (data.High > data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yOpen), ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen))); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yOpen)); } } this.Canvas.stroke(); y = yOpen; } else { y = yOpen } this.Canvas.fillStyle = downColor; if (isHScreen) { if (Math.abs(yClose - y) < 1) { this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { //宽度是负数竟然不会画, h5就可以 this.Canvas.fillRect(ToFixedRect(Math.min(yClose, y)), ToFixedRect(left), ToFixedRect(Math.abs(yClose - y)), ToFixedRect(dataWidth)); } } else { if (Math.abs(yClose - y) < 1) { this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y)); } } } if (data.Open > data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen))); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow)); } } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } this.Canvas.strokeStyle = downColor; this.Canvas.stroke(); } } this.DrawKBar_Unchagne=function(data, dataWidth, unchagneColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //平线 { if (this.OneLimitBarType===1 && this.IsOneLimitBar(data)) //一字板 { unchagneColor=this.GetOneLimitBarColor(data); } if (dataWidth >= this.MinBarWidth) { if ((dataWidth%2)!=0) dataWidth-=1; this.Canvas.strokeStyle = unchagneColor; this.Canvas.beginPath(); if (data.High > data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y, ToFixedPoint(x)); this.Canvas.lineTo(yOpen, ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed), y); this.Canvas.lineTo(ToFixedPoint(xFixed), yOpen); } y = yOpen; } else { y = yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(left+dataWidth), ToFixedPoint(y)); } if (data.Open > data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed), ToFixedPoint(yLow)); } } this.Canvas.stroke(); } else { this.Canvas.beginPath(); if (isHScreen) { if (data.High==data.Low) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow-1,ToFixedPoint(x)); } else { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } } else { if (data.High==data.Low) { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow+1); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } } this.Canvas.strokeStyle = unchagneColor; this.Canvas.stroke(); } } //是否是一字板 this.IsOneLimitBar=function(kItem) { if (kItem.Open==kItem.Close && kItem.High==kItem.Low && kItem.Open==kItem.High) return true; return false; } //一字板颜色 和昨收比较 this.GetOneLimitBarColor=function(kItem) { if (!kItem || !IFrameSplitOperator.IsNumber(kItem.YClose)) return this.UnchagneColor; if (kItem.Close>kItem.YClose) return this.UpColor; else if (kItem.Close=4) { this.Canvas.strokeStyle=barColor; if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(drawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(drawType==3?Math.min(yClose,yOpen):yClose)); } this.Canvas.stroke(); y=yClose; } else { y=yClose; } this.Canvas.fillStyle=barColor; if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (drawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (drawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(drawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(drawType==3?Math.max(yClose,yOpen):y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=barColor; this.Canvas.stroke(); } } //绘制自定义K线 this.DrawColorKBar=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (Math.abs(yClose-yOpen)<1) this.DrawColorKBar_Line(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); else if (colorData.Border || colorData.Type===0) this.DrawColorKBar_Border(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); else this.DrawColorKBar_NoBorder(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } //带边框柱子 this.DrawColorKBar_Border=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=this.MinColorBarWidth) { if ((dataWidth%2)!=0) dataWidth-=1; var topPrice=Math.max(data.Close,data.Open); var bottomPrice=Math.min(data.Close,data.Open); if (isHScreen) { var yBarTop=Math.max(yClose,yOpen); var yBarBottom=Math.min(yClose,yOpen); } else { var yBarTop=Math.min(yClose,yOpen); var yBarBottom=Math.max(yClose,yOpen); } var yBarHeight=Math.abs(yClose-yOpen); //上影线 if (data.High>topPrice && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yBarTop),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yBarTop)); } this.Canvas.stroke(); } //下影线 if (bottomPrice>data.Low && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yBarBottom),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yBarBottom)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } this.Canvas.stroke(); } //中心柱子 this.Canvas.beginPath(); if (isHScreen) { this.Canvas.rect(ToFixedPoint(yBarBottom),ToFixedPoint(left),ToFixedRect(yBarHeight),ToFixedRect(dataWidth)); } else { this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarHeight)); } this.Canvas.closePath(); if (colorData.Type==0) //空心柱子 { if (colorData.BarColor) //边框 { this.Canvas.strokeStyle=colorData.BarColor; this.Canvas.stroke(); } if (colorData.Border) { this.Canvas.strokeStyle=colorData.Border.Color; this.Canvas.stroke(); } } else if (colorData.Type==1) //实心 { if (colorData.BarColor) //内部填充 { this.Canvas.fillStyle=colorData.BarColor; this.Canvas.fill(); } if (colorData.Border) //边框 { this.Canvas.strokeStyle=colorData.Border.Color; this.Canvas.stroke(); } } } else { this.DrawColorKBar_MinBar(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } } //不带边框柱子 this.DrawColorKBar_NoBorder=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=this.MinColorBarWidth) { var topPrice=Math.max(data.Close,data.Open); var bottomPrice=Math.min(data.Close,data.Open); if (isHScreen) { var yBarTop=Math.max(yClose,yOpen); var yBarBottom=Math.min(yClose,yOpen); } else { var yBarTop=Math.min(yClose,yOpen); var yBarBottom=Math.max(yClose,yOpen); } var yBarHeight=Math.abs(yClose-yOpen); //上影线 if (data.High>topPrice && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yBarTop),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yBarTop)); } this.Canvas.stroke(); } //下影线 if (bottomPrice>data.Low && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yBarBottom),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yBarBottom)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } this.Canvas.stroke(); } //中心柱子 this.Canvas.beginPath(); if (isHScreen) { this.Canvas.rect(ToFixedPoint(yBarBottom),ToFixedPoint(left),ToFixedRect(yBarHeight),ToFixedRect(dataWidth)); } else { this.Canvas.rect(ToFixedRect(left),ToFixedRect(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarHeight)); } this.Canvas.closePath(); if (colorData.Type==1) //实心 { if (colorData.BarColor) //内部填充 { this.Canvas.fillStyle=colorData.BarColor; this.Canvas.fill(); } } } else { this.DrawColorKBar_MinBar(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } } this.DrawColorKBar_MinBar=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } /* var barColor; if (colorData.Type==0) //空心柱子 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } else if (colorData.Type==1) //实心 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } if (barColor) { this.Canvas.strokeStyle=barColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yOpen)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose)); } this.Canvas.stroke(); } */ } //十字线 this.DrawColorKBar_Line=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=this.MinColorBarWidth) { if (colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } var barColor; if (colorData.Type==0) //空心柱子 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } else if (colorData.Type==1) //实心 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } if (barColor) { this.Canvas.strokeStyle=barColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(yOpen)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(yOpen)); } this.Canvas.stroke(); } } else { if (colorData.Line) { var xFixed=left+dataWidth/2; this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } } this.ClearCustomKLine=function() { this.CustomKLine=null; } this.GetCustomKLine=function(kItem) { if (!this.CustomKLine) return null; if (!kItem) return null; var key=kItem.Date*1000000; if (IFrameSplitOperator.IsNumber(kItem.Time)) key+=kItem.Time; if (!this.CustomKLine.has(key)) return null; var value=this.CustomKLine.get(key); return value; } this.DrawTrade = function () //交易系统 { if (!this.TradeData) return; var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; if (isHScreen) { xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; chartright = this.ChartBorder.GetBottom(); } var sellData = this.TradeData.Sell; var buyData = this.TradeData.Buy; var arrowWidth = dataWidth; if (arrowWidth > 10) arrowWidth = 10; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; var buy = false, sell = false; if (sellData && i < sellData.length) sell = sellData[i] > 0; if (buyData && i < buyData.length) buy = buyData[i] > 0; if (!sell && !buy) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yLow = this.ChartFrame.GetYFromData(data.Low); var yHigh = this.ChartFrame.GetYFromData(data.High); var yOpen = this.ChartFrame.GetYFromData(data.Open); var yClose = this.ChartFrame.GetYFromData(data.Close); var y = yHigh; if (buy) { this.Canvas.fillStyle = this.UpColor; this.Canvas.strokeStyle = this.UnchagneColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yLow - 1, x); this.Canvas.lineTo(yLow - arrowWidth - 1, x - arrowWidth / 2); this.Canvas.lineTo(yLow - arrowWidth - 1, x + arrowWidth / 2); } else { this.Canvas.moveTo(x, yLow + 1); this.Canvas.lineTo(x - arrowWidth / 2, yLow + arrowWidth + 1); this.Canvas.lineTo(x + arrowWidth / 2, yLow + arrowWidth + 1); } this.Canvas.closePath(); this.Canvas.fill(); this.Canvas.stroke(); } if (sell) { this.Canvas.fillStyle = this.DownColor; this.Canvas.strokeStyle = this.UnchagneColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh + 1, x); this.Canvas.lineTo(yHigh + arrowWidth + 1, x - arrowWidth / 2); this.Canvas.lineTo(yHigh + arrowWidth + 1, x + arrowWidth / 2); } else { this.Canvas.moveTo(x, yHigh - 1); this.Canvas.lineTo(x - arrowWidth / 2, yHigh - arrowWidth - 1); this.Canvas.lineTo(x + arrowWidth / 2, yHigh - arrowWidth - 1); } this.Canvas.closePath(); this.Canvas.fill(); this.Canvas.stroke(); } } } this.Draw = function () { this.PtMax = { X: null, Y: null, Value: null, Align: 'left' }; //清空最大 this.PtMin = { X: null, Y: null, Value: null, Align: 'left' }; //清空最小 this.ChartFrame.ChartKLine = { Max: null, Min: null }; //保存K线上 显示最大最小值坐标 this.DrawKRange={ Start:null, End:null }; this.AryPriceGapCache=[]; if (this.IsShow == false) return; if (this.DrawType == 1) { this.DrawCloseLine(); if (this.PriceGap.Enable) this.DrawPriceGap(); return; } else if (this.DrawType == 2) { this.DrawAKLine(); } else if (this.DrawType == 4) { this.DrawCloseArea(); } else if (this.DrawType==9) { this.DrawKBar(); } else { this.DrawKBar(); } this.DrawTrade(); if (this.PriceGap.Enable) this.DrawPriceGap(); if (this.IsShowMaxMinPrice) //标注最大值最小值 { if (this.ChartFrame.IsHScreen === true) this.HScreenDrawMaxMinPrice(this.PtMax, this.PtMin); else this.DrawMaxMinPrice(this.PtMax, this.PtMin); } } this.OnFormatHighLowTitle=function(ptMax, ptMin) { if (!ptMax || !ptMin) return null; if (!IFrameSplitOperator.IsNumber(ptMax.Value) || !IFrameSplitOperator.IsNumber(ptMin.Value)) return null; var defaultfloatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol); //小数位数 var title= { High:ptMax.Value.toFixed(defaultfloatPrecision), Low:ptMin.Value.toFixed(defaultfloatPrecision) }; if (!this.GetEventCallback) return title; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_KLINE_HIGH_LOW_TITLE); if (!event || !event.Callback) return title; var data={ Max:ptMax, Min:ptMin, Symbol:this.Symbol, Title:{ High:title.High, Low:title.Low }, Decimal:defaultfloatPrecision, PreventDefault:false }; event.Callback(event, data, this); if (data.PreventDefault) return data.Title; //使用外部回调的数值 return title; } this.DrawMaxMinPrice = function (ptMax, ptMin) { if (ptMax.X == null || ptMax.Y == null || ptMax.Value == null) return; if (ptMin.X == null || ptMin.Y == null || ptMin.Value == null) return; var title=this.OnFormatHighLowTitle(ptMax,ptMin); if (!title) return; var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow; var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow; var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset; var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset; var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol); this.Canvas.font = this.TextFont; this.Canvas.textAlign = ptMax.Align; this.Canvas.textBaseline = 'bottom'; var left = ptMax.X; if (IFrameSplitOperator.IsNumber(highYOffset)) ptMax.Y+=highYOffset; //var text = ptMax.Value.toFixed(defaultfloatPrecision); var text=title.High; var textColor=this.TextColor; if (title.HighColor) textColor=title.HighColor; this.Canvas.fillStyle = textColor; if (ptMax.Align == 'left') text = leftArrow + text; else text = text + rightArrow; this.Canvas.fillText(text, left, ptMax.Y); this.ChartFrame.ChartKLine.Max = { X: left, Y: ptMax.Y, Text: { BaseLine: 'bottom' } }; this.Canvas.textAlign = ptMin.Align; this.Canvas.textBaseline = 'top'; var left = ptMin.X; if (IFrameSplitOperator.IsNumber(lowYOffset)) ptMin.Y+=lowYOffset; //text = ptMin.Value.toFixed(defaultfloatPrecision); var text=title.Low; var textColor=this.TextColor; if (title.LowColor) textColor=title.LowColor; this.Canvas.fillStyle = textColor; if (ptMin.Align == 'left') text = leftArrow + text; else text = text + rightArrow; this.Canvas.fillText(text, left, ptMin.Y); this.ChartFrame.ChartKLine.Min = { X: left, Y: ptMin.Y, Text: { BaseLine: 'top' } }; } this.HScreenDrawMaxMinPrice = function (ptMax, ptMin) //横屏模式下显示最大最小值 { if (ptMax.X == null || ptMax.Y == null || ptMax.Value == null) return; if (ptMin.X == null || ptMin.Y == null || ptMin.Value == null) return; var title=this.OnFormatHighLowTitle(ptMax,ptMin); if (!title) return; var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow; var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow; var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset; var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset; var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol); var xText = ptMax.Y; var yText = ptMax.X; if (IFrameSplitOperator.IsNumber(highYOffset)) xText+=highYOffset; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.font = this.TextFont; if (title.HighColor) this.Canvas.fillStyle=title.HighColor; else this.Canvas.fillStyle=this.TextColor; this.Canvas.textAlign = ptMax.Align; this.Canvas.textBaseline = 'bottom'; var text=title.High; //var text = ptMax.Value.toFixed(defaultfloatPrecision); if (ptMax.Align == 'left') text = leftArrow + text; else text = text + rightArrow; this.Canvas.fillText(text, 0, 0); this.Canvas.restore(); var xText = ptMin.Y; var yText = ptMin.X; if (IFrameSplitOperator.IsNumber(lowYOffset)) xText+=lowYOffset; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.font = this.TextFont; if (title.LowColor) this.Canvas.fillStyle=title.LowColor; else this.Canvas.fillStyle=this.TextColor; this.Canvas.textAlign = ptMin.Align; this.Canvas.textBaseline = 'top'; var text=title.Low; //var text = ptMin.Value.toFixed(defaultfloatPrecision); if (ptMin.Align == 'left') text = leftArrow + text; else text = text + rightArrow; this.Canvas.fillText(text, 0, 0); this.Canvas.restore(); } //画某一天的信息地雷 画在底部 this.DrawInfoDiv = function (item) { if (!this.InfoData || this.InfoData.size <= 0) return; var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var infoData = this.InfoData.get(item.DayData.Date.toString()); if (!infoData || infoData.Data.length <= 0) return; var bHScreen = (this.ChartFrame.IsHScreen === true); if (this.InfoDrawType === 1) { this.Canvas.font = this.GetDynamicFont(dataWidth); this.Canvas.fillStyle = this.InfoPointColor2; this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'top'; if (bHScreen) { var xText = item.YMin; var yText = item.X; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText('▲', 0, 0); this.Canvas.restore(); } else { var left = ToFixedPoint(item.X); this.Canvas.fillText('▲', left, item.YMin); } } else { var dataWidth = this.ChartFrame.DataWidth; var radius = dataWidth / 2; if (radius > 3) radius = 3; var x = item.X; var y = this.ChartFrame.ChartBorder.GetBottom() - 2 - radius; if (bHScreen) y = this.ChartFrame.ChartBorder.GetLeft() + 2 + radius; this.Canvas.fillStyle = this.InfoPointColor; this.Canvas.beginPath(); if (bHScreen) this.Canvas.arc(y, x, radius, 0, Math.PI * 2, true); else this.Canvas.arc(ToFixedPoint(x), y, radius, 0, Math.PI * 2, true); this.Canvas.closePath(); this.Canvas.fill(); } } this.GetTooltipData = function (x, y, tooltip) { return false; } this.GetMaxMin = function () //计算当天显示数据的最大最小值 { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Max = null; range.Min = null; if (this.IsShow == false) return range; if (this.DrawType==1 || this.DrawType==4 ) // 1=收盘价线 4=收盘价面积图 { for(var i=this.Data.DataOffset,j=0;idata.Close) range.Min=data.Close; } } else { for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; if (range.Max == null) range.Max = data.High; if (range.Min == null) range.Min = data.Low; if (range.Max < data.High) range.Max = data.High; if (range.Min > data.Low) range.Min = data.Low; } } return range; } this.DrawLastPointEvent=function(ptLast) { if (!this.GetEventCallback) return; //通知外部绘制最后一个点 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_KLINE_LAST_POINT); if (event) { var kWidth={ Data: this.ChartFrame.DataWidth, Distance:this.ChartFrame.DistanceWidth }; if (ptLast) var data={ LastPoint:{ X:ptLast.X, Y:ptLast.Y, XLeft:ptLast.XLeft, XRight:ptLast.XRight }, KItem:ptLast.KItem, DrawType:this.DrawType, KWidth:kWidth, ChartRight:ptLast.ChartRight }; else var data={ LastPoint:null, KItem:null, KWidth:kWidth }; event.Callback(event,data,this); } } ////////////////////////////////////////////////////////////// // 标识缺口 ///////////////////////////////////////////////////////////// this.DrawPriceGap=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.AryPriceGapCache)) return; if (this.PriceGap.Count<=0) return; var index=this.AryPriceGapCache.length-this.PriceGap.Count; if (index<0) index=0; var isHScreen=(this.ChartFrame.IsHScreen===true); var border=null; if (isHScreen) border=this.ChartBorder.GetHScreenBorder(); else border=this.ChartBorder.GetBorder(); this.Canvas.font=this.PriceGapStyple.Text.Font; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; var textHeight=this.Canvas.measureText("擎").width; var decNum=JSCommonCoordinateData.GetfloatPrecision(this.Symbol); for(var i=index;irect.Right) { rtText.Right=rect.Right; rtText.Left=rtText.Right-rtText.Width; } this.Canvas.fillStyle=this.PriceGapStyple.Text.Color; this.Canvas.fillText(text,rtText.Left,rtText.Bottom); } //this.Canvas.fillStyle="rgb(250,250,250)" //this.Canvas.fillRect(rtText.Left, rtText.Top, rtText.Width, rtText.Height); } } } //是否有缺口 this.IsPriceGap=function(item, preItem) { if (!preItem || !item) return 0; if (preItem.Data.Low>item.Data.High) return 2; //下缺口 if (preItem.Data.High=start.Data.Low) { this.AryPriceGapCache.splice(i,1); --i; continue; } if (kItem.High>end.Data.High) item.Data[1]=kItemInfo; } } } } function ChartColorKline() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartColorKline'; //类名 this.Symbol; //股票代码 this.Color='rgb(0,255,44)'; this.IsEmptyBar=false; this.DrawType=0; //0=实心K线柱子 3=空心K线柱子 this.KLineColor; //Map key=K线索引 value=设置 this.DrawName; this.Draw=function() { if (!this.IsShow) return; if (this.DrawName=="DRAWCOLORKLINE") { this.DrawColorBar(); } else { if (!this.KLineColor) return; this.DrawBar(); } } this.DrawUpBarItem=function(data, xOffset, dataWidth, option) { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; var yLow=this.ChartFrame.GetYFromData(data.Low); var yHigh=this.ChartFrame.GetYFromData(data.High); var yOpen=this.ChartFrame.GetYFromData(data.Open); var yClose=this.ChartFrame.GetYFromData(data.Close); var y=yHigh; if (dataWidth>=4) { if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):yClose)); } this.Canvas.stroke(); y=yClose; } else { y=yClose; } if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (this.DrawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (this.DrawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.DrawDownBarItem=function(data, xOffset, dataWidth, option) { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; var yLow=this.ChartFrame.GetYFromData(data.Low); var yHigh=this.ChartFrame.GetYFromData(data.High); var yOpen=this.ChartFrame.GetYFromData(data.Open); var yClose=this.ChartFrame.GetYFromData(data.Close); var y=yHigh; if (dataWidth>=4) { if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yOpen)); } this.Canvas.stroke(); y=yOpen; } else { y=yOpen } if (isHScreen) { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yClose-y),ToFixedRect(dataWidth)); } else { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yClose)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yClose-y))); } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.DrawUnChangeBarItem=function(data, xOffset, dataWidth, option) { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; var yLow=this.ChartFrame.GetYFromData(data.Low); var yHigh=this.ChartFrame.GetYFromData(data.High); var yOpen=this.ChartFrame.GetYFromData(data.Open); var yClose=this.ChartFrame.GetYFromData(data.Close); var y=yHigh; if (dataWidth>=4) { this.Canvas.beginPath(); if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yOpen,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),y); this.Canvas.lineTo(ToFixedPoint(x),yOpen); } y=yOpen; } else { y=yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } this.Canvas.stroke(); } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.DrawBar=function() { var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; if (this.IsHScreen) { xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; chartright=this.ChartBorder.GetBottom(); } for(var i=this.Data.DataOffset,j=0;ichartright) break; if (itemOption.Color) { this.Canvas.strokeStyle=itemOption.Color; this.Canvas.fillStyle=itemOption.Color; } else { this.Canvas.strokeStyle=this.Color; this.Canvas.fillStyle=this.Color; } if (data.Opendata.Close) //阴线 { this.DrawDownBarItem(data,xOffset,dataWidth,itemOption); } else //平线 { this.DrawUnChangeBarItem(data,xOffset,dataWidth,itemOption); } } } this.DrawColorBar=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; } for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; if (data.Open==data.Close) this.DrawKBar_Unchagne(data, dataWidth, this.Color, this.IsEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); else this.DrawKBar_Custom(data, dataWidth, this.Color, this.IsEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } } this.DrawKBar_Unchagne=function(data, dataWidth, unchagneColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=4) { if ((dataWidth%2)!=0) dataWidth-=1; this.Canvas.strokeStyle=unchagneColor; this.Canvas.beginPath(); if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yOpen,ToFixedPoint(x)); } else { var xFixed=ToFixedPoint(left+dataWidth/2); this.Canvas.moveTo(xFixed,y); this.Canvas.lineTo(xFixed,yOpen); } y=yOpen; } else { y=yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(left+dataWidth),ToFixedPoint(y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=ToFixedPoint(left+dataWidth/2); this.Canvas.moveTo(xFixed,ToFixedPoint(y)); this.Canvas.lineTo(xFixed,ToFixedPoint(yLow)); } } this.Canvas.stroke(); } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { if (data.High==data.Low) { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow+1); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } } this.Canvas.strokeStyle=unchagneColor; this.Canvas.stroke(); } } this.DrawKBar_Custom=function(data, dataWidth, barColor, isEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } if (dataWidth>=4) { this.Canvas.strokeStyle=barColor; if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(isEmptyBar?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen))); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose)); } } this.Canvas.stroke(); y=yClose; } else { y=yClose; } this.Canvas.fillStyle=barColor; if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(isEmptyBar?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen))); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=barColor; this.Canvas.stroke(); } } this.GetMaxMin=function() { var range={Max:null,Min:null }; if (this.DrawName=="DRAWCOLORKLINE") { var xPointCount=this.ChartFrame.XPointCount; for(var i=this.Data.DataOffset,j=0;idata.Low) range.Min=data.Low; } } return range; } } function ChartDrawIcon() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartDrawIcon"; this.IsHScreen=false; //是否横屏 this.DrawCallback; //function(op, obj) op:1=开始 2=绘制 4=销毁 this.IsDestroy=false; //是否已销毁 this.TextAlign = 'left'; this.TextBaseline="middle"; this.IconID; this.Color; this.FixedIconSize; this.DrawItem=[]; this.Identify; this.Draw=function() { this.DrawItem=[]; if (this.DrawCallback) this.DrawCallback(1, {Self:this} ); this.DrawAllText(); if (this.DrawCallback) this.DrawCallback(2, { Self:this, Draw:this.DrawItem } ); } this.DrawAllText=function() { var isHScreen = (this.ChartFrame.IsHScreen === true) var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var top = this.ChartBorder.GetTopEx(); var bottom = this.ChartBorder.GetBottomEx(); if (isHScreen) { chartright = this.ChartBorder.GetBottom(); top = this.ChartBorder.GetRightEx(); bottom = this.ChartBorder.GetLeftEx(); } var xPointCount = this.ChartFrame.XPointCount; var isArrayText = Array.isArray(this.Text); for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; var drawTextInfo= { Text: { Color:this.Color, Align:this.TextAlign, Baseline:this.TextBaseline, }, X:x, Y:y, IconID:this.IconID }; this.DrawItem.push(drawTextInfo); } } this.OnDestroy=function() { this.IsDestroy=true; if (this.DrawCallback) this.DrawCallback(4, { Self:this } ); } } /* 文字输出 支持横屏 数组不为null的数据中输出 this.Text文本 */ function ChartSingleText() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(255,193,37)"; //线段颜色 this.TextFont = "14px 微软雅黑"; //字体 this.Text; this.TextAlign = 'left'; this.Direction = 0; //0=middle 1=bottom 2=top this.FixedFontSize=-1; //固定字体大小 this.YOffset = 0; this.Position; //指定输出位置 this.TextBG; //{ Color:"rgb(0,0,92)", Border:"rgb(205,0,92)", Margin:[0,1,1,1], } // { Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] } this.ShowOffset={ X:0, Y:0 }; //显示偏移 this.TextSize= { Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWICON.Text.FontName } this.ReloadResource=function(resource) { if (this.Name=="DRAWTEXT") { this.TextSize= { Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWTEXT.FontName } } else if (this.Name=="DRAWNUMBER") { this.TextSize= { Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWNUMBER.FontName } } } this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (this.Name=="DRAWTEXTREL" || this.Name=="DRAWTEXTABS") { this.DrawRectText(); return; } if (this.Position) { this.DrawPosition(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true) var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var top = this.ChartBorder.GetTopEx(); var bottom = this.ChartBorder.GetBottomEx(); if (isHScreen) { chartright = this.ChartBorder.GetBottom(); top = this.ChartBorder.GetRightEx(); bottom = this.ChartBorder.GetLeftEx(); } var xPointCount = this.ChartFrame.XPointCount; var isArrayText = Array.isArray(this.Text); var text; var drawTextInfo={ Text:{ }, Font:{ } }; //上下位置 if (this.Direction == 1) { this.Canvas.textBaseline = 'bottom'; drawTextInfo.Text={ Baseline: 'bottom'}; } else if (this.Direction == 2) { this.Canvas.textBaseline = 'top'; drawTextInfo.Text={ Baseline: 'top'}; } else { this.Canvas.textBaseline = 'middle'; drawTextInfo.Text={ Baseline: 'middle'}; } //字体大小 if (this.FixedFontSize>0) this.TextFont=`${this.FixedFontSize}px ${this.TextSize.FontName}`; else this.TextFont = this.GetDynamicFontEx(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName); drawTextInfo.Font={ Height:this.GetFontHeight(this.TextFont) }; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; y+=this.ShowOffset.Y; x+=this.ShowOffset.X; this.Canvas.textAlign = this.TextAlign; this.Canvas.fillStyle = this.Color; this.Canvas.font = this.TextFont; drawTextInfo.Text.Color=this.Color; drawTextInfo.Text.Align=this.TextAlign; drawTextInfo.X=x; drawTextInfo.Y=y; if (this.YOffset > 0 && this.Direction > 0) { var yPrice = y; this.Canvas.save(); this.Canvas.setLineDash([5, 10]); this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); if (isHScreen) { if (this.Direction == 1) { y = top - this.YOffset; yPrice += 5; } else { y = bottom + this.YOffset; yPrice -= 5; } this.Canvas.moveTo(ToFixedPoint(yPrice), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(x)); } else { if (this.Direction == 1) { y = top + this.YOffset; yPrice += 5; } else { y = bottom - this.YOffset; yPrice -= 5; } this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(yPrice)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(y)); } this.Canvas.stroke(); this.Canvas.restore(); } if (isArrayText) { text = this.Text[i]; if (!text) continue; if (isHScreen) { if (this.Name=='DRAWNUMBER') { if (this.Direction==1) y+=g_JSChartResource.DRAWABOVE.YOffset; else if (this.Direction==2) y-=4; } } else { if (this.Name=='DRAWNUMBER') { if (this.Direction==1) y-=g_JSChartResource.DRAWABOVE.YOffset; else if (this.Direction==2) y+=4; } } if (this.Name=="DRAWTEXT") this.DrawTextV2(text,drawTextInfo,isHScreen); else this.DrawText(text, x, y, isHScreen); } else { if (this.Name=="DRAWTEXT") { this.DrawTextV2(this.Text,drawTextInfo,isHScreen); } else { this.DrawText(this.Text, x, y, isHScreen); } } } } this.DrawPosition=function() //绘制在指定位置上 { if (!this.Text) return; var isHScreen=(this.ChartFrame.IsHScreen===true) if (isHScreen) { var y=this.ChartBorder.GetRightEx()-this.ChartBorder.GetWidthEx()*this.Position.Y; var x=this.ChartBorder.GetTop()+this.ChartBorder.GetHeight()*this.Position.X; } else { var x=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*this.Position.X; var y=this.ChartBorder.GetTopEx()+this.ChartBorder.GetHeight()*this.Position.Y; } this.Canvas.fillStyle=this.Color; //TYPE:0为左对齐,1为右对齐. if (this.Position.Type==0) this.Canvas.textAlign='left'; else if (this.Position.Type==1) this.Canvas.textAlign='right'; else this.Canvas.textAlign='center'; if (this.Direction==1) this.Canvas.textBaseline='bottom'; else if (this.Direction==2) this.Canvas.textBaseline='top'; else this.Canvas.textBaseline='middle'; this.DrawText(this.Text,x,y,isHScreen); } this.DrawText = function (text, x, y, isHScreen) { if (isHScreen) { this.Canvas.save(); this.Canvas.translate(y, x); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text, 0, 0); this.Canvas.restore(); } else { this.Canvas.fillText(text, x, y); } } this.DrawTextV2=function(text, drawInfo, isHScreen) { var textWidth=this.Canvas.measureText(text).width; if (isHScreen) { var x=drawInfo.Y; var y=drawInfo.X; if (drawInfo.Text.Align=="right") y=y-textWidth; else if (drawInfo.Text.Align=="center") y=y-textWidth/2; if (drawInfo.Text.Baseline=="top") x-=drawInfo.Font.Height; else if (drawInfo.Text.Baseline=="middle") x-=drawInfo.Font.Height/2; if (this.TextBG && (this.TextBG.Color || this.TextBG.Border)) { var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右 var xRect=x-margin[0]; var yRect=y-margin[2]; var bgWidth=textWidth+margin[2]+margin[3]; var bgHeight=drawInfo.Font.Height+margin[0]+margin[1]; if (this.TextBG.Color) { this.Canvas.fillStyle=this.TextBG.Color; this.Canvas.fillRect(xRect,yRect,bgHeight,bgWidth); } if (this.TextBG.Border) { this.Canvas.strokeStyle=this.TextBG.Border; this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgHeight),ToFixedRect(bgWidth)); } } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=drawInfo.Text.Color; 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=drawInfo.X; var y=drawInfo.Y; if (drawInfo.Text.Align=="right") x=x-textWidth; else if (drawInfo.Text.Align=="center") x=x-textWidth/2; if (drawInfo.Text.Baseline=="top") y+=drawInfo.Font.Height; else if (drawInfo.Text.Baseline=="middle") y+=drawInfo.Font.Height/2; if (this.TextBG && (this.TextBG.Color || this.TextBG.Border)) { var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右 var xRect=x-margin[2]; var yRect=y-drawInfo.Font.Height-margin[1]; var bgWidth=textWidth+margin[2]+margin[3]; var bgHeight=drawInfo.Font.Height+margin[0]+margin[1]; if (this.TextBG.Color) { this.Canvas.fillStyle=this.TextBG.Color; this.Canvas.fillRect(xRect,yRect,bgWidth,bgHeight); } if (this.TextBG.Border) { this.Canvas.strokeStyle=this.TextBG.Border; this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgWidth),ToFixedRect(bgHeight)); } } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=drawInfo.Text.Color; this.Canvas.fillText(text,x,y); } } this.DrawRectText=function() { if (!this.DrawData) return; var isHScreen=(this.ChartFrame.IsHScreen===true) var border=this.ChartFrame.GetBorder(); if (this.Name=="DRAWTEXTREL") { if (isHScreen) { var height=border.RightTitle-border.LeftEx; var width=border.BottomEx-border.TopEx; var x=this.DrawData.Point.X/1000*width+border.TopEx; var y=border.RightTitle-this.DrawData.Point.Y/1000*width; } else { var width=border.RightEx-border.LeftEx; var height=border.BottomEx-border.TopTitle; var x=this.DrawData.Point.X/1000*width+border.LeftEx; var y=this.DrawData.Point.Y/1000*height+border.TopTitle; } } else if (this.Name=="DRAWTEXTABS") { if (isHScreen) { var x=this.DrawData.Point.X+border.TopEx; var y=border.RightTitle-this.DrawData.Point.Y; } else { var x=this.DrawData.Point.X+border.LeftEx; var y=this.DrawData.Point.Y+border.TopTitle; } } else { return; } if (this.Direction==1) this.Canvas.textBaseline='bottom'; else if (this.Direction==2) this.Canvas.textBaseline='top'; else this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.font=this.TextFont; this.Canvas.fillStyle=this.Color; this.DrawText(this.DrawData.Text,x,y,isHScreen); } this.SuperGetMaxMin=this.GetMaxMin; this.GetMaxMin=function() { if (this.Name=="DRAWTEXTREL" || this.Name=="DRAWTEXTABS") { return { Min:null,Max:null }; } else { return this.SuperGetMaxMin(); } } } function ChartDrawText() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawText'; //类名 this.Color = "rgb(255,193,37)"; //线段颜色 this.TextFont = "14px 微软雅黑"; //字体 this.Text; this.TextAlign = 'left'; this.TextBaseline="middle"; this.FixedFontSize=-1; //固定字体大小 this.YOffset = 0; this.FixedPosition=-1; //固定位置输出 1顶部, 2底部 this.TextBG; //{ Color:"rgb(0,0,92)", Border:"rgb(205,0,92)", Margin:[0,1,1,1], } // { Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] } this.VerticalLine; //垂直线 this.ShowOffset={ X:0, Y:0 }; //显示偏移 this.TextSize= { Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWICON.Text.FontName } this.ReloadResource=function(resource) { this.TextSize= { Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWTEXT.FontName } } this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true) var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var top = this.ChartBorder.GetTopEx(); var bottom = this.ChartBorder.GetBottomEx(); if (isHScreen) { chartright = this.ChartBorder.GetBottom(); top = this.ChartBorder.GetRightEx(); bottom = this.ChartBorder.GetLeftEx(); } var xPointCount = this.ChartFrame.XPointCount; var isArrayText = Array.isArray(this.Text); var text; var drawTextInfo={ Text:{ Color:this.Color, Align:this.TextAlign, Baseline:this.TextBaseline }, Font:{ } }; //字体大小 if (this.FixedFontSize>0) this.TextFont=`${this.FixedFontSize}px ${this.TextSize.FontName}`; else this.TextFont = this.GetDynamicFontEx(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName); drawTextInfo.Font={ Height:this.GetFontHeight(this.TextFont) }; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y; if (this.FixedPosition===1) y=top; else if (this.FixedPosition===2) y=bottom; else y=this.ChartFrame.GetYFromData(value); if (x > chartright) break; y+=this.ShowOffset.Y; x+=this.ShowOffset.X; drawTextInfo.X=x; drawTextInfo.Y=y; if (isArrayText) { text = this.Text[i]; if (!text) continue; this.DrawText(text,drawTextInfo,isHScreen); } else { this.DrawText(this.Text,drawTextInfo,isHScreen); } this.DrawVerticalLine(i, drawTextInfo, isHScreen); } } this.DrawText=function(text, drawInfo, isHScreen) { var textWidth=this.Canvas.measureText(text).width; if (isHScreen) { var x=drawInfo.Y; var y=drawInfo.X; if (drawInfo.Text.Align=="right") y=y-textWidth; else if (drawInfo.Text.Align=="center") y=y-textWidth/2; if (drawInfo.Text.Baseline=="top") x-=drawInfo.Font.Height; else if (drawInfo.Text.Baseline=="middle") x-=drawInfo.Font.Height/2; if (this.TextBG && (this.TextBG.Color || this.TextBG.Border)) { var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右 var xRect=x-margin[0]; var yRect=y-margin[2]; var bgWidth=textWidth+margin[2]+margin[3]; var bgHeight=drawInfo.Font.Height+margin[0]+margin[1]; if (this.TextBG.Color) { this.Canvas.fillStyle=this.TextBG.Color; this.Canvas.fillRect(xRect,yRect,bgHeight,bgWidth); } if (this.TextBG.Border) { this.Canvas.strokeStyle=this.TextBG.Border; this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgHeight),ToFixedRect(bgWidth)); } drawInfo.Rect={Bottom:xRect, Top:xRect+bgHeight }; } else { var xRect=x; var bgHeight=drawInfo.Font.Height; drawInfo.Rect={Bottom:xRect, Top:xRect+bgHeight }; } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=drawInfo.Text.Color; 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=drawInfo.X; var y=drawInfo.Y; if (drawInfo.Text.Align=="right") x=x-textWidth; else if (drawInfo.Text.Align=="center") x=x-textWidth/2; if (drawInfo.Text.Baseline=="top") y+=drawInfo.Font.Height; else if (drawInfo.Text.Baseline=="middle") y+=drawInfo.Font.Height/2; if (this.TextBG && (this.TextBG.Color || this.TextBG.Border)) { var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右 var xRect=x-margin[2]; var yRect=y-drawInfo.Font.Height-margin[1]; var bgWidth=textWidth+margin[2]+margin[3]; var bgHeight=drawInfo.Font.Height+margin[0]+margin[1]; if (this.TextBG.Color) { this.Canvas.fillStyle=this.TextBG.Color; this.Canvas.fillRect(xRect,yRect,bgWidth,bgHeight); } if (this.TextBG.Border) { this.Canvas.strokeStyle=this.TextBG.Border; this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgWidth),ToFixedRect(bgHeight)); } drawInfo.Rect={Top:yRect, Bottom:yRect+bgHeight }; } else { var yRect=y-drawInfo.Font.Height; var bgHeight=drawInfo.Font.Height; drawInfo.Rect={Top:yRect, Bottom:yRect+bgHeight }; } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=drawInfo.Text.Color; this.Canvas.fillText(text,x,y); } } //画连线 this.DrawVerticalLine=function(index, drawTextInfo, isHScreen) { if (!this.VerticalLine) return; var item=this.VerticalLine.Data[index]; if (!item) return; if (!IFrameSplitOperator.IsNumber(item.High)) return; if (!IFrameSplitOperator.IsNumber(item.Low)) return; var yHigh=this.ChartFrame.GetYFromData(item.High); var yLow=this.ChartFrame.GetYFromData(item.Low); var yLine, yLine2; if (isHScreen) { if (drawTextInfo.Rect.Bottom>yHigh) { yLine=drawTextInfo.Rect.Bottom-1; yLine2=yHigh+1; } else if (drawTextInfo.Rect.TopyLow) { yLine=drawTextInfo.Rect.Top-1; yLine2=yLow+1; } else { return; } } this.Canvas.save(); var pixelTatio =1; var xLine=drawTextInfo.X; if (this.VerticalLine.LineType==1) { if (this.VerticalLine.LineDotted) this.Canvas.setLineDash(this.VerticalLine.LineDotted); else this.Canvas.setLineDash([3,3]); } if (IFrameSplitOperator.IsPlusNumber(this.VerticalLine.LineWidth)) { this.Canvas.lineWidth=this.VerticalLine.LineWidth*pixelTatio; } this.Canvas.strokeStyle=this.VerticalLine.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yLine),ToFixedPoint(xLine)); this.Canvas.lineTo(ToFixedPoint(yLine2),ToFixedPoint(xLine)); } else { this.Canvas.moveTo(ToFixedPoint(xLine),ToFixedPoint(yLine)); this.Canvas.lineTo(ToFixedPoint(xLine),ToFixedPoint(yLine2)); } this.Canvas.stroke(); this.Canvas.restore(); } } function ChartDrawNumber() { this.newMethod=ChartDrawText; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawNumber'; //类名 this.ReloadResource=function(resource) { this.TextSize= { Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWNUMBER.FontName } } } //线段 function ChartLine() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName ='ChartLine'; this.Color = "rgb(255,193,37)"; //线段颜色 this.LineWidth; //线段宽度 this.DrawType = 0; //画图方式 0=无效数平滑 1=无效数不画断开 this.IsDotLine = false; //虚线 this.LineDash=g_JSChartResource.DOTLINE.LineDash; this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; switch (this.DrawType) { case 0: return this.DrawLine(); case 1: return this.DrawStraightLine(); } } this.DrawLine = function () { var bHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (bHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; this.Canvas.save(); if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth; var bFirstPoint = true; var drawCount = 0; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.GetYFromData(value); if (x > chartright) break; if (bFirstPoint) { this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y, x); //横屏坐标轴对调 else this.Canvas.moveTo(x, y); bFirstPoint = false; } else { if (bHScreen) this.Canvas.lineTo(y, x); else this.Canvas.lineTo(x, y); } ++drawCount; } if (drawCount > 0) this.Canvas.stroke(); this.Canvas.restore(); } //无效数不画 this.DrawStraightLine = function () { var bHScreen = (this.ChartFrame.IsHScreen === true); var isMinute=this.IsMinuteFrame(); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright = this.ChartBorder.GetRight(); if (bHScreen) chartright = this.ChartBorder.GetBottom(); if (bHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var xPointCount = this.ChartFrame.XPointCount; this.Canvas.save(); if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth; this.Canvas.strokeStyle = this.Color; if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint = true; var drawCount = 0; for(var i=this.Data.DataOffset,j=0;i 0) this.Canvas.stroke(); bFirstPoint = true; drawCount = 0; continue; } if (isMinute) { var x = this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; } var y = this.GetYFromData(value); if (x > chartright) break; if (bFirstPoint) { this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y, x); //横屏坐标轴对调 else this.Canvas.moveTo(x, y); bFirstPoint = false; } else { if (bHScreen) this.Canvas.lineTo(y, x); else this.Canvas.lineTo(x, y); } ++drawCount; } if (drawCount > 0) this.Canvas.stroke(); this.Canvas.restore(); } this.GetYFromData = function (value) { return this.ChartFrame.GetYFromData(value); } } //独立线段 //独立线段 function ChartSingleLine() { this.newMethod=ChartLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartSingleLine'; //类名 this.MaxMin=null; //当前的显示范围 this.Draw=function() { this.MaxMin=null; if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsHideScriptIndex()) return; if (!this.Data || !this.Data.Data) return; this.MaxMin=this.GetCurrentMaxMin(); if (!this.MaxMin) return; if (!IFrameSplitOperator.IsNumber(this.MaxMin.Max) || !IFrameSplitOperator.IsNumber(this.MaxMin.Min)) return; switch(this.DrawType) { default: return this.DrawStraightLine(); } } //获取当前页的最大最小值 this.GetCurrentMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={ Max:null, Min:null }; for(var i=this.Data.DataOffset,j=0;ivalue) range.Min=value; } return range; } this.GetMaxMin=function() { return { Max:null, Min:null }; } this.GetYFromData=function(value) { var bHScreen = (this.ChartFrame.IsHScreen === true); if (bHScreen) { if (value <= this.MaxMin.Min) return this.ChartBorder.GetLeftEx(); if (value >= this.MaxMin.Max) return this.ChartBorder.GetRightEx(); var width = this.ChartBorder.GetWidthEx() * (value - this.MaxMin.Min) / (this.MaxMin.Max - this.MaxMin.Min); return this.ChartBorder.GetLeftEx() + width; } else { if(value<=this.MaxMin.Min) return this.ChartBorder.GetBottomEx(); if(value>=this.MaxMin.Max) return this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx()*(value-this.MaxMin.Min)/(this.MaxMin.Max-this.MaxMin.Min); return this.ChartBorder.GetBottomEx()-height; } } } //面积图 支持横屏 function ChartArea() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartArea'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.AreaColor; //面积颜色 this.LineWidth; //线段宽度 this.LineDash; //虚线 this.AreaDirection=0 //0=向下 1=向上 this.DrawSelectedStatus=this.DrawLinePoint; this.PtInChart=this.PtInLine; this.ExportData=this.ExportArrayData; this.GetItemData=this.GetArrayItemData; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.DrawArea(); } //无效数不画 this.DrawArea=function() { var bHScreen=(this.ChartFrame.IsHScreen===true); var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } this.Canvas.save(); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth; this.Canvas.strokeStyle=this.Color; if (this.AreaColor) this.Canvas.fillStyle=this.AreaColor; else this.Canvas.fillStyle=ColorToRGBA(this.Color,0.6); if (IFrameSplitOperator.IsNonEmptyArray(this.LineDash)) this.Canvas.setLineDash(this.LineDas); //画虚线 var bFirstPoint=true; var ptFirst=null, ptEnd=null //起始结束点 var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.stroke(); if (ptFirst && ptEnd) { if (bHScreen) { if (this.AreaDirection==1) { this.Canvas.lineTo(border.RightEx,ptEnd.X); this.Canvas.lineTo(border.RightEx,ptFirst.X); } else { this.Canvas.lineTo(border.LeftEx,ptEnd.X); this.Canvas.lineTo(border.LeftEx,ptFirst.X); } this.Canvas.closePath(); this.Canvas.fill(); } else { if (this.AreaDirection==1) { this.Canvas.lineTo(ptEnd.X, border.TopEx); this.Canvas.lineTo(ptFirst.X, border.TopEx); } else { this.Canvas.lineTo(ptEnd.X, border.BottomEx); this.Canvas.lineTo(ptFirst.X, border.BottomEx); } this.Canvas.closePath(); this.Canvas.fill(); } } bFirstPoint=true; drawCount=0; ptFirst=null; ptEnd=null; continue; } if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; } var y=this.GetYFromData(value,false); if (x>chartright) break; if (bFirstPoint) { this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; ptFirst={ X:x, Y:y }; } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); ptEnd={ X:x, Y:y }; } ++drawCount; } if (drawCount>0) { if (drawCount==1 && ptFirst) //如果只有1个点, 画一个像素的横线 { if (bHScreen) this.Canvas.lineTo(ptFirst.Y,ptFirst.X+1*GetDevicePixelRatio()); else this.Canvas.lineTo(ptFirst.X+1*GetDevicePixelRatio(),ptFirst.Y); } this.Canvas.stroke(); if (ptFirst && ptEnd) { if (bHScreen) { if (this.AreaDirection==1) { this.Canvas.lineTo(border.RightEx,ptEnd.X); this.Canvas.lineTo(border.RightEx,ptFirst.X); } else { this.Canvas.lineTo(border.LeftEx,ptEnd.X); this.Canvas.lineTo(border.LeftEx,ptFirst.X); } this.Canvas.closePath(); this.Canvas.fill(); } else { if (this.AreaDirection==1) { this.Canvas.lineTo(ptEnd.X, border.TopEx); this.Canvas.lineTo(ptFirst.X, border.TopEx); } else { this.Canvas.lineTo(ptEnd.X, border.BottomEx); this.Canvas.lineTo(ptFirst.X, border.BottomEx); } this.Canvas.closePath(); this.Canvas.fill(); } } } this.Canvas.restore(); } } //子线段 function ChartSubLine() { this.newMethod = ChartLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName = 'ChartSubLine'; //类名 this.Color = "rgb(255,193,37)"; //线段颜色 this.LineWidth; //线段宽度 this.DrawType = 0; //画图方式 0=无效数平滑 1=无效数不画断开 this.IsDotLine = false; //虚线 this.SubFrame = { Max: null, Min: null }; this.Draw = function () { if (!this.IsShow) return; if (!this.Data || !this.Data.Data) return; this.CalculateDataMaxMin(); switch (this.DrawType) { case 0: return this.DrawLine(); case 1: return this.DrawStraightLine(); } } this.GetYFromData = function (value) { var bHScreen = (this.ChartFrame.IsHScreen === true); if (bHScreen) { if (value <= this.SubFrame.Min) return this.ChartBorder.GetLeftEx(); if (value >= this.SubFrame.Max) return this.ChartBorder.GetRightEx(); var width = this.ChartBorder.GetWidthEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min); return this.ChartBorder.GetLeftEx() + width; } else { if (value <= this.SubFrame.Min) return this.ChartBorder.GetBottomEx(); if (value >= this.SubFrame.Max) return this.ChartBorder.GetTopEx(); var height = this.ChartBorder.GetHeightEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min); return this.ChartBorder.GetBottomEx() - height; } } this.CalculateDataMaxMin = function () { this.SubFrame = { Max: null, Min: null }; var bHScreen = (this.ChartFrame.IsHScreen === true); var chartright = this.ChartBorder.GetRight(); if (bHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); if (x > chartright) break; if (this.SubFrame.Min == null || this.SubFrame.Min > value) this.SubFrame.Min = value; if (this.SubFrame.Max == null || this.SubFrame.Max < value) this.SubFrame.Max = value; } } this.GetMaxMin = function () //数据不参与坐标轴最大最小值计算 { var range = { Min: null, Max: null }; return range; } } //POINTDOT 圆点 支持横屏 function ChartPointDot() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(255,193,37)"; //线段颜色 this.Radius = 1; //点半径 this.ClassName = 'ChartPointDot'; this.EnableUpDownColor=false; //是否是红绿点 this.HistoryData; this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var bHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (bHScreen === true) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; this.Canvas.save(); this.Canvas.fillStyle = this.Color; var colorDot; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; if (this.EnableUpDownColor) { var kItem=this.HistoryData.Data[i]; if (kItem.Close>value) colorDot="rgb(255,61,61)"; else colorDot='rgb(0,199,65)'; this.Canvas.fillStyle=colorDot; } this.Canvas.beginPath(); if (bHScreen) this.Canvas.arc(y, x, this.Radius, 0, Math.PI * 2, true); else this.Canvas.arc(x, y, this.Radius, 0, Math.PI * 2, true); this.Canvas.closePath(); this.Canvas.fill(); } this.Canvas.restore(); } } //通达信语法 STICK 支持横屏 function ChartStick() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(255,193,37)"; //线段颜色 this.LineWidth; //线段宽度 this.ClassName = 'ChartStick'; this.DrawLine = function () { if (this.ChartFrame.IsMinSize) return; if (this.IsHideScriptIndex()) return; if (!this.Data || !this.Data.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen === true) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; this.Canvas.save(); if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth; var bFirstPoint = true; var drawCount = 0; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; if (bFirstPoint) { this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(y, x); else this.Canvas.moveTo(x, y); bFirstPoint = false; } else { if (isHScreen) this.Canvas.lineTo(y, x); else this.Canvas.lineTo(x, y); } ++drawCount; } if (drawCount > 0) this.Canvas.stroke(); this.Canvas.restore(); } this.DrawStick = function () { if (!this.Data || !this.Data.Data) return; var bHScreen = (this.ChartFrame.IsHScreen === true); var chartright = this.ChartBorder.GetRight(); if (bHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var yBottom = this.ChartBorder.GetBottom(); var xLeft = this.ChartBorder.GetLeft(); this.Canvas.save(); this.Canvas.strokeStyle = this.Color; if (this.LineWidth) this.Canvas.lineWidth = this.LineWidth; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; this.Canvas.beginPath(); if (bHScreen) { this.Canvas.moveTo(xLeft, x); this.Canvas.lineTo(y, x); this.Canvas.stroke(); } else { var xFix = parseInt(x.toString()) + 0.5; this.Canvas.moveTo(xFix, y); this.Canvas.lineTo(xFix, yBottom); } this.Canvas.stroke(); } this.Canvas.restore(); } this.Draw = function () { if (!this.IsShow) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } this.DrawStick(); } } //通达信语法 LINESTICK 支持横屏 function ChartLineStick() { this.newMethod = ChartStick; //派生 this.newMethod(); delete this.newMethod; this.ClassName = 'ChartLineStick'; this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } this.DrawStick(); this.DrawLine(); } } //柱子 支持横屏 function ChartStickLine() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName ='ChartStickLine'; this.Color = "rgb(255,193,37)"; //线段颜色 this.BarType = 0; //柱子类型 0=实心 1=空心 -1=画虚线空心柱 this.LineDotted=[3,3]; //虚线设置 this.Width=0; //柱子宽度 0=1 3,50=k线宽度 101=K线宽度+间距宽度 this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度 this.SetEmptyBar=function() //设置空心柱子 { if (this.BarType!=1 && this.BarType!=-1) return false; this.Canvas.lineWidth=1; this.Canvas.strokeStyle=this.Color; var emptyBGColor=g_JSChartResource.EmptyBarBGColor; if (emptyBGColor) this.Canvas.fillStyle=emptyBGColor; if (this.BarType==-1) //虚线 { this.Canvas.setLineDash(this.LineDotted); //虚线 } return true; } this.IsEmptyBar=function() { return (this.BarType==1 || this.BarType==-1); } this.Draw = function () { if (this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin; var isMinute=this.IsMinuteFrame(); if (isHScreen) { chartright = this.ChartBorder.GetBottom(); xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin; } this.Canvas.save(); var bFillBar = false; var bFillKLine = false; var emptyBGColor=g_JSChartResource.EmptyBarBGColor; if (isMinute) { if (this.Width>1) this.Canvas.lineWidth=2; else this.Canvas.lineWidth=1; this.Canvas.strokeStyle=this.Color; } else if(this.Width==0) { this.SetEmptyBar(); this.Canvas.lineWidth=1; this.Canvas.strokeStyle=this.Color; } else if (this.Width==50 || this.Width==3) { if (dataWidth >= this.MinBarWidth) { bFillKLine = true; this.SetEmptyBar(); if (!this.IsEmptyBar()) this.Canvas.fillStyle = this.Color; this.Canvas.strokeStyle = this.Color; } else //太细了 画竖线 { this.Canvas.lineWidth = 1; this.Canvas.strokeStyle = this.Color; } } else if (this.Width==101) { var lineWidth=dataWidth+distanceWidth+1; this.Canvas.lineWidth=lineWidth; this.Canvas.strokeStyle=this.Color; } else if (this.Width <=3 ) { var minWidth=2; var barWidth=dataWidth*(this.Width/3); if (barWidth chartright) break; if (bFillBar) { if (isHScreen) { var left=x-barWidth/2; var width=barWidth; if (this.IsEmptyBar()) //空心 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(Math.min(y,y2)),ToFixedPoint(left),ToFixedRect(Math.abs(y-y2)),ToFixedRect(width)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(Math.min(y,y2)),ToFixedRect(left),ToFixedRect(Math.abs(y-y2)),ToFixedRect(width)); } } else { var left=x-barWidth/2; var width=barWidth; if (left+width>chartright) width=chartright-left; //不要超过右边框子 if (this.IsEmptyBar()) //空心 { if (emptyBGColor) this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,y2)),ToFixedRect(width),ToFixedRect(Math.abs(y-y2))); this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(Math.min(y,y2)),ToFixedRect(width),ToFixedRect(Math.abs(y-y2))); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,y2)),ToFixedRect(width),ToFixedRect(Math.abs(y-y2))); } } } else if (bFillKLine) { if (this.BarType == 1) //实心 { if (isHScreen) { this.Canvas.beginPath(); this.Canvas.fillRect(ToFixedRect(Math.min(y, y2)), ToFixedRect(xOffset), ToFixedRect(Math.abs(y - y2)), ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.beginPath(); this.Canvas.rect(ToFixedRect(xOffset), ToFixedRect(Math.min(y, y2)), ToFixedRect(dataWidth), ToFixedRect(Math.abs(y - y2))); this.Canvas.stroke(); } } else { if (isHScreen) this.Canvas.fillRect(ToFixedRect(Math.min(y, y2)), ToFixedRect(xOffset), ToFixedRect(Math.abs(y - y2)), ToFixedRect(dataWidth)); else this.Canvas.fillRect(ToFixedRect(xOffset), ToFixedRect(Math.min(y, y2)), ToFixedRect(dataWidth), ToFixedRect(Math.abs(y - y2))); } } else { if (isHScreen) { this.Canvas.beginPath(); this.Canvas.moveTo(y, ToFixedPoint(x)); this.Canvas.lineTo(y2, ToFixedPoint(x)); this.Canvas.stroke(); } else { var xFix = parseInt(x.toString()) + 0.5; this.Canvas.beginPath(); this.Canvas.moveTo(xFix, y); this.Canvas.lineTo(xFix, y2); this.Canvas.stroke(); } } } this.Canvas.restore(); } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; if (!this.Data || !this.Data.Data) return range; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var data = this.Data.Data[i]; if (data == null) continue; var value2 = data.Value2; if (value2 == null) value2 = 0; if (data == null || isNaN(data.Value) || isNaN(value2)) continue; var valueMax = Math.max(data.Value, value2); var valueMin = Math.min(data.Value, value2); if (range.Max == null) range.Max = valueMax; if (range.Min == null) range.Min = valueMin; if (range.Max < valueMax) range.Max = valueMax; if (range.Min > valueMin) range.Min = valueMin; } return range; } } //画矩形 function ChartRectangle() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName ='ChartRectangle'; this.Color = []; this.Rect; this.BorderColor = g_JSChartResource.FrameBorderPen; this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Color || !this.Rect) return; if (this.Color.length <= 0) return; this.Canvas.strokeStyle = this.BorderColor; var bFill = false; if (this.Color.length == 2) { /* TODO 渐变下次做吧 if (this.ColorAngle==0) { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() }; } else { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() }; } let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y); gradient.addColorStop(0, this.Color[0]); gradient.addColorStop(1, this.Color[1]); this.Canvas.fillStyle=gradient; */ this.Canvas.fillStyle = this.Color[0]; bFill = true; } else if (this.Color.length == 1) { if (this.Color[0]) { this.Canvas.fillStyle = this.Color[0]; bFill = true; } } else { return; } var chartWidth = this.ChartBorder.GetWidth(); var chartHeight = this.ChartBorder.GetHeightEx(); var left = this.Rect.Left / 1000 * chartWidth; var top = this.Rect.Top / 1000 * chartHeight; var right = this.Rect.Right / 1000 * chartWidth; var bottom = this.Rect.Bottom / 1000 * chartHeight; left = this.ChartBorder.GetLeft() + left top = this.ChartBorder.GetTopEx() + top; right = this.ChartBorder.GetLeft() + right; bottom = this.ChartBorder.GetTopEx() + bottom; var width = Math.abs(left - right); var height = Math.abs(top - bottom); if (bFill) this.Canvas.fillRect(left, top, width, height); this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(top), ToFixedRect(width), ToFixedRect(height)); this.Canvas.stroke(); } } //K线叠加 function ChartOverlayKLine() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(65,105,225)"; this.MainData; //主图K线数据 this.SourceData; //叠加的原始数据 this.Name = "ChartOverlayKLine"; this.Title; this.DrawType = 0; this.ClassName ='ChartOverlayKLine'; this.CustomDrawType = null; //图形类型 this.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID; this.ShowRange={ }; //K线显示范围 { Start:, End:, DataCount:, ShowCount: } this.DrawKRange={ Start:null, End:null }; //当前屏K线的索引{ Start: , End:} this.YInfoType=4; this.SetOption = function (option) { if (!option) return; if (IFrameSplitOperator.IsNumber(option.DrawType)) this.CustomDrawType = option.DrawType; if (IFrameSplitOperator.IsNumber(option.YInfoType)) this.YInfoType=option.YInfoType; } this.DrawKBar = function (firstOpen) //firstOpen 当前屏第1个显示数据 { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var isFristDraw = true; var firstOverlayOpen = null; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.ShowRange.FirstOpen=firstOpen; this.DrawKRange.Start=this.Data.DataOffset; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (!data || data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; if (firstOverlayOpen == null) { firstOverlayOpen = data.Open; this.ShowRange.FirstOverlayOpen=data.Open; } if (isFristDraw) { this.Canvas.strokeStyle = this.Color; this.Canvas.fillStyle = this.Color; this.Canvas.beginPath(); isFristDraw = false; } var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yLow = this.ChartFrame.GetYFromData(data.Low / firstOverlayOpen * firstOpen); var yHigh = this.ChartFrame.GetYFromData(data.High / firstOverlayOpen * firstOpen); var yOpen = this.ChartFrame.GetYFromData(data.Open / firstOverlayOpen * firstOpen); var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen); var y = yHigh; this.DrawKRange.End=i; if (data.Open < data.Close) //阳线 { if (dataWidth >= 4) { if (data.High > data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : yClose), ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : yClose)); } y = yClose; } else { y = yClose; } if (isHScreen) { if (Math.abs(yOpen - y) < 1) { this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (this.DrawType == 3) this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth)); //空心柱 else this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth)); } } else { if (Math.abs(yOpen - y) < 1) { this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1 } else { if (this.DrawType == 3) this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y)); //空心柱 else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y)); } } if (data.Open > data.Low) { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow)); } } } else { if (isHScreen) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } } } else if (data.Open > data.Close) //阴线 { if (dataWidth >= 4) { if (data.High > data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yOpen), ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yOpen)); } y = yOpen; } else { y = yOpen } if (isHScreen) { if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yClose - y), ToFixedRect(dataWidth)); } else { if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y)); } if (data.Open > data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow)); } } } else { if (isHScreen) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } } } else // 平线 { if (dataWidth >= 4) { if (data.High > data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y, ToFixedPoint(x)); this.Canvas.lineTo(yOpen, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), y); this.Canvas.lineTo(ToFixedPoint(x), yOpen); } y = yOpen; } else { y = yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(right), ToFixedPoint(y)); } if (data.Open > data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow)); } } } else { if (isHScreen) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } } } } if (isFristDraw == false) this.Canvas.stroke(); } this.DrawAKLine = function (firstOpen) //美国线 { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var firstOverlayOpen = null; this.Canvas.strokeStyle = this.Color; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.ShowRange.FirstOpen=firstOpen; this.DrawKRange.Start=this.Data.DataOffset; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; if (firstOverlayOpen == null) { firstOverlayOpen = data.Open; this.ShowRange.FirstOverlayOpen=data.Open; } var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yLow = this.ChartFrame.GetYFromData(data.Low / firstOverlayOpen * firstOpen); var yHigh = this.ChartFrame.GetYFromData(data.High / firstOverlayOpen * firstOpen); var yOpen = this.ChartFrame.GetYFromData(data.Open / firstOverlayOpen * firstOpen); var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen); this.DrawKRange.End=i; this.Canvas.beginPath(); //最高-最低 if (isHScreen) { this.Canvas.moveTo(yHigh, ToFixedPoint(x)); this.Canvas.lineTo(yLow, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), yHigh); this.Canvas.lineTo(ToFixedPoint(x), yLow); } this.Canvas.stroke(); if (dataWidth >= 4) { this.Canvas.beginPath(); //开盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen), left); this.Canvas.lineTo(ToFixedPoint(yOpen), x); } else { this.Canvas.moveTo(left, ToFixedPoint(yOpen)); this.Canvas.lineTo(x, ToFixedPoint(yOpen)); } this.Canvas.stroke(); this.Canvas.beginPath(); //收盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yClose), right); this.Canvas.lineTo(ToFixedPoint(yClose), x); } else { this.Canvas.moveTo(right, ToFixedPoint(yClose)); this.Canvas.lineTo(x, ToFixedPoint(yClose)); } this.Canvas.stroke(); } } } this.DrawCloseLine = function (firstOpen) //收盘价线 { var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var firstOverlayOpen = null; var bFirstPoint = true; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.ShowRange.FirstOpen=firstOpen; this.DrawKRange.Start=this.Data.DataOffset; this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount) { var data = this.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; if (firstOverlayOpen == null) { firstOverlayOpen = data.Open; this.ShowRange.FirstOverlayOpen=data.Open; } var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = left + (right - left) / 2; var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) this.Canvas.moveTo(yClose, x); else this.Canvas.moveTo(x, yClose); bFirstPoint = false; } else { if (isHScreen) this.Canvas.lineTo(yClose, x); else this.Canvas.lineTo(x, yClose); } } if (bFirstPoint == false) this.Canvas.stroke(); } this.Draw = function () { this.TooltipRect = []; this.DrawKRange={ Start:null, End:null }; if (!this.MainData || !this.Data) return; var xPointCount = this.ChartFrame.XPointCount; var firstOpen = null; //主线数据第1个开盘价 for (var i = this.Data.DataOffset, j = 0; i < this.MainData.Data.length && j < xPointCount; ++i, ++j) { var data = this.MainData.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; firstOpen = data.Open; break; } if (firstOpen == null) return; var drawTypeBackup = this.DrawType; //备份下线段类型 if (this.CustomDrawType != null) this.DrawType = this.CustomDrawType; if (this.DrawType == 1) this.DrawCloseLine(firstOpen); else if (this.DrawType == 2) this.DrawAKLine(firstOpen); else this.DrawKBar(firstOpen); this.DrawType = drawTypeBackup; //还原线段类型 } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Max = null; range.Min = null; if (!this.MainData || !this.Data) return range; var firstOpen = null; //主线数据第1个收盘价 for (var i = this.Data.DataOffset, j = 0; i < this.MainData.Data.length && j < xPointCount; ++i, ++j) { var data = this.MainData.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; firstOpen = data.Close; break; } if (firstOpen == null) return range; var firstOverlayOpen = null; var high, low; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var data = this.Data.Data[i]; if (!data || data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; if (firstOverlayOpen == null) firstOverlayOpen = data.Open; high = data.High / firstOverlayOpen * firstOpen; low = data.Low / firstOverlayOpen * firstOpen; if (range.Max == null) range.Max = high; if (range.Min == null) range.Min = low; if (range.Max < high) range.Max = high; if (range.Min > low) range.Min = low; } return range; } } // 多文本集合 支持横屏 function ChartMultiText() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName ='ChartMultiText'; this.Texts = []; //[ {Index:, Value:, Text:, Color:, Font: , Baseline:, Line:{ Color:, Dash:[虚线点], KData:"H/L", Offset:[5,10], Width:线粗细 } } ] this.Font = g_JSChartResource.DefaultTextFont; this.Color = g_JSChartResource.DefaultTextColor; this.IsHScreen = false; //是否横屏 this.BuildKey=function(item) { if (IFrameSplitOperator.IsNumber(item.Time)) { var key=`${item.Date}-${item.Time}`; } else { var key=`${item.Date}`; } return key; } this.GetShowTextData=function() { var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var mapText=new Map(); //key='date-time' value={ Data:[] } for(var i=0; i=0 && indexchartright) break; var x=left+(right-left)/2; var textItem=mapText.get(key); for(var k=0;k=chartright) { this.Canvas.textAlign='right'; x=chartright; } else if (x-textWidth/2yPrice) //文字在下方 { yText-=item.Line.Offset[1]; yPrice+=item.Line.Offset[0] } else if (yText0) this.Canvas.lineWidth=item.Line.Width; //线宽 this.Canvas.strokeStyle = item.Line.Color; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(yText, ToFixedPoint(x)); this.Canvas.lineTo(yPrice,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yText); this.Canvas.lineTo(ToFixedPoint(x),yPrice); } this.Canvas.stroke(); this.Canvas.restore(); } } } } this.GetMaxMin = function () { var range = { Min: null, Max: null }; if (!this.Texts) return range; var xPointCount = this.ChartFrame.XPointCount; var start = this.Data.DataOffset; var end = start + xPointCount; for (var i in this.Texts) { var item = this.Texts[i]; if (item.Index >= start && item.Index < end) { if (range.Max == null) range.Max = item.Value; else if (range.Max < item.Value) range.Max = item.Value; if (range.Min == null) range.Min = item.Value; else if (range.Min > item.Value) range.Min = item.Value; } } return range; } } // 多dom节点 function ChartMultiHtmlDom() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiHtmlDom"; this.Texts=[]; //[ {Index:, Value:, Text: ] Text=dom内容 this.IsHScreen=false; //是否横屏 this.DrawCallback; //function(op, obj) op:1=开始 2=结束 3=绘制单个数据 4=销毁 this.DrawItem=[]; this.IsDestroy=false; //是否已销毁 this.Draw=function() { this.DrawItem=[]; if (this.DrawCallback) this.DrawCallback(1, {Self:this} ); this.DrawDom(); if (this.DrawCallback) this.DrawCallback(2, { Self:this, Draw:this.DrawItem } ); } this.OnDestroy=function() { this.IsDestroy=true; if (this.DrawCallback) this.DrawCallback(4, { Self:this } ); } this.DrawDom=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || this.Data.length<=0) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; for(var i in this.Texts) { var item=this.Texts[i]; if (!item.Text) continue; if (!IFrameSplitOperator.IsNumber(item.Index)) continue; var index=item.Index-offset; var kItem=this.Data.Data[item.Index]; //K线数据 var obj={ KData:kItem, Item:item, IsShow:false, Self:this }; if (index>=0 && index=start && item.Indexitem.Value) range.Min=item.Value; } } return range; } } // 线段集合 支持横屏 function ChartMultiLine() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiLine"; this.Lines = []; // [ {Point:[ {Index, Value }, ], Color: }, ] this.IsHScreen = false; this.LineWidth=1; this.LineDash; //箭头配置 this.ArrawAngle=35; //三角斜边一直线夹角 this.ArrawLength=10; //三角斜边长度 this.ArrawLineWidth=5; //箭头粗细 this.Arrow={ Start:false, End:false }; //Start=是否绘制开始箭头 <- End=是否绘制结束箭头 -> this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || this.Data.length <= 0) return; this.IsHScreen = (this.ChartFrame.IsHScreen === true); var xPointCount = this.ChartFrame.XPointCount; var offset = this.Data.DataOffset; var drawLines = []; var arrowLines=[]; for (var i=0; i= 0 && index < xPointCount) { var x = this.ChartFrame.GetXFromIndex(index); var y = this.ChartFrame.GetYFromData(point.Value); var pointItem={X:x, Y:y, End:false }; drawPoints.Point.push({ X: x, Y: y }); if (j==0 || j==1) drawArrowPoints.Start.push(pointItem); //起始点 if (j==line.Point.length-1 || j==line.Point.length-2) drawArrowPoints.End.push(pointItem); //结束点 } else { if (drawPoints.Point.length>0) drawPoints.Point[drawPoints.Point.length-1].End=true; //点断开 } } if (drawPoints.Point.length >= 2) { drawLines.push(drawPoints); arrowLines.push(drawArrowPoints); } } this.Canvas.save(); for (var i=0; i0) this.Canvas.stroke(); drawCount=0; } } if (drawCount>0) this.Canvas.stroke(); //绘制箭头 if (arrow.End.length==2 && this.Arrow.End==true) this.DrawArrow(arrow.End[0],arrow.End[1]); if (arrow.Start.length==2 && this.Arrow.Start==true) this.DrawArrow(arrow.Start[1],arrow.Start[0]); } this.DrawArrow=function(ptStart,ptEnd) { //计算箭头 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.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.setLineDash([]); this.Canvas.lineWidth=this.ArrawLineWidth; this.Canvas.stroke(); } this.GetMaxMin = function () { var range = { Min: null, Max: null }; var xPointCount = this.ChartFrame.XPointCount; var start = this.Data.DataOffset; var end = start + xPointCount; for (var i in this.Lines) { var line = this.Lines[i]; for (var j in line.Point) { var point = line.Point[j]; if (point.Index >= start && point.Index < end) { if (range.Max == null) range.Max = point.Value; else if (range.Max < point.Value) range.Max = point.Value; if (range.Min == null) range.Min = point.Value; else if (range.Min > point.Value) range.Min = point.Value; } } } return range; } } // 线段集合 支持横屏 function ChartMultiPoint() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiPoint"; this.PointGroup=[]; // [ {Point:[ {Index, Value }, ], Color: }, ] this.IsHScreen=false; this.LineWidth=1; this.PointRadius=5; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || this.Data.length<=0) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.PointGroup)) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; this.Canvas.save(); for(var i=0; i=0 && index=start && point.Indexpoint.Value) range.Min=point.Value; } } } return range; } } // 柱子集合 支持横屏 function ChartMultiBar() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Bars = []; // [ {Point:[ {Index, Value, Value2 }, ], Color:, Width: , Type: 0 实心 1 空心 }, ] this.IsHScreen = false; this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || this.Data.length <= 0) return; this.IsHScreen = (this.ChartFrame.IsHScreen === true); var xPointCount = this.ChartFrame.XPointCount; var offset = this.Data.DataOffset; var dataWidth = this.ChartFrame.DataWidth; var drawBars = []; for (var i in this.Bars) { var item = this.Bars[i]; var drawPoints = { Point: [], Color: item.Color, Width: dataWidth, Type: 0 }; if (item.Type > 0) drawPoints.Type = item.Type; if (item.Width > 0) { drawPoints.Width = item.Width; if (drawPoints.Width > dataWidth) drawPoints.Width = dataWidth; } else { if (drawPoints.Width < 4) drawPoints.Width = 1; } for (var j in item.Point) { var point = item.Point[j]; if (!IFrameSplitOperator.IsNumber(point.Index)) continue; var index = point.Index - offset; if (index >= 0 && index < xPointCount) { var x = this.ChartFrame.GetXFromIndex(index); var y = this.ChartFrame.GetYFromData(point.Value); var y2 = this.ChartFrame.GetYFromData(point.Value2); drawPoints.Point.push({ X: x, Y: y, Y2: y2 }); } } if (drawPoints.Point.length > 0) drawBars.push(drawPoints) } for (var i in drawBars) { var item = drawBars[i]; if (item.Width >= 4) { if (item.Type == 1) this.DrawHollowBar(item); else this.DrawFillBar(item); } else { this.DrawLineBar(item); } } } this.DrawLineBar = function (bar) { this.Canvas.strokeStyle = bar.Color; var backupLineWidth = this.Canvas.lineWidth; this.Canvas.lineWidth = bar.Width; for (var i in bar.Point) { var item = bar.Point[i]; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(ToFixedPoint(item.Y), ToFixedPoint(item.X)); this.Canvas.lineTo(ToFixedPoint(item.Y2), ToFixedPoint(item.X)); } else { this.Canvas.moveTo(ToFixedPoint(item.X), ToFixedPoint(item.Y)); this.Canvas.lineTo(ToFixedPoint(item.X), ToFixedPoint(item.Y2)); } this.Canvas.stroke(); } this.Canvas.lineWidth = backupLineWidth; } this.DrawFillBar = function (bar) { this.Canvas.fillStyle = bar.Color; for (var i in bar.Point) { var item = bar.Point[i]; var x = item.X - (bar.Width / 2); var y = Math.min(item.Y, item.Y2); var barWidth = bar.Width; var barHeight = Math.abs(item.Y - item.Y2); if (this.IsHScreen) this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(x), ToFixedRect(barHeight), ToFixedRect(barWidth)); else this.Canvas.fillRect(ToFixedRect(x), ToFixedRect(y), ToFixedRect(barWidth), ToFixedRect(barHeight)); } } this.DrawHollowBar = function (bar) //空心柱子 { this.Canvas.strokeStyle = bar.Color; var backupLineWidth = 1; for (var i in bar.Point) { var item = bar.Point[i]; var x = item.X - (bar.Width / 2); var y = Math.min(item.Y, item.Y2); var barWidth = bar.Width; var barHeight = Math.abs(item.Y - item.Y2); this.Canvas.beginPath(); if (this.IsHScreen) this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(x), ToFixedRect(barHeight), ToFixedRect(barWidth)); else this.Canvas.rect(ToFixedPoint(x), ToFixedPoint(y), ToFixedRect(barWidth), ToFixedRect(barHeight)); this.Canvas.stroke(); } this.Canvas.lineWidth = backupLineWidth; } this.GetMaxMin = function () { var range = { Min: null, Max: null }; var xPointCount = this.ChartFrame.XPointCount; var start = this.Data.DataOffset; var end = start + xPointCount; for (var i in this.Bars) { var item = this.Bars[i]; for (var j in item.Point) { var point = item.Point[j]; if (point.Index >= start && point.Index < end) { var minValue = Math.min(point.Value, point.Value2); var maxValue = Math.max(point.Value, point.Value2); if (range.Max == null) range.Max = maxValue; else if (range.Max < maxValue) range.Max = maxValue; if (range.Min == null) range.Min = minValue; else if (range.Min > minValue) range.Min = minValue; } } } return range; } } //分钟信息地雷 支持横屏 function ChartMinuteInfo() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName = "ChartMinuteInfo"; this.Data = new Map() //Map key=date-time, value=[{Date, Time, Title, Type, ID:}] this.SourceData; this.ChartMinutePrice; this.YClose; this.TextColor = g_JSChartResource.MinuteInfo.TextColor; this.Font = g_JSChartResource.MinuteInfo.Font; this.PointColor = g_JSChartResource.MinuteInfo.PointColor; this.PointRadius=g_JSChartResource.MinuteInfo.PointRadius; this.LineColor = g_JSChartResource.MinuteInfo.LineColor; this.TextBGColor = g_JSChartResource.MinuteInfo.TextBGColor; this.TextHeight = 18; this.TextRectCache = []; this.InfoDrawCache = []; this.FrameBottom; this.FrameTop; this.FrameLeft; this.FrameRight; this.YOffset = 5; this.IsHScreen = false; this.SetOption = function (option) { if (option.TextColor) this.TextColor = option.TextColor; if (option.TextBGColor) this.TextBGColor = option.TextBGColor; if (option.Font) this.Font = option.Font; if (option.PointColor) this.PointColor = option.PointColor; if (option.LineColor) this.LineColor = option.LineColor; if (option.TextHeight > 0) this.TextHeight = option.TextHeight; } this.Draw = function () { if (!this.ChartMinutePrice) return; if (!this.Data || this.Data.size <= 0) return; this.TextRectCache = []; this.InfoDrawCache = []; this.IsHScreen = (this.ChartFrame.IsHScreen === true); var xPointCount = this.ChartFrame.XPointCount; var minuteCount = this.ChartFrame.MinuteCount; this.FrameBottom = this.ChartBorder.GetBottom(); this.FrameTop = this.ChartBorder.GetTop(); this.FrameLeft = this.ChartBorder.GetLeft(); this.FrameRight = this.ChartBorder.GetRight(); if (this.IsHScreen) { this.FrameRight = this.ChartBorder.GetBottom(); this.FrameLeft = this.ChartBorder.GetTop(); this.FrameBottom = this.ChartBorder.GetLeft(); this.FrameTop = this.ChartBorder.GetRight(); } this.YClose = this.ChartMinutePrice.YClose; var data = this.ChartMinutePrice.Data; var isBeforeData = false; if (this.ChartMinutePrice.SourceData) { data = this.ChartMinutePrice.SourceData; isBeforeData = true; } this.Canvas.font = this.Font; for (var i = data.DataOffset, j = 0; i < data.Data.length && j < xPointCount; ++i, ++j) { var item = this.SourceData.Data[i]; if (isBeforeData && item.Before) continue; if (!item) continue; var dateTime = item.DateTime; if (!this.Data.has(dateTime)) continue; if (this.IsHScreen) this.CalcuateInfoHScreenPosition(this.Data.get(dateTime), j, item); else this.CalcuateInfoPosition(this.Data.get(dateTime), j, item); } for (var i in this.InfoDrawCache) { var item = this.InfoDrawCache[i]; this.DrawInfoLines(item); } for (var i in this.InfoDrawCache) { var item = this.InfoDrawCache[i]; this.DrawInfoText(item); } this.TextRectCache = []; this.InfoDrawCache = []; } this.CalcuateInfoPosition = function (infoItem, index, minuteItem) { if (!infoItem || !infoItem.Data || infoItem.Data.length <= 0) return; var showItem = infoItem.Data[0]; var textWidth = this.Canvas.measureText(showItem.Title).width + 4; var textHeight = this.TextHeight; var x = this.ChartFrame.GetXFromIndex(index); var y = this.ChartFrame.GetYFromData(minuteItem.Close); x = ToFixedPoint(x); var isDrawLeft = x < (this.FrameLeft + Math.abs(this.FrameLeft - this.FrameRight) / 2); var ARRAY_OFFSET = [2, 4, 3, 2, 3, 3, 2]; var offset = textHeight + ARRAY_OFFSET[index % ARRAY_OFFSET.length]; var yData = { Y: [ { Value: y + (textHeight + this.YOffset), Offset: offset }, { Value: y - (2 * textHeight + this.YOffset), Offset: -offset } ] }; if (minuteItem.Close < this.YClose) yData.Y = yData.Y.reverse(); var rtBorder = { X: x, Y: null, Width: textWidth, Height: textHeight }; if (!isDrawLeft) rtBorder.X -= rtBorder.Width; this.FixTextRect(rtBorder, yData); var InfoDrawItem = { Border: rtBorder, Start: { X: x, Y: y }, IsLeft: isDrawLeft, Title: showItem.Title }; if (showItem.Content) InfoDrawItem.Content=showItem.Content; if (showItem.Link) InfoDrawItem.Link=showItem.Link; if (showItem.Color) InfoDrawItem.Color=showItem.Color; if (showItem.BGColor) InfoDrawItem.BGColor=showItem.BGColor; this.InfoDrawCache.push(InfoDrawItem); this.TextRectCache.push(rtBorder); } this.CalcuateInfoHScreenPosition = function (infoItem, index, minuteItem) { if (!infoItem || !infoItem.Data || infoItem.Data.length <= 0) return; var showItem = infoItem.Data[0]; var textHeight = this.Canvas.measureText(showItem.Title).width + 4; var textWidth = this.TextHeight; var y = this.ChartFrame.GetXFromIndex(index); var x = this.ChartFrame.GetYFromData(minuteItem.Close); y = ToFixedPoint(y); var isDrawLeft = y < (this.FrameLeft + Math.abs(this.FrameLeft - this.FrameRight) / 2); var ARRAY_OFFSET = [2, 4, 3, 2, 3, 3, 2]; var offset = textWidth + ARRAY_OFFSET[index % ARRAY_OFFSET.length]; var xData = { X: [ { Value: x + (textWidth + this.YOffset), Offset: offset }, { Value: x - (2 * textWidth + this.YOffset), Offset: -offset } ] }; if (minuteItem.Close > this.YClose) xData.X = xData.X.reverse(); var rtBorder = { X: null, Y: y, Width: textWidth, Height: textHeight }; if (!isDrawLeft) rtBorder.Y -= rtBorder.Height; this.FixHScreenTextRect(rtBorder, xData); var InfoDrawItem = { Border: rtBorder, Start: { X: x, Y: y }, IsLeft: isDrawLeft, Title: showItem.Title }; if (showItem.Content) InfoDrawItem.Content=showItem.Content; if (showItem.Link) InfoDrawItem.Link=showItem.Link; if (showItem.Color) InfoDrawItem.Color=showItem.Color; if (showItem.BGColor) InfoDrawItem.BGColor=showItem.BGColor; this.InfoDrawCache.push(InfoDrawItem); this.TextRectCache.push(rtBorder); } this.DrawInfoLines = function (item) { var rtBorder = item.Border; var isDrawLeft = item.IsLeft; this.Canvas.strokeStyle = this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(item.Start.X, item.Start.Y); if (isDrawLeft) { this.Canvas.lineTo(rtBorder.X, rtBorder.Y); } else { if (this.IsHScreen) this.Canvas.lineTo(rtBorder.X, rtBorder.Y + rtBorder.Height); else this.Canvas.lineTo(rtBorder.X + rtBorder.Width, rtBorder.Y); } this.Canvas.stroke(); this.Canvas.fillStyle = this.PointColor; this.Canvas.beginPath(); this.Canvas.arc(item.Start.X, item.Start.Y, this.PointRadius, 0, 2 * Math.PI); this.Canvas.closePath(); this.Canvas.fill(); } this.DrawInfoText = function (item) { var rtBorder = item.Border; var x = rtBorder.X, y = rtBorder.Y; if (item.BGColor) this.Canvas.fillStyle=item.BGColor else this.Canvas.fillStyle = this.TextBGColor; this.Canvas.fillRect(x, y, rtBorder.Width, rtBorder.Height); this.Canvas.strokeStyle = this.LineColor; this.Canvas.beginPath(); this.Canvas.rect(x, y, rtBorder.Width, rtBorder.Height); this.Canvas.stroke(); if (this.IsHScreen) { this.Canvas.save(); this.Canvas.translate(rtBorder.X, rtBorder.Y); this.Canvas.rotate(90 * Math.PI / 180); x = 0; y = 0; } this.Canvas.textAlign = 'left' this.Canvas.textBaseline = 'middle'; if (item.Color) this.Canvas.fillStyle=item.Color; else this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; if (this.IsHScreen) this.Canvas.fillText(item.Title, x + 2, y - rtBorder.Width / 2); else this.Canvas.fillText(item.Title, x+2, y + rtBorder.Height / 2); if (this.IsHScreen) this.Canvas.restore(); } this.FixTextRect = function (rect, yData) { for (var k in yData.Y) { var yItem = yData.Y[k]; rect.Y = yItem.Value; var y; for (var j = 0; j < 10; ++j) { var isOverlap = false; for (var i in this.TextRectCache) { var item = this.TextRectCache[i]; if (this.IsOverlap(item, rect)) { isOverlap = true; break; } } if (isOverlap == false) return; y = rect.Y; y += yItem.Offset; if (y + rect.Height > this.FrameBottom || y < this.FrameTop) break; rect.Y = y; } } } this.FixHScreenTextRect = function (rect, xData) { for (var k in xData.X) { var xItem = xData.X[k]; rect.X = xItem.Value; var x; for (var j = 0; j < 10; ++j) { var isOverlap = false; for (var i in this.TextRectCache) { var item = this.TextRectCache[i]; if (this.IsOverlap(item, rect)) { isOverlap = true; break; } } if (isOverlap == false) return; x = rect.X; x += xItem.Offset; if (x + rect.Width < this.FrameBottom || x > this.FrameTop) break; rect.X = x; } } } this.IsOverlap = function (rc1, rc2) { if (rc1.X + rc1.Width > rc2.X && rc2.X + rc2.Width > rc1.X && rc1.Y + rc1.Height > rc2.Y && rc2.Y + rc2.Height > rc1.Y) return true; else return false; } this.GetMaxMin = function () { var range = { Min: null, Max: null }; return range; } } //买卖盘 function ChartBuySell() { this.newMethod = ChartSingleText; //派生 this.newMethod(); delete this.newMethod; this.ClassName = "ChartBuySell"; this.TextFont = g_JSChartResource.KLineTrain.Font; //"bold 14px arial"; //买卖信息字体 this.LastDataIcon = g_JSChartResource.KLineTrain.LastDataIcon; //{Color:'rgb(0,0,205)',Text:'↓'}; this.BuyIcon = g_JSChartResource.KLineTrain.BuyIcon; //{Color:'rgb(0,0,205)',Text:'B'}; this.SellIcon = g_JSChartResource.KLineTrain.SellIcon; //{Color:'rgb(0,0,205)',Text:'S'}; this.BuySellData = new Map(); //Key=数据索引index Value:Data:[ { Op: 买/卖 0=buy 1=sell, Date:, Time, Price: Vol:}, ] this.LastDataDrawType=0; //0=画在最后一个数据上 1=画在指定索引上 this.LastDataIndex=-1; this.AddTradeItem = function (tradeItem) { if (this.BuySellData.has(tradeItem.Key)) { var Trade = this.BuySellData.get(tradeItem.Key); Trade.Data.push(tradeItem); } else { this.BuySellData.set(tradeItem.Key, { Data: [tradeItem] }); } } this.ClearTradeData = function () { this.BuySellData = new Map(); } this.Draw = function () { if (!this.Data || !this.Data.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen === true) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var bottom = this.ChartBorder.GetBottomEx(); var top = this.ChartBorder.GetTopEx(); var height = this.ChartBorder.GetHeightEx(); if (isHScreen) { top = this.ChartBorder.GetRightEx(); bottom = this.ChartBorder.GetLeftEx(); height = this.ChartBorder.GetWidthEx(); } this.Canvas.font = this.TextFont; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null) continue; if (x > chartright) break; var bDrawLastData=false; if (this.LastDataDrawType==1) { if (i==this.LastDataIndex) bDrawLastData=true; } else { if (i==this.Data.Data.length-1) bDrawLastData=true; } if (bDrawLastData) { var x = this.ChartFrame.GetXFromIndex(j); var yHigh = this.ChartFrame.GetYFromData(value.High); if (this.LastDataIcon.Text) { this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'bottom'; this.Canvas.fillStyle = this.LastDataIcon.Color; this.Canvas.font = this.TextFont; this.DrawText(this.LastDataIcon.Text, x, yHigh, isHScreen); } else { var obj = { X: x, Top: top, Bottom: bottom, Height: height, DataWidth: dataWidth, Color: this.LastDataIcon.Color, IsHScreen: isHScreen, }; this.DrawLastData(obj); } } var key = i; if (!this.BuySellData.has(key)) continue; var trade = this.BuySellData.get(key); var x = this.ChartFrame.GetXFromIndex(j); var yHigh = this.ChartFrame.GetYFromData(value.High); var yLow = this.ChartFrame.GetYFromData(value.Low); var drawInfo = [false, false]; //0=buy 1=sell for (var k in trade.Data) { if (drawInfo[0] == true && drawInfo[1] == true) break; //买卖图标只画一次 var bsItem = trade.Data[k]; if (bsItem.Op == 0 && drawInfo[0] == false) //买 标识在最低价上 { this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'top'; this.Canvas.fillStyle = this.BuyIcon.Color; this.DrawText(this.BuyIcon.Text, x, yLow, isHScreen); drawInfo[0] = true; } else if (bsItem.Op == 1 && drawInfo[1] == false) //卖 标识在最高价上 { this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'bottom'; this.Canvas.fillStyle = this.SellIcon.Color; this.DrawText(this.SellIcon.Text, x, yHigh, isHScreen); drawInfo[1] = true; } } } } this.DrawLastData=function(obj) { this.Canvas.fillStyle = obj.Color; var width = obj.DataWidth; if (this.LastDataIcon.Width >= 2 && this.LastDataIcon.Width < obj.DataWidth) width = this.LastDataIcon.Width; var left = obj.X - width / 2; if (obj.IsHScreen) { this.Canvas.fillRect(ToFixedRect(obj.Bottom), ToFixedRect(left), ToFixedRect(obj.Height), ToFixedRect(width)); } else { var left = obj.X - width/2; this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(obj.Top), ToFixedRect(width), ToFixedRect(obj.Height)); } } } //分钟成交量 function ChartMinuteVolumBar() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.UpColor = g_JSChartResource.UpBarColor; this.DownColor = g_JSChartResource.DownBarColor; this.UnchangeColor=g_JSChartResource.UnchagneBarColor; //平盘 this.BarColorType=1; //柱子颜色显示类型 0=红绿 1=红绿白 this.CustomColor=g_JSChartResource.Minute.VolBarColor; this.YClose; //前收盘 this.Draw = function () { var isHScreen = (this.ChartFrame.IsHScreen === true) var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var yBottom = this.ChartFrame.GetYFromData(0); var yPrice = this.YClose; //上一分钟的价格 if (this.CustomColor) this.Canvas.strokeStyle=this.CustomColor; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var item = this.Data.Data[i]; if (!item || !item.Vol) continue; var y = this.ChartFrame.GetYFromData(item.Vol); var x = this.ChartFrame.GetXFromIndex(i); if (x > chartright) break; //价格>=上一分钟价格 红色 否则绿色 if (!this.CustomColor) this.Canvas.strokeStyle = this.GetMinuteBarColor(item.Close, yPrice); this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(y, ToFixedPoint(x)); this.Canvas.lineTo(yBottom, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), y); this.Canvas.lineTo(ToFixedPoint(x), yBottom); } this.Canvas.stroke(); yPrice = item.Close; } } //连续交易成交量柱子颜色 this.GetMinuteBarColor=function(price, yPrice) { if (this.BarColorType==1) //通达信模式 { if (price>yPrice) return this.UpColor; else if (price= yPrice ? this.UpColor:this.DownColor; } } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = 0; range.Max = null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var item = this.Data.Data[i]; if (!item || !item.Vol) continue; if (range.Max == null) range.Max = item.Vol; if (range.Max < item.Vol) range.Max = item.Vol; } return range; } } //MACD森林线 支持横屏 function ChartMACD() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName ='ChartMACD'; this.UpColor = g_JSChartResource.UpBarColor; this.DownColor = g_JSChartResource.DownBarColor; this.LineWidth=1; this.Draw = function () { if (this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (this.ChartFrame.IsHScreen === true) { this.HScreenDraw(); return; } var isMinute=this.IsMinuteFrame(); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; var lineWidth=this.LineWidth; if (this.LineWidth==50) lineWidth=dataWidth; else if (lineWidth>dataWidth) lineWidth=dataWidth; this.Canvas.save(); this.Canvas.lineWidth=lineWidth; var bFirstPoint = true; var drawCount = 0; var yBottom = this.ChartFrame.GetYFromData(0); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; var xFix = parseInt(x.toString()) + 0.5; //毛边修正 this.Canvas.beginPath(); this.Canvas.moveTo(xFix, yBottom); this.Canvas.lineTo(xFix, y); if (value >= 0) this.Canvas.strokeStyle = this.UpColor; else this.Canvas.strokeStyle = this.DownColor; this.Canvas.stroke(); this.Canvas.closePath(); } this.Canvas.restore(); } this.HScreenDraw = function () { var isMinute=this.IsMinuteFrame(); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var yBottom = this.ChartFrame.GetYFromData(0); var lineWidth=this.LineWidth; if (this.LineWidth==50) lineWidth=dataWidth; else if (lineWidth>dataWidth) lineWidth=dataWidth; this.Canvas.save(); this.Canvas.lineWidth=lineWidth; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } var y = this.ChartFrame.GetYFromData(value); if (x > chartright) break; this.Canvas.beginPath(); this.Canvas.moveTo(yBottom, ToFixedPoint(x)); this.Canvas.lineTo(y, ToFixedPoint(x)); if (value >= 0) this.Canvas.strokeStyle = this.UpColor; else this.Canvas.strokeStyle = this.DownColor; this.Canvas.stroke(); this.Canvas.closePath(); } this.Canvas.restore(); } } //堆积柱状图 function ChartStackedBar() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartStackedBar"; this.Data; //{ Data:[ [bar1, bar2], [bar1,bar2 ] ] }; this.BarName=[]; this.BarColor=['rgb(255,165,0)',"rgb(95,158,160)"]; this.LineWidth=1; this.BarType=0; //0=线段 1=K线宽度一致 this.IsHScreen; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (this.IsHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var top=border.RightEx; var bottom=border.LeftEx; } else { var border=this.ChartFrame.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var top=border.TopEx; var bottom=border.BottomEx; } var isMinute=this.IsMinuteFrame(); this.Canvas.save(); if (this.BarType==1) { } else { if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth; var lineWidth=this.Canvas.lineWidth; } var yZero=this.ChartFrame.GetYFromData(0); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } if (x>chartright) break; if (this.BarType==1) { if (dataWidth>=4) //柱子太细就直接画竖线 this.DrawKBarItem(bars, x, left, right, top, bottom, yZero, dataWidth); else this.DrawBarItem(bars, x, top, bottom, yZero, lineWidth); } else { this.DrawBarItem(bars, x, top, bottom, yZero, lineWidth); } } this.Canvas.restore(); } this.DrawKBarItem=function(aryBar, x, left, right, top, bottom,yZero, barWidth) { var plusValue=0, yPlus=yZero; //正数 var negativeValue=0, yNegative= yZero; //负数 for(var i=0;i0) { plusValue+=item; var y=this.ChartFrame.GetYFromData(plusValue); var rtBar={Left: left, Top:y, Width:barWidth, Height:(yPlus-y)}; yPlus=y; } else { negativeValue+=item; var y=this.ChartFrame.GetYFromData(negativeValue); var rtBar={Left:left, Top:y, Width:barWidth, Height:(yNegative-y)}; yNegative=y; } if (this.IsHScreen) this.Canvas.fillRect(rtBar.Top,rtBar.Left, rtBar.Height, rtBar.Width); else this.Canvas.fillRect(rtBar.Left, rtBar.Top, rtBar.Width, rtBar.Height); } } this.DrawBarItem=function(aryBar,x, top, bottom, yZero, lineWidth) { var x=ToFixedPoint(x); var plusValue=0, yPlus=yZero; //正数 var negativeValue=0, yNegative=yZero; //负数 for(var i=0;i0) { plusValue+=item; var y=this.ChartFrame.GetYFromData(plusValue); var line={X:x, Y:yPlus, X2:x, Y2:y}; yPlus=y; } else { negativeValue+=item; var y=this.ChartFrame.GetYFromData(negativeValue); var line={X:x, Y:yNegative, X2:x, Y2:y}; yNegative=y; } this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(line.Y,line.X); this.Canvas.lineTo(line.Y2,line.X2); } else { this.Canvas.moveTo(line.X,line.Y); this.Canvas.lineTo(line.X2,line.Y2); } this.Canvas.strokeStyle=this.BarColor[i]; this.Canvas.stroke(); } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; if(!this.Data || !this.Data.Data) return range; for(var i=this.Data.DataOffset,j=0;i0) plusValue+=barValue; else if (barValue<0) negativeValue+=barValue; } if (range.Max==null) { range.Max=plusValue; range.Min=negativeValue; } if (range.MaxnegativeValue) range.Min=negativeValue; } return range; } } function ChartStepLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartStepLine'; //类名 this.LineWidth=1; //线段宽度 this.DotLine; this.IsHScreen; this.IsDotLine=false; //虚线 this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); this.Canvas.save(); this.DrawLine(); this.Canvas.restore(); } this.DrawLine=function() { var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var lockRect=this.GetLockRect(); if (this.IsHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; if (lockRect) chartright=lockRect.Top; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; if (lockRect) chartright=lockRect.Left; } if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth; if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 if (this.DotLine) this.Canvas.setLineDash(this.DotLine); //画虚线 this.Canvas.strokeStyle=this.Color; var bFirstPoint=true; var drawCount=0; var prePoint={ X:null, Y:null }; for(var i=this.Data.DataOffset; i>=0; --i) { var value=this.Data.Data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; var y=this.GetYFromData(value,false); var x=null; if (isMinute) x=this.ChartFrame.GetXFromIndex(0); else x=xOffset; this.Canvas.beginPath(); if (this.IsHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; prePoint.Y=y; prePoint.X=x; } for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } if (x>chartright) break; var value=this.Data.Data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; var y=this.GetYFromData(value,false); if (bFirstPoint) { this.Canvas.beginPath(); if (this.IsHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; prePoint.X=x; prePoint.Y=y; } else { if (this.IsHScreen) { this.Canvas.lineTo(prePoint.Y,x) this.Canvas.lineTo(y,x); } else { this.Canvas.lineTo(x,prePoint.Y) this.Canvas.lineTo(x,y); } prePoint.X=x; prePoint.Y=y; } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); } } //////////////////////////////////////////////////////////////////////////////// // 等待提示 function ChartSplashPaint() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Font = g_JSChartResource.DefaultTextFont; //字体 this.TextColor = g_JSChartResource.DefaultTextColor; //文本颜色 this.IsEnableSplash = false; this.SplashTitle = '数据加载中.....'; this.HQChart; this.EnableSplash=function(bEnable) { this.IsEnableSplash=bEnable; if (this.HQChart) { var event=this.HQChart.GetEnableSplashEvent(); if (event) { var data={ Enable:bEnable }; event.Callback(event,data,this); } } } this.SetTitle=function(title) { this.SplashTitle=title; } this.Draw = function () { if (!this.IsEnableSplash) return; if (this.Frame.IsHScreen === true) { this.HScreenDraw(); return; } var xCenter = (this.Frame.ChartBorder.GetLeft() + this.Frame.ChartBorder.GetRight()) / 2; var yCenter = (this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.GetBottom()) / 2; this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; this.Canvas.fillText(this.SplashTitle, xCenter, yCenter); } this.HScreenDraw = function () //横屏 { var xCenter = (this.Frame.ChartBorder.GetLeft() + this.Frame.ChartBorder.GetRight()) / 2; var yCenter = (this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.GetBottom()) / 2; this.Canvas.save(); this.Canvas.translate(xCenter, yCenter); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; this.Canvas.fillText(this.SplashTitle, 0, 0); this.Canvas.restore(); } } //填充背景 支持横屏 function ChartBackground() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartBackground"; this.Color=null; this.ColorAngle=0; //0 竖向 1 横向 this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的 this.IsHScreen=false; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Color) return; if (this.Color.length<=0) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); if (this.Color.length==2) { if (this.IsHScreen) { if (this.ColorAngle==0) { var ptStart={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; } else { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() }; } } else { if (this.ColorAngle==0) { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() }; } else { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() }; } } let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y); gradient.addColorStop(0, this.Color[0]); gradient.addColorStop(1, this.Color[1]); this.Canvas.fillStyle=gradient; } else if (this.Color.length==1) { this.Canvas.fillStyle=this.Color[0]; } else { return; } if (this.Name=="DRAWGBK2" || this.Name=="KLINE_BG") { this.DrawRegion(); return; } if (this.IsHScreen) { var left=this.ChartBorder.GetLeftEx(); var top=this.ChartBorder.GetTop(); var width=this.ChartBorder.GetWidthEx(); var height=this.ChartBorder.GetHeight(); } else { var left=this.ChartBorder.GetLeft(); var top=this.ChartBorder.GetTopEx(); var width=this.ChartBorder.GetWidth(); var height=this.ChartBorder.GetHeightEx(); } this.Canvas.fillRect(left, top,width, height); } this.DrawRegion=function() { var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); if (this.IsHScreen) { top=this.ChartBorder.GetRightEx(); bottom=this.ChartBorder.GetLeftEx(); } var aryPoint=[]; //点坐标 for(var i=this.Data.DataOffset,j=0;i0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; if (this.IsHScreen) { this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth); this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth); } else { this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y); this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y); } } this.Canvas.closePath(); this.Canvas.fill(); } firstPoint=true; pointCount=0; aryLine2=[]; color=null; } if (!item) continue; if (firstPoint) { this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(item.Line.X, item.Line.Y-halfWidth); this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth); } else { this.Canvas.moveTo(item.Line.X-halfWidth, item.Line.Y); this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y); } firstPoint=false; color=item.Color; } else { if (this.IsHScreen) { this.Canvas.lineTo(item.Line.X, item.Line.Y-halfWidth); this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth); } else { this.Canvas.lineTo(item.Line.X-halfWidth, item.Line.Y); this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y); } } aryLine2.push(item); ++pointCount; } if (pointCount>0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; if (this.IsHScreen) { this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth); this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth); } else { this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y); this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y); } } this.Canvas.closePath(); this.Canvas.fill(); } } this.GetMaxMin=function() { return { Min:null, Max:null }; } } //填充部分背景 支持横屏 function ChartBackgroundDiv() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartBackgroundDiv"; this.AryColor; this.ColorType=0; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.AryColor)) return; if (!this.Data || !this.Data.Data) return; var bHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var border,xOffset, chartright, yTop, yBottom; if (bHScreen) { border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; yTop=border.LeftEx; yBottom=border.RightEx; } else { border=this.ChartBorder.GetBorder(); xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.RightEx; yTop=border.TopEx; yBottom=border.BottomEx; } var rtBG=null //{ Left:null, Top:null, Right:null, Bottom:null }; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (!item) { if (rtBG) this.DrawDiv(rtBG,bHScreen); rtBG=null; } else { var y=yTop; var y2=yBottom; if (IFrameSplitOperator.IsNonEmptyArray(item.AryValue)) { var value=this.ChartFrame.GetYFromData(item.AryValue[0]); var value2=this.ChartFrame.GetYFromData(item.AryValue[1]); y=Math.min(value, value2); y2=Math.max(value, value2); } if (bHScreen) { if (!rtBG) { rtBG={ Left:y, Right:y2, Top:left, Bottom:right }; } else { rtBG.Bottom=right; if (rtBG.Left>y) rtBG.Left=y; if (rtBG.Righty) rtBG.Top=y; if (rtBG.Bottom chartright) break; } lOffsetWidth = (dataWidth + distanceWidth) * this.LockCount; } if (lOffsetWidth == 0) { lOffsetWidth = (xOffset - this.ChartBorder.GetLeft()) * this.WidthDiv; } var lLeft = xOffset - lOffsetWidth; if (lLeft < this.ChartBorder.GetLeft()) lLeft = this.ChartBorder.GetLeft(); var lHeight = this.ChartBorder.GetBottom() - this.ChartBorder.GetTop(); var lWidth = this.ChartBorder.GetRight() - lLeft; this.Canvas.fillStyle = this.BGColor; this.Canvas.fillRect(lLeft, this.ChartBorder.GetTop(), lWidth, lHeight); var xCenter = lLeft + lWidth / 2; var yCenter = this.ChartBorder.GetTop() + lHeight / 2; this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; this.Canvas.fillText(this.Title, xCenter, yCenter); this.LockRect = { Left: lLeft, Top: this.ChartBorder.GetTop(), Width: lWidth, Heigh: lHeight }; //保存上锁区域 } this.HScreenDraw = function () { var xOffset = this.ChartBorder.GetBottom(); var lOffsetWidth = 0; if (this.ChartFrame.Data != null) { var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; //求最后1个数据的位置 for (var i = this.ChartFrame.Data.DataOffset, j = 0; i < this.ChartFrame.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var data = this.ChartFrame.Data.Data[i]; if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; } lOffsetWidth = (dataWidth + distanceWidth) * this.LockCount; } if (lOffsetWidth == 0) { lOffsetWidth = (xOffset - this.ChartBorder.GetTop()) * this.WidthDiv; } var lLeft = xOffset - lOffsetWidth; if (lLeft < this.ChartBorder.GetTop()) lLeft = this.ChartBorder.GetTop(); var lHeight = this.ChartBorder.GetRight() - this.ChartBorder.GetLeft(); var lWidth = this.ChartBorder.GetBottom() - lLeft; this.Canvas.fillStyle = this.BGColor; this.Canvas.fillRect(this.ChartBorder.GetLeft(), lLeft, lHeight, lWidth); var xCenter = this.ChartBorder.GetLeft() + lHeight / 2; var yCenter = lLeft + lWidth / 2; this.Canvas.save(); this.Canvas.translate(xCenter, yCenter); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; this.Canvas.fillText(this.Title, 0, 0); this.Canvas.restore(); this.LockRect = { Left: this.ChartBorder.GetLeft(), Top: lLeft, Width: lHeight, Heigh: lWidth }; //保存上锁区域 } //x,y是否在上锁区域 this.GetTooltipData = function (x, y, tooltip) { if (this.LockRect == null) return false; if (this.IsPointInRect(x, y, this.LockRect.Left, this.LockRect.Top, this.LockRect.Width, this.LockRect.Heigh)) { tooltip.Data = { ID: this.LockID, Callback: this.Callback, IndexName: this.IndexName }; tooltip.ChartPaint = this; return true; } return false; } this.IsPointInRect = function (x, y, left, top, width, heigh) { if (x > left && x < left + width && y > top && y < top + heigh) return true; return false; } } //通达信语法 VOLSTICK 支持横屏 function ChartVolStick() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.UpColor = g_JSChartResource.UpBarColor; this.DownColor = g_JSChartResource.DownBarColor; this.HistoryData; //历史数据 this.KLineDrawType = 0; this.BarType; //柱子状态 1=实心 0=空心 2=涨实跌空 如果设置了这个属性, 属性KLineDrawType无效 this.ClassName = 'ChartVolStick'; this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度 this.Draw = function () { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsHideScriptIndex()) return; if (this.ChartFrame.IsHScreen === true) { this.HScreenDraw(); return; } var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; var yBottom = this.ChartFrame.GetYFromData(0); var isMinute=this.IsMinuteFrame(); this.Canvas.save(); if (dataWidth >= this.MinBarWidth) { //只有K线, 分时图dataWidth=1 yBottom = ToFixedRect(yBottom); for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; var kItem = this.HistoryData.Data[i]; if (value == null || kItem == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var y = this.ChartFrame.GetYFromData(value); var barColor=this.GetBarColor(kItem); var bUp = barColor.IsUp; //高度调整为整数 var height = ToFixedRect(Math.abs(yBottom - y)>=1 ? yBottom - y : 1); y = yBottom - height; var bSolidBar=this.IsSolidBar(bUp); //实心柱子 if (bSolidBar) { this.Canvas.fillStyle=barColor.Color; this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), height); } else { this.Canvas.strokeStyle=barColor.Color; this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), height); this.Canvas.stroke(); } } } else //太细了直接话线 { var preKItem=null; var barColor=null; this.Canvas.lineWidth=1; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; var kItem = this.HistoryData.Data[i]; if (value == null || kItem == null) continue; var y = this.ChartFrame.GetYFromData(value); if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; } if (x > chartright) break; if (isMinute) barColor=this.GetMinuteBarColor(kItem,preKItem); //分时图颜色单独计算 else barColor=this.GetBarColor(kItem); this.Canvas.strokeStyle=barColor.Color; //var x = this.ChartFrame.GetXFromIndex(j); this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(x), y); this.Canvas.lineTo(ToFixedPoint(x), yBottom); this.Canvas.stroke(); preKItem=kItem; } } this.Canvas.restore(); } this.GetBarColor=function(kItem) { if (kItem.Close>=kItem.Open) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨 else return { Color:this.DownColor, IsUp:false }; } this.GetMinuteBarColor=function(kItem, preItem) { var prePrice=kItem.YClose; if (preItem) prePrice=preItem.Close; if (kItem.Close>=prePrice) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨 else return { Color:this.DownColor, IsUp:false }; } //true=实心 false=空心 this.IsSolidBar=function(bUp) { var bSolidBar=true; //实心柱子 if (this.BarType===0 || this.BarType===1 || this.BarType===2) { if (this.BarType===0) //空心 bSolidBar=false; else if (this.BarType===2) //涨实跌空 bSolidBar=bUp; } else { if (this.KLineDrawType==6) //完全空心柱 bSolidBar=false; else if (bUp && (this.KLineDrawType==1 || this.KLineDrawType==2 || this.KLineDrawType==3)) //空心柱子 bSolidBar=false; } return bSolidBar; } this.HScreenDraw = function () //横屏画法 { var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var chartBottom = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var isMinute=this.IsMinuteFrame(); var yBottom = this.ChartFrame.GetYFromData(0); if (dataWidth >= this.MinBarWidth) { yBottom = ToFixedRect(yBottom); for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; var kItem = this.HistoryData.Data[i]; if (value == null || kItem == null) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartBottom) break; var y = this.ChartFrame.GetYFromData(value); var barColor=this.GetBarColor(kItem); var bUp=barColor.IsUp; //高度调整为整数 var height = ToFixedRect(y - yBottom); var bSolidBar=this.IsSolidBar(bUp); //实心柱子 if (bSolidBar) { this.Canvas.fillStyle=barColor.Color; this.Canvas.fillRect(yBottom, ToFixedRect(left), height, ToFixedRect(dataWidth)); } else { this.Canvas.strokeStyle=barColor.Color; this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(yBottom), ToFixedPoint(left), height, ToFixedRect(dataWidth)); this.Canvas.stroke(); } } } else //太细了直接话线 { var preKItem=null; var barColor=null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; var kItem = this.HistoryData.Data[i]; if (value == null || kItem == null) continue; var y = this.ChartFrame.GetYFromData(value); if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; } if (x > chartBottom) break; if (isMinute) barColor=this.GetMinuteBarColor(kItem,preKItem); //分时图颜色单独计算 else barColor=this.GetBarColor(kItem); this.Canvas.strokeStyle=barColor.Color; //var x = this.ChartFrame.GetXFromIndex(j); this.Canvas.beginPath(); this.Canvas.moveTo(y, ToFixedPoint(x)); this.Canvas.lineTo(yBottom, ToFixedPoint(x)); this.Canvas.stroke(); preKItem=kItem; } } } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = { Min:null, Max:null }; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (!IFrameSplitOperator.IsNumber(range.Max) || range.Maxvalue) range.Min=value } if (range.Max>0 && range.Min>0) range.Min=0; else if (range.Max<0 && range.Min<0) range.Max=0; return range; } } function ChartText() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.TextFont = "14px 微软雅黑"; this.Draw = function () { if (this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; for (var i in this.Data.Data) { var value = this.Data.Data[i]; if (value == null) continue; var price = value.Value; var position = value.Position; if (position == 'Left') { var x = this.ChartFrame.GetXFromIndex(0); var y = this.ChartFrame.GetYFromData(price); if (x > chartright) continue; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = value.Color; this.Canvas.font = this.TextFont; this.Canvas.fillText(value.Message, x, y); } } } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; if (!this.Data || !this.Data.Data) return range; for (var i in this.Data.Data) { var data = this.Data.Data[i]; if (data == null || isNaN(data.Value)) continue; var value = data.Value; if (range.Max == null) range.Max = value; if (range.Min == null) range.Min = value; if (range.Max < value) range.Max = value; if (range.Min > value) range.Min = value; } return range; } } /* 水平面积 只有1个数据 Data 数据结构 Value, Value2 区间最大最小值 Color=面积的颜色 Title=标题 TitleColor=标题颜色 支持横屏 */ function ChartStraightArea() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(255,193,37)"; //线段颜色 this.Font = '11px 微软雅黑'; this.Draw = function () { if (this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; if (this.ChartFrame.IsHScreen === true) { this.HScreenDraw(); return; } var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var bottom = this.ChartBorder.GetBottom(); var left = this.ChartBorder.GetLeft(); var xPointCount = this.ChartFrame.XPointCount; var xRight = this.ChartFrame.GetXFromIndex(xPointCount - 1); //画背景 for (let i in this.Data.Data) { let item = this.Data.Data[i]; if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue; if (item.Color == null) continue; let valueMax = Math.max(item.Value, item.Value2); let valueMin = Math.min(item.Value, item.Value2); let yTop = this.ChartFrame.GetYFromData(valueMax); let yBottom = this.ChartFrame.GetYFromData(valueMin); this.Canvas.fillStyle = item.Color; this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(yTop), ToFixedRect(xRight - left), ToFixedRect(yBottom - yTop)); } for (let i in this.Data.Data) { let item = this.Data.Data[i]; if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue; if (item.Color == null) continue; let valueMax = Math.max(item.Value, item.Value2); let valueMin = Math.min(item.Value, item.Value2); let yTop = this.ChartFrame.GetYFromData(valueMax); let yBottom = this.ChartFrame.GetYFromData(valueMin); if (item.Title && item.TitleColor) { let x = xRight; if (item.Align == 'left') { this.Canvas.textAlign = 'left'; x = left; } else { this.Canvas.textAlign = 'right'; x = xRight; } this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = item.TitleColor; this.Canvas.font = this.Font; let y = yTop + (yBottom - yTop) / 2; this.Canvas.fillText(item.Title, x, y); } } } this.HScreenDraw = function () { var bottom = this.ChartBorder.GetBottom(); var top = this.ChartBorder.GetTop(); var height = this.ChartBorder.GetHeight(); for (let i in this.Data.Data) { let item = this.Data.Data[i]; if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue; if (item.Color == null) continue; let valueMax = Math.max(item.Value, item.Value2); let valueMin = Math.min(item.Value, item.Value2); var yTop = this.ChartFrame.GetYFromData(valueMax); var yBottom = this.ChartFrame.GetYFromData(valueMin); this.Canvas.fillStyle = item.Color; this.Canvas.fillRect(ToFixedRect(yBottom), ToFixedRect(top), ToFixedRect(yTop - yBottom), ToFixedRect(height)); if (item.Title && item.TitleColor) { var xText = yTop + (yBottom - yTop) / 2; var yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = item.TitleColor; this.Canvas.font = this.Font; this.Canvas.fillText(item.Title, 0, -2); this.Canvas.restore(); } } } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; if (!this.Data || !this.Data.Data) return range; for (let i in this.Data.Data) { let item = this.Data.Data[i]; if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue; let valueMax = Math.max(item.Value, item.Value2); let valueMin = Math.min(item.Value, item.Value2); if (range.Max == null) range.Max = valueMax; if (range.Min == null) range.Min = valueMin; if (range.Max < valueMax) range.Max = valueMax; if (range.Min > valueMin) range.Min = valueMin; } return range; } } // DRAWBAND 面积图 支持横屏 function ChartBand() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.IsDrawFirst = true; this.ClassName="ChartBand"; this.FirstColor = g_JSChartResource.Index.LineColor[0]; this.SecondColor = g_JSChartResource.Index.LineColor[1]; this.Draw = function () { if (this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } var isHScreen=this.ChartFrame.IsHScreen; var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var xPointCount = this.ChartFrame.XPointCount; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; var x = 0; var y = 0; var y2 = 0; var firstlinePoints = []; var secondlinePoints = []; var lIndex = 0; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value.Value == null || value.Value2 == null) continue; x = this.ChartFrame.GetXFromIndex(j); y = this.ChartFrame.GetYFromData(value.Value); y2 = this.ChartFrame.GetYFromData(value.Value2); if (isHScreen) { firstlinePoints[lIndex] = { x: y, y: x }; secondlinePoints[lIndex] = { x: y2, y: x }; } else { firstlinePoints[lIndex] = { x: x, y: y }; secondlinePoints[lIndex] = { x: x, y: y2 }; } lIndex++; } if (firstlinePoints.length>1 && secondlinePoints.length>1) { this.DrawBand(firstlinePoints, secondlinePoints); } } this.ClipTop=function(aryFrist) { var isHScreen=this.ChartFrame.IsHScreen; this.Canvas.beginPath(); for(var i=0;i= 0; --i) { this.Canvas.lineTo(arySecond[i].x, arySecond[i].y); } this.Canvas.closePath(); this.Canvas.fillStyle = clrArea; this.Canvas.fill(); } this.DrawBand=function(aryFrist, arySecond) { if (this.FirstColor) { this.Canvas.save(); this.ClipTop(aryFrist); this.DrawArea(aryFrist, arySecond, this.FirstColor); this.Canvas.restore(); } if (this.SecondColor) { this.Canvas.save(); this.ClipBottom(aryFrist); this.DrawArea(aryFrist, arySecond, this.SecondColor); this.Canvas.restore(); } } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (value == null || value.Value == null || value.Value2 == null) continue; var maxData = value.Value > value.Value2 ? value.Value : value.Value2; var minData = value.Value < value.Value2 ? value.Value : value.Value2; if (range.Max == null) range.Max = maxData; else if (range.Max < maxData) range.Max = maxData; if (range.Min == null) range.Min = minData; else if (range.Min > minData) range.Min = minData; } return range; } } //分钟线叠加 支持横屏 function ChartOverlayMinutePriceLine() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(65,105,225)"; this.MainData; //主图数据 this.Name = "ChartOverlayMinutePriceLine"; this.Title; this.Symbol; //叠加的股票代码 this.YClose; //叠加的股票前收盘 this.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID; this.OverlayType=0; //叠加方式 0=百分比叠加 1=绝对叠加 this.Draw = function () { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen === true) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var minuteCount = this.ChartFrame.MinuteCount; var yClose=null, mainYClose=null; var bFirstPoint = true; var drawCount = 0, showValue=0, pointCount=0; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var item=this.Data.Data[i]; if (item && IFrameSplitOperator.IsNumber(item.Close)) { if (bFirstPoint) //百分比使用每天的昨收计算 { yClose=item.YClose; var minItem=this.MainData.Data[i]; mainYClose=minItem.YClose; } var value=item.Close; showValue=value; //绝对叠加 if (this.OverlayType==0) showValue=value/yClose*mainYClose; //百分比 var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(showValue, false); if (bFirstPoint) { this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(y, x); else this.Canvas.moveTo(x, y); bFirstPoint = false; } else { if (isHScreen) this.Canvas.lineTo(y, x); else this.Canvas.lineTo(x, y); } ++drawCount; } ++pointCount; if (pointCount>=minuteCount) //上一天的数据和这天地数据线段要断开 { bFirstPoint=true; pointCount=0; if (drawCount>0) this.Canvas.stroke(); drawCount=0; } } if (drawCount > 0) this.Canvas.stroke(); } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range={ Min:null, Max:null }; var minuteCount=this.ChartFrame.MinuteCount; var yClose=null, mainYClose=null; var bFirstPoint=true; var pointCount=0; for(var i=this.Data.DataOffset,j=0;ivalue) range.Min=value; ++pointCount; if (pointCount>=minuteCount) { bFirstPoint=true; pointCount=0; } } return range; } } //线段 多数据(一个X点有多条Y数据) 支持横屏 function ChartLineMultiData() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(255,193,37)"; //线段颜色 this.Draw = function () { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var bFirstPoint = true; var drawCount = 0; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var aryValue = this.Data.Data[i]; if (aryValue == null) continue; var x = this.ChartFrame.GetXFromIndex(j); if (x > chartright) break; for (var index in aryValue) { var value = aryValue[index].Value; var y = this.ChartFrame.GetYFromData(value); if (bFirstPoint) { this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(y, x); else this.Canvas.moveTo(x, y); bFirstPoint = false; } else { if (isHScreen) this.Canvas.lineTo(y, x); else this.Canvas.lineTo(x, y); } ++drawCount; } } if (drawCount > 0) this.Canvas.stroke(); } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; if (!this.Data || !this.Data.Data) return range; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var aryValue = this.Data.Data[i]; if (aryValue == null) continue; for (var index in aryValue) { var value = aryValue[index].Value; if (range.Max == null) range.Max = value; if (range.Min == null) range.Min = value; if (range.Max < value) range.Max = value; if (range.Min > value) range.Min = value; } } return range; } } //直线 水平直线 只有1个数据 支持横屏 function ChartStraightLine() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color = "rgb(255,193,37)"; //线段颜色 this.Draw = function () { if (!this.Data || !this.Data.Data) return; if (this.Data.Data.length != 1) return; var isHScreen = this.ChartFrame.IsHScreen; var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetTop(); var xPointCount = this.ChartFrame.XPointCount; var yValue = this.Data.Data[0]; var y = this.ChartFrame.GetYFromData(yValue); var xLeft = this.ChartFrame.GetXFromIndex(0); var xRight = this.ChartFrame.GetXFromIndex(xPointCount - 1); var yFix = parseInt(y.toString()) + 0.5; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yFix, xLeft); this.Canvas.lineTo(yFix, xRight); } else { this.Canvas.moveTo(xLeft, yFix); this.Canvas.lineTo(xRight, yFix); } this.Canvas.strokeStyle = this.Color; this.Canvas.stroke(); } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = null; range.Max = null; if (!this.Data || !this.Data.Data) return range; if (this.Data.Data.length != 1) return range; range.Min = this.Data.Data[0]; range.Max = this.Data.Data[0]; return range; } } //////////////////////////////////////////////////////////////////////////////////////////////////// // 其他图形 // // //////////////////////////////////////////////////////////////////////////////////////////////////// /* 饼图 */ function ChartPie() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Draw = function () { if (!this.Data || !this.Data.Data || !(this.Data.Data.length > 0)) return this.DrawEmptyData(); let left = this.ChartBorder.GetLeft(); let right = this.ChartBorder.GetRight(); let top = this.ChartBorder.GetTop(); let bottom = this.ChartBorder.GetBottom(); let width = this.ChartBorder.GetWidth(); let height = this.ChartBorder.GetHeight(); //圆半径 let radius = width / 4 * 0.8; this.Canvas.save(); this.Canvas.translate(left + radius, top + height / 2); let totalValue = 0; //求和 for (let i in this.Data.Data) { totalValue += this.Data.Data[i].Value; } let startAngle = Math.PI * 1.5; let start = startAngle; let end = startAngle; //画饼图 for (let i in this.Data.Data) { let item = this.Data.Data[i]; let rate = item.Value / totalValue; //占比 // 绘制扇形 this.Canvas.beginPath(); this.Canvas.moveTo(0, 0); end += rate * 2 * Math.PI;//终止角度 this.Canvas.strokeStyle = "white"; this.Canvas.fillStyle = item.Color; this.Canvas.arc(0, 0, radius, start, end); this.Canvas.fill(); this.Canvas.closePath(); this.Canvas.stroke(); start += rate * 2 * Math.PI;//起始角度 } //画文字 this.Canvas.restore(); let textLeft = left + width / 2 + 5; // let textTop = top + height / 2 + 20; let textTop = top; this.Canvas.textBaseline = "bottom"; this.Canvas.font = "12px 微软雅黑"; for (let i = 0, j = 0; i < this.Data.Data.length; ++i) { let item = this.Data.Data[i]; if (!item.Text) continue; this.Canvas.fillStyle = item.Color; this.Canvas.fillRect(textLeft, textTop - 15, 13, 13); this.Canvas.fillStyle = 'rgb(102,102,102)'; this.Canvas.fillText(item.Text, textLeft + 16, textTop); // textTop += 20; textTop += 17; if (textTop > top + height / 2 + radius) { ++j; if (j >= 2) break; // textTop = top + height / 2 + 20; textTop = top; textLeft = right - (width / 4) + 5; } } } //空数据 this.DrawEmptyData = function () { console.log('[ChartPie::DrawEmptyData]') let left = this.ChartBorder.GetLeft(); let right = this.ChartBorder.GetRight(); let top = this.ChartBorder.GetTop(); let bottom = this.ChartBorder.GetBottom(); let width = this.ChartBorder.GetWidth(); let height = this.ChartBorder.GetHeight(); //圆半径 let radius = width / 4 * 0.8; this.Canvas.save(); this.Canvas.translate(left + radius, top + height / 2); this.Canvas.beginPath(); this.Canvas.fillStyle = 'rgb(211,211,211)'; this.Canvas.strokeStyle = "white"; this.Canvas.arc(0, 0, radius * 0.8, 0, 2 * Math.PI); this.Canvas.fill(); this.Canvas.closePath(); this.Canvas.stroke(); this.Canvas.restore(); } } /* 圆环 */ function ChartCircle() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.BGColor = 'white'; //背景色 this.TextHeight = 25; //空数据 this.DrawEmptyData = function () { console.log('[ChartCircle::DrawEmptyData]') } this.Draw = function () { if (!this.Data || !this.Data.Data || !(this.Data.Data.length > 0)) return this.DrawEmptyData(); let left = this.ChartBorder.GetLeft(); let right = this.ChartBorder.GetRight(); let top = this.ChartBorder.GetTop(); let bottom = this.ChartBorder.GetBottom(); let width = this.ChartBorder.GetWidth(); let height = this.ChartBorder.GetHeight(); //圆半径 let lTextHeight = this.TextHeight; let size = width - lTextHeight; if (size > height - lTextHeight) size = height - lTextHeight; let radius = (size - lTextHeight) / 2; this.Canvas.save(); this.Canvas.translate(left + width / 2, top + height / 2 - lTextHeight / 2); let totalValue = 0; //求和 for (let i in this.Data.Data) { totalValue += this.Data.Data[i].Value; } let startAngle = Math.PI * 1.5; let start = startAngle; let end = startAngle; //画饼图 for (let i in this.Data.Data) { let item = this.Data.Data[i]; let rate = item.Value / totalValue; //占比 //console.log('[ChartPie::Draw]', i, rate, item); // 绘制扇形 this.Canvas.beginPath(); this.Canvas.moveTo(0, 0); end += rate * 2 * Math.PI;//终止角度 this.Canvas.strokeStyle = "white"; this.Canvas.fillStyle = item.Color; this.Canvas.arc(0, 0, radius, start, end); this.Canvas.fill(); this.Canvas.closePath(); this.Canvas.stroke(); start += rate * 2 * Math.PI;//起始角度 } //中心画一个背景色的圆 this.Canvas.beginPath(); this.Canvas.fillStyle = this.BGColor; this.Canvas.arc(0, 0, radius * 0.5, 0, 2 * Math.PI); this.Canvas.fill(); this.Canvas.closePath(); this.Canvas.stroke(); this.Canvas.restore(); //画文字 this.Canvas.restore(); let textLeft = left; let textTop = top + height / 2 - lTextHeight / 2 + radius + 5 + 20; this.Canvas.textBaseline = "bottom"; this.Canvas.textAlign = 'left'; this.Canvas.font = "14px 微软雅黑"; let textWidth = 0; //以圆心左右显示 for (let i = 0, j = 0; i < this.Data.Data.length; ++i) { let item = this.Data.Data[i]; if (!item.Text) continue; this.Canvas.fillStyle = item.Color; if (j % 2 == 0) { textLeft = left + width / 2 - 10; textWidth = this.Canvas.measureText(item.Text).width; textLeft = textLeft - textWidth - 16; this.Canvas.fillRect(textLeft, textTop - 15, 13, 13); this.Canvas.fillStyle = 'rgb(102,102,102)'; this.Canvas.fillText(item.Text, textLeft + 16, textTop); } else { textLeft = left + width / 2 + 10 + 10; this.Canvas.fillRect(textLeft, textTop - 15, 13, 13); this.Canvas.fillStyle = 'rgb(102,102,102)'; this.Canvas.fillText(item.Text, textLeft + 16, textTop); textTop += 20; } if (textTop > bottom) break; ++j; } } } // 中国地图 function ChartChinaMap() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ImageData = null; this.Left; this.Top; this.Width; this.Height; this.ImageWidth; this.ImageHeight; this.DefaultColor = [217, 222, 239]; this.Color = [ { Name: '海南', Color: 'rgb(217,222,223)' }, { Name: '内蒙古', Color: 'rgb(217,222,225)' }, { Name: '新疆', Color: 'rgb(217,222,226)' }, { Name: '青海', Color: 'rgb(217,222,227)' }, { Name: '西藏', Color: 'rgb(217,222,228)' }, { Name: '云南', Color: 'rgb(217,222,229)' }, { Name: '黑龙江', Color: 'rgb(217,222,230)' }, { Name: '吉林', Color: 'rgb(217,222,231)' }, { Name: '辽宁', Color: 'rgb(217,222,232)' }, { Name: '河北', Color: 'rgb(217,222,233)' }, { Name: '山东', Color: 'rgb(217,222,234)' }, { Name: '江苏', Color: 'rgb(217,222,235)' }, { Name: '浙江', Color: 'rgb(217,222,236)' }, { Name: '福建', Color: 'rgb(217,222,237)' }, { Name: '广东', Color: 'rgb(217,222,238)' }, { Name: '广西', Color: 'rgb(217,222,239)' }, { Name: '贵州', Color: 'rgb(217,222,240)' }, { Name: '湖南', Color: 'rgb(217,222,241)' }, { Name: '江西', Color: 'rgb(217,222,242)' }, { Name: '安徽', Color: 'rgb(217,222,243)' }, { Name: '湖北', Color: 'rgb(217,222,244)' }, { Name: '重庆', Color: 'rgb(217,222,245)' }, { Name: '四川', Color: 'rgb(217,222,246)' }, { Name: '甘肃', Color: 'rgb(217,222,247)' }, { Name: '陕西', Color: 'rgb(217,222,248)' }, { Name: '山西', Color: 'rgb(217,222,249)' }, { Name: '河南', Color: 'rgb(217,222,250)' } ]; this.Draw = function () { let left = this.ChartBorder.GetLeft() + 1; let right = this.ChartBorder.GetRight() - 1; let top = this.ChartBorder.GetTop() + 1; let bottom = this.ChartBorder.GetBottom() - 1; let width = this.ChartBorder.GetWidth() - 2; let height = this.ChartBorder.GetHeight() - 2; let imageWidth = CHINA_MAP_IMAGE.width; let imageHeight = CHINA_MAP_IMAGE.height; let drawImageWidth = imageWidth; let drawImageHeight = imageHeight; if (height < drawImageHeight || width < drawImageWidth) { this.ImageData = null; return; } if (this.Left != left || this.Top != top || this.Width != width || this.Height != height || this.ImageWidth != imageWidth || this.ImageHeight != imageHeight) { this.ImageData = null; this.ImageWidth = imageWidth; this.ImageHeight = imageHeight; this.Left = left; this.Top = top; this.Width = width; this.Height = height; console.log(imageWidth, imageHeight); } if (this.ImageData == null) { this.Canvas.drawImage(CHINA_MAP_IMAGE, 0, 0, imageWidth, imageHeight, left, top, drawImageWidth, drawImageHeight); this.ImageData = this.Canvas.getImageData(left, top, drawImageWidth, drawImageHeight); let defaultColorSet = new Set(); //默认颜色填充的色块 let colorMap = new Map(); //定义颜色填充的色块 let nameMap = new Map(); if (this.Data.length > 0) { for (let i in this.Data) { let item = this.Data[i]; nameMap.set(item.Name, item.Color) } } console.log(this.Data); for (let i in this.Color) { let item = this.Color[i]; if (nameMap.has(item.Name)) { colorMap.set(item.Color, nameMap.get(item.Name)); } else { defaultColorSet.add(item.Color); } } var color; for (let i = 0; i < this.ImageData.data.length; i += 4) { color = 'rgb(' + this.ImageData.data[i] + ',' + this.ImageData.data[i + 1] + ',' + this.ImageData.data[i + 2] + ')'; if (defaultColorSet.has(color)) { this.ImageData.data[i] = this.DefaultColor[0]; this.ImageData.data[i + 1] = this.DefaultColor[1]; this.ImageData.data[i + 2] = this.DefaultColor[2]; } else if (colorMap.has(color)) { let colorValue = colorMap.get(color); this.ImageData.data[i] = colorValue[0]; this.ImageData.data[i + 1] = colorValue[1]; this.ImageData.data[i + 2] = colorValue[2]; } } this.Canvas.clearRect(left, top, drawImageWidth, drawImageHeight); this.Canvas.putImageData(this.ImageData, left, top, 0, 0, drawImageWidth, drawImageHeight); } else { this.Canvas.putImageData(this.ImageData, left, top, 0, 0, drawImageWidth, drawImageHeight); } } } // 雷达图 function ChartRadar() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.BorderPoint = []; //边框点 this.DataPoint = []; //数据点 this.CenterPoint = {}; this.StartAngle = 0; this.Color = 'rgb(198,198,198)'; this.AreaColor = 'rgba(242,154,118,0.4)'; //面积图颜色 this.AreaLineColor = 'rgb(242,154,118)'; this.TitleFont = '24px 微软雅黑'; this.TitleColor = 'rgb(102,102,102)'; this.BGColor = ['rgb(255,255,255)', 'rgb(224,224,224)']//背景色 this.DrawBorder = function () //画边框 { if (this.BorderPoint.length <= 0) return; this.Canvas.font = this.TitleFont; this.Canvas.strokeStyle = this.Color; const aryBorder = [1, 0.8, 0.6, 0.4, 0.2]; for (let j in aryBorder) { var rate = aryBorder[j]; var isFirstDraw = true; for (let i in this.BorderPoint) { var item = this.BorderPoint[i]; item.X = this.CenterPoint.X + item.Radius * Math.cos(item.Angle * Math.PI / 180) * rate; item.Y = this.CenterPoint.Y + item.Radius * Math.sin(item.Angle * Math.PI / 180) * rate; if (isFirstDraw) { this.Canvas.beginPath(); this.Canvas.moveTo(item.X, item.Y); isFirstDraw = false; } else { this.Canvas.lineTo(item.X, item.Y); } if (j == 0) this.DrawText(item); } this.Canvas.closePath(); this.Canvas.stroke(); this.Canvas.fillStyle = this.BGColor[j % 2 == 0 ? 0 : 1]; this.Canvas.fill(); } this.Canvas.beginPath(); for (let i in this.BorderPoint) { var item = this.BorderPoint[i]; item.X = this.CenterPoint.X + item.Radius * Math.cos(item.Angle * Math.PI / 180); item.Y = this.CenterPoint.Y + item.Radius * Math.sin(item.Angle * Math.PI / 180); this.Canvas.moveTo(this.CenterPoint.X, this.CenterPoint.Y); this.Canvas.lineTo(item.X, item.Y); } this.Canvas.stroke(); } this.DrawArea = function () { if (!this.DataPoint || this.DataPoint.length <= 0) return; this.Canvas.fillStyle = this.AreaColor; this.Canvas.strokeStyle = this.AreaLineColor; this.Canvas.beginPath(); var isFirstDraw = true; for (let i in this.DataPoint) { var item = this.DataPoint[i]; if (isFirstDraw) { this.Canvas.beginPath(); this.Canvas.moveTo(item.X, item.Y); isFirstDraw = false; } else { this.Canvas.lineTo(item.X, item.Y); } } this.Canvas.closePath(); this.Canvas.fill(); this.Canvas.stroke(); } this.DrawText = function (item) { if (!item.Text) return; //console.log(item.Text, item.Angle); this.Canvas.fillStyle = this.TitleColor; var xText = item.X, yText = item.Y; //显示每个角度的位置 if (item.Angle > 0 && item.Angle < 45) { this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'middle'; xText += 2; } else if (item.Angle >= 0 && item.Angle < 90) { this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'top'; xText += 2; } else if (item.Angle >= 90 && item.Angle < 135) { this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'top'; xText -= 2; } else if (item.Angle >= 135 && item.Angle < 180) { this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'top'; xText -= 2; } else if (item.Angle >= 180 && item.Angle < 225) { this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'middle'; xText -= 2; } else if (item.Angle >= 225 && item.Angle <= 270) { this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'bottom'; } else if (item.Angle > 270 && item.Angle < 315) { this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; xText += 2; } else { this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'middle'; xText += 2; } this.Canvas.fillText(item.Text, xText, yText); } this.Draw = function () { this.BorderPoint = []; this.DataPoint = []; this.InternalBorderPoint = []; this.CenterPoint = {}; if (!this.Data || !this.Data.Data || !(this.Data.Data.length > 0)) this.CalculatePoints(null); else this.CalculatePoints(this.Data.Data); this.DrawBorder(); this.DrawArea(); } this.CalculatePoints = function (data) { let left = this.ChartBorder.GetLeft(); let right = this.ChartBorder.GetRight(); let top = this.ChartBorder.GetTop(); let bottom = this.ChartBorder.GetBottom(); let width = this.ChartBorder.GetWidth(); let height = this.ChartBorder.GetHeight(); let ptCenter = { X: left + width / 2, Y: top + height / 2 }; //中心点 let radius = Math.min(width / 2, height / 2) - 2 //半径 let count = Math.max(5, data ? data.length : 0); let averageAngle = 360 / count; for (let i = 0; i < count; ++i) { let ptBorder = { Index: i, Radius: radius, Angle: i * averageAngle + this.StartAngle }; let angle = ptBorder.Angle; if (data && i < data.length) { var item = data[i]; let ptData = { Index: i, Text: item.Text }; ptBorder.Text = item.Name; if (!item.Value) { ptData.X = ptCenter.X; ptData.Y = ptCenter.Y; } else { var value = item.Value; if (value >= 1) value = 1; var dataRadius = radius * value; ptData.X = ptCenter.X + dataRadius * Math.cos(angle * Math.PI / 180); ptData.Y = ptCenter.Y + dataRadius * Math.sin(angle * Math.PI / 180); } this.DataPoint.push(ptData); } this.BorderPoint.push(ptBorder); } this.CenterPoint = ptCenter; } } /////////////////////////////////////////////////////////////////////////////////////////////////// //十字光标 function ChartCorssCursor() { this.Frame; this.Canvas; //画布 this.HPenColor = g_JSChartResource.CorssCursorHPenColor; //水平线颜色 this.HPenType = 0; //水平线样式 0=虚线 1=实线 this.VPenColor = g_JSChartResource.CorssCursorVPenColor; //垂直线颜色 this.VPenType = 0; //垂直线颜色 0=虚线 1=实线 2=K线宽度 this.Font = g_JSChartResource.CorssCursorTextFont; //字体 this.TextColor = g_JSChartResource.CorssCursorTextColor; //文本颜色 this.TextBGColor = g_JSChartResource.CorssCursorBGColor; //文本背景色 this.TextHeight = 15; //文本字体高度 this.LastPoint; this.CursorIndex; //当前数据的位置 this.PointX; this.PointY; this.StringFormatX; this.StringFormatY; this.IsShow = true; //是否显示 this.ShowTextMode = { Left: 1, Right: 1, Bottom: 1 }; //0=不显示 1=显示在框架外 2=显示在框架内 this.TextFormat= { Right:0 }; //0=默认 1=价格显示(分时图才有用) this.IsShowCorss = true; //是否显示十字光标 this.IsShowClose = false; //Y轴始终显示收盘价 this.IsOnlyDrawMinute=false; //是否只能画在走势图价格线上 this.IsFixXLastTime=false; //是否修正X轴,超出当前时间的,X轴调整到当前最后的时间. this.RightMargin={ Left:2, Right:2, Top:2, Bottom:1 }; JSChartResource.CopyMargin(this.RightMargin, g_JSChartResource.CorssCursor.RightMargin); //内部使用 this.Close = null; //收盘价格 this.GetCloseYPoint = function (index) { this.Close = null; if (!this.StringFormatX.Data) return null; var data = this.StringFormatX.Data; if (!data.Data || data.Data.length <= 0) return null; var dataIndex = data.DataOffset + index; if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1; if (dataIndex < 0) return null; var klineData = data.Data[dataIndex]; if (!klineData) return null; this.Close = klineData.Close; var yPoint = this.Frame.GetYFromData(this.Close); return yPoint; } this.GetMinuteCloseYPoint=function(index) { if (!IFrameSplitOperator.IsNumber(index)) return null; index=parseInt(index); if (!this.StringFormatX.Data) return null; var data = this.StringFormatX.Data; if (!data.Data || data.Data.length <= 0) return null; var dataIndex = data.DataOffset + index; if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1; if (dataIndex < 0) return null; var close = data.Data[dataIndex]; if (!IFrameSplitOperator.IsNumber(index)) return null; this.Close=close; var yPoint = this.Frame.GetYFromData(this.Close); return yPoint; } this.FixMinuteLastTimeXPoint=function(index) { if (!IFrameSplitOperator.IsNumber(index)) return null; index=parseInt(index); if (!this.StringFormatX.Data) return null; var data = this.StringFormatX.Data; if (!data.Data || data.Data.length <= 0) return null; var dataIndex = data.DataOffset + index; if (dataIndex 2) this.Canvas.lineWidth = barWidth; } this.Canvas.beginPath(); if (this.Frame.SubFrame.length > 0) { for (var i in this.Frame.SubFrame) { var frame = this.Frame.SubFrame[i].Frame; top = frame.ChartBorder.GetTopTitle(); bottom = frame.ChartBorder.GetBottom(); this.Canvas.moveTo(ToFixedPoint(x), top); this.Canvas.lineTo(ToFixedPoint(x), bottom); } } else { this.Canvas.moveTo(ToFixedPoint(x), top); this.Canvas.lineTo(ToFixedPoint(x), bottom); } this.Canvas.stroke(); this.Canvas.restore(); } var xValue = this.Frame.GetXData(x); var yValueExtend = {}; var yValue = this.Frame.GetYData(y, yValueExtend); this.StringFormatY.RValue = yValueExtend.RightYValue; //右侧子坐标 if (this.IsShowClose && this.Close != null) yValue = this.Close; this.StringFormatX.Value = this.CursorIndex; this.StringFormatY.Value = yValue; this.StringFormatY.RValue=yValueExtend.RightYValue; //右侧子坐标 this.StringFormatY.Point={X:x, Y:y}; this.StringFormatY.FrameID = yValueExtend.FrameID; if (((this.ShowTextMode.Left == 1 && this.Frame.ChartBorder.Left >= 30) || this.ShowTextMode.Left == 2 || (this.ShowTextMode.Right == 1 && this.Frame.ChartBorder.Right >= 30) || this.ShowTextMode.Right == 2) && this.StringFormatY.Operator()) { var text = this.StringFormatY.Text; this.Canvas.font = this.Font; var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素 if (this.Frame.ChartBorder.Left >= 30 && this.ShowTextMode.Left == 1) { this.Canvas.fillStyle = this.TextBGColor; if (left < textWidth) //左边空白的地方太少了画布下 { this.Canvas.fillRect(2, y - this.TextHeight / 2, textWidth, this.TextHeight); this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, 2 + 2, y, textWidth); } else { this.Canvas.fillRect(left - 2, y - this.TextHeight / 2, -textWidth, this.TextHeight); this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, left - 4, y, textWidth); } } else if (this.ShowTextMode.Left == 2) { this.Canvas.fillStyle = this.TextBGColor; this.Canvas.fillRect(left, y - this.TextHeight / 2, textWidth, this.TextHeight); this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, left + 2, y, textWidth); } var complexText= { ShowType:0, //0=单行(默认) 1=多行 Font:this.Font, Color:this.TextColor, Text:[ { Text:text, Margin:this.RightMargin } ], }; var yTop=y-this.TextHeight/2; var textSize={ Width:0, Height:0, Text:[] }; if (this.StringFormatY.PercentageText) { if (this.TextFormat.Right==0) { text=this.StringFormatY.PercentageText+'%'; complexText.Text[0].Text=text; } } if (this.StringFormatY.RText) { text = this.StringFormatY.RText; complexText.Text[0].Text=text; } if (this.StringFormatY.RComplexText && IFrameSplitOperator.IsNonEmptyArray(this.StringFormatY.RComplexText.Text)) { complexText=this.StringFormatY.RComplexText; if (!complexText.Font) complexText.Font=this.Font; if (!complexText.Font) complexText.Color=this.TextColor; } this.CalculateComplexTextSize(complexText, textSize); if (this.Frame.ChartBorder.Right >= 30 && this.ShowTextMode.Right == 1) { if (rightWidth > textSize.Width) //右边不够就不画 { var itemLeft=right+2; this.DrawTextBGRect(itemLeft, yTop, textSize.Width, textSize.Height); this.DrawComplexTextV2(itemLeft,yTop,complexText,textSize); } else { var itemLeft=chartRight-2-textSize.Width; this.DrawTextBGRect(itemLeft, yTop, textSize.Width, textSize.Height); this.DrawComplexTextV2(itemLeft,yTop,complexText,textSize); } } else if (this.ShowTextMode.Right == 2) { var showLeft = right - textSize.Width; this.DrawTextBGRect(showLeft,yTop,textSize.Width,textSize.Height); this.DrawComplexTextV2(showLeft,yTop,complexText,textSize); } } //Bottom==8 自定义X轴文字位置 if ((this.ShowTextMode.Bottom == 1 || this.ShowTextMode.Bottom==8) && this.StringFormatX.Operator()) { var text = this.StringFormatX.Text; this.Canvas.font = this.Font; this.Canvas.fillStyle = this.TextBGColor; var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素 var bShowText=true; var yText=bottom + 2; //文字顶部坐标 if (this.ShowTextMode.Bottom==8) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_CORSSCURSOR_POSITION); if (event && event.Callback) { var yCenter=yText+this.TextHeight/2; var yTop=yText; var sendData={ YCenter:yCenter, YTop:yTop, Height:this.TextHeight, IsShowText:bShowText }; event.Callback(event, sendData, this); yCenter=sendData.YCenter; yText=sendData.YTop; bShowText=sendData.IsShowText; } } if (bShowText) { if (x - textWidth / 2 < 3) //左边位置不够了, 顶着左边画 { this.Canvas.fillRect(x - 1, yText, textWidth, this.TextHeight); this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "top"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, x + 1, yText, textWidth); } else if ((right - left) - x < textWidth) { //右边位置不够用,顶着右边画 this.Canvas.fillRect(x - textWidth, yText, textWidth, this.TextHeight); this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "top"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, x - 1, yText, textWidth); } else { this.Canvas.fillRect(x - textWidth / 2, yText, textWidth, this.TextHeight); this.Canvas.textAlign = "center"; this.Canvas.textBaseline = "top"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, x, yText, textWidth); } } } } this.DrawTextBGRect=function(x,y, height, width) { this.Canvas.fillStyle=this.TextBGColor; this.Canvas.fillRect(ToFixedPoint(x),ToFixedPoint(y),ToFixedRect(height),ToFixedRect(width)); //this.Canvas.fillRect(x,y,height,width); } this.CalculateComplexTextSize=function(complexText, size) { if (!complexText || !IFrameSplitOperator.IsNonEmptyArray(complexText.Text)) return; var showType=0; if (complexText.ShowType==1) showType=complexText.ShowType; if (showType==1) //多行 { var textWidth=0, textHeight=0; for(var i=0; i 2) this.Canvas.lineWidth = barWidth; } this.Canvas.beginPath(); //画横线 if (this.Frame.SubFrame.length > 0) { for (var i in this.Frame.SubFrame) { var frame = this.Frame.SubFrame[i].Frame; this.Canvas.moveTo(frame.ChartBorder.GetLeft(), ToFixedPoint(y)); this.Canvas.lineTo(frame.ChartBorder.GetRightTitle(), ToFixedPoint(y)); } } else { this.Canvas.moveTo(left, ToFixedPoint(y)); this.Canvas.lineTo(right, ToFixedPoint(y)); } this.Canvas.stroke(); this.Canvas.restore(); } var xValue = this.Frame.GetXData(y); var yValueExtend = {}; var yValue = this.Frame.GetYData(x, yValueExtend); this.StringFormatX.Value = xValue; this.StringFormatY.Value = yValue; this.StringFormatY.RValue=yValueExtend.RightYValue; //右侧子坐标 this.StringFormatY.Point={X:x, Y:y}; this.StringFormatY.FrameID = yValueExtend.FrameID; if (((this.ShowTextMode.Left == 1 && this.Frame.ChartBorder.Top >= 30) || this.ShowTextMode.Left == 2 || (this.ShowTextMode.Right == 1 && this.Frame.ChartBorder.Bottom >= 30) || this.ShowTextMode.Right == 2) && this.StringFormatY.Operator()) { var text = this.StringFormatY.Text; this.Canvas.font = this.Font; var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素 if (this.Frame.ChartBorder.Top >= 30 && this.ShowTextMode.Left == 1) { var xText = x, yText = top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle = this.TextBGColor; if (top >= textWidth) { this.Canvas.fillRect(-textWidth, -(this.TextHeight / 2), textWidth, this.TextHeight); this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, -2, 0, textWidth); } else { this.Canvas.fillRect((textWidth - top), -(this.TextHeight / 2), -textWidth, this.TextHeight); this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, (textWidth - top) - 2, 0, textWidth); } this.Canvas.restore(); } else if (this.ShowTextMode.Left == 2) { var xText = x; var yText = top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle = this.TextBGColor; this.Canvas.fillRect(0, -(this.TextHeight / 2), textWidth, this.TextHeight); this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, 2, 0, textWidth); this.Canvas.restore(); } if (this.StringFormatY.RText) { text=this.StringFormatY.RText; var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 } if (this.Frame.ChartBorder.Bottom >= 30 && this.ShowTextMode.Right == 1) { var xText = x, yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle = this.TextBGColor; if (bottomWidth > textWidth) { this.Canvas.fillRect(0, -(this.TextHeight / 2), textWidth, this.TextHeight); this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, 2, 0, textWidth); } else { this.Canvas.fillRect((bottomWidth - textWidth), -(this.TextHeight / 2), textWidth, this.TextHeight); this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, (bottomWidth - textWidth) + 2, 0, textWidth); } this.Canvas.restore(); } else if (this.ShowTextMode.Right == 2) { var xText = x; var yText = bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle = this.TextBGColor; this.Canvas.fillRect(0, -(this.TextHeight / 2), -textWidth, this.TextHeight); this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "middle"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, -2, 0, textWidth); this.Canvas.restore(); } } if ((this.ShowTextMode.Bottom === 1 ||this.ShowTextMode.Bottom==8) && this.StringFormatX.Operator()) { var text = this.StringFormatX.Text; this.Canvas.font = this.Font; this.Canvas.fillStyle = this.TextBGColor; var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素 var bShowText=true; var yText = y; var xText=left; if (this.ShowTextMode.Bottom==8) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_CORSSCURSOR_POSITION); if (event && event.Callback) { var sendData={ XText:xText, Height:this.TextHeight, IsShowText:bShowText }; event.Callback(event, sendData, this); xText=sendData.XText; bShowText=sendData.IsShowText; } } if (bShowText) { if (y - textWidth / 2 < 3) //左边位置不够了, 顶着左边画 { this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillRect(0, 0, textWidth, this.TextHeight); this.Canvas.textAlign = "center"; this.Canvas.textBaseline = "top"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, 0, 0, textWidth); this.Canvas.restore(); } else { this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillRect(-(textWidth / 2), 0, textWidth, this.TextHeight); this.Canvas.textAlign = "center"; this.Canvas.textBaseline = "top"; this.Canvas.fillStyle = this.TextColor; this.Canvas.fillText(text, 0, 0, textWidth); this.Canvas.restore(); } } } } } //分钟线 function ChartMinutePriceLine() { this.newMethod = ChartLine; //派生 this.newMethod(); delete this.newMethod; this.YClose; this.IsDrawArea = true; //是否画价格面积图 this.AreaColor = 'rgba(0,191,255,0.1)'; this.Draw = function () { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.IsShow) return; if (!this.Data) return; var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen === true) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var minuteCount = this.ChartFrame.MinuteCount; var bottom = this.ChartBorder.GetBottom(); var left = this.ChartBorder.GetLeft(); var bFirstPoint = true; var ptFirst = {}; //第1个点 var drawCount = 0; var pointCount=0; this.Canvas.save(); this.ClipClient(isHScreen); //裁剪区域 防止线段毛刺超出图形 if (IFrameSplitOperator.IsPlusNumber(this.LineWidth>0)) this.Canvas.lineWidth=this.LineWidth; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; ++pointCount; if (value == null) continue; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (bFirstPoint) { this.Canvas.strokeStyle = this.Color; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(y, x); else this.Canvas.moveTo(x, y); bFirstPoint = false; ptFirst = { X: x, Y: y }; } else { if (isHScreen) this.Canvas.lineTo(y, x); else this.Canvas.lineTo(x, y); } ++drawCount; if (pointCount >= minuteCount) //上一天的数据和这天地数据线段要断开 { bFirstPoint = true; this.Canvas.stroke(); if (this.IsDrawArea) //画面积 { if (isHScreen) { this.Canvas.lineTo(left, x); this.Canvas.lineTo(left, ptFirst.X); this.SetFillStyle(this.AreaColor, this.ChartBorder.GetRight(), bottom, this.ChartBorder.GetLeftEx(), bottom); } else { this.Canvas.lineTo(x, bottom); this.Canvas.lineTo(ptFirst.X, bottom); this.SetFillStyle(this.AreaColor, left, this.ChartBorder.GetTopEx(), left, bottom); } this.Canvas.fill(); } drawCount = 0; pointCount=0; } } if (drawCount > 0) { this.Canvas.stroke(); if (this.IsDrawArea) //画面积 { if (isHScreen) { this.Canvas.lineTo(left, x); this.Canvas.lineTo(left, ptFirst.X); this.SetFillStyle(this.AreaColor, this.ChartBorder.GetRight(), bottom, this.ChartBorder.GetLeftEx(), bottom); } else { this.Canvas.lineTo(x, bottom); this.Canvas.lineTo(ptFirst.X, bottom); this.SetFillStyle(this.AreaColor, left, this.ChartBorder.GetTopEx(), left, bottom); } this.Canvas.fill(); } } this.Canvas.restore(); } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; if (this.YClose == null) return range; range.Min = this.YClose; range.Max = this.YClose; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (!value) continue; if (range.Max == null) range.Max = value; if (range.Min == null) range.Min = value; if (range.Max < value) range.Max = value; if (range.Min > value) range.Min = value; } if (range.Max == this.YClose && range.Min == this.YClose) { range.Max = this.YClose + this.YClose * 0.1; range.Min = this.YClose - this.YClose * 0.1; return range; } var distance = Math.max(Math.abs(this.YClose - range.Max), Math.abs(this.YClose - range.Min)); range.Max = this.YClose + distance; range.Min = this.YClose - distance; return range; } } //////////////////////////////////////////////////////////////////////////////// //深度图十字光标 function DepthChartCorssCursor() { this.Frame; this.Canvas; //画布 this.Data; this.Symbol; this.HQChart; this.HPenType=0; //水平线样式 0=虚线 1=实线 this.VPenType=0; //垂直线颜色 0=虚线 1=实线 this.LineDash=g_JSChartResource.DepthCorss.LineDash; this.AskColor=g_JSChartResource.DepthCorss.AskColor.Line; //卖 this.BidColor=g_JSChartResource.DepthCorss.BidColor.Line; //买 this.LineWidth=g_JSChartResource.DepthCorss.LineWidth; this.IsShowTooltip=true; this.Tooltip= { LineHeight:g_JSChartResource.DepthCorss.Tooltip.LineHeight, Border: { Top:g_JSChartResource.DepthCorss.Tooltip.Border.Top, Left:g_JSChartResource.DepthCorss.Tooltip.Border.Left, Right:g_JSChartResource.DepthCorss.Tooltip.Border.Right, Bottom:g_JSChartResource.DepthCorss.Tooltip.Border.Bottom, ItemSpace: g_JSChartResource.DepthCorss.Tooltip.Border.ItemSpace }, Font:g_JSChartResource.DepthCorss.Tooltip.Font, TextColor:g_JSChartResource.DepthCorss.Tooltip.TextColor, BGColor:g_JSChartResource.DepthCorss.Tooltip.BGColor }; // Width: Height: this.Font=g_JSChartResource.CorssCursorTextFont; //字体 this.TextColor=g_JSChartResource.CorssCursorTextColor; //文本颜色 this.TextBGColor=g_JSChartResource.CorssCursorBGColor; //文本背景色 this.TextHeight=20; //文本字体高度 this.LastPoint; this.PointX; this.PointY; this.StringFormatX; this.StringFormatY; this.IsShowCorss=true; //是否显示十字光标 this.IsShow=true; this.GetVol=function(price, isAsk) { if (!this.Data) return null; var aryData=isAsk? this.Data.Asks:this.Data.Bids; if (!aryData || !Array.isArray(aryData) || aryData.length<=0) return null; for(var i in aryData) { var item=aryData[i]; if (item.Price==price) return item.Vol; } return null; } this.Draw=function() { this.Status=0; if (!this.LastPoint) return; if (!this.Data) return; if (!this.IsShow) return; var x=this.LastPoint.X; var y=this.LastPoint.Y; var isInClient=false; var rtClient = new Rect(this.Frame.ChartBorder.GetLeft(), this.Frame.ChartBorder.GetTop(), this.Frame.ChartBorder.GetWidth(), this.Frame.ChartBorder.GetHeight()); isInClient = rtClient.IsPointIn(x, y); this.PointY=null; this.PointY==null; if (!isInClient) return; if (this.Frame.IsHScreen===true) { return; } var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); var top=this.Frame.ChartBorder.GetTopTitle(); var bottom=this.Frame.ChartBorder.GetBottom(); var rightWidth=this.Frame.ChartBorder.Right; var chartRight=this.Frame.ChartBorder.GetChartWidth(); var xValue=this.Frame.GetXData(x); var xInfo=this.Frame.GetXFromPrice(xValue); //调整价格到有数据的点上 if (!xInfo) return; var yVol=this.GetVol(xInfo.Price, xInfo.IsAsk); y=this.Frame.GetYFromData(yVol); //调整Y轴, 让它在线段上 xInfo.Vol=yVol; xInfo.Y=y; this.PointY=[[left,y],[right,y]]; this.PointX=[[x,top],[x,bottom]]; if (this.IsShowCorss) { if (xInfo.IsAsk) this.Canvas.strokeStyle=this.AskColor; else this.Canvas.strokeStyle=this.BidColor; this.Canvas.save(); this.Canvas.lineWidth=this.LineWidth; var lineWidth=this.Canvas.lineWidth; if (this.HPenType==1 || this.HPenType==0) //0=实线 1=虚线 { if (this.HPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线 var yFix=ToFixedPoint(y); this.Canvas.beginPath(); this.Canvas.moveTo(left,yFix); this.Canvas.lineTo(right,yFix); this.Canvas.stroke(); if (this.HPenType==0) this.Canvas.setLineDash([]); } if (this.VPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线 var xFix=ToFixedPoint(xInfo.X); this.Canvas.beginPath(); this.Canvas.moveTo(xFix,top); this.Canvas.lineTo(xFix,bottom); this.Canvas.stroke(); if (this.VPenType==0) this.Canvas.setLineDash([]); this.Canvas.restore(); } if (this.HQChart) { var event=this.HQChart.GetEvent(JSCHART_EVENT_ID.ON_DRAW_DEPTH_TOOLTIP); if (event) { event.Callback(event,xInfo,this); } } if (this.IsShowTooltip) { var aryText=this.GetFormatTooltip(xInfo); this.DrawTooltip(aryText, xInfo); } } //[{Title:, TitleColor:, Text:, Color:}] this.GetFormatTooltip=function(drawData) { var aryText=[]; var floatPrecision=2; if (this.Symbol) floatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol); //价格小数位数 var item= { Title:g_JSChartLocalization.GetText('Depth-Price',this.HQChart.LanguageID), TitleColor:this.Tooltip.TextColor, Text:drawData.Price.toFixed(floatPrecision), Color:this.Tooltip.TextColor }; aryText.push(item); var item= { Title:g_JSChartLocalization.GetText('Depth-Sum',this.HQChart.LanguageID), TitleColor:this.Tooltip.TextColor, Text:drawData.Vol.toFixed(4), Color:this.Tooltip.TextColor }; aryText.push(item); return aryText; } this.DrawTooltip=function(aryText,data) { if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return; this.Canvas.font=this.Tooltip.Font; var maxWidth=0, lineCount=0, itemCount=0; for(var i=0;i=chartRight) left=data.X-this.Tooltip.Width; if (topxRange.Max) break; } var x=this.ChartFrame.GetXFromIndex(item.Price); var y=this.ChartFrame.GetYFromData(item.Vol); aryPoint.push({X:x,Y:y}); } if (aryPoint.length<=1) return; var left=this.ChartBorder.GetLeft(); var bottom=this.ChartBorder.GetBottom(); var right=this.ChartBorder.GetRight(); this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, bottom); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.lineTo(item.X,item.Y); } this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y); this.Canvas.lineTo(isLeft?left:right,bottom); this.Canvas.lineTo(aryPoint[0].X,bottom); this.Canvas.closePath(); this.Canvas.fillStyle = colorArea; this.Canvas.fill(); this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, bottom); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.lineTo(item.X,item.Y); } this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y); this.Canvas.strokeStyle=colorLine; this.Canvas.stroke(); } this.GetMaxMin=function() { var range={ Min:null, Max:null, XMin:null, XMax:null }; var xRange=this.ChartFrame.VerticalRange; for(var i in this.Data.Asks) { var item=this.Data.Asks[i]; if (item.Price>xRange.Max) break; if (range.XMin==null || range.XMin>item.Price) range.XMin=item.Price; if (range.XMax==null || range.XMaxitem.Vol) range.Min=item.Vol; if (range.Max==null || range.Maxitem.Price) range.XMin=item.Price; if (range.XMax==null || range.XMaxitem.Vol) range.Min=item.Vol; if (range.Max==null || range.Max