UNPKG

hqchart

Version:

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

1,570 lines (1,285 loc) 405 kB
/* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装股票列表控件 (H5版本) 不提供内置测试数据 */ function JSReportChart(divElement) { this.DivElement=divElement; this.JSChartContainer; //表格控件 this.ResizeListener; //大小变动监听 //h5 canvas this.CanvasElement=document.createElement("canvas"); this.CanvasElement.className='jsreportlist-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("[JSReportChart::JSReportChart] divElement hasChildNodes", divElement.childNodes); } divElement.appendChild(this.CanvasElement); //额外的画布 this.MapExtraCanvasElement=new Map(); //key=画布名字, value={ Element:, Canvas:} this.CreateExtraCanvasElement=function(name, option) { if (this.MapExtraCanvasElement.has(name)) return this.MapExtraCanvasElement.get(name); var element=document.createElement("canvas"); element.className='jsreportlist-drawing-extra'; element.id=Guid(); if (name==JSReportChart.CorssCursorCanvasKey) element.setAttribute("tabindex",5); else element.setAttribute("tabindex",1); if (element.style) { element.style.outline='none'; element.style.position="absolute"; element.style.left='0px'; element.style.top='0px'; element.style["pointer-events"]="none"; } if (option) { if (IFrameSplitOperator.IsNumber(option.TabIndex)) element.setAttribute("tabindex",option.TabIndex); if (IFrameSplitOperator.IsNumber(option.ZIndex)) element.style["z-index"]=option.ZIndex; } if (this.CanvasElement) { element.height=this.CanvasElement.height; element.width=this.CanvasElement.width; if (element.style) { element.style.width=this.CanvasElement.style.width; element.style.height=this.CanvasElement.style.height } } divElement.appendChild(element); var item={ Element:element, Canvas:null }; this.MapExtraCanvasElement.set(name, item); } this.GetExtraCanvas=function(name) { if (!this.MapExtraCanvasElement.has(name)) return null; var item=this.MapExtraCanvasElement.get(name); if (!item.Element) return null; if (!item.Canvas) item.Canvas=item.Element.getContext("2d"); return item; } 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; //扩展画布 for(var mapItem of this.MapExtraCanvasElement) { var item=mapItem[1]; var element=item.Element; if (!element) continue; element.height=this.CanvasElement.height; element.width=this.CanvasElement.width; element.style.width=this.CanvasElement.style.width; element.style.height=this.CanvasElement.style.height; } JSConsole.Chart.Log(`[JSReportChart::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.CreateJSReportChartContainer(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.EnablePopMenuV2===true) chart.InitalPopMenu(); if (option.FloatTooltip && option.FloatTooltip.Enable) chart.InitalFloatTooltip(option.FloatTooltip); //提示信息 if (option.MinuteChartTooltip && option.MinuteChartTooltip.Enable) chart.InitalMinuteChartTooltip(option.MinuteChartTooltip); if (option.KLineChartTooltip && option.KLineChartTooltip.Enable) chart.InitalKLineChartTooltip(option.KLineChartTooltip); if (option.Symbol) chart.Symbol=option.Symbol; if (option.Name) chart.Name=option.Name; var requestOption={ Callback:null }; if (chart.Symbol) requestOption.Callback=function(){ chart.RequestMemberListData(); }; if (option.LoadStockList===false) { chart.ChartSplashPaint.IsEnableSplash=false; chart.Draw(); } else { chart.RequestStockListData(requestOption); //下载码表 } } this.CreateJSReportChartContainer=function(option) { var chart=new JSReportChartContainer(this.CanvasElement); chart.GetExtraCanvas=(name)=>{ return this.GetExtraCanvas(name); } chart.Create(option); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) chart.SetColumn(option.Column); if (IFrameSplitOperator.IsNonEmptyArray(option.Tab)) chart.SetTab(option.Tab); if (IFrameSplitOperator.IsNumber(option.TabSelected)) chart.SetSelectedTab(option.TabSelected); if (IFrameSplitOperator.IsBool(option.EnableDragRow)) chart.EnableDragRow=option.EnableDragRow; if (IFrameSplitOperator.IsNumber(option.DragRowType)) chart.DragRowType=option.DragRowType; if (IFrameSplitOperator.IsBool(option.EnableDragHeader)) chart.EnableDragHeader=option.EnableDragHeader; if (IFrameSplitOperator.IsNumber(option.WheelPageType)) chart.WheelPageConfig.Type=option.WheelPageType; if (IFrameSplitOperator.IsBool(option.PageUpDownCycle)) chart.PageUpDownCycle=option.PageUpDownCycle; if (IFrameSplitOperator.IsBool(option.EnablePageUpdate)) chart.EnablePageUpdate=option.EnablePageUpdate; if (option.WheelPage) { var item=option.WheelPage; if (IFrameSplitOperator.IsNumber(item.Type)) chart.WheelPageConfig.Type=item.Type; if (IFrameSplitOperator.IsPlusNumber(item.RowStep)) chart.WheelPageConfig.RowStep=item.RowStep; if (IFrameSplitOperator.IsBool(item.EnableCtrlTurn)) chart.WheelPageConfig.EnableCtrlTurn=item.EnableCtrlTurn; } //数据下载提示信息 if (IFrameSplitOperator.IsObject(option.SplashTitle)) { var item=option.SplashTitle; if (item) chart.SplashTitle.StockList=item.StockList; if (item) chart.SplashTitle.MemberList=item.MemberList; } if (option.VScrollbar) chart.SetVScrollbar(option.VScrollbar); if (option.SortInfo) { var item=option.SortInfo; if (item.Search) chart.SortInfo.Field=chart.FindFiledIndex(item.Search); if (IFrameSplitOperator.IsNumber(item.Field)) chart.SortInfo.Field=item.Field; if (IFrameSplitOperator.IsNumber(item.Sort)) chart.SortInfo.Sort=item.Sort; } if (option.VirtualTable) { var item=option.VirtualTable; if (IFrameSplitOperator.IsBool(item.Enable)) chart.Data.Virtual.Enable=item.Enable; } var reportChart=chart.GetReportChart(); if (reportChart) { if (IFrameSplitOperator.IsNumber(option.TextOverflowStyle)) reportChart.TextOverflowStyle=option.TextOverflowStyle; if (IFrameSplitOperator.IsNumber(option.MultiSelectModel)) reportChart.MultiSelectModel=option.MultiSelectModel; if (IFrameSplitOperator.IsNumber(option.SelectedStyle)) reportChart.SelectedStyle=option.SelectedStyle; if (option.BottomTab) { var item=option.BottomTab; if (IFrameSplitOperator.IsBool(item.IsShow)) reportChart.Tab.IsShow=item.IsShow; } } this.SetChartBorder(chart, option); //是否自动更新 if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate; if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; //数据筛选 if (option.DataFilter) { var item=option.DataFilter; if (IFrameSplitOperator.IsBool(item.Enable)) chart.DataFilterConfig.Enable=item.Enable; } //注册事件 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.CreateResizeListener=function() { this.ResizeListener = new ResizeObserver((entries)=>{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } this.OnDivResize=function(entries) { JSConsole.Chart.Log("[JSReportChart::OnDivResize] entries=", entries); this.OnSize(); } ///////////////////////////////////////////////////////////////////////////// //对外接口 //切换股票代码接口 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.SetSelectedRow=function(option) { if (this.JSChartContainer) this.JSChartContainer.SetSelectedRow(option); } this.DeleteSymbol=function(arySymbol, option) { if (this.JSChartContainer) this.JSChartContainer.DeleteSymbol(arySymbol, option); } this.AddSymbol=function(arySymbol, option) { if (this.JSChartContainer) this.JSChartContainer.AddSymbol(arySymbol, option); } this.EnableDataFilter=function(bEnable, option) //启动|关闭筛选 { if (this.JSChartContainer) this.JSChartContainer.EnableDataFilter(bEnable, option); } //事件回调 this.AddEventCallback=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function') { JSConsole.Chart.Log('[JSReportChart:AddEventCallback] obj=', obj); this.JSChartContainer.AddEventCallback(obj); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSReportChart: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('[JSReportChart:Draw] '); this.JSChartContainer.Draw(); } } } JSReportChart.Init=function(divElement) { var jsChartControl=new JSReportChart(divElement); jsChartControl.OnSize(); return jsChartControl; } //自定义风格 JSReportChart.SetStyle=function(option) { if (option) g_JSChartResource.SetStyle(option); } //获取颜色配置 (设置配必须啊在JSChart.Init()之前) JSReportChart.GetResource=function() { return g_JSChartResource; } function HQReportItem() { this.OriginalSymbol; //原始代码 this.Symbol; this.Name; this.YClose; this.Open; this.Price; this.High; this.Low; this.Amount; this.Vol; this.Increase; //涨幅 this.UpDown; //涨跌 this.Exchange; //换手 this.Amplitude; //振幅 this.BuyPrice; //买价/量 this.BuyVol; this.SellPrice; //卖价/量 this.SellVol; this.AvPrice; //均价 this.LimitHigh; //涨停价 this.LimitLow; //跌停价 this.VolIn; //内盘 this.VolOut; //外盘 this.DealNum; //现量 this.OutShares; //流通股本 this.TotalShares; //总股本 this.MarketValue; //总市值 this.CircMarketValue;//流通市值 this.CloseLine; //{Data:[], Max:, Min:, Count: } this.ExtendData; //扩展数据 this.Time; this.Date; } function JSReportChartContainer(uielement) { this.ClassName='JSReportChartContainer'; this.Frame; //框架画法 this.ChartPaint=[]; //图形画法 this.ChartSplashPaint=null; //等待提示 this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息 this.SplashTitle={ StockList:"下载码表中.....", MemberList:"下载成分中....." } ; this.Canvas=uielement.getContext("2d"); //画布 this.Symbol; //板块代码 this.Name; //板块名称 this.NetworkFilter; //数据回调接口 this.Data={ XOffset:0, YOffset:0, Data:[], Virtual:{ Enable:false, Count:0 } }; //股票列表 (Virtual 虚拟表) this.SourceData={ Data:[] } ; //原始股票顺序(排序还原用) this.BlockData=new Map(); //当前板块数据 this.MapStockData=new Map(); //原始股票数据 this.FixedRowData={ Data:[], Type:0, Symbol:[] }; //顶部固定行Data:[{ Value:, Text:, Color:, TextAgiln: }], Type:0=自定义数据, 1 =(股票数据) Symbol:[], this.FlashBG=new Map(); this.FlashBGTimer=null; //闪烁背景 Value:{ LastTime:数据最后的时间, Data: { Key:ID, BGColor:, Time: , Count: 次数 } }; this.GlobalOption={ FlashBGCount:0 }; //this.FixedRowData.Data=[ [null, {Value:11, Text:"11" }], [null, null, null, {Value:12, Text:"ddddd", Color:"rgb(45,200,4)"}]]; this.SortInfo={ Field:-1, Sort:0 }; //排序信息 {Field:排序字段id, Sort:0 不排序 1升序 2降序 } //行拖拽 this.DragRow; this.DragColumnWidth; //列宽拖动 this.EnableDragRow=false; this.DragRowType=0; //0=插入 1=交换 this.AutoDragScrollTimer=null; this.EnablePageScroll=false; this.DragMove; //={ Click:{ 点击的点}, Move:{最后移动的点}, PreMove:{上一个点的位置} }; //表头拖拽 this.DragHeader; this.EnableDragHeader=false; //事件回调 this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} this.AutoUpdateTimer=null; this.AutoUpdateFrequency=15000; //15秒更新一次数据 this.EnablePageUpdate=true; //当前页更新模式 ture=翻页都请求数据 false=所有页的数据一次下载完成 this.DelayUpdateTimer=null; //延迟更新 this.DelayUpdateFrequency=500; //延迟更新时间 this.UIElement=uielement; this.LastPoint=new Point(); //鼠标位置 this.IsOnTouch=false; this.TouchDrag; this.TouchMoveMinAngle=70; //左右移动最小角度 this.YStepPixel=5*GetDevicePixelRatio(); this.XStepPixel=10*GetDevicePixelRatio(); this.PageUpDownCycle=true; //翻页循环 this.DragPageCycle=true; //手机翻页循环 //this.WheelPageType=0; //鼠标滚轴翻页模式 0=一页一页翻 1=一条一条翻 //鼠标滚轴配置 // Type:0=一页一页翻 1=一条一条翻, // RowStep:单条数据滚动步长 // EnableCtrlTurn Ctrl+滚轴翻页 this.WheelPageConfig={ Type:0, RowStep:1, EnableCtrlTurn:false } //拖拽滚动条 this.DragXScroll=null; //{Start:{x,y}, End:{x, y}} this.DragYScroll=null; this.IsShowVScrollbar=false; this.IsDestroy=false; //是否已经销毁了 this.JSPopMenu; //内置菜单 this.IsShowRightMenu=true; // this.TooltipMinuteChart; //分时图 this.TooltipKLineChart; //分时图 this.FloatTooltip; //提示浮框 //MouseOnStatus:{ RowIndex:行, ColumnIndex:列} this.LastMouseStatus={ MoveStatus:null, TooltipStatus:null, MouseOnStatus:null }; this.RequestStatus={ IsFinishStockList:false, IsFinishMemberList:false }; //下载状态 this.DataFilterConfig={ Enable:false, }; //数据筛选 this.ChartDestroy=function() //销毁 { this.IsDestroy=true; this.StopAutoUpdate(); this.DestroyMinuteChartTooltip(); this.DestroyKLineChartTooltip(); this.DestroyFloatTooltip(); } this.StopAutoDragScrollTimer=function() { JSConsole.Chart.Log("[JSReportChartContainer::StopAutoDragScrollTimer] stop "); this.EnablePageScroll=false; if (this.AutoDragScrollTimer!=null) { clearTimeout(this.AutoDragScrollTimer); this.AutoDragScrollTimer = null; } } this.InitalPopMenu=function() //初始化弹出窗口 { if (this.JSPopMenu) return; this.JSPopMenu=new JSPopMenu(); //内置菜单 this.JSPopMenu.Inital(); } 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; } this.InitalKLineChartTooltip=function(option) { if (this.TooltipKLineChart) return; this.TooltipKLineChart=new JSTooltipKLineChart(); this.TooltipKLineChart.Inital(this, option); this.TooltipKLineChart.Create(); } this.DestroyKLineChartTooltip=function() { if (!this.TooltipKLineChart) return; this.TooltipKLineChart.Destroy(); this.TooltipKLineChart=null; } this.InitalFloatTooltip=function(option) { if (this.FloatTooltip) return; this.FloatTooltip=new JSFloatTooltip(); this.FloatTooltip.Inital(this, option); this.FloatTooltip.Create(); } this.HideFloatTooltip=function() { if (!this.FloatTooltip) return; this.FloatTooltip.Hide(); } this.DestroyFloatTooltip=function() { if (!this.FloatTooltip) return; this.FloatTooltip.Destroy(); this.FloatTooltip=null; } 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:3, }; this.FloatTooltip.Update(sendData); } //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.ShowKLineChartTooltip=function(x,y, data) { if (!this.TooltipKLineChart) 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.TooltipKLineChart.Show(data, x,y); } this.HideKLineChartTooltip=function() { if (!this.TooltipKLineChart) return; this.TooltipKLineChart.Hide(); } this.HideAllTooltip=function() { this.HideKLineChartTooltip(); this.HideMinuteChartTooltip(); this.HideFloatTooltip(); } this.AutoScrollPage=function(step) { this.AutoDragScrollTimer=setTimeout(() => { this.ChartOperator_Temp_ScrollPage(step); },300); } this.ChartOperator_Temp_ScrollPage=function(moveSetp) { if (!this.EnablePageScroll) return; var reportChart=this.GetReportChart() if (!reportChart) return; if (moveSetp>0) { var pageStatus=reportChart.GetCurrentPageStatus(); if (pageStatus.IsEnd) return; this.MoveYOffset(moveSetp, false); ++moveSetp; } else if (moveSetp<0) { if (this.Data.YOffset<=0) return; this.MoveYOffset(moveSetp, false); --moveSetp; } else { return; } this.Draw(); if (!this.EnablePageScroll) return; this.AutoScrollPage(moveSetp); return; } //清空画布 this.ClearCanvas=function(canvas) { if (!canvas) return; if (!this.UIElement) return; canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); } //清空固定行数据 this.ClearFixedRowData=function() { this.FixedRowData.Data=[]; this.FixedRowData.Symbol=[]; } //设置固定行 this.SetFixedRowCount=function(value) { var chart=this.GetReportChart(); if (!chart) return; chart.FixedRowCount=value; } //创建 this.Create=function(option) { this.UIElement.JSChartContainer=this; //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.IsEnableSplash=true; //创建框架 this.Frame=new JSReportFrame(); 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 ChartReport(); 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.GetStockDataCallback=(symbol)=>{ return this.GetStockData(symbol);} chart.GetBlockDataCallback=(symbol)=>{ return this.GetBlockData(symbol);} chart.GetFlashBGDataCallback=(symbol, time)=>{ return this.GetFlashBGData(symbol, time); } chart.Data=this.Data; chart.GlobalOption=this.GlobalOption; chart.FixedRowData=this.FixedRowData; chart.SortInfo=this.SortInfo; chart.Tab=new ChartReportTab(); chart.Tab.Frame=this.Frame; chart.Tab.Canvas=this.Canvas; chart.Tab.ChartBorder=this.Frame.ChartBorder; chart.Tab.Report=chart; chart.VScrollbar=new ChartVScrollbar(); chart.VScrollbar.Frame=this.Frame; chart.VScrollbar.Canvas=this.Canvas; chart.VScrollbar.ChartBorder=this.Frame.ChartBorder; chart.VScrollbar.Report=chart; chart.VScrollbar.IsShowCallback=()=> { if (this.DragYScroll) return true; return this.IsShowVScrollbar; } this.ChartPaint[0]=chart; //页脚 if (option && option.PageInfo===true) { var pageInfoChart=new ChartReportPageInfo(); pageInfoChart.Frame=this.Frame; pageInfoChart.ChartBorder=this.Frame.ChartBorder; pageInfoChart.Canvas=this.Canvas; pageInfoChart.Report=chart; this.ChartPaint[1]=pageInfoChart; } if (option) { if (IFrameSplitOperator.IsBool(option.IsShowHeader)) chart.IsShowHeader=option.IsShowHeader; //是否显示表头 if (IFrameSplitOperator.IsNumber(option.FixedColumn)) chart.FixedColumn=option.FixedColumn; //固定列 if (IFrameSplitOperator.IsNumber(option.BorderLine)) this.Frame.BorderLine=option.BorderLine; //边框 if (IFrameSplitOperator.IsBool(option.TabShow)) chart.Tab.IsShow=option.TabShow; if (IFrameSplitOperator.IsNumber(option.FixedRowCount)) chart.FixedRowCount=option.FixedRowCount; //固定行 if (IFrameSplitOperator.IsNumber(option.SelectedModel)) chart.SelectedModel=option.SelectedModel; if (IFrameSplitOperator.IsNumber(option.HeaderRowCount)) chart.HeaderRowCount=option.HeaderRowCount; if (IFrameSplitOperator.IsNonEmptyArray(option.FixedSymbol)) { chart.FixedRowCount=0; this.FixedRowData.Type=1; this.FixedRowData.Symbol=[]; var aryData=option.FixedSymbol; for(var i=0; i<aryData.length; ++i) { var item=aryData[i]; this.FixedRowData.Symbol.push(item.Symbol); ++chart.FixedRowCount; } } if (option.CellBorder) { var item=option.CellBorder; if (IFrameSplitOperator.IsBool(item.IsShowVLine)) chart.CellBorderConfig.IsShowVLine=item.IsShowVLine; if (IFrameSplitOperator.IsBool(item.IsShowHLine)) chart.CellBorderConfig.IsShowHLine=item.IsShowHLine; if (IFrameSplitOperator.IsBool(item.IsFullLine)) chart.CellBorderConfig.IsFullLine=item.IsFullLine; } } 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 (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 this.UIElement.ondblclick=(e)=>{ this.UIOnDblClick(e); } this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); } this.UIElement.onmouseup=(e)=>{ this.UIOnMounseUp(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.UIElement.ontouchstart=(e)=> { this.OnTouchStart(e); } this.UIElement.ontouchmove=(e)=> {this.OnTouchMove(e); } this.UIElement.ontouchend=(e)=> {this.OnTouchEnd(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; //手机端需要根据分辨率比调整线段宽度 this.LastMouseStatus.MouseOnStatus=null; 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(this.LastMouseStatus); } for(var i=0; i<this.ChartPaint.length; ++i) { var item=this.ChartPaint[i]; if (!item.IsDrawFirst) item.Draw(this.LastMouseStatus); } if (this.GlobalOption.FlashBGCount>0) { this.DelayDraw(500); } } this.DelayDraw=function(frequency) { if (typeof (this.FlashBGTimer) == 'number') { clearTimeout(this.FlashBGTimer); this.FlashBGTimer = null; } this.FlashBGTimer=setTimeout(()=> { this.Draw(); },frequency); } this.ResetReportStatus=function() { this.Data.XOffset=0; this.Data.YOffset=0; } this.ResetReportSelectStatus=function() { var chart=this.GetReportChart(); if (chart) { chart.SelectedRow=-1; chart.SelectedFixedRow=-1; chart.MultiSelectedRow=[]; } } this.ClearData=function() { this.SourceData.Data=[]; this.Data.Data=[]; this.Data.Virtual.Count=0; this.BlockData=new Map(); } this.ClearMapStockData=function() { this.MapStockData=new Map(); } this.ResetSortStatus=function() { this.SortInfo.Field=-1; this.SortInfo.Sort=0; } this.SetSelectedRow=function(option) { var reportChart=this.GetReportChart(); if (!reportChart) return false; if (!reportChart.SetSelectedRow(option)) return false; this.Draw(); } //设置股票列表 this.SetSymbolList=function(arySymbol, option) { this.ClearData(); this.ResetReportStatus(); this.ResetSortStatus(); if (IFrameSplitOperator.IsNonEmptyArray(arySymbol)) { for(var i=0;i<arySymbol.length;++i) { this.Data.Data.push(arySymbol[i]); } } var chart=this.ChartPaint[0]; if (chart) chart.Data=this.Data; this.Draw(); } this.ChangeSymbol=function(symbol, option) { this.Symbol=symbol; this.ClearData(); this.ResetReportStatus(); this.ResetSortStatus(); this.ResetReportSelectStatus(); if (option) { if (IFrameSplitOperator.IsNumber(option.TabSelected)) { var chartTab=this.GetTabChart(); if (chartTab) chartTab.SelectedTabIndex=option.TabSelected; } if (Array.isArray(option.FixedSymbol)) { var chart=this.GetReportChart(); if (chart) { chart.FixedRowCount=0; this.FixedRowData.Type=1; this.FixedRowData.Symbol=[]; var aryData=option.FixedSymbol; for(var i=0; i<aryData.length; ++i) { var item=aryData[i]; this.FixedRowData.Symbol.push(item.Symbol); ++chart.FixedRowCount; } this.SetSizeChange(true); } } if (option.SortInfo) { var item=option.SortInfo; if (item.Search) this.SortInfo.Field=this.FindFiledIndex(item.Search); if (IFrameSplitOperator.IsNumber(item.Field)) this.SortInfo.Field=item.Field; if (IFrameSplitOperator.IsNumber(item.Sort)) this.SortInfo.Sort=item.Sort; } if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) //字段重新设置 { this.SetColumn(option.Column, { Draw:false }) } if (IFrameSplitOperator.IsBool(option.IsReloadStockList) && option.IsReloadStockList) { var requestOption={ Callback:null }; if (this.Symbol) requestOption.Callback=()=>{ this.RequestMemberListData(); }; this.MapStockData=new Map(); this.RequestStatus.IsFinishStockList=false; this.RequestStatus.IsFinishMemberList=false; this.RequestStockListData(requestOption); return; } } this.RequestMemberListData(); } //更新数据 option={ SortInfo:{ Search:, Field:, Sort: } } this.UpdateFullData=function(data, option) { var arySymbol=[]; if (IFrameSplitOperator.IsNonEmptyArray(data.data)) { //0=证券代码 1=股票名称 for(var i=0;i<data.data.length;++i) { var item=data.data[i]; var symbol=item[0]; var stock=null; if (this.MapStockData.has(symbol)) { stock=this.MapStockData.get(symbol); } else { stock=new HQReportItem(); stock.OriginalSymbol=symbol; this.MapStockData.set(symbol, stock); } stock.Symbol=this.GetSymbolNoSuffix(symbol); stock.Name=item[1]; this.ReadStockJsonData(stock, item); arySymbol.push(symbol); } } //设置显示数据 this.Data.Data=[]; this.SourceData.Data=[]; if (IFrameSplitOperator.IsNonEmptyArray(arySymbol)) { for(var i=0;i<arySymbol.length;++i) { this.Data.Data.push(arySymbol[i]); this.SourceData.Data.push(arySymbol[i]); } } if (option && option.SortInfo) { //本地排序 var item=option.SortInfo; if (item.Search) this.SortInfo.Field=this.FindFiledIndex(item.Search); if (IFrameSplitOperator.IsNumber(item.Field)) this.SortInfo.Field=item.Field; if (IFrameSplitOperator.IsNumber(item.Sort)) this.SortInfo.Sort=item.Sort; } //排序 var chart=this.GetReportChart(); if (chart && (this.SortInfo.Sort==1 || this.SortInfo.Sort==2) && IFrameSplitOperator.IsNumber(this.SortInfo.Field) && this.SortInfo.Field>=0) { var column=chart.Column[this.SortInfo.Field]; this.LocalDataSort(column, this.SortInfo); } this.Draw(); } //设置全部的数据 this.SetFullData=function(data, option) { this.ClearMapStockData(); this.ClearData(); this.ResetReportStatus(); this.ResetSortStatus(); this.ResetReportSelectStatus(); this.UpdateFullData(data, option); /* //缓存所有数据 var arySymbol=[]; if (IFrameSplitOperator.IsNonEmptyArray(data.data)) { //0=证券代码 1=股票名称 for(var i=0;i<data.data.length;++i) { var item=data.data[i]; var symbol=item[0]; var stock=null; if (this.MapStockData.has(symbol)) { stock=this.MapStockData.get(symbol); } else { stock=new HQReportItem(); stock.OriginalSymbol=symbol; this.MapStockData.set(symbol, stock); } stock.Symbol=this.GetSymbolNoSuffix(symbol); stock.Name=item[1]; this.ReadStockJsonData(stock, item); arySymbol.push(symbol); } } //设置显示数据 if (IFrameSplitOperator.IsNonEmptyArray(arySymbol)) { for(var i=0;i<arySymbol.length;++i) { this.Data.Data.push(arySymbol[i]); this.SourceData.Data.push(arySymbol[i]); } } this.Draw(); */ } this.RequestMemberListData=function() { if (this.RequestStatus.IsFinishStockList==false) return; //码表没有下完 //this.ChartSplashPaint.SetTitle(this.SplashTitle.MemberList); //this.ChartSplashPaint.EnableSplash(true); //this.Draw(); this.RequestStatus.IsFinishMemberList=false; var self=this; if (this.NetworkFilter) { var obj= { Name:'JSReportChartContainer::RequestMemberListData', //类名:: Explain:'板块成分数据', Request:{ Data: { symbol: this.Symbol } }, Self:this, PreventDefault:false }; if (this.SortInfo.Field>=0 && this.SortInfo.Sort>0) { var reportChart=this.GetReportChart(); if (reportChart) { var column=reportChart.Column[this.SortInfo.Field]; obj.Sort={ Column:column, Field:this.SortInfo.Field, Sort:this.SortInfo.Sort} ; } } this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMemberListData(data); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } //throw { Name:'JSReportChartContainer::RequestMemberListData', Error:'(板块成分数据)不提供内置测试数据' }; } this.RecvMemberListData=function(recvData) { this.ClearData(); if (IFrameSplitOperator.IsNonEmptyArray(recvData.data)) { for(var i=0;i<recvData.data.length;++i) { this.Data.Data.push(recvData.data[i]); this.SourceData.Data.push(recvData.data[i]); } } if (recvData.Virtual) //虚拟表设置 { var item=recvData.Virtual; if (IFrameSplitOperator.IsNumber(item.Count)) this.Data.Virtual.Count=item.Count; } this.RequestStatus.IsFinishMemberList=true; this.DataFilter(); //实时本地数据排序 var chart=this.GetReportChart(); if (chart && (this.SortInfo.Sort==1 || this.SortInfo.Sort==2) && IFrameSplitOperator.IsNumber(this.SortInfo.Field) && this.SortInfo.Field>=0) { var column=chart.Column[this.SortInfo.Field]; this.LocalDataSort(column, this.SortInfo); } this.Draw(); this.UpdateStockData(); } //删除股票 this.DeleteSymbol=function(arySymbol, option) { if (!IFrameSplitOperator.IsNonEmptyArray(arySymbol)) return false; var setSymbol=new Set(arySymbol); var bFinder=false; if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) { var aryData=[]; for(var i=0;i<this.SourceData.Data.length;++i) { var item=this.SourceData.Data[i]; if (setSymbol.has(item)) { bFinder=true; continue; } aryData.push(item); } if (bFinder) this.SourceData.Data=aryData; } if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { var aryData=[]; for(var i=0;i<this.Data.Data.length;++i) { var item=this.Data.Data[i]; if (setSymbol.has(item)) { bFinder=true; continue; } aryData.push(item); } if (bFinder) this.Data.Data=aryData; } if (!bFinder) return false; this.Draw(); this.UpdateStockData(); return true; } //添加股票 this.AddSymbol=function(arySymbol, option) { if (!IFrameSplitOperator.IsNonEmptyArray(arySymbol)) return false; var bDuplicate=true; if (option && IFrameSplitOperator.IsBool(option.Duplicate)) bDuplicate=option.Duplicate; //是否去重 var mapSymbol=new Map(); for(var i=0;i<arySymbol.length;++i) { var item={ Symbol:arySymbol[i], IsExist:false, IsExist2:false }; mapSymbol.set(item.Symbol, item); } if (bDuplicate) { if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) { for(var i=0;i<this.SourceData.Data.length;++i) { var item=this.Data.Data[i]; if (mapSymbol.has(item)) { mapSymbol.get(item).IsExist=true; } } } if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { for(var i=0;i<this.Data.Data.length;++i) { var item=this.Data.Data[i]; if (mapSymbol.has(item)) { mapSymbol.get(item).IsExist2=true; } } } } for(var mapItem of mapSymbol) { var item=mapItem[1]; if (!item.IsExist) this.SourceData.Data.push(item.Symbol); if (!item.IsExist2) this.Data.Data.push(item.Symbol); } this.Draw(); this.UpdateStockData(); return true; } //下载码表 this.RequestStockListData=function(option) { this.RequestStatus.IsFinishStockList=false; this.ChartSplashPaint.SetTitle(this.SplashTitle.StockList); this.ChartSplashPaint.EnableSplash(true); this.Draw(); var self=this; if (this.NetworkFilter) { var obj= { Name:'JSReportChartContainer::RequestStockListData', //类名:: Explain:'码表数据', Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvStockListData(data,option); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } //throw { Name:'JSReportChartContainer::RequestStockListData', Error:'(码表数据)不提供内置测试数据' }; } this.RecvStockListData=function(data, option) { if (IFrameSplitOperator.IsNonEmptyArray(data.data)) { //0=证券代码 1=股票名称 for(var i=0;i<data.data.length;++i) { var item=data.data[i]; var symbol=item[0]; var stock=null; if (this.MapStockData.has(symbol)) { stock=this.MapStockData.get(symbol); } else { stock=new HQReportItem(); stock.OriginalSymbol=symbol; this.MapStockData.set(symbol, stock); } stock.Symbol=this.GetSymbolNoSuffix(symbol); stock.Name=item[1]; if (IFrameSplitOperator.IsNumber(item[88])) stock.PriceColorType=item[88]; this.ReadStockJsonData(stock, item); } } this.RequestStatus.IsFinishStockList=true; if (option && option.Callback) { option.Callback(); return; } this.Draw(); this.UpdateStockData(); } //更新股票数据 this.UpdateMapStockData=function(data) { if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.data)) return; //0=证券代码 1=股票名称 for(var i=0;i<data.data.length;++i) { var item=data.data[i]; var symbol=item[0]; var stock=null; if (this.MapStockData.has(symbol)) { stock=this.MapStockData.get(symbol); } else { stock=new HQReportItem(); stock.OriginalSymbol=symbol; this.MapStockData.set(symbol, stock); } stock.Symbol=this.GetSymbolNoSuffix(symbol); stock.Name=item[1]; this.ReadStockJsonData(stock, item); } } //获取个股数据 this.GetStockData=function(symbol) { if (!this.MapStockData) return null; if (!this.MapStockData.has(symbol)) return null; return this.MapStockData.get(symbol); } this.GetBlockData=function(symbol) { if (!this.BlockData) return null; if (!this.BlockData.has(symbol)) return null; return this.BlockData.get(symbol); } //obj={ ID:, Color: , Time:, Count: } this.SetFlashBGItem=function(symbol, obj) { var item={ ID:obj.ID, Color:obj.Color, Count:1 }; if (IFrameSplitOperator.IsNumber(obj.Count)) item.Count=obj.Count; if (IFrameSplitOperator.IsNumber(obj.Time)) item.Time=obj.Time; else item.Time=Date.now(); if (this.FlashBG.has(symbol)) { var stockItem=this.FlashBG.get(symbol); stockItem.LastTime=item.Time; stockItem.Data.set(item.ID, item); } else { var stockItem={ LastTime:item.Time, Data:new Map([ [item.ID, item ] ]) }; this.FlashBG.set(symbol, stockItem); } } this.GetFlashBGData=function(symbol, time) { if (!this.FlashBG) return null; if (!this.FlashBG.has(symbol)) return null; var timeDiff=3*1000; var stockItem=this.FlashBG.get(symbol); if (time-stockItem.LastTime>=timeDiff) //超时的删除 { this.FlashBG.delete(symbol); return null; } if (!stockItem.Data || stockItem.Data.size<=0) { this.FlashBG.delete(symbol); return null; } var aryDelID=[]; //超时需要参数的 for(var mapItem of stockItem.Data) { var item=mapItem[1]; if (time-item.Time>=timeDiff || item.Count<=0) aryDelID.push(item.ID); } if (IFrameSplitOperator.IsNonEmptyArray(aryDelID)) { for(var i=0; i<aryDelID.length; ++i) { stockItem.Data.delete(aryDelID[i]); } if (stockItem.Data.size<=0) { this.FlashBG.delete(symbol); return null; } } return stockItem; } //delay=是否延迟 this.DelayUpdateStockData=function() {