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
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,
|
|
};
|