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

3180 lines
111 KiB

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