UNPKG

hqchart

Version:

HQChart - H5, 微信小程序 沪深/港股/数字货币/期货/美股 K线图(kline),走势图,缩放,拖拽,十字光标,画图工具,截图,筹码图. 分析家语法,通达信语法,(麦语法),第3方数据对接

1,543 lines (1,245 loc) 80.8 kB
/* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装订单表格控件 (H5版本) 使用新的class语法 */ class JSOrderChart { DivElement=null; JSChartContainer=null; //表格控件 ResizeListener=null; //大小变动监听 CanvasElement=null; constructor(divElement) { this.DivElement=divElement; //h5 canvas this.CanvasElement=document.createElement("canvas"); this.CanvasElement.className='jsorderlist-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("[JSOrderChart::JSOrderChart] divElement hasChildNodes", divElement.childNodes); } divElement.appendChild(this.CanvasElement); } OnSize() { //画布大小通过div获取 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(`[JSOrderChart::OnSize] devicePixelRatio=${window.devicePixelRatio}, height=${this.CanvasElement.height}, width=${this.CanvasElement.width}`); if (this.JSChartContainer && this.JSChartContainer.OnSize) { this.JSChartContainer.OnSize(); } } SetOption(option) { var chart=this.CreateJSOrderChartContainer(option); if (!chart) return false; if (option.OnCreatedCallback) option.OnCreatedCallback(chart); this.JSChartContainer=chart; this.DivElement.JSChart=this; //div中保存一份 //注册事件 if (IFrameSplitOperator.IsNonEmptyArray(option.EventCallback)) { for(var i=0;i<option.EventCallback.length;++i) { var item=option.EventCallback[i]; chart.AddEventCallback(item); } } if (option.EnableResize==true) this.CreateResizeListener(); //if (option.FloatTooltip && option.FloatTooltip.Enable) chart.InitalFloatTooltip(option.FloatTooltip); //提示信息 if (!option.Symbol) { chart.Draw(); } else { chart.ChangeSymbol(option.Symbol); } } CreateResizeListener() { this.ResizeListener = new ResizeObserver((entries)=>{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } OnDivResize=function(entries) { JSConsole.Chart.Log("[JSOrderChart::OnDivResize] entries=", entries); this.OnSize(); } CreateJSOrderChartContainer(option) { var chart=new JSOrderChartContainer(this.CanvasElement); chart.Create(option); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; if (option.Column) chart.SetColumn(option.Column); this.SetChartBorder(chart, option); //是否自动更新 if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate; if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; var orderChart=chart.GetOrderChart(); //注册事件 if (option.EventCallback) { for(var i=0;i<option.EventCallback.length;++i) { var item=option.EventCallback[i]; chart.AddEventCallback(item); } } return chart; } SetChartBorder(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; } ///////////////////////////////////////////////////////////////////////////// //对外接口 //切换股票代码接口 ChangeSymbol(symbol, option) { if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol,option); } //事件回调 AddEventCallback=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function') { JSConsole.Chart.Log('[JSOrderChart:AddEventCallback] obj=', obj); this.JSChartContainer.AddEventCallback(obj); } } //重新加载配置 ReloadResource(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSOrderChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } ChartDestroy=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestroy) == 'function') { this.JSChartContainer.ChartDestroy(); } } //初始化 静态方法 static Init(divElement) { var jsChartControl=new JSOrderChart(divElement); jsChartControl.OnSize(); return jsChartControl; } } class JSOrderChartContainer { ClassName='JSOrderChartContainer'; Frame; //框架画法 ChartPaint=[]; //图形画法 ChartSplashPaint=null; //等待提示 LoadDataSplashTitle="数据加载中"; //下载数据提示信息 Canvas=null; //画布 Symbol=null; Name=null; TradeDate=null; NetworkFilter=null; //数据回调接口 Data={ DataOffset:0, Data:[], BasePrice:null }; //显示数据 SourceData={ Data:[], MapData:new Map(), BasePrice:null }; //原始数据 { Price:, Color:, BGColor:, Data:{ } } //事件回调 MapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} AutoUpdateTimer=null; AutoUpdateFrequency=15000; //更新频率 GotoBasePageConfig={ Enable:true, Timer:null, Frequency:5000, StartTime:null }; //自动回到基准页面 FloatTooltip=null; //提示浮框 UIElement=null; LastPoint={ X:null, Y:null }; //鼠标位置 //MouseOnStatus:{ RowIndex:行, ColumnIndex:列} LastMouseStatus={ MoveStatus:null, TooltipStatus:null, MouseOnStatus:null }; IsDestroy=false; //是否已经销毁了 constructor(uielement) { this.Canvas=uielement.getContext("2d"); //画布 this.UIElement=uielement; } ChartDestroy() //销毁 { this.IsDestroy=true; this.StopAutoUpdate(); this.DestroyFloatTooltip(); } HideFloatTooltip() { if (!this.FloatTooltip) return; this.FloatTooltip.Hide(); } DestroyFloatTooltip() { if (!this.FloatTooltip) return; this.FloatTooltip.Destroy(); this.FloatTooltip=null; } InitalFloatTooltip(option) { if (this.FloatTooltip) return; this.FloatTooltip=new JSFloatTooltip(); this.FloatTooltip.Inital(this, option); this.FloatTooltip.Create(); } DrawFloatTooltip(point,toolTip) { if (!this.FloatTooltip) return; this.UpdateFloatTooltip(point, toolTip) } UpdateFloatTooltip(point, toolTip) { if (!this.FloatTooltip) return; var sendData= { Tooltip:toolTip, Point:point, DataType:6, }; this.FloatTooltip.Update(sendData); } HideAllTooltip() { this.HideFloatTooltip(); } CloneArray=function(aryData) { var data=[]; if (!IFrameSplitOperator.IsNonEmptyArray(aryData)) return data; for(var i=0;i<aryData.length;++i) { data.push(aryData[i]); } return data; } //创建 //windowCount 窗口个数 Create(option) { this.UIElement.JSChartContainer=this; //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); //创建框架 this.Frame=new JSOrderFrame(); 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; this.ChartSplashPaint.Frame = this.Frame; //创建表格 var chart=new ChartOrderList(); chart.Frame=this.Frame; chart.ChartBorder=this.Frame.ChartBorder; chart.Canvas=this.Canvas; chart.UIElement=this.UIElement; chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartPaint[0]=chart; if (option) { if (IFrameSplitOperator.IsNumber(option.BorderLine)) this.Frame.BorderLine=option.BorderLine; //边框 if (IFrameSplitOperator.IsBool(option.IsShowHeader)) chart.IsShowHeader=option.IsShowHeader; } var bRegisterKeydown=true; var bRegisterWheel=true; if (option) { if (option.KeyDown===false) { bRegisterKeydown=false; JSConsole.Chart.Log('[JSOrderChartContainer::Create] not register keydown event.'); } if (option.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[JSOrderChartContainer::Create] not register wheel event.'); } if (IFrameSplitOperator.IsBool(option.EnableSelected)) chart.SelectedData.Enable=option.EnableSelected; } if (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); } this.UIElement.ondblclick=(e)=>{ this.UIOnDblClick(e); } this.UIElement.oncontextmenu=(e)=> { this.UIOnContextMenu(e); } this.UIElement.onmousemove=(e)=>{ this.UIOnMouseMove(e);} this.UIElement.onmouseout=(e)=>{ this.UIOnMounseOut(e); } this.UIElement.onmouseleave=(e)=>{ this.UIOnMouseleave(e); } } SetColumn(columnData) { var chart=this.GetOrderChart(); if (chart) chart.SetColumn(columnData); } Draw() { 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; //手机端需要根据分辨率比调整线段宽度 if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) { this.Frame.Draw( { IsEnableSplash:this.ChartSplashPaint.IsEnableSplash} ); this.ChartSplashPaint.Draw(); return; } this.Frame.Draw(); this.Frame.DrawLogo(); //框架内图形 for(var i=0;i<this.ChartPaint.length;++i) { var item=this.ChartPaint[i]; if (item.IsDrawFirst) item.Draw(); } for(var i=0; i<this.ChartPaint.length; ++i) { var item=this.ChartPaint[i]; if (!item.IsDrawFirst) item.Draw(); } } ClearData() { this.Data={ DataOffset:0, Data:[], BasePrice:null }; //分笔数据 this.SourceData={ Data:[], MapData:new Map(), BasePrice:null }; //原始分笔数据 } ChangeSymbol(symbol, option) { this.Symbol=symbol; this.ClearData(); var chart=this.GetOrderChart() if (chart) { chart.Data=null; chart.SelectedData.Data=null; chart.MoveOnData.Data=null; } if (option) { if (IFrameSplitOperator.IsNumber(option.TradeDate)) this.TradeDate=option.TradeDate; } if (!this.Symbol) { this.Draw(); return; } this.RequestOrderData(); } CancelAutoUpdate() //关闭停止更新 { if (typeof (this.AutoUpdateTimer) == 'number') { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = null; } } AutoUpdateEvent(bStart, explain) //自定更新事件, 是给websocket使用 { var eventID=bStart ? JSCHART_EVENT_ID.RECV_START_AUTOUPDATE:JSCHART_EVENT_ID.RECV_STOP_AUTOUPDATE; if (!this.MapEvent.has(eventID)) return; var self=this; var event=this.MapEvent.get(eventID); var data={ Stock:{ Symbol:this.Symbol, Name:this.Name, DayCount:this.DayCount }, Explain: explain }; if (bStart) { data.Callback=function(data) //数据到达更新回调 { self.RecvDealUpdateData(data); } } event.Callback(event,data,this); } //全量数据下载 RequestOrderData() { this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.Draw(); var self=this; if (this.NetworkFilter) { var obj= { Name:'JSOrderChartContainer::RequestOrderData', //类名:: Explain:'价格列表', Request:{ Data: { symbol:self.Symbol, tradeDate:self.TradeDate } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvOrderData(data); self.AutoUpdateEvent(true,'JSOrderChartContainer::RecvOrderData'); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } } SortSourceData() { if (!IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) return; this.SourceData.Data.sort((left,right)=>{ return right.Price-left.Price; }); } RecvOrderData(data) { var chart=this.GetOrderChart(); if (!chart) return; var aryOrder=JSOrderChartContainer.JsonDataToOrderData(data); if (data && IFrameSplitOperator.IsNumber(data.basePrice)) this.SourceData.BasePrice=data.basePrice; if (IFrameSplitOperator.IsNonEmptyArray(aryOrder)) { for(var i=0;i<aryOrder.length; ++i) { var item=aryOrder[i]; if (!IFrameSplitOperator.IsNumber(item.Price)) continue; if (this.SourceData.MapData.has(item.Price)) continue; //去重 //插入 this.SourceData.MapData.set(item.Price, item); this.SourceData.Data.push(item); } } this.SortSourceData(); this.Data={ DataOffset:0, Data:this.SourceData.Data.slice(), BasePrice:this.SourceData.BasePrice }; this.Symbol=data.symbol; this.Name=data.name; var chart=this.GetOrderChart(); chart.Data=this.Data; chart.Symbol=this.Symbol; this.GotoBasePage(); this.Draw(); } RecvOrderUpdateData(data) { var chart=this.GetOrderChart(); if (!chart) return; var aryOrder=JSOrderChartContainer.JsonDataToOrderData(data); if (data && IFrameSplitOperator.IsNumber(data.basePrice)) this.SourceData.BasePrice=data.basePrice; var bUpdate=false; if (IFrameSplitOperator.IsNonEmptyArray(aryOrder)) { for(var i=0;i<aryOrder.length; ++i) { var item=aryOrder[i]; if (!IFrameSplitOperator.IsNumber(item.Price)) continue; if (this.SourceData.MapData.has(item.Price)) //更新 { var priceItem=this.SourceData.MapData.get(item.Price); if (!priceItem.Data) { priceItem.Data=item.Data; } else { var merged=Object.assign({}, priceItem.Data, item.Data); //合并 priceItem.Data=merged; } bUpdate=true; } else { //插入 this.SourceData.MapData.set(item.Price, item); this.SourceData.Data.push(item); bUpdate=true; } } } this.SortSourceData(); this.Data.Data=this.SourceData.Data.slice(); this.Data.BasePrice=this.SourceData.BasePrice; if (bUpdate) this.Draw(); } GotoBasePage(option) { if (!IFrameSplitOperator.IsNumber(this.SourceData.BasePrice)) return false; var chart=this.GetOrderChart(); if (!chart) return false; var index=-1; for(var i=0;i<this.Data.Data.length;++i) { var item=this.Data.Data[i]; if (item.Price===this.SourceData.BasePrice) { index=i; break; } } if (index<0) return false; var pageSize=chart.GetPageSize(chart.SizeChange); var offset=index-parseInt(pageSize/2); if (offset<0) offset=0; this.Data.DataOffset=offset; if (option && option.Draw===true) this.Draw(); this.StopGotoPagePageTimer(); return true; } IsInBasePage() { var chart=this.GetOrderChart(); if (!chart) return false; if (!this.Data) return false; if (!IFrameSplitOperator.IsNumber(this.Data.BasePrice)) return false; if (chart.MapDrawPrice.has(this.Data.BasePrice)) return true; return false; } //增量数据下载 RequestOrderUpdateData() { var self=this; if (this.NetworkFilter) { var obj= { Name:'JSOrderChartContainer::RequestOrderUpdateData', //类名::函数名 Explain:'增量价格列表', Request:{ Data: { symbol: self.Symbol } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvOrderUpdateData(data); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; } } GetOrderChart() { return this.ChartPaint[0]; } AutoUpdate(waitTime) //waitTime 更新时间 { this.CancelAutoUpdate(); if (!this.IsAutoUpdate) return; if (!this.Symbol) return; var self = this; var marketStatus=MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol); if (marketStatus==0 || marketStatus==3) //闭市,盘后 { this.AutoUpdateTimer=setTimeout(function() { self.AutoUpdate(); },20000); return; } var frequency=this.AutoUpdateFrequency; if (marketStatus==1) //盘前 { this.AutoUpdateTimer=setTimeout(function() { self.AutoUpdate(); },frequency); } else if (marketStatus==2) //盘中 { this.AutoUpdateTimer=setTimeout(function() { self.RequestOrderUpdateData(); },frequency); } } StopAutoUpdate() { this.CancelAutoUpdate(); this.AutoUpdateEvent(false,'JSOrderChartContainer::StopAutoUpdate'); if (!this.IsAutoUpdate) return; this.IsAutoUpdate=false; } //设置事件回调 //{event:事件id, callback:回调函数} AddEventCallback(object) { if (!object || !object.event || !object.callback) return; var data={Callback:object.callback, Source:object}; this.MapEvent.set(object.event,data); } RemoveEventCallback(eventid) { if (!this.MapEvent.has(eventid)) return; this.MapEvent.delete(eventid); } GetEventCallback(id) //获取事件回调 { if (!this.MapEvent.has(id)) return null; var item=this.MapEvent.get(id); return item; } OnSize() { if (!this.Frame) return; this.SetSizeChange(true); this.Draw(); } SetSizeChange(bChanged) { var chart=this.GetOrderChart(); if (chart) chart.SizeChange=bChanged; } OnWheel(e) //滚轴 { JSConsole.Chart.Log('[JSOrderChartContainer::OnWheel]',e); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; var x = e.clientX-this.UIElement.getBoundingClientRect().left; var y = e.clientY-this.UIElement.getBoundingClientRect().top; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); if (!isInClient) return; var chart=this.GetOrderChart(); if (!chart) return; var wheelValue=e.wheelDelta; if (!IFrameSplitOperator.IsObjectExist(e.wheelDelta)) wheelValue=e.deltaY* -0.01; var option={ Move:{ Count:1 }}; if (e && e.ctrlKey) option={ Move:{ Page:1 }} var pageType=0 if (wheelValue<0) //下一条 { this.HideAllTooltip(); if (this.GotoNextPage(option)) { this.Draw(); this.DelayGotoBasePage(); } } else if (wheelValue>0) //上一页 { this.HideAllTooltip(); if (this.GotoPreviousPage(option)) { this.Draw(); this.DelayGotoBasePage(); } } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } OnKeyDown(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var keyID = e.keyCode ? e.keyCode :e.which; switch(keyID) { case 38: //up this.HideAllTooltip(); //if (this.GotoPreviousPage()) this.Draw(); break; case 40: //down this.HideAllTooltip(); //if (this.GotoNextPage()) this.Draw(); break; } //不让滚动条滚动 if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } UIOnMouseDown(e) { this.DragCenter=null; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.TryDragCenter(x,y,e)) //拖动 { return; } var chart=this.GetOrderChart(); if (!chart) return false; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var clickData=chart.OnMouseDown(x,y,e); if (!clickData) return; if ((clickData.Type==1 || clickData.Type==2) && (e.button==0 || e.button==2)) //点单元格 { if (clickData.Redraw==true) this.Draw(); } } TryDragCenter(x,y,e) { var chart=this.GetOrderChart(); if (!chart) return false; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var pageSize=chart.GetPageSize(); if (pageSize>this.Data.Data.length) return false; if (!chart.PtInCenter(x,y)) return false; this.DragCenter= { Click:{ X:e.clientX, Y:e.clientY }, LastMove:{ X:e.clientX, Y:e.clientY} }; this.SetCursor({Cursor:"grabbing"}); document.onmousemove=(e)=>{ this.DocOnMouseMove(e); } document.onmouseup=(e)=> { this.DocOnMouseUp(e); } } DocOnMouseMove(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return; var chart=this.GetOrderChart(); if (!chart) return; var dragCenter=this.DragCenter; if (!dragCenter) return; var moveYSetp=dragCenter.LastMove.Y-e.clientY; if(Math.abs(moveYSetp)<5) return; var pixelTatio = GetDevicePixelRatio(); moveYSetp*=pixelTatio; var rowHeight=chart.RowHeight; if (Math.abs(moveYSetp)<rowHeight) return; var bDraw=false; if (moveYSetp>0) { var moveCount=Math.abs(moveYSetp)/rowHeight; if (this.GotoNextPage({ Move:{ Count:moveCount }})) bDraw=true; } else if (moveYSetp<0) { var moveCount=Math.abs(moveYSetp)/rowHeight; if (this.GotoPreviousPage({ Move:{ Count:moveCount }})) bDraw=true; } dragCenter.LastMove.X=e.clientX; dragCenter.LastMove.Y=e.clientY; this.SetCursor({Cursor:"grabbing"}); if (bDraw) this.Draw(); } DocOnMouseUp(e) { //清空事件 document.onmousemove=null; document.onmouseup=null; this.DragCenter=null; this.SetCursor({Cursor:"default"}); } UIOnMouseMove(e) { if (this.DragCenter) return; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var oldMouseOnStatus=this.LastMouseStatus.MouseOnStatus; this.LastMouseStatus.OnMouseMove=null; var bDrawTooltip=false; if (this.LastMouseStatus.TooltipStatus) bDrawTooltip=true; this.LastMouseStatus.TooltipStatus=null; var chartTooltipData=null; this.LastMouseStatus.OnMouseMove={ X:x, Y:y }; var mouseStatus={ Cursor:"default", Name:"Default"};; //鼠标状态 var chart=this.GetOrderChart(); var bDraw=false; var cell=null; if (chart) { var data=chart.OnMouseOn(x, y, e); //单元格提示信息 if (data) { if (data.Redraw===true) bDraw=data.Redraw; if (data.Cell) { cell=data.Cell; bDrawTooltip=true; } //this.LastMouseStatus.TooltipStatus={ X:x, Y:y, Data:tooltipData, ClientX:e.clientX, ClientY:e.clientY }; } } if (bDraw) this.Draw(); this.SendMouseOnEvent({ Data:cell, X:x, Y:y, FuncName:"UIOnMouseMove" }); if (this.LastMouseStatus.TooltipStatus) { var xTooltip = e.clientX-this.UIElement.getBoundingClientRect().left; var yTooltip = e.clientY-this.UIElement.getBoundingClientRect().top; //this.DrawFloatTooltip({X:xTooltip, Y:yTooltip, YMove:20/pixelTatio},this.LastMouseStatus.TooltipStatus.Data); } else { this.HideFloatTooltip(); } } SendMouseOnEvent(data) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_MOVEON_ORDER_CELL); if (!event || !event.Callback) return; event.Callback(event,data, this) } //设置鼠标形状 {Cursor:鼠标形状 } SetCursor(obj) { if (!obj || !obj.Cursor) return; if (obj.Cursor=="default") this.UIElement.style.cursor="default"; else this.UIElement.style.cursor=obj.Cursor; } UIOnDblClick(e) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var chart=this.GetOrderChart(); if (chart) chart.OnDblClick(x,y,e); } UIOnContextMenu(e) { e.preventDefault(); } UIOnMounseOut(e) { this.ClearMoveOnStatus("UIOnMouseleave"); this.HideAllTooltip(); } UIOnMouseleave(e) { this.ClearMoveOnStatus("UIOnMouseleave"); this.HideAllTooltip(); } ClearMoveOnStatus(funcName) { var chart=this.GetOrderChart(); if (!chart) return; if (!chart.MoveOnData.Data) return; chart.MoveOnData.Data=null; this.Draw(); this.SendMouseOnEvent({ Data:null, X:x, Y:y, FuncName:funcName }); } //option ={ Move:{ Step:1, Page: 1 }} GotoNextPage(option) { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.GetOrderChart(); if (!chart) return false; var pageSize=chart.GetPageSize(); if (pageSize>this.Data.Data.length) return false; var moveStep=1; if (option && option.Move) { var item=option.Move; if (IFrameSplitOperator.IsPlusNumber(item.Step)) { moveStep=item.Step; } else if (IFrameSplitOperator.IsPlusNumber(item.Page)) { moveStep=pageSize; } } var offset=this.Data.DataOffset+moveStep; if (offset+pageSize==this.Data.Data.length-1) return false; if (offset+pageSize>this.Data.Data.length) //最后一页不够一屏调整到满屏 { this.Data.DataOffset=this.Data.Data.length-pageSize; } else { this.Data.DataOffset=offset; } return true; } //option ={ Move:{ Step:1, Page: 1 }} GotoPreviousPage(option) { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.GetOrderChart(); if (!chart) return false; if (this.Data.DataOffset<=0) return false; var pageSize=chart.GetPageSize(); var moveStep=1; if (option && option.Move) { var item=option.Move; if (IFrameSplitOperator.IsPlusNumber(item.Step)) { moveStep=item.Step; } else if (IFrameSplitOperator.IsPlusNumber(item.Page)) { moveStep=pageSize; } } var offset=this.Data.DataOffset-moveStep; if (offset<0) offset=0; this.Data.DataOffset=offset; return true; } ReloadResource(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) { this.SetSizeChange(true); this.Draw(); } } DelayGotoBasePage() { this.StopGotoPagePageTimer(); if (this.IsInBasePage()) return; var config=this.GotoBasePageConfig; if (config.Enable===false) return; config.StartTime=new Date(); config.Time=setTimeout(()=> { if (this.IsInBasePage()) return; this.GotoBasePage({ Draw:true }); },config.Frequency); } StopGotoPagePageTimer() { var config=this.GotoBasePageConfig; clearTimeout(config.Timer); config.Timer = null; config.StartTime=null; } static JsonDataToOrderData(data) { var symbol=data.symbol; var result=[]; if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return result; for(var i=0;i<data.data.length;++i) { var item=data.data[i]; var newItem={ Price:item.Price, Data:{ } }; if (item.BGColor) newItem.BGColor=item.BGColor; if (IFrameSplitOperator.IsNumber(item.BGColorID)) newItem.BGColorID=item.BGColorID; if (item.Color) newItem.Color=item.Color; if (IFrameSplitOperator.IsNumber(item.ColorID)) newItem.ColorID=item.ColorID; if (item.Data) { if (IFrameSplitOperator.IsObject(item.Data[201])) newItem.Data.ReserveNumber1=item.Data[201]; if (IFrameSplitOperator.IsObject(item.Data[202])) newItem.Data.ReserveNumber2=item.Data[202]; if (IFrameSplitOperator.IsObject(item.Data[203])) newItem.Data.ReserveNumber3=item.Data[203]; if (IFrameSplitOperator.IsObject(item.Data[204])) newItem.Data.ReserveNumber4=item.Data[204]; if (IFrameSplitOperator.IsObject(item.Data[205])) newItem.Data.ReserveNumber5=item.Data[205]; if (IFrameSplitOperator.IsObject(item.Data[206])) newItem.Data.ReserveNumber6=item.Data[206]; if (IFrameSplitOperator.IsObject(item.Data[207])) newItem.Data.ReserveNumber7=item.Data[207]; if (IFrameSplitOperator.IsObject(item.Data[208])) newItem.Data.ReserveNumber8=item.Data[208]; if (IFrameSplitOperator.IsObject(item.Data[209])) newItem.Data.ReserveNumber9=item.Data[209]; if (IFrameSplitOperator.IsObject(item.Data[210])) newItem.Data.ReserveNumber10=item.Data[210]; } result.push(newItem); } return result; } } class JSOrderFrame { ChartBorder; Canvas; //画布 //BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 LogoTextColor=g_JSChartResource.FrameLogo.TextColor; LogoTextFont=g_JSChartResource.FrameLogo.Font; ReloadResource(resource) { this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; } Draw(option) { 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; } DrawLogo() { var text=g_JSChartResource.FrameLogo.Text; if (!IFrameSplitOperator.IsString(text)) return; this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.font=this.LogoTextFont; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; var x=this.ChartBorder.GetLeft()+5; var y=this.ChartBorder.GetBottom()-5; this.Canvas.fillText(text,x,y); } } var ORDER_COLUMN_ID= { PRICE_ID:0, //预留数值类型 10个 RESERVE_NUMBER1_ID:201, //ReserveNumber1: RESERVE_NUMBER2_ID:202, RESERVE_NUMBER3_ID:203, RESERVE_NUMBER4_ID:204, RESERVE_NUMBER5_ID:205, RESERVE_NUMBER6_ID:206, RESERVE_NUMBER7_ID:207, RESERVE_NUMBER8_ID:208, RESERVE_NUMBER9_ID:209, RESERVE_NUMBER10_ID:210, //预留字符串类型 10个 301-399 RESERVE_STRING1_ID:301, //ReserveString1: RESERVE_STRING2_ID:302, RESERVE_STRING3_ID:303, RESERVE_STRING4_ID:304, RESERVE_STRING5_ID:305, RESERVE_STRING6_ID:306, RESERVE_STRING7_ID:307, RESERVE_STRING8_ID:308, RESERVE_STRING9_ID:309, RESERVE_STRING10_ID:310, } var MAP_ORDER_COLUMN_FIELD=new Map( [ [ORDER_COLUMN_ID.RESERVE_NUMBER1_ID,"ReserveNumber1"], [ORDER_COLUMN_ID.RESERVE_NUMBER2_ID,"ReserveNumber2"], [ORDER_COLUMN_ID.RESERVE_NUMBER3_ID,"ReserveNumber3"], [ORDER_COLUMN_ID.RESERVE_NUMBER4_ID,"ReserveNumber4"], [ORDER_COLUMN_ID.RESERVE_NUMBER5_ID,"ReserveNumber5"], [ORDER_COLUMN_ID.RESERVE_NUMBER6_ID,"ReserveNumber6"], [ORDER_COLUMN_ID.RESERVE_NUMBER7_ID,"ReserveNumber7"], [ORDER_COLUMN_ID.RESERVE_NUMBER8_ID,"ReserveNumber8"], [ORDER_COLUMN_ID.RESERVE_NUMBER9_ID,"ReserveNumber9"], [ORDER_COLUMN_ID.RESERVE_NUMBER10_ID,"ReserveNumber10"], [ORDER_COLUMN_ID.RESERVE_STRING1_ID,"ReserveString1"], [ORDER_COLUMN_ID.RESERVE_STRING2_ID,"ReserveString2"], [ORDER_COLUMN_ID.RESERVE_STRING3_ID,"ReserveString3"], [ORDER_COLUMN_ID.RESERVE_STRING4_ID,"ReserveString4"], [ORDER_COLUMN_ID.RESERVE_STRING5_ID,"ReserveString5"], [ORDER_COLUMN_ID.RESERVE_STRING6_ID,"ReserveString6"], [ORDER_COLUMN_ID.RESERVE_STRING7_ID,"ReserveString7"], [ORDER_COLUMN_ID.RESERVE_STRING8_ID,"ReserveString8"], [ORDER_COLUMN_ID.RESERVE_STRING9_ID,"ReserveString9"], [ORDER_COLUMN_ID.RESERVE_STRING10_ID,"ReserveString10"], ]); class ChartOrderList { Canvas=null; //画布 ChartBorder=null; //边框信息 ChartFrame=null; //框架画法 Name=null; //名称 ClassName='ChartOrderList'; //类名 IsDrawFirst=false; GetEventCallback=null; Data=null; //数据 { Data:[ { Price:, Color:, BGColor:, Data:{ } } ], Offset: } Symbol=null; Decimal=2; //小数位数 IsShowHeader=true; //是否显示表头 IsShowFooter=true; //是否显示页脚 SelectedData={ Data:null, Enable:true }; //{ Data:{ ColIndex:null, Price:null, Type:null }, Enable:是否启动 } MoveOnData={ Data:null, Enable:true }; //鼠标在上面 SizeChange=true; //涨跌颜色 UpColor=g_JSChartResource.OrderList.UpTextColor; DownColor=g_JSChartResource.OrderList.DownTextColor; UnchangeColor=g_JSChartResource.OrderList.UnchagneTextColor; BorderColor=g_JSChartResource.OrderList.BorderColor; //边框线 SelectedConfig={ BGColor:g_JSChartResource.OrderList.Selected.BGColor, LineColor:g_JSChartResource.OrderList.Selected.LineColor, LineWidth:g_JSChartResource.OrderList.Selected.LineWidth }; MoveOnConfig={ LineColor:g_JSChartResource.OrderList.MoveOn.LineColor, LineWidth:g_JSChartResource.OrderList.MoveOn.LineWidth } //表头配置 HeaderFontConfig={ Size:g_JSChartResource.OrderList.Header.Font.Size, Name:g_JSChartResource.OrderList.Header.Font.Name }; HeaderColor=g_JSChartResource.OrderList.Header.Color; HeaderMargin= { Left:g_JSChartResource.OrderList.Header.Margin.Left, Right:g_JSChartResource.OrderList.Header.Margin.Right, Top:g_JSChartResource.OrderList.Header.Margin.Top, Bottom:g_JSChartResource.OrderList.Header.Margin.Bottom }; //表格内容配置 ItemFontConfig={ Size:g_JSChartResource.OrderList.Item.Font.Size, Name:g_JSChartResource.OrderList.Item.Font.Name }; ItemMargin= { Left:g_JSChartResource.OrderList.Item.Margin.Left, Right:g_JSChartResource.OrderList.Item.Margin.Right, Top:g_JSChartResource.OrderList.Item.Margin.Top, Bottom:g_JSChartResource.OrderList.Item.Margin.Bottom, }; FooterConfig= { Font:{ Size:g_JSChartResource.OrderList.Header.Font.Size, Name:g_JSChartResource.OrderList.Header.Font.Name }, Margin:CloneData(g_JSChartResource.OrderList.Header.Margin ) } //缓存 HeaderFont=12*GetDevicePixelRatio() +"px 微软雅黑"; ItemFont=15*GetDevicePixelRatio() +"px 微软雅黑"; FooterFont=12*GetDevicePixelRatio() +"px 微软雅黑"; RowHeight=20; RowCount=0; HeaderHeight=0; FooterHeight=0; //自定义颜色 AryColor=g_JSChartResource.OrderList.AryColor.slice(); Column= { Left: [ //{ Type:ORDER_COLUMN_ID.RESERVE_NUMBER1_ID, Title:"数值1", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.Time, MaxText:"8888.88" }, ], Right: [ //{ Type:ORDER_COLUMN_ID.RESERVE_NUMBER3_ID, Title:"数值3", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.Time, MaxText:"888888" } ], Center:{ Title:"", TextAlign:"center", MaxText:"88888.88" }, } RectClient={ }; RectCenter=null; //上下可以拖动的中间区域 AryCellRect=[]; //{ Rect:, Type: 1=单行 } //Type:20=分时图 //{ Rect, Data, Index, Column, Type }} TooltipRect=[]; MapDrawPrice=new Map(); //当前绘制的价格列表 SetOption(option) { if (!option) return; if (IFrameSplitOperator.IsBool(option.IsShowHeader)) this.IsShowHeader=option.IsShowHeader; if (IFrameSplitOperator.IsBool(option.IsShowFooter)) this.IsShowFooter=option.IsShowFooter; } ReloadResource(resource) { this.UpColor=g_JSChartResource.OrderList.UpTextColor; this.DownColor=g_JSChartResource.OrderList.DownTextColor; this.UnchangeColor=g_JSChartResource.OrderList.UnchagneTextColor; this.BorderColor=g_JSChartResource.OrderList.BorderColor; //边框线 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.OrderList.Header.Font.Size, Name:g_JSChartResource.OrderList.Header.Font.Name }; this.HeaderColor=g_JSChartResource.OrderList.Header.Color; this.HeaderMargin= { Left:g_JSChartResource.OrderList.Header.Margin.Left, Right:g_JSChartResource.OrderList.Header.Margin.Right, Top:g_JSChartResource.OrderList.Header.Margin.Top, Bottom:g_JSChartResource.OrderList.Header.Margin.Bottom }; //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.OrderList.Item.Font.Size, Name:g_JSChartResource.OrderList.Item.Font.Name }; this.ItemMargin= { Left:g_JSChartResource.OrderList.Item.Margin.Left, Right:g_JSChartResource.OrderList.Item.Margin.Right, Top:g_JSChartResource.OrderList.Item.Margin.Top, Bottom:g_JSChartResource.OrderList.Item.Margin.Bottom, }; this.AryColor=g_JSChartResource.OrderList.AryColor.slice(); } GetColorByID(id) { if (!IFrameSplitOperator.IsNumber(id)) return null; if (id<0 || id>=this.AryColor.length) return null; return this.AryColor[id]; } CreateColumnItem(item) { if (!item) return null; var colItem=this.GetDefaultColunm(item.Type); if (!colItem) return null; if (item.Title) colItem.Title=item.Title; if (item.TitleAlign) colItem.TitleAlign=item.TitleAlign; if (item.HeaderColor) colItem.HeaderColor=item.HeaderColor; if (item.TextAlign) colItem.TextAlign=item.TextAlign; if (item.TextColor) colItem.TextColor=item.TextColor; if (item.MaxText) colItem.MaxText=item.MaxText; if (this.IsReserveNumber(item.Type)) { if (item.Format) colItem.Format=item.Format; //数据格式化设置{ Type:1=原始 2=千分位分割 3=万亿转换, ExFloatPrecision:万亿转换以后的小数位数 } if (IFrameSplitOperator.IsNumber(item.ColorType)) colItem.ColorType=item.ColorType; //0=默认 1=(>0, =0, <0) 2=(>=0, <0) if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) colItem.FloatPrecision=item.FloatPrecision; if (item.StringFormat) colItem.StringFormat=item.StringFormat; //"{0}%" 输出增加固定字符 } if (item.MoveOn) { colItem.MoveOn={ }; if (item.MoveOn.LineColor) colItem.MoveOn.LineColor=item.MoveOn.LineColor; if (IFrameSplitOperator.IsNumber(item.MoveOn.LineColorID)) colItem.MoveOn.LineColorID=item.MoveOn.LineColorID; if (IFrameSplitOperator.IsNumber(item.MoveOn.LineWidth)) colItem.MoveOn.LineWidth=item.MoveOn.LineWidth; } return colItem } SetColumn(columnData) { if (!columnData) return; if (columnData.Left && IFrameSplitOperator.IsArray(columnData.Left.Data)) { this.Column.Left=[]; var aryData=columnData.Left.Data; for(var i=0;i<aryData.length;++i) { var item=aryData[i]; var colItem=this.CreateColumnItem(item); if (!colItem) continue; this.Column.Left.push(colItem); } } if (columnData.Right && IFrameSplitOperator.IsArray(columnData.Right.Data)) { this.Column.Right=[]; var aryData=columnData.Right.Data; for(var i=0;i<aryData.length;++i) { var item=aryData[i]; var colItem=this.CreateColumnItem(item); if (!colItem) continue; this.Column.Right.push(colItem); } } if (columnData.Center) { item=columnData.Center; var colItem=this.CreateColumnItem(item); if (colItem) this.Column.Center=colItem; } } GetDefaultColunm(id) { var DEFAULT_COLUMN= [ { Type:ORDER_COLUMN_ID.PRICE_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"99999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER1_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER2_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER3_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER4_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER5_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER6_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER7_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER8_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER9_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_NUMBER10_ID, Title:"", TextAlign:"right", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:ORDER_COLUMN_ID.RESERVE_STRING1_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResource.OrderList.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:ORDER_COLUMN_ID.RESERVE_STRING2_ID, Title:"", TextAlign:"center", TextColor:g_JSChartResou