UNPKG

hqchart

Version:

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

1,490 lines (1,222 loc) 88.3 kB
/* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装成交明细表格控件 (H5版本) */ function JSDealChart(divElement) { this.DivElement=divElement; this.JSChartContainer; //表格控件 this.ResizeListener; //大小变动监听 //h5 canvas this.CanvasElement=document.createElement("canvas"); this.CanvasElement.className='jsdeallist-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("[JSDealChart::JSDealList] divElement hasChildNodes", divElement.childNodes); } divElement.appendChild(this.CanvasElement); this.OnSize=function() { //画布大小通过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(`[JSDealChart::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.CreateJSDealChartContainer(option); if (!chart) return false; if (option.OnCreatedCallback) option.OnCreatedCallback(chart); this.JSChartContainer=chart; this.DivElement.JSChart=this; //div中保存一份 //注册事件 if (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.MinuteChartTooltip && option.MinuteChartTooltip.Enable) chart.InitalMinuteChartTooltip(option.MinuteChartTooltip); if (option.FloatTooltip && option.FloatTooltip.Enable) chart.InitalFloatTooltip(option.FloatTooltip); //提示信息 if (!option.Symbol) { chart.Draw(); } else { chart.ChangeSymbol(option.Symbol); } } this.CreateResizeListener=function() { this.ResizeListener = new ResizeObserver((entries)=>{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } this.OnDivResize=function(entries) { JSConsole.Chart.Log("[JSDealChart::OnDivResize] entries=", entries); this.OnSize(); } this.CreateJSDealChartContainer=function(option) { var chart=new JSDealChartContainer(this.CanvasElement); chart.Create(option); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) chart.SetColumn(option.Column); if (IFrameSplitOperator.IsNumber(option.ShowOrder)) chart.ChartPaint[0].ShowOrder=option.ShowOrder; this.SetChartBorder(chart, option); //是否自动更新 if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate; if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; if (IFrameSplitOperator.IsBool(option.EnableFilter)) chart.EnableFilter=option.EnableFilter; var dealChart=chart.GetDealChart(); if (dealChart) { if (IFrameSplitOperator.IsNumber(option.SelectedStyle)) dealChart.SelectedStyle=option.SelectedStyle; } //注册事件 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.ChangeSymbol=function(symbol, option) { if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol,option); } this.SetColumn=function(aryColumn, option) { if (this.JSChartContainer) this.JSChartContainer.SetColumn(aryColumn,option); } this.EnableFilter=function(bEnable, option) //启动|关闭筛选 { if (this.JSChartContainer) this.JSChartContainer.EnableFilter(bEnable, option); } //事件回调 this.AddEventCallback=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function') { JSConsole.Chart.Log('[JSDealChart:AddEventCallback] obj=', obj); this.JSChartContainer.AddEventCallback(obj); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSDealChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } this.ChartDestroy=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestroy) == 'function') { this.JSChartContainer.ChartDestroy(); } } } JSDealChart.Init=function(divElement) { var jsChartControl=new JSDealChart(divElement); jsChartControl.OnSize(); return jsChartControl; } function JSDealChartContainer(uielement) { this.ClassName='JSDealChartContainer'; this.Frame; //框架画法 this.ChartPaint=[]; //图形画法 this.ChartSplashPaint=null; //等待提示 this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息 this.Canvas=uielement.getContext("2d"); //画布 this.ShowCanvas=null; this.Symbol; this.Name; this.TradeDate; this.NetworkFilter; //数据回调接口 this.Data={ DataOffset:0, Data:[] }; //分笔数据 this.SourceData={DataOffset:0, Data:[] }; //原始分笔数据 this.IsShowLastPage=true; //显示最后一页 //事件回调 this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} this.AutoUpdateTimer=null; this.AutoUpdateFrequency=15000; //更新频率 this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息 this.TooltipMinuteChart; //分时图 this.FloatTooltip; //提示浮框 this.UIElement=uielement; this.LastPoint=new Point(); //鼠标位置 //MouseOnStatus:{ RowIndex:行, ColumnIndex:列} this.LastMouseStatus={ MoveStatus:null, TooltipStatus:null, MouseOnStatus:null }; this.IsDestroy=false; //是否已经销毁了 this.ChartDestroy=function() //销毁 { this.IsDestroy=true; this.StopAutoUpdate(); this.DestroyMinuteChartTooltip(); this.DestroyFloatTooltip(); } this.EnableFilterData=false; //是否启动筛选 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; } //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.HideFloatTooltip=function() { if (!this.FloatTooltip) return; this.FloatTooltip.Hide(); } this.DestroyFloatTooltip=function() { if (!this.FloatTooltip) return; this.FloatTooltip.Destroy(); this.FloatTooltip=null; } this.InitalFloatTooltip=function(option) { if (this.FloatTooltip) return; this.FloatTooltip=new JSFloatTooltip(); this.FloatTooltip.Inital(this, option); this.FloatTooltip.Create(); } this.DrawFloatTooltip=function(point,toolTip) { if (!this.FloatTooltip) return; this.UpdateFloatTooltip(point, toolTip) } this.UpdateFloatTooltip=function(point, toolTip) { if (!this.FloatTooltip) return; var sendData= { Tooltip:toolTip, Point:point, DataType:5, }; this.FloatTooltip.Update(sendData); } this.HideAllTooltip=function() { this.HideMinuteChartTooltip(); this.HideFloatTooltip(); } //筛选数据 this.FilterData=function(aryDeal) { if (!this.EnableFilterData) return aryDeal; //过滤由外部处理 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FILTER_DEAL_DATA); if (!event || !event.Callback) return aryDeal; var sendData={ Data:aryDeal, Result:[] }; //{ Data:原始数据, Result:[] 过滤以后的数据 } event.Callback(event,sendData,this); return sendData.Result; } this.EnableFilter=function(bEnable, option) //启动|关闭筛选 { this.EnableFilterData=bEnable; this.Data.Data=this.FilterData(this.SourceData.Data); this.Data.DataOffset=0; if (option) { if (option.GotoLastPage==true) this.GotoLastPage(); if (option.Redraw==true) this.Draw(); } } this.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 窗口个数 this.Create=function(option) { this.UIElement.JSChartContainer=this; //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); //创建框架 this.Frame=new JSDealFrame(); 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 ChartDealList(); 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.IsBool(option.IsSingleTable)) chart.IsSingleTable=option.IsSingleTable; //单表模式 if (IFrameSplitOperator.IsBool(option.IsShowHeader)) chart.IsShowHeader=option.IsShowHeader; //是否显示表头 if (IFrameSplitOperator.IsBool(option.IsShowLastPage)) this.IsShowLastPage=option.IsShowLastPage; //是否显示最后一页 if (IFrameSplitOperator.IsNumber(option.BorderLine)) this.Frame.BorderLine=option.BorderLine; //边框 } var bRegisterKeydown=true; var bRegisterWheel=true; if (option) { if (option.KeyDown===false) { bRegisterKeydown=false; JSConsole.Chart.Log('[JSDealChartContainer::Create] not register keydown event.'); } if (option.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[JSDealChartContainer::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); } } 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; //手机端需要根据分辨率比调整线段宽度 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(); } } this.ChangeSymbol=function(symbol, option) { this.Symbol=symbol; this.Data={ DataOffset:0, Data:[] }; //分笔数据 this.SourceData={DataOffset:0, Data:[] }; //原始分笔数据 var chart=this.ChartPaint[0]; if (chart) chart.Data=null; if (option) { if (IFrameSplitOperator.IsNumber(option.TradeDate)) this.TradeDate=option.TradeDate; if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) this.SetColumn(option.Column); } if (!this.Symbol) { this.Draw(); return; } this.RequestDealData(); } this.CancelAutoUpdate=function() //关闭停止更新 { if (typeof (this.AutoUpdateTimer) == 'number') { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = null; } } this.AutoUpdateEvent=function(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); } //全量数据下载 this.RequestDealData=function() { this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.Draw(); var self=this; if (this.NetworkFilter) { var obj= { Name:'JSDealChartContainer::RequestDealData', //类名:: Explain:'成交明细', Request:{ Data: { symbol:self.Symbol, tradeDate:self.TradeDate } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvDealData(data); self.AutoUpdateEvent(true,'JSDealChartContainer::RequestDealData'); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } var cacheUrl=`${g_JSChartResource.CacheDomain}/cache/dealday/today/${this.Symbol}.json`; JSNetwork.HttpRequest({ url: cacheUrl, type:"get", dataType: "json", async:true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvDealData(data); self.AutoUpdate(1); }, error: function(http,e) { self.ChartSplashPaint.EnableSplash(false); self.AutoUpdate(); //self.RecvError(http,e,param);; } }); } this.RecvDealData=function(data) { var chart=this.GetDealChart(); if (!chart) return; var aryDeal=JSDealChartContainer.JsonDataToDealData(data); if (chart.ShowOrder===1 && IFrameSplitOperator.IsNonEmptyArray(aryDeal)) //倒序 aryDeal=aryDeal.reverse(); this.SourceData={ DataOffset:0, Data:aryDeal }; this.Data={ DataOffset:0, Data:this.FilterData(this.CloneArray(aryDeal)) }; this.Symbol=data.symbol; this.Name=data.name; var chart=this.ChartPaint[0]; chart.Data=this.Data; chart.Symbol=this.Symbol; chart.YClose=data.yclose; chart.YFClose=data.yfclose; chart.Open=data.open; if (this.IsShowLastPage) this.SetLastPageDataOffset(); //显示最后一屏 this.Draw(); } this.SetLastPageDataOffset=function() { var chart=this.GetDealChart(); if (!chart) return; if (chart.ShowOrder===1) { this.Data.DataOffset=0; } else { var dataCount=0; if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) dataCount=this.SourceData.Data.length; var pageSize=chart.GetPageSize(true); var offset=dataCount-pageSize; if (offset<0) offset=0; this.Data.DataOffset=offset; } } //增量数据下载 this.RequestDealUpdateData=function() { var self=this; if (this.NetworkFilter) { var obj= { Name:'JSDealChartContainer::RequestDealUpdateData', //类名::函数名 Explain:'增量成交明细', Request:{ Data: { symbol: self.Symbol } }, Self:this, PreventDefault:false }; if (this.Data && IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { var lastItem=this.Data.Data[this.Data.Data.length-1]; //最后一条数据 obj.LastItem=lastItem; } this.NetworkFilter(obj, function(data) { self.RecvDealUpdateData(data); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; } } this.GetDealChart=function() { return this.ChartPaint[0]; } this.RecvDealUpdateData=function(data) { var aryDeal=JSDealChartContainer.JsonDataToDealData(data); if (!IFrameSplitOperator.IsNonEmptyArray(aryDeal)) return; var chart=this.GetDealChart(); if (!chart) return; if (data.UpdateType===1) //全量更新 { if (chart.ShowOrder===1) { if (IFrameSplitOperator.IsNonEmptyArray(aryDeal)) aryDeal=aryDeal.reverse(); this.SourceData.Data=aryDeal; this.Data.Data=this.FilterData(this.CloneArray(aryDeal)); } else { this.SourceData.Data=aryDeal; var oldCount=0, newCount=0; if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) oldCount=this.Data.Data.length; this.Data.Data=this.FilterData(this.CloneArray(aryDeal)); if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) newCount=this.Data.Data.length; if (oldCount==0) { if (this.IsShowLastPage) this.SetLastPageDataOffset(); //显示最后一屏 } else if (newCount>oldCount) //增长 偏移增加 { var pageSize=chart.GetPageSize(); var count=newCount-oldCount; for(var i=0;i<count;++i) { if (this.Data.DataOffset+pageSize<this.Data.Data.length) ++this.Data.DataOffset; } } else { if (this.Data.DataOffset>= this.Data.Data.length) this.Data.DataOffset=0; } } } else { this.AddDealData(this.SourceData, aryDeal); this.AddDealData(this.Data,this.FilterData(aryDeal)); } if (data.IsShowLastPage===true) this.SetLastPageDataOffset(); this.Draw(); } this.AddDealData=function(dealData, aryNewData) { var chart=this.GetDealChart(); if (!chart) return; if (!dealData.Data) //原来是空的 { if (chart.ShowOrder===1 && IFrameSplitOperator.IsNonEmptyArray(aryNewData)) aryNewData=aryNewData.reverse(); dealData.Data=aryNewData; } else { if (chart.ShowOrder===1) { for(var i=0;i<aryNewData.length;++i) { dealData.Data.unshift(aryNewData[i]); } } else { var pageSize=chart.GetPageSize(); for(var i=0;i<aryNewData.length;++i) { dealData.Data.push(aryNewData[i]); if (dealData.DataOffset+pageSize<dealData.Data.length) ++dealData.DataOffset; } } } } this.AutoUpdate=function(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.RequestDealUpdateData(); },frequency); } } this.StopAutoUpdate=function() { this.CancelAutoUpdate(); this.AutoUpdateEvent(false,'JSDealChartContainer::StopAutoUpdate'); if (!this.IsAutoUpdate) return; this.IsAutoUpdate=false; } //设置事件回调 //{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.OnSize=function() { if (!this.Frame) return; this.SetSizeChange(true); var chart=this.ChartPaint[0]; if (chart && this.Data && this.Data.DataOffset>0 && IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { var pageSize=chart.GetPageSize(true); if (pageSize+this.Data.DataOffset>=this.Data.Data.length) //当前屏不能显示满,调整 this.GotoLastPage(); } this.Draw(); } this.SetSizeChange=function(bChanged) { var chart=this.ChartPaint[0]; if (chart) chart.SizeChange=bChanged; } this.OnWheel=function(e) //滚轴 { JSConsole.Chart.Log('[JSDealChartContainer::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.ChartPaint[0]; if (!chart) return; var wheelValue=e.wheelDelta; if (!IFrameSplitOperator.IsObjectExist(e.wheelDelta)) wheelValue=e.deltaY* -0.01; if (wheelValue<0) //下一页 { this.HideAllTooltip(); if (this.GotoNextPage()) this.Draw(); } else if (wheelValue>0) //上一页 { this.HideAllTooltip(); if (this.GotoPreviousPage()) this.Draw(); } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnKeyDown=function(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; } this.GetReportChart=function() { var chart=this.ChartPaint[0]; return chart; } this.UIOnMouseDown=function(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.ChartPaint[0]; if (!chart) return; var clickData=chart.OnMouseDown(x,y,e); if (!clickData) return; if ((clickData.Type==1) && (e.button==0 || e.button==2)) //点击行 { if (clickData.Redraw==true) this.Draw(); } } 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 oldMouseOnStatus=this.LastMouseStatus.MouseOnStatus; this.LastMouseStatus.OnMouseMove=null; var bDrawTooltip=false; if (this.LastMouseStatus.TooltipStatus) bDrawTooltip=true; this.LastMouseStatus.TooltipStatus=null; var bShowMinuteTooltip=false; var chartTooltipData=null; this.LastMouseStatus.OnMouseMove={ X:x, Y:y }; var mouseStatus={ Cursor:"default", Name:"Default"};; //鼠标状态 var report=this.GetReportChart(); var bDraw=false; if (report) { var tooltipData=report.GetTooltipData(x,y); //单元格提示信息 if (tooltipData) { if (tooltipData.Type==20) { if (tooltipData.Data && tooltipData.Data.Symbol) { bShowMinuteTooltip=true; chartTooltipData={ Symbol:tooltipData.Data.Symbol, Rect:tooltipData.Rect }; } } /* else if (tooltipData.Type==21) { if (tooltipData.Stock && tooltipData.Stock.Symbol) { bShowKLineTooltip=true; chartTooltipData={ Symbol:tooltipData.Stock.OriginalSymbol, Rect:tooltipData.Rect }; } } */ else { this.LastMouseStatus.TooltipStatus={ X:x, Y:y, Data:tooltipData, ClientX:e.clientX, ClientY:e.clientY }; bDrawTooltip=true; } } } if (mouseStatus) this.UIElement.style.cursor=mouseStatus.Cursor; if (bDraw) this.Draw(); 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(); } if (!bShowMinuteTooltip) this.HideMinuteChartTooltip(); if (bShowMinuteTooltip) this.ShowMinuteChartTooltip(null, null, chartTooltipData); } this.UIOnDblClick=function(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.ChartPaint[0]; if (chart) chart.OnDblClick(x,y,e); } this.UIOnContextMenu=function(e) { e.preventDefault(); } this.UIOnMounseOut=function(e) { this.HideAllTooltip(); } this.UIOnMouseleave=function(e) { this.HideAllTooltip(); } this.GotoNextPage=function() { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageSize=chart.GetPageSize(); if (pageSize>this.Data.Data.length) return false; var offset=this.Data.DataOffset+pageSize; 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; } this.GotoPreviousPage=function() { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; if (this.Data.DataOffset<=0) return false; var pageSize=chart.GetPageSize(); var offset=this.Data.DataOffset; offset-=pageSize; if (offset<0) offset=0; this.Data.DataOffset=offset; return true; } this.GotoLastPage=function() { var chart=this.ChartPaint[0]; if (!chart) return; //显示最后一屏 var pageSize=chart.GetPageSize(true); var offset=this.Data.Data.length-pageSize; if (offset<0) offset=0; this.Data.DataOffset=offset; } this.SetColumn=function(aryColunm, option) { var chart=this.ChartPaint[0]; if (chart) { chart.SetColumn(aryColunm); chart.SizeChange=true; if (option && option.Redraw) this.Draw(); } } 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) { this.SetSizeChange(true); this.Draw(); } } } JSDealChartContainer.JsonDataToDealData=function(data) { var symbol=data.symbol; var result=[]; if (!IFrameSplitOperator.IsNonEmptyArray(data.detail)) return result; //0=时间 1=价格 2=成交量 3=成交金额 4=BS 5=字符串时间 6=ID 100=Guid for(var i=0;i<data.detail.length;++i) { var item=data.detail[i]; var dealItem={ Time:item[0], Price:item[1], Vol:item[2], BS:item[4], Amount:item[3], Guid:Guid() }; dealItem.Source=item; if (item[5]) dealItem.StrTime=item[5]; if (item[6]) dealItem.ID=item[6]; if (item[11]) dealItem.Symbol=item[11]; //股票代码 if (item[12]) dealItem.Name=item[12]; //股票名称 if (item[13] || item[13]===null) dealItem.BGColor=item[13]; //整行颜色 if (item[100]) dealItem.Guid=item[100]; //柱子类型 if (item[50]) dealItem.MultiBar1=item[50]; if (item[51]) dealItem.MultiBar2=item[51]; if (item[52]) dealItem.MultiBar3=item[52]; if (item[53]) dealItem.MultiBar4=item[53]; //10个数值型 101-199 if (IFrameSplitOperator.IsNumber(item[101])) dealItem.ReserveNumber1=item[101]; if (IFrameSplitOperator.IsNumber(item[102])) dealItem.ReserveNumber2=item[102]; if (IFrameSplitOperator.IsNumber(item[103])) dealItem.ReserveNumber3=item[103]; if (IFrameSplitOperator.IsNumber(item[104])) dealItem.ReserveNumber4=item[104]; if (IFrameSplitOperator.IsNumber(item[105])) dealItem.ReserveNumber5=item[105]; if (IFrameSplitOperator.IsNumber(item[106])) dealItem.ReserveNumber6=item[106]; if (IFrameSplitOperator.IsNumber(item[107])) dealItem.ReserveNumber7=item[107]; if (IFrameSplitOperator.IsNumber(item[108])) dealItem.ReserveNumber8=item[108]; if (IFrameSplitOperator.IsNumber(item[109])) dealItem.ReserveNumber9=item[109]; if (IFrameSplitOperator.IsNumber(item[110])) dealItem.ReserveNumber10=item[110]; //10个字符型 201-299 if (IFrameSplitOperator.IsString(item[201]) || IFrameSplitOperator.IsObject(item[201])) dealItem.ReserveString1=item[201]; if (IFrameSplitOperator.IsString(item[202]) || IFrameSplitOperator.IsObject(item[202])) dealItem.ReserveString2=item[202]; if (IFrameSplitOperator.IsString(item[203]) || IFrameSplitOperator.IsObject(item[203])) dealItem.ReserveString3=item[203]; if (IFrameSplitOperator.IsString(item[204]) || IFrameSplitOperator.IsObject(item[204])) dealItem.ReserveString4=item[204]; if (IFrameSplitOperator.IsString(item[205]) || IFrameSplitOperator.IsObject(item[205])) dealItem.ReserveString5=item[205]; if (IFrameSplitOperator.IsString(item[206]) || IFrameSplitOperator.IsObject(item[206])) dealItem.ReserveString6=item[206]; if (IFrameSplitOperator.IsString(item[207]) || IFrameSplitOperator.IsObject(item[207])) dealItem.ReserveString7=item[207]; if (IFrameSplitOperator.IsString(item[208]) || IFrameSplitOperator.IsObject(item[208])) dealItem.ReserveString8=item[208]; if (IFrameSplitOperator.IsString(item[209]) || IFrameSplitOperator.IsObject(item[209])) dealItem.ReserveString9=item[209]; if (IFrameSplitOperator.IsString(item[210]) || IFrameSplitOperator.IsObject(item[210])) dealItem.ReserveString10=item[210]; result.push(dealItem); } return result; } function JSDealFrame() { this.ChartBorder; this.Canvas; //画布 this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; this.ReloadResource=function(resource) { this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; } this.Draw=function(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; 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 = 'left'; this.Canvas.textBaseline = 'bottom'; var x=this.ChartBorder.GetLeft()+5; var y=this.ChartBorder.GetBottom()-5; this.Canvas.fillText(text,x,y); } } var DEAL_COLUMN_ID= { TIME_ID:0, //时间 PRICE_ID:1, //成交价格 VOL_ID:2, //成交量 DEAL_ID:3, //成交笔数 BS_ID:4, UPDOWN_ID:5, //涨跌 STRING_TIME_ID:6, //字符串时间 INDEX_ID:7, //序号 从1开始 CENTER_BAR_ID:9, //中心柱子 CUSTOM_TEXT_ID:10, //自定义文本 SYMBOL_ID:11, //股票代码 NAME_ID:12, //股票名称 //预留数值类型 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, MULTI_BAR_ID:50, //多颜色柱子 MULTI_BAR2_ID:51, MULTI_BAR3_ID:52, MULTI_BAR4_ID:53 } var MAP_DEAL_COLUMN_FIELD=new Map( [ [DEAL_COLUMN_ID.SYMBOL_ID, "Symbol"], [DEAL_COLUMN_ID.NAME_ID, "Name"], [DEAL_COLUMN_ID.PRICE_ID, "Price"], [DEAL_COLUMN_ID.MULTI_BAR_ID, "MultiBar1"], [DEAL_COLUMN_ID.MULTI_BAR2_ID, "MultiBar2"], [DEAL_COLUMN_ID.MULTI_BAR3_ID, "MultiBar3"], [DEAL_COLUMN_ID.MULTI_BAR4_ID, "MultiBar4"], [DEAL_COLUMN_ID.RESERVE_NUMBER1_ID,"ReserveNumber1"], [DEAL_COLUMN_ID.RESERVE_NUMBER2_ID,"ReserveNumber2"], [DEAL_COLUMN_ID.RESERVE_NUMBER3_ID,"ReserveNumber3"], [DEAL_COLUMN_ID.RESERVE_NUMBER4_ID,"ReserveNumber4"], [DEAL_COLUMN_ID.RESERVE_NUMBER5_ID,"ReserveNumber5"], [DEAL_COLUMN_ID.RESERVE_NUMBER6_ID,"ReserveNumber6"], [DEAL_COLUMN_ID.RESERVE_NUMBER7_ID,"ReserveNumber7"], [DEAL_COLUMN_ID.RESERVE_NUMBER8_ID,"ReserveNumber8"], [DEAL_COLUMN_ID.RESERVE_NUMBER9_ID,"ReserveNumber9"], [DEAL_COLUMN_ID.RESERVE_NUMBER10_ID,"ReserveNumber10"], [DEAL_COLUMN_ID.RESERVE_STRING1_ID,"ReserveString1"], [DEAL_COLUMN_ID.RESERVE_STRING2_ID,"ReserveString2"], [DEAL_COLUMN_ID.RESERVE_STRING3_ID,"ReserveString3"], [DEAL_COLUMN_ID.RESERVE_STRING4_ID,"ReserveString4"], [DEAL_COLUMN_ID.RESERVE_STRING5_ID,"ReserveString5"], [DEAL_COLUMN_ID.RESERVE_STRING6_ID,"ReserveString6"], [DEAL_COLUMN_ID.RESERVE_STRING7_ID,"ReserveString7"], [DEAL_COLUMN_ID.RESERVE_STRING8_ID,"ReserveString8"], [DEAL_COLUMN_ID.RESERVE_STRING9_ID,"ReserveString9"], [DEAL_COLUMN_ID.RESERVE_STRING10_ID,"ReserveString10"], ]); function ChartDealList() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartDealList'; //类名 this.IsDrawFirst=false; this.GetEventCallback; this.Data; //数据 { Data:[ { Time:, Price:, Vol:, BS:, StrTime } ], Offset: } //this.Data={Offset:0, Data:[ {Time:925, Price:20.1, Vol:10000050, BS:1, Deal:45 }, {Time:925, Price:18.2, Vol:1150, BS:1, Deal:5 }] }; this.Symbol; this.YClose; //昨收 this.YFClose; //昨结算 this.Open; //开盘价 this.Decimal=2; //小数位数 this.IsSingleTable=false; //单表模式 this.IsShowHeader=true; //是否显示表头 this.ShowOrder=1; //0=顺序 1=倒序 this.SelectedData={ Index:null, Guid:null, Enable:false }; //{ Index:序号, Guid, Enable:是否启动 } this.SizeChange=true; //涨跌颜色 this.UpColor=g_JSChartResource.DealList.UpTextColor; this.DownColor=g_JSChartResource.DealList.DownTextColor; this.UnchangeColor=g_JSChartResource.DealList.UnchagneTextColor; this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 this.SelectedConfig={ BGColor:g_JSChartResource.DealList.Selected.BGColor, LineColor:g_JSChartResource.DealList.Selected.LineColor, LineWidth:g_JSChartResource.DealList.Selected.LineWidth }; this.SelectedStyle=1; //选中行样式 1=整行填充 2=底部绘制直线 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.DealList.Header.Font.Size, Name:g_JSChartResource.DealList.Header.Font.Name }; this.HeaderColor=g_JSChartResource.DealList.Header.Color; this.HeaderMergin= { Left:g_JSChartResource.DealList.Header.Mergin.Left, Right:g_JSChartResource.DealList.Header.Mergin.Right, Top:g_JSChartResource.DealList.Header.Mergin.Top, Bottom:g_JSChartResource.DealList.Header.Mergin.Bottom }; //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.DealList.Row.Font.Size, Name:g_JSChartResource.DealList.Row.Font.Name }; this.RowMergin={ Top:g_JSChartResource.DealList.Row.Mergin.Top, Bottom:g_JSChartResource.DealList.Row.Mergin.Bottom }; this.BarMergin= { Top:g_JSChartResource.DealList.Row.BarMergin.Top, Left:g_JSChartResource.DealList.Row.BarMergin.Left, Right:g_JSChartResource.DealList.Row.BarMergin.Right, Bottom:g_JSChartResource.DealList.Row.BarMergin.Bottom }; //缓存 this.HeaderFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.RowCount=0; this.TableWidth=0; this.TableCount=0; this.HeaderHeight=0; this.Column= [ { Type:DEAL_COLUMN_ID.TIME_ID, Title:"时间", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.Time, MaxText:"88:88:88" , Foramt:"HH:MM:SS"}, { Type:DEAL_COLUMN_ID.PRICE_ID, Title:"价格", TextAlign:"center", Width:null, MaxText:"888888.88"}, { Type:DEAL_COLUMN_ID.VOL_ID, Title:"成交", TextAlign:"right", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.Vol, MaxText:"888888"}, { Type:DEAL_COLUMN_ID.BS_ID, Title:"", TextAlign:"right", Width:null, MaxText:"擎" } ]; this.RectClient={}; this.AryCellRect=[]; //{ Rect:, Type: 1=单行 } //Type:20=分时图 //{ Rect, Data, Index, Column, Type }} this.TooltipRect=[]; this.ReloadResource=function(resource) { this.UpColor=g_JSChartResource.DealList.UpTextColor; this.DownColor=g_JSChartResource.DealList.DownTextColor; this.UnchangeColor=g_JSChartResource.DealList.UnchagneTextColor; this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.DealList.Header.Font.Size, Name:g_JSChartResource.DealList.Header.Font.Name }; this.HeaderColor=g_JSChartResource.DealList.Header.Color; this.HeaderMergin= { Left:g_JSChartResource.DealList.Header.Mergin.Left, Right:g_JSChartResource.DealList.Header.Mergin.Right, Top:g_JSChartResource.DealList.Header.Mergin.Top, Bottom:g_JSChartResource.DealList.Header.Mergin.Bottom }; //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.DealList.Row.Font.Size, Name:g_JSChartResource.DealList.Row.Font.Name }; this.RowMergin={ Top:g_JSChartResource.DealList.Row.Mergin.Top, Bottom:g_JSChartResource.DealList.Row.Mergin.Bottom }; for(var i=0;i<this.Column.length;++i) { var item=this.Column[i]; if (item.Type==DEAL_COLUMN_ID.TIME_ID || item.Type==DEAL_COLUMN_ID.STRING_TIME_ID) item.TextColor=g_JSChartResource.DealList.FieldColor.Time; else if (item.Type==DEAL_COLUMN_ID.VOL_ID) item.TextColor=g_JSChartResource.DealList.FieldColor.Vol; else if (item.Type==DEAL_COLUMN_ID.DEAL_ID) item.TextColor=g_JSChartResource.DealList.FieldColor.Deal; else if (item.Type==DEAL_COLUMN_ID.INDEX_ID) item.TextColor=g_JSChartResource.DealList.FieldColor.Index; } } this.SetColumn=function(aryColumn) { if (!IFrameSplitOperator.IsNonEmptyArray(aryColumn)) return; this.Column=[]; for(var i=0;i<aryColumn.length;++i) { var item=aryColumn[i]; var colItem=this.GetDefaultColunm(item.Type); if (!colItem) continue; if (item.Title) colItem.Title=item.Title; if (item.TextAlign) colItem.Text