hqchart
Version:
HQChart - H5, 微信小程序 沪深/港股/数字货币/期货/美股 K线图(kline),走势图,缩放,拖拽,十字光标,画图工具,截图,筹码图. 分析家语法,通达信语法,(麦语法),第3方数据对接
1,209 lines (976 loc) • 39.4 kB
JavaScript
/*
Copyright (c) 2018 jones
http://www.apache.org/licenses/LICENSE-2.0
开源项目 https://github.com/jones2000/HQChart
jones_2000@163.com
底部状态栏 (H5版本)
不提供内置测试数据
*/
function JSStatusBarChart(divElement)
{
this.DivElement=divElement;
this.JSChartContainer; //表格控件
this.ResizeListener; //大小变动监听
//h5 canvas
this.CanvasElement=document.createElement("canvas");
this.CanvasElement.className='jsstatusbar-drawing';
this.CanvasElement.id=Guid();
this.CanvasElement.setAttribute("tabindex",0);
if (this.CanvasElement.style) this.CanvasElement.style.outline='none';
if(divElement.hasChildNodes())
{
JSConsole.Chart.Log("[JSStatusBarChart::JSStatusBarChart] divElement hasChildNodes", divElement.childNodes);
}
divElement.appendChild(this.CanvasElement);
this.OnSize=function()
{
//画布大小通过div获取 如果有style里的大小 使用style里的
var height=this.DivElement.offsetHeight;
var width=this.DivElement.offsetWidth;
if (this.DivElement.style.height && this.DivElement.style.width)
{
if (this.DivElement.style.height.includes("px"))
height=parseInt(this.DivElement.style.height.replace("px",""));
if (this.DivElement.style.width.includes("px"))
width=parseInt(this.DivElement.style.width.replace("px",""));
}
this.CanvasElement.height=height;
this.CanvasElement.width=width;
this.CanvasElement.style.width=this.CanvasElement.width+'px';
this.CanvasElement.style.height=this.CanvasElement.height+'px';
var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
this.CanvasElement.height*=pixelTatio;
this.CanvasElement.width*=pixelTatio;
JSConsole.Chart.Log(`[JSStatusBarChart::OnSize] devicePixelRatio=${window.devicePixelRatio}, height=${this.CanvasElement.height}, width=${this.CanvasElement.width}`);
if (this.JSChartContainer && this.JSChartContainer.OnSize)
{
this.JSChartContainer.OnSize();
}
}
this.SetOption=function(option)
{
var chart=this.CreateJSStatusBarChartContainer(option);
if (!chart) return false;
if (option.OnCreatedCallback) option.OnCreatedCallback(chart);
this.JSChartContainer=chart;
this.DivElement.JSChart=this; //div中保存一份
if (option.EnableResize==true) this.CreateResizeListener();
if (option.MinuteChartTooltip && option.MinuteChartTooltip.Enable) chart.InitalMinuteChartTooltip(option.MinuteChartTooltip);
chart.Draw();
chart.RequestData();
}
this.CreateResizeListener=function()
{
this.ResizeListener = new ResizeObserver((entries)=>{ this.OnDivResize(entries); });
this.ResizeListener.observe(this.DivElement);
}
this.OnDivResize=function(entries)
{
JSConsole.Chart.Log("[JSStatusBarChart::OnDivResize] entries=", entries);
this.OnSize();
}
this.CreateJSStatusBarChartContainer=function(option)
{
var chart=new JSStatusBarChartContainer(this.CanvasElement);
chart.Create(option);
this.SetChartBorder(chart, option);
if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) chart.SetColumn(option.Column);
if (option.RightToolbar) chart.SetRightToolbar(option.RightToolbar);
//是否自动更新
if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter;
if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate;
if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency;
//注册事件
if (option.EventCallback)
{
for(var i=0;i<option.EventCallback.length;++i)
{
var item=option.EventCallback[i];
chart.AddEventCallback(item);
}
}
return chart;
}
this.SetChartBorder=function(chart, option)
{
if (!option.Border) return;
var item=option.Border;
if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left;
if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right;
if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top;
if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom;
var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
chart.Frame.ChartBorder.Left*=pixelTatio;
chart.Frame.ChartBorder.Right*=pixelTatio;
chart.Frame.ChartBorder.Top*=pixelTatio;
chart.Frame.ChartBorder.Bottom*=pixelTatio;
}
//事件回调
this.AddEventCallback=function(obj)
{
if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function')
{
JSConsole.Chart.Log('[JSStatusBarChart:AddEventCallback] obj=', obj);
this.JSChartContainer.AddEventCallback(obj);
}
}
//重新加载配置
this.ReloadResource=function(option)
{
if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function')
{
JSConsole.Chart.Log('[JSStatusBarChart:ReloadResource] ');
this.JSChartContainer.ReloadResource(option);
}
}
this.ChartDestroy=function()
{
if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestroy) == 'function')
{
this.JSChartContainer.ChartDestroy();
}
}
this.Draw=function()
{
if(this.JSChartContainer && typeof(this.JSChartContainer.Draw)=='function')
{
JSConsole.Chart.Log('[JSStatusBarChart:Draw] ');
this.JSChartContainer.Draw();
}
}
}
JSStatusBarChart.Init=function(divElement)
{
var jsChartControl=new JSStatusBarChart(divElement);
jsChartControl.OnSize();
return jsChartControl;
}
//自定义风格
JSStatusBarChart.SetStyle=function(option)
{
if (option) g_JSChartResource.SetStyle(option);
}
//获取颜色配置 (JSStatusBarChart.Init()之前)
JSStatusBarChart.GetResource=function()
{
return g_JSChartResource;
}
JSStatusBarChart.GetfloatPrecision=function(symbol)
{
return GetfloatPrecision(symbol);
}
function JSStatusBarChartContainer(uielement)
{
this.ClassName='JSStatusBarChartContainer';
this.Frame; //框架画法
this.ChartPaint=[]; //图形画法
this.Canvas=uielement.getContext("2d"); //画布
this.NetworkFilter; //数据回调接口
this.Data=
{
MapSymbol:new Map(), //key=symbol, { Value:, Text:, } 股票数据
};
//事件回调
this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{ Callback:回调,}
this.AutoUpdateTimer=null;
this.AutoUpdateFrequency=15000; //15秒更新一次数据
this.ToolbarTimer=null;
this.TooltipMinuteChart; //分时图
this.UIElement=uielement;
this.IsDestroy=false; //是否已经销毁了
this.ChartDestroy=function() //销毁
{
this.IsDestroy=true;
this.StopAutoUpdate();
if (this.ToolbarTimer)
{
clearInterval(this.ToolbarTimer);
this.ToolbarTimer=null;
}
this.DestroyMinuteChartTooltip();
}
this.InitalMinuteChartTooltip=function(option)
{
if (this.TooltipMinuteChart) return;
this.TooltipMinuteChart=new JSTooltipMinuteChart();
this.TooltipMinuteChart.Inital(this, option);
this.TooltipMinuteChart.Create();
}
this.DestroyMinuteChartTooltip=function()
{
if (!this.TooltipMinuteChart) return;
this.TooltipMinuteChart.Destroy();
this.TooltipMinuteChart=null;
}
//设置事件回调
//{event:事件id, callback:回调函数}
this.AddEventCallback=function(object)
{
if (!object || !object.event || !object.callback) return;
var data={Callback:object.callback, Source:object};
this.mapEvent.set(object.event,data);
}
this.RemoveEventCallback=function(eventid)
{
if (!this.mapEvent.has(eventid)) return;
this.mapEvent.delete(eventid);
}
this.GetEventCallback=function(id) //获取事件回调
{
if (!this.mapEvent.has(id)) return null;
var item=this.mapEvent.get(id);
return item;
}
this.ClearData=function()
{
this.Data.MapSymbol=new Map();
}
this.RequestData=function(option)
{
this.CancelAutoUpdate();
this.ClearData();
if (option)
{
if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) this.SetColumn(option.Column);
}
this.Draw();
this.RequestStockData();
if (this.IsAutoUpdate)
{
var frequency=this.AutoUpdateFrequency;
setInterval(()=>
{
var marketStatus=MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol);
if (marketStatus==0 || marketStatus==3) //闭市,盘后
return;
this.RequestStockData();
}, frequency)
}
}
this.CancelAutoUpdate=function() //关闭停止更新
{
if (this.AutoUpdateTimer)
{
clearInterval(this.AutoUpdateTimer);
this.AutoUpdateTimer = null;
}
}
this.StopAutoUpdate=function()
{
this.CancelAutoUpdate();
if (!this.IsAutoUpdate) return;
this.IsAutoUpdate=false;
}
this.RequestStockData=function()
{
if (!this.NetworkFilter) return;
var chart=this.ChartPaint[0];
if (!chart) return;
if (!IFrameSplitOperator.IsNonEmptyArray(chart.Column)) return;
var arySymbol=[];
for(var i=0;i<chart.Column.length;++i)
{
var item=chart.Column[i];
var newItem={ Symbol:item.Symbol, Fields:[] };
arySymbol.push(newItem);
}
var obj=
{
Name:'JSStatusBarChartContainer::RequestStockData', //类名::函数名
Explain:'工具栏股票数据',
Request: { Data:{ stocks:arySymbol } },
Self:this,
PreventDefault:false
};
this.NetworkFilter(obj, (data)=>
{
this.RecvStockData(data);
});
if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求
}
this.RecvStockData=function(recv)
{
if (!recv) return;
if (!IFrameSplitOperator.IsNonEmptyArray(recv.data)) return;
for(var i=0;i<recv.data.length;++i)
{
var item=recv.data[i];
if (!item.Symbol) continue;
var stockItem=null;
if (this.Data.MapSymbol.has(item.Symbol))
{
stockItem=this.Data.MapSymbol.get(item.Symbol);
}
else
{
stockItem={ Symbol:item.Symbol, MapData:new Map() };
stockItem.YClose=item.YClose;
if (IFrameSplitOperator.IsNumber(item.FYClose)) stockItem.YClose=item.FYClose;
this.Data.MapSymbol.set(item.Symbol,stockItem);
}
for(var j=0;j<item.Data.length;++j)
{
var itemData=item.Data[j];
stockItem.MapData.set(itemData.Key,itemData.Value);
}
}
if (!this.ToolbarTimer) this.Draw();
}
//创建
this.Create=function(option)
{
this.UIElement.JSChartContainer=this;
//创建框架
this.Frame=new JSStatusBarFrame();
this.Frame.ChartBorder=new ChartBorder();
this.Frame.ChartBorder.UIElement=this.UIElement;
this.Frame.ChartBorder.Top=30;
this.Frame.ChartBorder.Left=5;
this.Frame.ChartBorder.Bottom=20;
this.Frame.Canvas=this.Canvas;
//创建表格
var chart=new ChartStatusBarStockData();
chart.Frame=this.Frame;
chart.ChartBorder=this.Frame.ChartBorder;
chart.Canvas=this.Canvas;
chart.UIElement=this.UIElement;
chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); }
chart.Data=this.Data;
chart.BorderData=this.BorderData;
chart.GlobalOption=this.GlobalOption;
chart.FixedRowData=this.FixedRowData;
chart.SortInfo=this.SortInfo;
this.ChartPaint[0]=chart;
if (option)
{
}
this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); }
this.UIElement.onmousemove=(e)=>{ this.UIOnMouseMove(e); }
this.UIElement.onmouseout=(e)=>{ this.UIOnMounseOut(e); }
this.UIElement.oncontextmenu=(e)=> { this.UIOnContextMenu(e); }
/*
this.UIElement.ondblclick=(e)=>{ this.UIOnDblClick(e); }
this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); }
this.UIElement.onmouseleave=(e)=>{ this.UIOnMouseleave(e); }
*/
var frequency=500;
this.ToolbarTimer=setInterval(()=>
{
this.Draw();
}, frequency)
}
this.UIOnMouseDown=function(e)
{
var pixelTatio = GetDevicePixelRatio();
this.ClickDownPoint={ X:e.clientX, Y:e.clientY };
var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
if (e && e.button==0) //左键点击
{
var ptClick={ X:this.ClickDownPoint.X, Y:this.ClickDownPoint.Y };
this.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICK_STATUSBAR_ITEM, ptClick, e);
}
}
this.UIOnContextMenu=function(e)
{
if (e) //去掉系统右键菜单
{
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
e.returnValue=false;
}
}
this.GetChartTooltipData=function(x,y,option)
{
var toolTip=new TooltipData();
for(var i=0;i<this.ChartPaint.length;++i)
{
var item=this.ChartPaint[i];
if (item.GetTooltipData(x,y,toolTip))
{
return toolTip;
}
}
return null;
}
this.UIOnMouseMove=function(e)
{
var pixelTatio = GetDevicePixelRatio();
var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio;
var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio;
//var bShowKLineTooltip=false;
var bShowMinuteTooltip=false;
var chartTooltipData=null;
var tooltipData=this.GetChartTooltipData(x,y);
if (tooltipData)
{
if (tooltipData.Type==121)
{
var item=tooltipData.Data;
if (item && item.Data && item.Data.Symbol)
{
bShowMinuteTooltip=true;
chartTooltipData={ Symbol:item.Data.Symbol, Rect:item.Rect, Position:1 };
}
}
}
//if (!bShowKLineTooltip) this.HideKLineChartTooltip();
if (!bShowMinuteTooltip) this.HideMinuteChartTooltip();
if (bShowMinuteTooltip) this.ShowMinuteChartTooltip(null, null, chartTooltipData);
//if (bShowKLineTooltip) this.ShowKLineChartTooltip(null, null, chartTooltipData);
}
this.UIOnMounseOut=function(e)
{
this.HideAllTooltip();
}
this.TryClickPaintEvent=function(eventID, ptClick, e)
{
var event=this.GetEventCallback(eventID);
if (!event) return false;
if (ptClick.X==e.clientX && ptClick.Y==e.clientY)
{
var pixelTatio = GetDevicePixelRatio();
var x = (e.clientX-uielement.getBoundingClientRect().left)*pixelTatio;
var y = (e.clientY-uielement.getBoundingClientRect().top)*pixelTatio;
var toolTip=new TooltipData();
for(var i=0;i<this.ChartPaint.length;++i)
{
var item=this.ChartPaint[i];
if (item.GetTooltipData(x,y,toolTip))
{
if (toolTip.Data)
{
var data= { X:e.clientX, Y:e.clientY, Tooltip:toolTip };
event.Callback(event, data, this);
return true;
}
}
}
}
return false;
}
this.Draw=function()
{
if (this.UIElement.width<=0 || this.UIElement.height<=0) return;
this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度
this.Frame.Draw();
this.Frame.DrawLogo();
//框架内图形
for(var i=0;i<this.ChartPaint.length;++i)
{
var item=this.ChartPaint[i];
item.Draw();
}
}
this.OnSize=function()
{
if (!this.Frame) return;
this.SetSizeChange(true);
this.Draw();
}
this.SetSizeChange=function(bChanged)
{
for(var i=0;i<this.ChartPaint.length;++i)
{
var chart=this.ChartPaint[i];
if (chart) chart.SizeChange=bChanged;
}
}
this.ReloadResource=function(option)
{
this.Frame.ReloadResource(option);
for(var i=0;i<this.ChartPaint.length;++i)
{
var item=this.ChartPaint[i];
if (item.ReloadResource) item.ReloadResource(option);
}
if (option && (option.Redraw || option.Draw))
{
this.SetSizeChange(true);
this.Draw();
}
if (this.TooltipMinuteChart) this.TooltipMinuteChart.ReloadResource(option); //分时图
}
this.SetColumn=function(aryColunm, option)
{
var chart=this.ChartPaint[0];
if (!chart) return;
chart.SetColumn(aryColunm);
chart.SizeChange=true;
if (option && option.Redraw) this.Draw();
}
this.SetRightToolbar=function(toolbar, option)
{
var chart=this.ChartPaint[0];
if (!chart) return;
chart.SetRightToolbar(toolbar);
chart.SizeChange=true;
if (option && option.Redraw) this.Draw();
}
this.GetStatusBarChart=function()
{
var chart=this.ChartPaint[0];
if (!chart) return null;
return chart;
}
//data={ Symbol }
this.ShowMinuteChartTooltip=function(x,y, data)
{
if (!this.TooltipMinuteChart) return;
var rtClient=this.UIElement.getBoundingClientRect();
var rtScroll=GetScrollPosition();
var offsetLeft=rtClient.left+rtScroll.Left;
var offsetTop=rtClient.top+rtScroll.Top;
data.Offset={ Left:offsetLeft, Top:offsetTop };
this.TooltipMinuteChart.Show(data, x,y);
}
this.HideMinuteChartTooltip=function()
{
if (!this.TooltipMinuteChart) return;
this.TooltipMinuteChart.Hide();
}
this.HideAllTooltip=function()
{
//this.HideKLineChartTooltip();
this.HideMinuteChartTooltip();
}
}
function JSStatusBarFrame()
{
this.ChartBorder;
this.Canvas; //画布
this.BorderLine=null; //1=上 2=下 4=左 8=右
this.ClassName="JSStatusBarFrame";
this.BorderColor=g_JSChartResource.StatusBar.BorderColor; //边框线
this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor;
this.LogoTextFont=g_JSChartResource.FrameLogo.Font;
this.ReloadResource=function(resource)
{
this.BorderColor=g_JSChartResource.StatusBar.BorderColor; //边框线
this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor;
this.LogoTextFont=g_JSChartResource.FrameLogo.Font;
}
this.Draw=function()
{
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 (!IFrameSplitOperator.IsNumber(this.BorderLine))
{
this.Canvas.strokeStyle=this.BorderColor;
this.Canvas.strokeRect(left,top,width,height);
}
else
{
this.Canvas.strokeStyle=this.BorderColor;
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.DrawLogo=function()
{
/*
var text=g_JSChartResource.FrameLogo.Text;
if (!IFrameSplitOperator.IsString(text)) return;
this.Canvas.fillStyle=this.LogoTextColor;
this.Canvas.font=this.LogoTextFont;
this.Canvas.textAlign = 'right';
this.Canvas.textBaseline = 'bottom';
var x=this.ChartBorder.GetRight()-30;
var y=this.ChartBorder.GetBottom()-5;
this.Canvas.fillText(text,x,y);
*/
}
}
function ChartStatusBarStockData()
{
this.Canvas; //画布
this.ChartBorder; //边框信息
this.ChartFrame; //框架画法
this.Name; //名称
this.ClassName='ChartStatusBarStockData'; //类名
this.UIElement;
this.GetEventCallback; //获取事件
this.Data; //数据
this.SizeChange=true;
this.UpColor=g_JSChartResource.StatusBar.UpTextColor;
this.DownColor=g_JSChartResource.StatusBar.DownTextColor;
this.UnchangeColor=g_JSChartResource.StatusBar.UnchangeTextColor;
this.TableConfig=CloneData(g_JSChartResource.StatusBar.Table);
this.DateTimeConfig=CloneData(g_JSChartResource.StatusBar.DateTime);
//显示的字段
this.Column=
[
{
Symbol:"000001.sh",
Column:
[
{ Name:"名称", Key:"Name", Text:"000001", },
{ Name:"现价", Key:"Price", ColorType:3, FloatPrecision:-1, MaxText:"88888.88" },
{ Name:"涨幅", Key:"Increase", ColorType:1, FloatPrecision:2, StringFormat:"{Value}%", MaxText:"888.88%" },
{ Name:"涨跌", Key:"UpDown",ColorType:1, FloatPrecision:-1 },
{ Name:"总额", Key:"Amount", FloatPrecision:0, Format:{ Type:3, ExFloatPrecision:2 }, ColorID:1 }
]
},
{
Symbol:"600000.sh",
Column:
[
{ Name:"名称", Key:"Name", Text:"600000", },
{ Name:"现价", Key:"Price", ColorType:3, FloatPrecision:-1 },
{ Name:"涨幅", Key:"Increase", ColorType:1, FloatPrecision:2, StringFormat:"{Value}%" },
{ Name:"涨跌", Key:"UpDown",ColorType:1, FloatPrecision:-1 },
{ Name:"总额", Key:"Amount", FloatPrecision:0, Format:{ Type:3, ExFloatPrecision:2 } }
]
}
]
this.RightToolbarConfig=CloneData(g_JSChartResource.StatusBar.RightToolbar);
this.MapToolbarFlash=new Map(); //key=id, Value:{ Counter:, Enable: }
//右侧工具栏
this.RightToolbar=
{
/*
AryButton:
[
{ ID:2, Type:1, Icon:[{ Symbol:"\ue609", Color:"rgb(180,180,180)"} ] },
{
ID:1, Type:2, Icon:[{ Symbol:"\ue6d0", Color:"rgb(180,180,180)"} ],
Flash:
{
AryIcon:
[
[{ Symbol:"\ue6cb", Color:"rgb(0,191,255)"}],
[{ Symbol:"\ue6cb", Color:"rgb(255,165,0)"}],
[{ Symbol:"\ue6cb", Color:"rgb(255,215,0)"}],
]
}
},
]
*/
}
this.AryRectCell=[];
this.AryRectButton=[];
this.ReloadResource=function(resource)
{
this.UpColor=g_JSChartResource.StatusBar.UpTextColor;
this.DownColor=g_JSChartResource.StatusBar.DownTextColor;
this.UnchangeColor=g_JSChartResource.StatusBar.UnchangeTextColor;
this.TableConfig=CloneData(g_JSChartResource.StatusBar.Table);
this.DateTimeConfig=CloneData(g_JSChartResource.StatusBar.DateTime);
}
this.SetColumn=function(aryColumn)
{
this.Column=[];
if (!IFrameSplitOperator.IsNonEmptyArray(aryColumn)) return;
for(var i=0;i<aryColumn.length;++i)
{
var item=aryColumn[i];
if (!item) continue;
this.Column.push(CloneData(item));
}
}
this.SetRightToolbar=function(toolbar, option)
{
if (IFrameSplitOperator.IsNonEmptyArray(toolbar.AryButton))
{
this.RightToolbar.AryButton=toolbar.AryButton.slice();
for(var i=0;i<this.RightToolbar.AryButton.length;++i)
{
var item=this.RightToolbar.AryButton[i];
if (item.Type===2)
{
var value={ Counter:1, Enable:true };
if (IFrameSplitOperator.IsBool(item.Enable)) value.Enable=item.Enable;
this.MapToolbarFlash.set(item.ID, value)
}
}
}
}
this.Draw=function()
{
this.AryRectCell=[];
this.AryRectButton=[];
var border=this.ChartBorder.GetBorder();
var position = { Left:border.Left, Right:border.Right, Top:border.Top, Bottom:border.Bottom, Width:border.Right-border.Left, Border:border };
this.DrawRightToolbar(position);
this.DrawTable(position);
}
this.DrawTable=function(position)
{
if (!IFrameSplitOperator.IsNonEmptyArray(this.Column)) return;
var config=this.TableConfig;
var top=position.Top;
var left=position.Left+config.Margin.Left;
var yText=top+config.Margin.Top;
var xText=left;
this.Canvas.font=config.Font;
this.Canvas.textAlign = 'left';
this.Canvas.textBaseline = 'bottom';
var cellHeight=this.Canvas.measureText("擎").width+config.CellMargin.Top+config.CellMargin.Bottom;
var itemPos={ Left:xText, Right:position.Right, Top:yText, Height:cellHeight, Bottom:yText+cellHeight, IsBreak:false, CellCount:0 };
for(var i=0;i<this.Column.length;++i)
{
var item=this.Column[i];
if (!item || !item.Symbol) continue;
var rtCell={ Left:itemPos.Left, Top:itemPos.Top, Bottom:itemPos.Bottom, Right:itemPos.Left };
if (i>0) rtCell.Left-=config.Separator.Right;
this.DrawCellItem(item, itemPos );
if (itemPos.CellCount>0)
{
rtCell.Right=itemPos.Left;
rtCell.Width=rtCell.Right-itemPos.Left;
rtCell.Height=rtCell.Bottom-rtCell.Top;
this.AryRectCell.push({ Rect:rtCell, Data:item, Type:1 });
}
if (itemPos.IsBreak)
{
break;
}
itemPos.Left+=config.Separator.Left;
if (config.Separator.Line && config.Separator.Line.Color) //分割线
{
if (itemPos.Left>=itemPos.Right) break;
var subConfig=config.Separator.Line;
var lineWidth=1*GetDevicePixelRatio();
if (IFrameSplitOperator.IsNumber(subConfig.Width)) lineWidth=subConfig.Width;
this.Canvas.strokeStyle=subConfig.Color;
this.Canvas.beginPath();
this.Canvas.moveTo(ToFixedPoint(itemPos.Left),itemPos.Top+subConfig.Top);
this.Canvas.lineTo(ToFixedPoint(itemPos.Left),itemPos.Bottom-subConfig.Bottom);
this.Canvas.stroke();
}
itemPos.Left+=config.Separator.Right;
}
}
this.DrawCellItem=function(cellItem, itemPos)
{
var config=this.TableConfig;
var xText=itemPos.Left;
var yBottom=itemPos.Top+itemPos.Height-config.CellMargin.Bottom+config.CellMargin.YOffset;
var text=null;
var stockItem=null;
if (this.Data.MapSymbol.has(cellItem.Symbol)) stockItem=this.Data.MapSymbol.get(cellItem.Symbol);
for(var i=0;i<cellItem.Column.length ;++i)
{
var item=cellItem.Column[i];
if (!item) continue;
var color=config.AryTextColor[0];
var text=null;
if (stockItem && stockItem.MapData.has(item.Key))
{
var dataItem=stockItem.MapData.get(item.Key);
text=this.FormatValue(item, dataItem, stockItem);
if (IFrameSplitOperator.IsNumber(item.ColorID) && item.ColorID>=0 && item.ColorID<config.AryTextColor.length)
color=config.AryTextColor[item.ColorID];
if (item.ColorType===3 && IFrameSplitOperator.IsNumber(dataItem.Value))
color=this.GetPriceColor(dataItem.Value, stockItem);
else if (item.ColorType==1 && IFrameSplitOperator.IsNumber(dataItem.Value))
color=this.GetUpDownColor(dataItem.Value,0);
else if (item.ColorType==4)
color=this.UpColor;
else if (item.ColorType==5)
color=this.DownColor;
if (item.TextColor) color=item.TextColor;
}
if (!text && item.Text) text=item.Text;
if (text)
{
var textWidth=this.Canvas.measureText(text).width;
if (xText+textWidth+config.CellMargin.Left+config.CellMargin.Right>itemPos.Right)
{
itemPos.IsBreak=true;
break;
}
this.Canvas.fillStyle=color;
this.Canvas.fillText(text,xText+config.CellMargin.Left,yBottom);
xText+=(textWidth+config.CellMargin.Left+config.CellMargin.Right);
}
else if (item.MaxText)
{
text=item.MaxText;
var textWidth=this.Canvas.measureText(text).width;
xText+=(textWidth+config.CellMargin.Left+config.CellMargin.Right);
if (xText>itemPos.Right)
{
itemPos.IsBreak=true;
break;
}
}
++itemPos.CellCount;
}
itemPos.Left=xText;
}
this.FormatValue=function(column, data, stockItem)
{
var dec=0; //小数位数
if (IFrameSplitOperator.IsNumber(column.FloatPrecision))
{
if (column.FloatPrecision===-1) dec=GetfloatPrecision(stockItem.Symbol);
else dec=column.FloatPrecision;
}
var text=null;
if (!data) return text;
if (data.Text)
{
text=data.Text;
}
else if (IFrameSplitOperator.IsNumber(data.Value))
{
var value=data.Value;
text=value.toFixed(dec);
//格式化
if (column.Format && IFrameSplitOperator.IsNumber(column.Format.Type))
{
var format=column.Format;
switch(format.Type)
{
case 1: //原始数据
text=value.toFixed(dec);
break;
case 2: //千分位分割
text=IFrameSplitOperator.FormatValueThousandsString(value, dec);
break;
case 3:
var exfloatPrecision=1;
if (IFrameSplitOperator.IsNumber(format.ExFloatPrecision)) exfloatPrecision=format.ExFloatPrecision;
text=IFrameSplitOperator.FormatValueStringV2(value, dec,exfloatPrecision);
break;
}
}
}
if (column.StringFormat && text) text=column.StringFormat.replace('{Value}',text);
return text;
}
this.GetPriceColor=function(price, stockItem)
{
var upperSymbol=null;
if (stockItem.Symbol) upperSymbol=stockItem.Symbol.toUpperCase();
if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol))
{
if (!IFrameSplitOperator.IsNumber(stockItem.YFClose)) return this.UnchangeColor;
return this.GetUpDownColor(price, stockItem.YFClose);
}
else
{
if (!IFrameSplitOperator.IsNumber(stockItem.YClose)) return this.UnchangeColor;
return this.GetUpDownColor(price, stockItem.YClose);
}
}
this.GetUpDownColor=function(price, price2)
{
if (price>price2) return this.UpColor;
else if (price<price2) return this.DownColor;
else return this.UnchangeColor;
}
this.DrawRightToolbar=function(position)
{
var config=this.DateTimeConfig;
var top=position.Top;
var right=position.Right;
this.Canvas.font=config.Font;
this.Canvas.textAlign = 'left';
this.Canvas.textBaseline = 'bottom';
var cellHeight=this.Canvas.measureText("擎").width+config.Margin.Top+config.Margin.Bottom;
var yBottom=top+cellHeight-config.Margin.Bottom+config.Margin.YOffset;
var xText=right;
//时间
var datetime=new Date();
var text=IFrameSplitOperator.FormatDateTimeStringV2(datetime, config.Format);
var textWidth=this.Canvas.measureText(config.MaxText).width+config.Margin.Left+config.Margin.Right;
xText-=textWidth;
this.Canvas.fillStyle=config.TitleColor;
this.Canvas.fillText(text,xText+config.Margin.Left,yBottom);
position.Right=xText;
if (this.RightToolbar && IFrameSplitOperator.IsNonEmptyArray(this.RightToolbar.AryButton))
{
var config=this.RightToolbarConfig;
xText-=config.Margin.Right;
for(var i=this.RightToolbar.AryButton.length-1;i>=0;--i)
{
var item=this.RightToolbar.AryButton[i];
var aryItem=null;
if (item.Type==2) aryItem=this.GetFlashToolbarItem(item);
else aryItem=item.Icon;
if (!IFrameSplitOperator.IsNonEmptyArray(aryItem)) continue;
var iconFont=`${config.Icon.Size}px ${config.Icon.Family}`;
this.Canvas.font=iconFont;
var textWidth=config.Icon.Size+config.CellMargin.Left+config.CellMargin.Right;
xText-=textWidth;
yBottom=top+config.Margin.Top+(config.Icon.Size+config.CellMargin.Top+config.CellMargin.Bottom)-config.CellMargin.Bottom+config.CellMargin.YOffset;
for(var j=0;j<aryItem.length;++j)
{
var iconItem=aryItem[j];
var text=iconItem.Symbol;
this.Canvas.fillStyle=iconItem.Color;
this.Canvas.fillText(text,xText+config.CellMargin.Left,yBottom);
}
var rtButton={ Left:xText, Bottom:yBottom, Height:config.Icon.Size, Width:config.Icon.Size };
rtButton.Right=rtButton.Left+rtButton.Width;
rtButton.Top=rtButton.Bottom-rtButton.Height;
this.AryRectButton.push({ Rect:rtButton, Data:item, Type:2 });
}
}
position.Right=xText;
}
this.GetFlashToolbarItem=function(btnItem)
{
if (!btnItem.Flash || !IFrameSplitOperator.IsNonEmptyArray(btnItem.Flash.AryIcon)) return btnItem.Icon;
if (!this.MapToolbarFlash.has(btnItem.ID)) return btnItem.Icon;
var item=this.MapToolbarFlash.get(btnItem.ID);
if (!item.Enable) return btnItem.Icon;
item.Counter++;
var index=item.Counter%btnItem.Flash.AryIcon.length;
return btnItem.Flash.AryIcon[index];
}
this.GetTooltipData=function(x,y,tooltip)
{
for(var i=0;i<this.AryRectCell.length;++i)
{
var item=this.AryRectCell[i];
if (Path2DHelper.PtInRect(x,y, item.Rect))
{
tooltip.Data=item;
tooltip.ChartPaint=this;
tooltip.Type=121;
return true;
}
}
for(var i=0;i<this.AryRectButton.length;++i)
{
var item=this.AryRectButton[i];
if (Path2DHelper.PtInRect(x,y, item.Rect))
{
tooltip.Data=item;
tooltip.ChartPaint=this;
tooltip.Type=122;
return true;
}
}
return false;
}
}