/* copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装图形控件 (微信小程序版本) */ //日志 import { JSConsole } from "./umychart.console.wechat.js" import { JSNetwork } from "./umychart.network.wechart.js" import { JSCanvasElement } from "./umychart.element.wechart.js"; //行情数据结构体 及涉及到的行情算法(复权,周期等) import { ChartData, HistoryData, SingleData, MinuteData, CUSTOM_DAY_PERIOD_START, CUSTOM_DAY_PERIOD_END, CUSTOM_MINUTE_PERIOD_START, CUSTOM_MINUTE_PERIOD_END, CUSTOM_SECOND_PERIOD_START, CUSTOM_SECOND_PERIOD_END, Rect, DataPlus,g_DataPlus, JSCHART_EVENT_ID, JSCHART_DATA_FIELD_ID, PhoneDBClick, OVERLAY_STATUS_ID, } from "./umychart.data.wechat.js"; import { JSKLineInfoMap, KLINE_INFO_TYPE, JSMinuteInfoMap, } from "./umychart.klineinfo.wechat.js"; import { JSCommonCoordinateData, MARKET_SUFFIX_NAME , g_FuturesTimeData, g_NYMEXTimeData, g_COMEXTimeData, g_NYBOTTimeData, g_LMETimeData, g_CBOTTimeData, g_TOCOMTimeData, g_IPETimeData, GetfloatPrecision, } from "./umychart.coordinatedata.wechat.js"; import { JSCommonComplier } from "./umychart.complier.wechat.js"; //通达信编译器 import { JSCommonIndexScript, JSIndexScript } from "./umychart.index.data.wechat.js"; //系统指标定义 import { HQIndexFormula } from "./umychart.hqIndexformula.wechat.js"; //通达信编译器 import { IChartFramePainting, AverageWidthFrame, MinuteFrame, MinuteHScreenFrame, ZOOM_SEED, KLineFrame, KLineHScreenFrame, OverlayMinuteFrame, OverlayMinuteHScreenFrame, OverlayKLineFrame, OverlayKLineHScreenFrame, DepthChartFrame, } from "./umychart.chartframe.wechat.js" //图形库 import { IChartPainting, ChartSingleText, ChartKLine, ChartLine, ChartSubLine, ChartPointDot, ChartStick, ChartLineStick, ChartStickLine, ChartOverlayKLine, ChartMinuteInfo, ChartRectangle, ChartMultiText, ChartMultiLine, ChartMultiBar, ChartPie, ChartCircle, ChartChinaMap, ChartRadar, ChartCorssCursor, ChartBuySell, ChartMACD, ChartSplashPaint, ChartBackground, ChartMinuteVolumBar, ChartMultiHtmlDom, ChartLock, ChartVolStick, ChartBand, ChartOverlayMinutePriceLine, ChartLineMultiData, ChartStraightLine, DepthChartCorssCursor, ChartOrderbookDepth, ChartMinutePriceLine, ChartText, ChartStraightArea, } from "./umychart.chartpaint.wechat.js"; //扩展画法图形库 import { IExtendChartPainting, KLineTooltipPaint, BarragePaint, MinuteTooltipPaint, BackgroundPaint, g_ExtendChartPaintFactory, } from "./umychart.extendchart.wechat.js"; import { IndexInfo, BaseIndex, ScriptIndex, APIScriptIndex, OverlayScriptIndex, MarketLongShortIndex, MarketTimingIndex, MarketAttentionIndex, MarketHeatIndex, CustonIndexHeatIndex, BenfordIndex, } from './umychart.index.wechat.js' import{ g_JSChartResource, JSCHART_LANGUAGE_ID, g_JSChartLocalization, } from './umychart.resource.wechat.js' import { CoordinateInfo, IFrameSplitOperator, FrameSplitKLinePriceY, FrameSplitY, FrameSplitKLineX, FrameSplitMinutePriceY, FrameSplitMinuteX, FrameSplitXData, SplitData, PriceSplitData, FrameSplitXDepth, IChangeStringFormat, HQPriceStringFormat, HQDateStringFormat, HQMinuteTimeStringFormat, g_DivTooltipDataForamt, } from './umychart.framesplit.wechat.js' import { IChartTitlePainting, DynamicKLineTitlePainting, DynamicMinuteTitlePainting, DynamicChartTitlePainting, DynamicTitleData, STRING_FORMAT_TYPE, } from './umychart.charttitle.wechat.js' import { IChartDrawPicture, } from "./umychart.ChartDrawPicture.wechart.js" import { HQCHART_VERSION } from "./umychart.version.wechat.js" function JSChart(element) { this.JSChartContainer; //画图控件 this.CanvasElement = element; this.AddEventCallback = function (obj) //事件回调 {event:事件id, callback:回调函数} { if (this.JSChartContainer && typeof (this.JSChartContainer.AddEventCallback) == 'function') { JSConsole.Chart.Log('[JSChart:AddEventCallback] ', obj); this.JSChartContainer.AddEventCallback(obj); } } //设置语言 'EN', 'CN' this.SetLanguage=function(language) { if(this.JSChartContainer && typeof(this.JSChartContainer.SetLanguage)=='function') { JSConsole.Chart.Log('[JSChart:SetLanguage] ', language); this.JSChartContainer.SetLanguage(language); } } this.OnSize = function (option) { if (option) { if (IFrameSplitOperator.IsNumber(option.Width)) this.CanvasElement.Width=option.Width; if (IFrameSplitOperator.IsNumber(option.Height)) this.CanvasElement.Height=option.Height; } if (option && option.Redraw==false) return; if (this.JSChartContainer) { if (option && option.Type==1 && this.JSChartContainer.OnSize) { this.JSChartContainer.OnSize(); } else { if (this.JSChartContainer.Frame) this.JSChartContainer.Frame.SetSizeChage(true); this.JSChartContainer.Draw(); } } } 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; else option.Border.Left=chart.Frame.ChartBorder.Left; if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right; else option.Border.Right=chart.Frame.ChartBorder.Right; if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top; else option.Border.Top=chart.Frame.ChartBorder.Top; if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom; else option.Border.Bottom=chart.Frame.ChartBorder.Bottom; if (item.AutoLeft) { chart.Frame.AutoLeftBorder={ }; if (IFrameSplitOperator.IsNumber(item.AutoLeft.Blank)) chart.Frame.AutoLeftBorder.Blank=item.AutoLeft.Blank; if (IFrameSplitOperator.IsNumber(item.AutoLeft.MinWidth)) chart.Frame.AutoLeftBorder.MinWidth=item.AutoLeft.MinWidth; } if (item.AutoRight) { chart.Frame.AutoRightBorder={ }; if (IFrameSplitOperator.IsNumber(item.AutoRight.Blank)) chart.Frame.AutoRightBorder.Blank=item.AutoRight.Blank; if (IFrameSplitOperator.IsNumber(item.AutoRight.MinWidth)) chart.Frame.AutoRightBorder.MinWidth=item.AutoRight.MinWidth; } } //历史K线图 this.CreateKLineChartContainer = function (option) { var chart = null; if (option.Type === "历史K线图横屏") chart = new KLineChartHScreenContainer(this.CanvasElement); else chart = new KLineChartContainer(this.CanvasElement); if (option.NetworkFilter) chart.NetworkFilter = option.NetworkFilter; if (option.KLine) //k线图的属性设置 { if (option.KLine.DragMode >= 0) chart.DragMode = option.KLine.DragMode; if (option.KLine.Right >= 0) chart.Right = option.KLine.Right; if (option.KLine.Period >= 0) chart.Period = option.KLine.Period; if (option.KLine.MaxRequestDataCount > 0) chart.MaxRequestDataCount = option.KLine.MaxRequestDataCount; if (option.KLine.Info && option.KLine.Info.length > 0) chart.SetKLineInfo(option.KLine.Info, false); if (option.KLine.Policy && option.KLine.Policy.length > 0) chart.SetPolicyInfo(option.KLine.Policy, false); if (option.KLine.KLineDoubleClick == false) chart.MinuteDialog = this.MinuteDialog = null; if (option.KLine.MaxRequestMinuteDayCount > 0) chart.MaxRequestMinuteDayCount = option.KLine.MaxRequestMinuteDayCount; if (option.KLine.DrawType) chart.KLineDrawType = option.KLine.DrawType; if (option.KLine.RightSpaceCount >= 0) chart.RightSpaceCount = option.KLine.RightSpaceCount; if (option.KLine.DataWidth>=1) chart.KLineSize={ DataWidth:option.KLine.DataWidth }; if (IFrameSplitOperator.IsNumber(option.KLine.RightFormula)) chart.RightFormula=option.KLine.RightFormula; } if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle = option.SplashTitle; //设置提示信息内容 if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow; //双击缩放附图 if (!option.Windows || option.Windows.length <= 0) return null; if (option.Language) { var value=g_JSChartLocalization.GetLanguageID(option.Language); if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value; } if (option.SourceDatatLimit) chart.SetSourceDatatLimit(option.SourceDatatLimit); if (option.EnableZoomUpDown) chart.EnableZoomUpDown=option.EnableZoomUpDown; if (option.EnableMoveData) chart.EnableMoveData=option.EnableMoveData; if (option.TouchMoveMinAngle) chart.TouchMoveMinAngle=option.TouchMoveMinAngle; if (IFrameSplitOperator.IsBool(option.EnableScrollUpDown)) chart.EnableScrollUpDown=option.EnableScrollUpDown; if (option.ZoomStepPixel>0) chart.ZoomStepPixel=option.ZoomStepPixel; if (IFrameSplitOperator.IsNumber(option.DrawMoveWaitTime)) chart.DrawMoveWaitTime=option.DrawMoveWaitTime; if (IFrameSplitOperator.IsNumber(option.PressTime)) chart.PressTime=option.PressTime; //创建子窗口 chart.Create(option.Windows.length); this.SetChartBorder(chart, option); if (option.KLine) { var item=option.KLine; var klineChart=chart.ChartPaint[0]; if (option.KLine.PageSize > 0) { let maxPageSize = chart.GetMaxPageSize(); if (maxPageSize < option.KLine.PageSize) chart.PageSize = maxPageSize; else chart.PageSize = option.KLine.PageSize; } if (option.KLine.InfoDrawType) chart.ChartPaint[0].InfoDrawType = option.KLine.InfoDrawType; if (IFrameSplitOperator.IsNumber(item.OneLimitBarType)) klineChart.OneLimitBarType=item.OneLimitBarType; } if (option.DragDownload) { if (option.DragDownload.Day && option.DragDownload.Day.Enable == true) chart.DragDownload.Day.Enable = true; if (option.DragDownload.Minute && option.DragDownload.Minute.Enable == true) chart.DragDownload.Minute.Enable = true; } if (option.IsApiPeriod == true) chart.IsApiPeriod = option.IsApiPeriod; if (option.CorssCursorTouchEnd == true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (option.IsClickShowCorssCursor == true) chart.IsClickShowCorssCursor = option.IsClickShowCorssCursor; if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw; if (option.CorssCursorInfo) { var item=option.CorssCursorInfo; if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left = option.CorssCursorInfo.Left; if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right = option.CorssCursorInfo.Right; if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom = option.CorssCursorInfo.Bottom; if (option.CorssCursorInfo.IsShowCorss === false) chart.ChartCorssCursor.IsShowCorss = option.CorssCursorInfo.IsShowCorss; if (IFrameSplitOperator.IsBool(item.IsShowClose)) chart.ChartCorssCursor.IsShowClose = item.IsShowClose; //Y轴显示收盘价 if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.HPenType)) chart.ChartCorssCursor.HPenType = option.CorssCursorInfo.HPenType; if (option.CorssCursorInfo.VPenType > 0) chart.ChartCorssCursor.VPenType = option.CorssCursorInfo.VPenType; if (IFrameSplitOperator.IsNumber(item.DateFormatType)) chart.ChartCorssCursor.StringFormatX.DateFormatType=item.DateFormatType; if (IFrameSplitOperator.IsNumber(item.PriceFormatType)) chart.ChartCorssCursor.StringFormatY.PriceFormatType=item.PriceFormatType; if (IFrameSplitOperator.IsNumber(item.DataFormatType)) chart.ChartCorssCursor.StringFormatY.DataFormatType=item.DataFormatType; } if (typeof (option.UpdateUICallback) == 'function') //数据到达回调 chart.UpdateUICallback = option.UpdateUICallback; if (option.Frame) { for (var i in option.Frame) { var item = option.Frame[i]; if (!chart.Frame.SubFrame[i]) continue; var subFrame=chart.Frame.SubFrame[i].Frame; if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount; if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat; if (!isNaN(item.Height)) chart.Frame.SubFrame[i].Height = item.Height; if (item.IsShowBorder == false) chart.Frame.SubFrame[i].Frame.IsShowBorder = item.IsShowBorder; if (item.IsShowXLine == false) chart.Frame.SubFrame[i].Frame.IsShowXLine = item.IsShowXLine; if (item.IsShowYLine==false) chart.Frame.SubFrame[i].Frame.IsShowYLine=item.IsShowYLine; if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign; if (item.IsShowTitle == false) chart.Frame.SubFrame[i].Frame.IsShowTitle = false; if (IFrameSplitOperator.IsBool(item.IsShowIndexTitle)) chart.Frame.SubFrame[i].Frame.IsShowTitle=item.IsShowIndexTitle; if (item.UpdateTitleUICallback && chart.Frame.SubFrame[i].Frame.TitlePaint) chart.Frame.SubFrame[i].Frame.TitlePaint.UpdateUICallback = item.UpdateTitleUICallback; if (item.IsShowLeftText === false || item.IsShowLeftText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[0] = item.IsShowLeftText; //显示左边刻度 if (item.IsShowRightText === false || item.IsShowRightText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[1] = item.IsShowRightText; //显示右边刻度 if (item.TopSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace = item.TopSpace; if (item.BottomSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace = item.BottomSpace; if (item.Custom) chart.Frame.SubFrame[i].Frame.YSplitOperator.Custom = item.Custom; if (IFrameSplitOperator.IsNumber(item.SplitType)) { chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitType = item.SplitType; chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultSplitType=item.SplitType; } if (IFrameSplitOperator.IsNumber(item.FilterType)) subFrame.YSplitOperator.FilterType=item.FilterType; if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) chart.Frame.SubFrame[i].Frame.YSplitOperator.FloatPrecision = item.FloatPrecision; //强制指定小数位数(主图有效) if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine; if (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline; } } if (option.KLine) { var item=option.KLine; var klineChart=chart.ChartPaint[0]; if (IFrameSplitOperator.IsBool(item.ShowKLine)) klineChart.IsShow = item.ShowKLine; if (IFrameSplitOperator.IsBool(item.IsShowMaxMinPrice)) klineChart.IsShowMaxMinPrice = item.IsShowMaxMinPrice; if (item.PriceGap) { if (IFrameSplitOperator.IsBool(item.PriceGap.Enable)) klineChart.PriceGap.Enable=item.PriceGap.Enable; if (IFrameSplitOperator.IsNumber(item.PriceGap.Count)) klineChart.PriceGap.Count=item.PriceGap.Count; } } if (option.KLineTitle) { var item=option.KLineTitle; if (option.KLineTitle.IsShowName == false) chart.TitlePaint[0].IsShowName = false; if (option.KLineTitle.IsShowSettingInfo == false) chart.TitlePaint[0].IsShowSettingInfo = false; if (option.KLineTitle.IsShow == false) chart.TitlePaint[0].IsShow = false; if (option.KLineTitle.UpdateUICallback) chart.TitlePaint[0].UpdateUICallback = option.KLineTitle.UpdateUICallback if (option.KLineTitle.LineCount > 1) chart.TitlePaint[0].LineCount = option.KLineTitle.LineCount; if (IFrameSplitOperator.IsNumber(item.TextSpace)) chart.TitlePaint[0].TextSpace=item.TextSpace; if (IFrameSplitOperator.IsNumber(item.PeriodSpace)) chart.TitlePaint[0].PeriodSpace=item.PeriodSpace; if (IFrameSplitOperator.IsNumber(item.DateTimeSpace)) chart.TitlePaint[0].DateTimeSpace=item.DateTimeSpace; if (IFrameSplitOperator.IsNumber(item.NameSpace)) chart.TitlePaint[0].NameSpace=item.NameSpace; } //叠加股票 只支持叠加1个股票 if (option.Overlay) { for (var i=0;i 0) chart.WindowIndex[i].StringFormat = item.StringFormat; if (item.FloatPrecision >= 0) chart.WindowIndex[i].FloatPrecision = item.FloatPrecision; } } var frame=chart.Frame.SubFrame[i].Frame; if (item.Modify != null) chart.Frame.SubFrame[i].Frame.ModifyIndex = item.Modify; if (item.Change != null) chart.Frame.SubFrame[i].Frame.ChangeIndex = item.Change; if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) chart.Frame.SubFrame[i].Frame.IsDrawTitleBG=item.IsDrawTitleBG; if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) chart.Frame.SubFrame[i].Frame.IsShowNameArrow=item.IsShowNameArrow; if (IFrameSplitOperator.IsBool(item.IsShowTitleArrow)) frame.IsShowTitleArrow=item.IsShowTitleArrow; if (typeof (item.UpdateUICallback) == 'function') chart.WindowIndex[i].UpdateUICallback = item.UpdateUICallback; if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight = item.TitleHeight; if (item.IsShowIndexName == false) chart.Frame.SubFrame[i].Frame.IsShowIndexName = false; if (item.IndexParamSpace >= 0) chart.Frame.SubFrame[i].Frame.IndexParamSpace = item.IndexParamSpace; if (item.IndexTitleSpace >= 0) chart.Frame.SubFrame[i].Frame.IndexTitleSpace = item.IndexTitleSpace; if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) frame.HorizontalReserved=item.HorizontalReserved; } //叠加指标 if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex)) { for(var i=0;i=chart.Frame.SubFrame.length) continue; var itemString = JSON.stringify(item); var obj = JSON.parse(itemString); if (item.Index) obj.IndexName=item.Index; if (item.Windows>=0) obj.WindowIndex=item.Windows; chart.CreateOverlayWindowsIndex(obj); } } return chart; } //自定义指数历史K线图 this.CreateCustomKLineChartContainer = function (option) { var chart = new CustomKLineChartContainer(this.CanvasElement); if (option.KLine) //k线图的属性设置 { if (option.KLine.DragMode >= 0) chart.DragMode = option.KLine.DragMode; if (option.KLine.Right >= 0) chart.Right = option.KLine.Right; if (option.KLine.Period >= 0) chart.Period = option.KLine.Period; if (option.KLine.MaxRequestDataCount > 0) chart.MaxRequestDataCount = option.KLine.MaxRequestDataCount; if (option.KLine.Info && option.KLine.Info.length > 0) chart.SetKLineInfo(option.KLine.Info, false); if (option.KLine.KLineDoubleClick == false) chart.MinuteDialog = this.MinuteDialog = null; if (option.KLine.PageSize > 0) chart.PageSize = option.KLine.PageSize; if (option.KLine.IsShowTooltip == false) chart.IsShowTooltip = false; } if (option.CustomStock) chart.CustomStock = option.CustomStock; if (option.QueryDate) chart.QueryDate = option.QueryDate; if (typeof (option.UpdateUICallback) == 'function') chart.UpdateUICallback = option.UpdateUICallback; if (!option.Windows || option.Windows.length <= 0) return null; //创建子窗口 chart.Create(option.Windows.length); if (option.Border) { if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left = option.Border.Left; if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right = option.Border.Right; if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top = option.Border.Top; if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom = option.Border.Bottom; } if (option.IsShowCorssCursorInfo == false) //取消显示十字光标刻度信息 { chart.ChartCorssCursor.IsShowText = option.IsShowCorssCursorInfo; } if (option.Frame) { for (var i in option.Frame) { var item = option.Frame[i]; if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount; if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat; if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign; } } if (option.KLineTitle) { if (option.KLineTitle.IsShowName == false) chart.TitlePaint[0].IsShowName = false; if (option.KLineTitle.IsShowSettingInfo == false) chart.TitlePaint[0].IsShowSettingInfo = false; } //创建子窗口的指标 let scriptData = new JSCommonIndexScript.JSIndexScript(); for (var i in option.Windows) { var item = option.Windows[i]; if (item.Script) { chart.WindowIndex[i] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行 } else { var indexItem = JSIndexMap.Get(item.Index); if (indexItem) { chart.WindowIndex[i] = indexItem.Create(); chart.CreateWindowIndex(i); } else //系统指标里查找 { let indexInfo = scriptData.Get(item.Index); if (!indexInfo) continue; if (item.Lock) indexInfo.Lock = item.Lock; chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行 } } if (item.Modify != null) chart.Frame.SubFrame[i].Frame.ModifyIndex = item.Modify; if (item.Change != null) chart.Frame.SubFrame[i].Frame.ChangeIndex = item.Change; if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight = item.TitleHeight; } return chart; } //分钟走势图 this.CreateMinuteChartContainer = function (option) { var chart = null; if (option.Type === "分钟走势图横屏") chart = new MinuteChartHScreenContainer(this.CanvasElement); else chart = new MinuteChartContainer(this.CanvasElement); if (option.NetworkFilter) chart.NetworkFilter = option.NetworkFilter; var windowsCount = 2; if (option.Windows && option.Windows.length > 0) windowsCount += option.Windows.length; //指标窗口从第3个窗口开始 if (option.TouchMoveMinAngle) chart.TouchMoveMinAngle=option.TouchMoveMinAngle; if (IFrameSplitOperator.IsBool(option.EnableScrollUpDown)) chart.EnableScrollUpDown=option.EnableScrollUpDown; if (option.Info && option.Info.length > 0) chart.SetMinuteInfo(option.Info, false); if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle = option.SplashTitle; //设置提示信息内容 if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow; //双击缩放附图 if (IFrameSplitOperator.IsNumber(option.DrawMoveWaitTime)) chart.DrawMoveWaitTime=option.DrawMoveWaitTime; if (IFrameSplitOperator.IsNumber(option.PressTime)) chart.PressTime=option.PressTime; if (IFrameSplitOperator.IsBool(option.EnableNightDayBG)) chart.EnableNightDayBG=option.EnableNightDayBG; if (option.Language) { var value=g_JSChartLocalization.GetLanguageID(option.Language); if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value; } chart.Create(windowsCount); //创建子窗口 if (option.CorssCursorTouchEnd == true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (IFrameSplitOperator.IsBool(option.IsClickShowCorssCursor)) chart.IsClickShowCorssCursor = option.IsClickShowCorssCursor; if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw; if (option.CorssCursorInfo) //十字光标设置 { var item=option.CorssCursorInfo; if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left = option.CorssCursorInfo.Left; if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right = option.CorssCursorInfo.Right; if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom = option.CorssCursorInfo.Bottom; if (option.CorssCursorInfo.IsShowCorss === false) chart.ChartCorssCursor.IsShowCorss = option.CorssCursorInfo.IsShowCorss; if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime; if (IFrameSplitOperator.IsNumber(item.PriceFormatType)) chart.ChartCorssCursor.StringFormatY.PriceFormatType=item.PriceFormatType; if (IFrameSplitOperator.IsNumber(item.DataFormatType)) chart.ChartCorssCursor.StringFormatY.DataFormatType=item.DataFormatType; if (IFrameSplitOperator.IsNumber(item.RightTextFormat)) chart.ChartCorssCursor.TextFormat.Right=item.RightTextFormat; if (IFrameSplitOperator.IsBool(item.IsOnlyDrawMinute)) chart.ChartCorssCursor.IsOnlyDrawMinute = item.IsOnlyDrawMinute; //Y轴显示收盘价 if (IFrameSplitOperator.IsNumber(item.HPenType)) chart.ChartCorssCursor.HPenType=item.HPenType; if (IFrameSplitOperator.IsNumber(item.VPenType)) chart.ChartCorssCursor.VPenType=item.VPenType; } if (option.MinuteInfo) chart.CreateMinuteInfo(option.MinuteInfo); if (option.DayCount > 1) chart.DayCount = option.DayCount; this.SetChartBorder(chart, option); if (option.Frame) { for (var i=0 ;i= 0) chart.Frame.SubFrame[i].Height = item.Height; if (item.Custom) chart.Frame.SubFrame[i].Frame.YSplitOperator.Custom = item.Custom; if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine; if (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline; if (IFrameSplitOperator.IsBool(item.IsShowXLine)) chart.Frame.SubFrame[i].Frame.IsShowXLine = item.IsShowXLine; if (IFrameSplitOperator.IsBool(item.IsShowYLine)) chart.Frame.SubFrame[i].Frame.IsShowYLine=item.IsShowYLine; if (item.TopSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace = item.TopSpace; if (item.BottomSpace >= 0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace = item.BottomSpace; if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) frame.HorizontalReserved=item.HorizontalReserved; } chart.UpdateXShowText(); } if (option.MinuteTitle) { var item=option.MinuteTitle; if (option.MinuteTitle.IsShowName == false) chart.TitlePaint[0].IsShowName = false; if (option.MinuteTitle.IsShow == false) chart.TitlePaint[0].IsShow = false; if (option.MinuteTitle.UpdateUICallback) chart.TitlePaint[0].UpdateUICallback = option.MinuteTitle.UpdateUICallback if (option.MinuteTitle.LineCount > 1) chart.TitlePaint[0].LineCount = option.MinuteTitle.LineCount; if (IFrameSplitOperator.IsNumber(item.TextSpace)) chart.TitlePaint[0].TextSpace=item.TextSpace; } if (option.MinuteVol) { var item=option.MinuteVol; if (IFrameSplitOperator.IsNumber(item.BarColorType)) chart.ChartPaint[2].BarColorType=item.BarColorType; } if (typeof (option.UpdateUICallback) == 'function') //数据到达回调 chart.UpdateUICallback = option.UpdateUICallback; if (option.ExtendChart) //创建扩展画法 { for (var i in option.ExtendChart) { var item = option.ExtendChart[i]; chart.CreateExtendChart(item.Name, item); } } //叠加股票 只支持1只股票 if (IFrameSplitOperator.IsNonEmptyArray(option.Overlay)) { for (var i=0;i0) chart.Frame.SubFrame[0].Frame.YSplitOperator.SplitType=option.MinuteLine.SplitType; } let scriptData = new JSCommonIndexScript.JSIndexScript(); for (var i=0; i 0) chart.WindowIndex[index].StringFormat = item.StringFormat; if (item.FloatPrecision >= 0) chart.WindowIndex[index].FloatPrecision = item.FloatPrecision; } } if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[index].Frame.ChartBorder.TitleHeight = item.TitleHeight; //指标标题高度 if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) chart.Frame.SubFrame[index].Frame.IsDrawTitleBG=item.IsDrawTitleBG; if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) chart.Frame.SubFrame[index].Frame.IsShowNameArrow=item.IsShowNameArrow; if (IFrameSplitOperator.IsBool(item.IsShowTitleArrow)) chart.Frame.SubFrame[index].Frame.IsShowTitleArrow=item.IsShowTitleArrow; if (IFrameSplitOperator.IsNumber(item.YSplitType)) chart.Frame.SubFrame[index].Frame.YSplitOperator.SplitType=item.YSplitType; } //叠加指标 if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex)) { for(var i=0;i=chart.Frame.SubFrame.length) continue; var itemString = JSON.stringify(item); var obj = JSON.parse(itemString); if (item.Index) obj.IndexName=item.Index; if (item.Windows>=0) obj.WindowIndex=item.Windows; chart.CreateOverlayWindowsIndex(obj); } } return chart; } //历史分钟走势图 this.CreateHistoryMinuteChartContainer = function (option) { var chart = new HistoryMinuteChartContainer(this.CanvasElement); var windowsCount = 2; if (option.Windows && option.Windows.length > 0) windowsCount += option.Windows.length; //指标窗口从第3个窗口开始 chart.Create(windowsCount); //创建子窗口 if (option.IsShowCorssCursorInfo == false) //取消显示十字光标刻度信息 { chart.ChartCorssCursor.IsShowText = option.IsShowCorssCursorInfo; } if (option.Border) { if (!isNaN(option.Border.Left)) chart.Frame.ChartBorder.Left = option.Border.Left; if (!isNaN(option.Border.Right)) chart.Frame.ChartBorder.Right = option.Border.Right; if (!isNaN(option.Border.Top)) chart.Frame.ChartBorder.Top = option.Border.Top; if (!isNaN(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom = option.Border.Bottom; } if (option.Frame) { for (var i in option.Frame) { var item = option.Frame[i]; if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount; if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat; if (item.XMessageAlign == 'bottom') chart.Frame.SubFrame[i].Frame.XMessageAlign = item.XMessageAlign; } } let scriptData = new JSCommonIndexScript.JSIndexScript(); for (var i in option.Windows) //分钟数据指标从第3个指标窗口设置 { var item = option.Windows[i]; if (item.Script) { chart.WindowIndex[2 + parseInt(i)] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行 } else { var indexItem = JSIndexMap.Get(item.Index); if (indexItem) { chart.WindowIndex[2 + parseInt(i)] = indexItem.Create(); //创建子窗口的指标 chart.CreateWindowIndex(2 + parseInt(i)); } else { let indexInfo = scriptData.Get(item.Index); if (!indexInfo) continue; if (item.Lock) indexInfo.Lock = item.Lock; chart.WindowIndex[2 + parseInt(i)] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行 } } if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[2 + parseInt(i)].Frame.ChartBorder.TitleHeight = item.TitleHeight; } chart.TradeDate = 20181009; if (option.HistoryMinute) { if (option.HistoryMinute.TradeDate) chart.TradeDate = option.HistoryMinute.TradeDate; if (option.HistoryMinute.IsShowName != null) chart.TitlePaint[0].IsShowName = option.HistoryMinute.IsShowName; //动态标题是否显示股票名称 if (option.HistoryMinute.IsShowDate != null) chart.TitlePaint[0].IsShowDate = option.HistoryMinute.IsShowDate; //动态标题是否显示日期 } return chart; } this.CreateKLineTrainChartContainer = function (option) { if (option.Type=="简单K线训练" || option.Type=="简单K线训练横屏") { var bHScreen=(option.Type=='简单K线训练横屏'? true:false); var chart=new KLineTrainSimpleChartContainer(this.CanvasElement,bHScreen); } else { var bHScreen = (option.Type == 'K线训练横屏' ? true : false); var chart = new KLineTrainChartContainer(this.CanvasElement, bHScreen); } if (option.NetworkFilter) chart.NetworkFilter = option.NetworkFilter; if (option.IsApiPeriod == true) chart.IsApiPeriod = option.IsApiPeriod; if (option.KLine) //k线图的属性设置 { if (option.KLine.Right >= 0) chart.Right = option.KLine.Right; if (option.KLine.Period >= 0) chart.Period = option.KLine.Period; if (option.KLine.MaxRequestDataCount > 0) chart.MaxRequestDataCount = option.KLine.MaxRequestDataCount; if (option.KLine.Info && option.KLine.Info.length > 0) chart.SetKLineInfo(option.KLine.Info, false); if (option.KLine.PageSize > 0) chart.PageSize = option.KLine.PageSize; if (option.KLine.IsShowTooltip == false) chart.IsShowTooltip = false; if (option.KLine.MaxRequestMinuteDayCount > 0) chart.MaxRequestMinuteDayCount = option.KLine.MaxRequestMinuteDayCount; if (option.KLine.DrawType) chart.KLineDrawType = option.KLine.DrawType; } if (option.Train) { if (option.Train.DataCount) chart.TrainDataCount = option.Train.DataCount; if (option.Train.Callback) chart.TrainCallback = option.Train.Callback; if (option.Train.StartDate) chart.TrainStartDate = option.Train.StartDate; } if (!option.Windows || option.Windows.length <= 0) return null; //创建子窗口 chart.Create(option.Windows.length); this.SetChartBorder(chart, option); if (option.ExtendChart) //创建扩展画法 { for (var i in option.ExtendChart) { var item = option.ExtendChart[i]; chart.CreateExtendChart(item.Name, item); } } if (option.IsShowCorssCursorInfo == false) chart.ChartCorssCursor.IsShowText = option.IsShowCorssCursorInfo;//取消显示十字光标刻度信息 if (option.CorssCursorTouchEnd == true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (option.IsClickShowCorssCursor == true) chart.IsClickShowCorssCursor = option.IsClickShowCorssCursor; if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw; if (option.CorssCursorInfo) { var item=option.CorssCursorInfo; if (!isNaN(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left = option.CorssCursorInfo.Left; if (!isNaN(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right = option.CorssCursorInfo.Right; if (!isNaN(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom = option.CorssCursorInfo.Bottom; if (option.CorssCursorInfo.IsShowCorss === false) chart.ChartCorssCursor.IsShowCorss = option.CorssCursorInfo.IsShowCorss; if (IFrameSplitOperator.IsBool(item.IsShowClose)) chart.ChartCorssCursor.IsShowClose = item.IsShowClose; //Y轴显示收盘价 if (option.CorssCursorInfo.HPenType > 0) chart.ChartCorssCursor.HPenType = option.CorssCursorInfo.HPenType; if (option.CorssCursorInfo.VPenType > 0) chart.ChartCorssCursor.VPenType = option.CorssCursorInfo.VPenType; if (IFrameSplitOperator.IsBool(item.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=item.IsFixXLastTime; } if (option.Frame) { for (var i in option.Frame) { if (!chart.Frame.SubFrame[i]) continue; var item = option.Frame[i]; if (item.SplitCount) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitCount = item.SplitCount; if (item.StringFormat) chart.Frame.SubFrame[i].Frame.YSplitOperator.StringFormat = item.StringFormat; if (item.Height>0) chart.Frame.SubFrame[i].Height = item.Height; if (item.IsShowLeftText === false || item.IsShowLeftText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[0] = item.IsShowLeftText; //显示左边刻度 if (item.IsShowRightText === false || item.IsShowRightText === true) chart.Frame.SubFrame[i].Frame.IsShowYText[1] = item.IsShowRightText; //显示右边刻度 } } if (option.KLine) { if (option.KLine.ShowKLine == false) chart.ChartPaint[0].IsShow = false; if (option.KLine.IsShowMaxMinPrice == false) chart.ChartPaint[0].IsShowMaxMinPrice = false; } //股票名称 日期 周期都不显示 chart.TitlePaint[0].IsShowName = false; chart.TitlePaint[0].IsShowSettingInfo = false; chart.TitlePaint[0].IsShowDateTime = false; //创建子窗口的指标 let scriptData = new JSCommonIndexScript.JSIndexScript(); for (var i in option.Windows) { var item = option.Windows[i]; if (item.Script) { chart.WindowIndex[i] = new ScriptIndex(item.Name, item.Script, item.Args, item); //脚本执行 } else { let indexItem = JSIndexMap.Get(item.Index); if (indexItem) { chart.WindowIndex[i] = indexItem.Create(); chart.CreateWindowIndex(i); } else { let indexInfo = scriptData.Get(item.Index); if (!indexInfo) continue; if (item.Lock) indexInfo.Lock = item.Lock; chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行 } } if (item.Modify != null) chart.Frame.SubFrame[i].Frame.ModifyIndex = item.Modify; if (item.Change != null) chart.Frame.SubFrame[i].Frame.ChangeIndex = item.Change; if (!isNaN(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight = item.TitleHeight; } return chart; } //深度图 this.CreateDepthChartContainer=function(option) { var chart=null; chart=new DepthChartContainer(this.CanvasElement); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; if (option.EnableScrollUpDown==true) chart.EnableScrollUpDown=option.EnableScrollUpDown; if (IFrameSplitOperator.IsPlusNumber(option.MaxVolRate)) chart.MaxVolRate=option.MaxVolRate; if (option.ZoomStepPixel>0) chart.ZoomStepPixel=option.ZoomStepPixel; if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle = option.SplashTitle; //设置提示信息内容 if (option.Language) { var value=g_JSChartLocalization.GetLanguageID(option.Language); if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value; } chart.Create(option.Listener); if (option.Border) { if (IFrameSplitOperator.IsNumber(option.Border.Left)) chart.Frame.ChartBorder.Left=option.Border.Left; else option.Border.Left=chart.Frame.ChartBorder.Left; if (IFrameSplitOperator.IsNumber(option.Border.Right)) chart.Frame.ChartBorder.Right=option.Border.Right; else option.Border.Right=chart.Frame.ChartBorder.Right; if (IFrameSplitOperator.IsNumber(option.Border.Top)) chart.Frame.ChartBorder.Top=option.Border.Top; else option.Border.Top=chart.Frame.ChartBorder.Top; if (IFrameSplitOperator.IsNumber(option.Border.Bottom)) chart.Frame.ChartBorder.Bottom=option.Border.Bottom; else option.Border.Bottom=chart.Frame.ChartBorder.Bottom; } if (option.IsFullDraw == true) chart.IsFullDraw = option.IsFullDraw; if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (option.CorssCursorInfo) { var item=option.CorssCursorInfo; if (IFrameSplitOperator.IsNumber(item.HPenType)) chart.ChartCorssCursor.HPenType=item.HPenType; if (IFrameSplitOperator.IsNumber(item.VPenType)) chart.ChartCorssCursor.VPenType=item.VPenType; if (IFrameSplitOperator.IsBool(item.IsShowTooltip)) chart.ChartCorssCursor.IsShowTooltip=item.IsShowTooltip; } if (option.Frame) { var item=option.Frame if (item.SplitCount) chart.Frame.YSplitOperator.SplitCount=item.SplitCount; if (IFrameSplitOperator.IsNumber(item.SplitType)) chart.Frame.YSplitOperator.SplitType=item.SplitType; if (IFrameSplitOperator.IsNumber(item.Height)) chart.Frame.Height = item.Height; if (IFrameSplitOperator.IsNumber(item.LineType)) chart.Frame.YSplitOperator.LineType=item.LineType; if (Array.isArray(item.IgnoreYValue)) chart.Frame.YSplitOperator.IgnoreYValue=item.IgnoreYValue; if (item.IsShowLeftText===false || item.IsShowLeftText===true) { chart.Frame.IsShowYText[0]=item.IsShowLeftText; chart.Frame.YSplitOperator.IsShowLeftText=item.IsShowLeftText; //显示左边刻度 } if (item.IsShowRightText===false || item.IsShowRightText===true) { chart.Frame.IsShowYText[1]=item.IsShowRightText; chart.Frame.YSplitOperator.IsShowRightText=item.IsShowRightText; //显示右边刻度 } if (item.IsShowXLine==false) chart.Frame.IsShowXLine=item.IsShowXLine; if (item.IsShowYLine==false) chart.Frame.IsShowYLine=item.IsShowYLine; if (IFrameSplitOperator.IsNumber(item.XSplitCount)) chart.Frame.XSplitOperator.SplitCount=item.XSplitCount; } return chart; } //根据option内容绘制图形 this.SetOption = function (option) { JSConsole.Chart.Log('[JSChart::SetOption]', option) var chart = null; switch (option.Type) { case "历史K线图": case '历史K线图横屏': chart = this.CreateKLineChartContainer(option); break; case "自定义指数历史K线图": chart = this.CreateCustomKLineChartContainer(option); break; case "分钟走势图": case "分钟走势图横屏": chart = this.CreateMinuteChartContainer(option); break; case "历史分钟走势图": chart = this.CreateHistoryMinuteChartContainer(option); break; case 'K线训练': case 'K线训练横屏': case "简单K线训练": case "简单K线训练横屏": chart = this.CreateKLineTrainChartContainer(option); break; case "深度图": chart=this.CreateDepthChartContainer(option); break; default: return false; } if (!chart) return false; this.JSChartContainer = chart; if (option.OnCreatedCallback) option.OnCreatedCallback(chart); //是否自动更新 if (option.IsAutoUpdate == true || option.IsAutoUpate == true) chart.IsAutoUpdate = true; if (option.AutoUpdateFrequency > 0) chart.AutoUpdateFrequency = option.AutoUpdateFrequency; //注册事件 for(var i in option.EventCallback) { var item=option.EventCallback[i]; chart.AddEventCallback(item); } //设置股票代码 if (!option.Symbol) return false; chart.Draw(); chart.ChangeSymbol(option.Symbol); this.JSChartContainer.Draw(); } //切换股票代码接口 this.ChangeSymbol = function (symbol) { if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol); } //K线切换指标 this.ChangeIndex = function (windowIndex, indexName, option) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeIndex) == 'function') this.JSChartContainer.ChangeIndex(windowIndex, indexName, option); } //切换一个窗口指标,包含叠加指标,以及这个窗口的属性 this.ChangeIndexWindow=function(windowIndex, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeIndexWindow)=='function') this.JSChartContainer.ChangeIndexWindow(windowIndex, option); } //切换K线指标 this.ChangeScriptIndex = function (windowIndex, indexData) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeScriptIndex) == 'function') this.JSChartContainer.ChangeScriptIndex(windowIndex, indexData); } //获取当前显示的指标信息 this.GetIndexInfo = function () { if (this.JSChartContainer && typeof (this.JSChartContainer.GetIndexInfo) == 'function') return this.JSChartContainer.GetIndexInfo(); else return []; } //K线周期切换 this.ChangePeriod = function (period, option) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangePeriod) == 'function') this.JSChartContainer.ChangePeriod(period, option); } //切换系统指示 this.ChangeInstructionIndex = function (indexName) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeInstructionIndex) == 'function') this.JSChartContainer.ChangeInstructionIndex(indexName); } //切换自定义指示 this.ChangeInstructionScriptIndex = function (indexData) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeInstructionIndex) == 'function') this.JSChartContainer.ChangeInstructionScriptIndex(indexData); } //增加一个指标窗口 this.AddIndexWindow=function(indexName,option) { if (this.JSChartContainer && typeof(this.JSChartContainer.AddIndexWindow)=='function') this.JSChartContainer.AddIndexWindow(indexName,option); } this.AddScriptIndexWindow=function(indexInfo, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.AddScriptIndexWindow)=='function') this.JSChartContainer.AddScriptIndexWindow(indexInfo,option); } this.AddAPIIndexWindow=function(indexData, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.AddAPIIndexWindow)=='function') this.JSChartContainer.AddAPIIndexWindow(indexData,option); } //删除一个指标窗口 this.RemoveIndexWindow=function(id) { if (this.JSChartContainer && typeof(this.JSChartContainer.RemoveIndexWindow)=='function') this.JSChartContainer.RemoveIndexWindow(id); } //取消指示 this.CancelInstructionIndex = function () { if (this.JSChartContainer && typeof (this.JSChartContainer.CancelInstructionIndex) == 'function') this.JSChartContainer.CancelInstructionIndex(); } //切换指标模板 this.ChangeIndexTemplate = function (option) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeIndexTemplate) == 'function') { JSConsole.Chart.Log('[JSChart:ChangeIndexTemplate] ', option); this.JSChartContainer.ChangeIndexTemplate(option); } } this.CreateChartDrawPicture=function(name,option) { if(this.JSChartContainer && typeof(this.JSChartContainer.CreateChartDrawPicture)=='function') { JSConsole.Chart.Log('[JSChart:CreateChartDrawPicture] ', name); this.JSChartContainer.CreateChartDrawPicture(name,option); } } //K线复权切换 this.ChangeRight = function (right) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeRight) == 'function') this.JSChartContainer.ChangeRight(right); } //设置当前屏的起始日期 { Date:起始日期(必填), Time:起始时间(分钟K线必填) PageSize:一屏显示的数据个数(可选)} this.SetFirstShowDate=function(obj) { if (this.JSChartContainer && typeof(this.JSChartContainer.SetFirstShowDate)=='function') this.JSChartContainer.SetFirstShowDate(obj); } //K线切换类型 0=实心K线 1=收盘价线 2=美国线 3=空心K线 this.ChangeKLineDrawType = function (drawType) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeKLineDrawType) == 'function') this.JSChartContainer.ChangeKLineDrawType(drawType); } //叠加股票 this.OverlaySymbol = function (symbol,option) { if (this.JSChartContainer && typeof (this.JSChartContainer.OverlaySymbol) == 'function') this.JSChartContainer.OverlaySymbol(symbol, option); } //设置强制横屏 this.ForceLandscape = function (bForceLandscape) { if (this.JSChartContainer) { JSConsole.Chart.Log("[JSChart::ForceLandscape] bForceLandscape=" + bForceLandscape); this.JSChartContainer.IsForceLandscape = bForceLandscape; } } //锁|解锁指标 this.LockIndex = function (lockData) { if (this.JSChartContainer && typeof (this.JSChartContainer.LockIndex) == 'function') { JSConsole.Chart.Log('[JSChart:LockIndex] lockData', lockData); this.JSChartContainer.LockIndex(lockData); } } //历史分钟数据 更改日期 this.ChangeTradeDate = function (tradeDate) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeTradeDate) == 'function') { JSConsole.Chart.Log('[JSChart:ChangeTradeDate] date', tradeDate); this.JSChartContainer.ChangeTradeDate(tradeDate); } } //多日走势图 this.ChangeDayCount = function (count) { if (this.JSChartContainer && typeof (this.JSChartContainer.ChangeDayCount) == 'function') { JSConsole.Chart.Log('[JSChart:ChangeDayCount] count', count); this.JSChartContainer.ChangeDayCount(count); } } this.StopAutoUpdate = function () { if (this.JSChartContainer && typeof (this.JSChartContainer.StopAutoUpdate) == 'function') { JSConsole.Chart.Log("[JSChart::StopAutoUpdate] Stop."); this.JSChartContainer.StopAutoUpdate(); } } this.StopAutoUpdata = this.StopAutoUpdate; this.ChartDestory=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestory) == 'function') { JSConsole.Chart.Log("[JSChart::ChartDestory]"); this.JSChartContainer.ChartDestory(); } } this.OnTouchStart = function (e) { if (this.JSChartContainer) this.JSChartContainer.ontouchstart(e); } this.OnTouchMove = function (e) { if (this.JSChartContainer) this.JSChartContainer.ontouchmove(e); } this.OnTouchEnd = function (e) { if (this.JSChartContainer) this.JSChartContainer.ontouchend(e); } this.SaveToImage = function (callback) { if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImage) == 'function') this.JSChartContainer.SaveToImage(callback); } this.EnableSplashScreen=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.EnableSplashScreen)=='function') this.JSChartContainer.EnableSplashScreen(option); } //叠加指标 this.AddOverlayIndex=function(obj) //{WindowIndex:窗口ID, IndexName:指标ID, Identify:叠加指标ID(可选), API} { if (this.JSChartContainer && typeof(this.JSChartContainer.AddOverlayIndex)=='function') this.JSChartContainer.AddOverlayIndex(obj); } //删除叠加指标 this.DeleteOverlayWindowsIndex=function(identify) { if (this.JSChartContainer && typeof(this.JSChartContainer.DeleteOverlayWindowsIndex)=='function') this.JSChartContainer.DeleteOverlayWindowsIndex(identify); } this.ChangePriceGap=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ChangePriceGap)=='function') { JSConsole.Chart.Log('[JSChart:ChangePriceGap] '); return this.JSChartContainer.ChangePriceGap(option); } } } JSChart.LastVersion=null; //最新的版本号 //初始化 JSChart.Init = function (uielement) { JSConsole.Chart.Log('[JSChart.Init] uielement', uielement); var jsChartControl = new JSChart(uielement); jsChartControl.OnSize(); return jsChartControl; } JSChart.SetDomain = function (domain, cacheDomain) { if (domain) { g_JSChartResource.Domain = domain; g_JSChartResource.Index.StockHistoryDayApiUrl = domain + "/API/StockHistoryDay"; //历史数据api g_JSChartResource.Index.MarketLongShortApiUrl = domain + "/API/FactorTiming"; //市场多空 g_JSChartResource.Index.MarketAttentionApiUrl = domain + "/API/MarketAttention"; //市场关注度 g_JSChartResource.Index.MarketHeatApiUrl = domain + "/API/MarketHeat"; //行业,指数热度 } if (cacheDomain) g_JSChartResource.CacheDomain = cacheDomain; JSCommonComplier.JSComplier.SetDomain(domain, cacheDomain); //编译器数据api域名修改 } //自定义风格 JSChart.SetStyle = function (style) { if (style) g_JSChartResource.SetStyle(style); } JSChart.GetResource = function () //获取颜色配置 (设置配必须啊在JSChart.Init()之前) { return g_JSChartResource; } JSChart.GetMinuteTimeStringData=function() { return JSCommonCoordinateData.MinuteTimeStringData; } JSChart.GetMinuteCoordinateData=function() { return JSCommonCoordinateData.MinuteCoordinateData; } JSChart.GetKLineZoom = function () //K线缩放配置 { return ZOOM_SEED; } JSChart.SetKLineZoom=function(aryZoom) //设置K线缩放比例 { ZOOM_SEED.length=0; for(var i=0;i { if (!this.LastMovePoint) return; this.OnMouseMove(this.LastMovePoint.X, this.LastMovePoint.Y, e); this.DrawMoveTimer=null; }, this.DrawMoveWaitTime); } this.ontouchmove = function (e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var jsChart = this; var touches = this.GetToucheData(e, jsChart.IsForceLandscape); if (this.IsPhoneDragging(e)) { var drag = jsChart.MouseDrag; if (drag == null) { this.StartMoveTimer(touches, e); } else { var moveSetp = Math.abs(drag.LastMove.X - touches[0].clientX); moveSetp = parseInt(moveSetp); var isMoveCorssCursor=false; if (this.EnableClickModel) { if (this.ClickModel.IsShowCorssCursor===true) isMoveCorssCursor=true; else isMoveCorssCursor=false; } if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) { if(moveSetp<5 && moveUpDown<5) return; if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY,true)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==3) { if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY,true)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==20) //画图工具移动 { if(moveSetp<5 && moveUpDown<5) return; if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y,true)) { this.DrawDynamicInfo(); } } drag.LastMove.X=touches[0].clientX; drag.LastMove.Y=touches[0].clientY; } else if (isMoveCorssCursor) { jsChart.MouseDrag=null; jsChart.MoveCorssCursor(drag.Click,e); //移动十字光标 } else if (jsChart.DragMode == 1) //数据左右拖拽 { var moveAngle=this.GetMoveAngle(drag.LastMove,{X:touches[0].clientX, Y:touches[0].clientY}); var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY); if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true ) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_TOUCH_SCROLL_UP_DOWN); var isEnd=true; //是否退出 if (event && event.Callback) { var sendData={ DragData:drag, PreventDefault:false }; event.Callback(event, sendData, this); isEnd=(sendData.PreventDefault===false); } if (isEnd) { this.ClearTouchTimer(); return; } } if (this.EnableMoveData && this.EnableMoveData.Touch===false) { jsChart.MouseDrag = null; return; } if (moveSetp < 5) return; var isLeft = true; if (drag.LastMove.X < touches[0].clientX) isLeft = false;//右移数据 if (jsChart.DataMove(moveSetp, isLeft)) { jsChart.UpdataDataoffset(); jsChart.UpdatePointByCursorIndex(); jsChart.UpdateFrameMaxMin(); jsChart.ResetFrameXYSplit(); jsChart.Draw(); this.OnKLinePageChange("OnTouchMove"); } else { if (jsChart.DragDownloadData) jsChart.DragDownloadData(); } drag.LastMove.X = touches[0].clientX; drag.LastMove.Y = touches[0].clientY; } } if (this.PhoneTouchInfo) { this.PhoneTouchInfo.End.X=touches[0].clientX; this.PhoneTouchInfo.End.Y=touches[0].clientY; } } else if (this.IsPhonePinching(e)) { var phonePinch = jsChart.PhonePinch; if (!phonePinch) return; phonePinch.Operator=null; if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return; var yHeight = Math.abs(touches[0].pageY - touches[1].pageY); var yLastHeight = Math.abs(phonePinch.Last.Y - phonePinch.Last.Y2); var yStep = yHeight - yLastHeight; var xHeight = Math.abs(touches[0].pageX - touches[1].pageX); var xLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2); var xStep = xHeight - xLastHeight; var minStep=this.ZoomStepPixel; if (Math.abs(yStep) < minStep && Math.abs(xStep) < minStep) return; var step = yStep; if (Math.abs(yStep) < minStep) step = xStep; if (step > 0) //放大 { var cursorIndex = { IsLockRight:this.IsZoomLockRight }; cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0)); if (!jsChart.Frame.ZoomUp(cursorIndex)) return; phonePinch.Operator="ZoomUp"; jsChart.CursorIndex = cursorIndex.Index; jsChart.UpdatePointByCursorIndex(); jsChart.UpdataDataoffset(); jsChart.UpdateFrameMaxMin(); jsChart.ResetFrameXYSplit(); jsChart.Draw(); this.OnKLinePageChange("OnTouchMove"); } else //缩小 { var cursorIndex = { IsLockRight:this.IsZoomLockRight }; cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0)); if (!jsChart.Frame.ZoomDown(cursorIndex)) return; phonePinch.Operator="ZoomDown"; jsChart.CursorIndex = cursorIndex.Index; jsChart.UpdataDataoffset(); jsChart.UpdatePointByCursorIndex(); jsChart.UpdateFrameMaxMin(); jsChart.ResetFrameXYSplit(); jsChart.Draw(); this.OnKLinePageChange("OnTouchMove"); } phonePinch.Last = { X: touches[0].pageX, Y: touches[0].pageY, X2: touches[1].pageX, Y2: touches[1].pageY }; } } this.ontouchend = function (e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var bClearDrawPicture=true; if (this.CurrentChartDrawPicture) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==2 || drawPicture.Status==1 || drawPicture.Status==3) { drawPicture.PointStatus=drawPicture.Status; if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo(); else bClearDrawPicture=false; } else if (drawPicture.Status==20) { if (this.FinishMoveChartDrawPicture()) this.DrawDynamicInfo(); } } if (this.EnableZoomIndexWindow) { var time=Date.now(); this.PhoneDBClick.AddTouchEnd(time); if (this.PhoneDBClick.IsVaildDBClick()) { this.OnTouchDBClick(this.PhoneDBClick.Start); this.PhoneDBClick.Clear(); } } this.IsOnTouch = false; this.LastMovePoint=null; if (bClearDrawPicture===true) this.CurrentChartDrawPicture=null; JSConsole.Chart.Log('[JSChartContainer:ontouchend] IsOnTouch=' + this.IsOnTouch +' LastDrawStatus=' + this.LastDrawStatus); this.ClearDrawMoveTimer(); this.ClearTouchTimer(); this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchEnd"}, e); this.OnTouchFinished(); this.TouchDrawCount=0; this.PhonePinch=null; } this.OnTouchFinished=function() { if (this.EnableClickModel===true) { if (this.ClickModel.IsShowCorssCursor==true && this.TouchDrawCount>0) return; this.ClickModel.IsShowCorssCursor=false; this.Draw(); return; } this.Draw();//手放开 重新绘制 } this.OnTouchDBClick=function(points) { var x=points[0].X, y=points[0].Y; JSConsole.Chart.Log('[JSChartContainer:OnTouchDBClick] Phone dbclick', x, y); var frameId=this.Frame.PtInFrame(x,y); JSConsole.Chart.Log("[JSChartContainer::OnTouchDBClick] frameId",frameId); if (frameId>=this.Frame.ZoomStartWindowIndex) { if (this.ZoomIndexWindow(frameId, {X:x, Y:y})) { this.Frame.SetSizeChage(true); this.Draw(); return true; } } return false; } this.ZoomIndexWindow=function(frameID, option) //最大化/最小化指标窗口 { if (frameID<0 || frameID>=this.Frame.SubFrame.length) return false; return this.Frame.ZoomIndexWindow(frameID, option); } this.TouchEvent=function(obj,e) { var eventID=obj.EventID; var event=this.GetEvent(eventID); if (!event || !event.Callback) return false; var drag=this.PhoneTouchInfo if (!drag || !drag.Start || !drag.End ) return false; var clientX=drag.End.X; var clientY=drag.End.Y; var x=drag.End.X; var y=drag.End.Y; var data= { X:clientX, Y:clientY, FrameID:-1, FunctionName:obj.FunctionName, Drag: { Start:{ X:drag.Start.X, Y:drag.Start.Y }, End:{ X:drag.End.X, Y:drag.End.Y } } }; var isInClient=false; var rtClient = new Rect(this.Frame.ChartBorder.GetLeft(), this.Frame.ChartBorder.GetTop(), this.Frame.ChartBorder.GetWidth(), this.Frame.ChartBorder.GetHeight()); isInClient = rtClient.IsPointIn(x, y); if (isInClient) { if (this.Frame && this.Frame.IsHScreen) { var yValueExtend={}; var yValue=this.Frame.GetYData(x,yValueExtend); if (IFrameSplitOperator.IsNumber(yValueExtend.FrameID) && yValueExtend.FrameID>=0) { var xValue=this.Frame.GetXData(y); data.FrameID=yValueExtend.FrameID; data.Data={ X:xValue, Y:yValue } ; } } else { var yValueExtend={}; var yValue=this.Frame.GetYData(y,yValueExtend); if (IFrameSplitOperator.IsNumber(yValueExtend.FrameID) && yValueExtend.FrameID>=0) { var xValue=this.Frame.GetXData(x); data.FrameID=yValueExtend.FrameID; data.Data={ X:xValue, Y:yValue } ; } } } event.Callback(event, data, this); return true; } this.FullDraw=function(drawType) { var self = this; this.Canvas.clearRect(0, 0, this.UIElement.Width, this.UIElement.Height); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) //动画 { this.Frame.ClearCoordinateText(); this.Frame.Draw({ IsEnableSplash:this.ChartSplashPaint.IsEnableSplash}); //框架 this.ChartSplashPaint.Draw(); this.LastDrawStatus = 'FullDraw'; this.Canvas.draw(); return; } this.Frame.SetDrawOtherChart(() => { for (var i in this.ExtendChartPaint) { var item = this.ExtendChartPaint[i]; if (item.IsCallbackDraw) item.Draw(); } }); this.Frame.Draw(); //框架 if (this.Frame.DrawCustomVertical) { var eventCVericalDraw = this.GetEvent(JSCHART_EVENT_ID.ON_CUSTOM_VERTICAL_DRAW); this.Frame.DrawCustomVertical(eventCVericalDraw); } for (var i=0; iendKLine.Open) info.LineColor=g_JSChartResource.FrameLatestPrice.UpBarColor; else if (endKLine.Close0) return (dataCount-1)-hisData.DataOffset; return null; } this.Draw = function () { if (this.IsDestroy) return; if (this.IsFullDraw) { this.FullDraw('Draw'); ++this.TouchDrawCount; return; } if (this.IsOnTouch == true && (this.ClassName == 'MinuteChartContainer' || this.ClassName =='MinuteChartHScreenContainer')) return; var self = this; this.Canvas.clearRect(0, 0, this.UIElement.Width, this.UIElement.Height); this.Frame.SetDrawOtherChart(() => { for (var i in this.ExtendChartPaint) { var item = this.ExtendChartPaint[i]; if (item.IsCallbackDraw) item.Draw(); } }); //框架 this.Frame.Draw(); if (this.Frame.DrawCustomVertical) { var eventCVericalDraw = this.GetEvent(JSCHART_EVENT_ID.ON_CUSTOM_VERTICAL_DRAW); this.Frame.DrawCustomVertical(eventCVericalDraw); } if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) { this.Frame.DrawInsideHorizontal(); this.ChartSplashPaint.Draw(); this.LastDrawStatus = 'Draw'; this.Canvas.draw(); return; } for (var i=0; i { //JSConsole.Chart.Log("[DrawDynamicInfo] onload ", self.TempImage); self.Canvas.clearRect(0, 0, width, height); self.Canvas.drawImage(self.TempImage, 0, 0, width, height); self.DrawDynamicChart(false); } } else { self.Canvas.drawImage(this.Frame.ScreenImagePath, 0, 0, width, height); self.DrawDynamicChart(false); } } } this.DrawDynamicChart = function (bReserve) { var self = this; if (self.ChartCorssCursor) { self.ChartCorssCursor.LastPoint = self.LastPoint; self.ChartCorssCursor.CursorIndex = self.CursorIndex; self.ChartCorssCursor.Draw(); } for (var i in self.TitlePaint) { var item = self.TitlePaint[i]; if (!item.IsDynamic) continue; item.CursorIndex = self.CursorIndex; item.Draw(); } for (var i in this.ExtendChartPaint) //动态扩展图形 在动态标题以后画 { var item = this.ExtendChartPaint[i]; if (item.IsDynamic && item.DrawAfterTitle) item.Draw(); } if (this.EnableAnimation) { for (var i in this.ExtendChartPaint) //动画 { var item = this.ExtendChartPaint[i]; if (item.IsAnimation === true) item.Draw(); } } this.LastDrawStatus = 'DrawDynamicInfo'; JSConsole.Chart.Log('[JSChartContainer:DrawDynamicChart][ID=' + this.UIElement.ID + '] draw .....'); self.Canvas.draw(bReserve, function () { JSConsole.Chart.Log('[JSChartContainer:DrawDynamicChart] finish.'); }); } this.DrawAnimation = function () //绘制动画 如弹幕 { if (!this.EnableAnimation) return; if (this.Frame.ScreenImagePath && !this.IsOnTouch) { for (var i in this.ExtendChartPaint) { var item = this.ExtendChartPaint[i]; if (item.IsAnimation === true) item.IsMoveStep = true; //移动弹幕 } this.DrawDynamicInfo(); } var self = this; this.UIElement.WebGLCanvas.requestAnimationFrame(() => { this.DrawAnimation(); }); } this.StartAnimation = function (option) { JSConsole.Chart.Log('[JSChartContainer::StartAnimation] ', this.UIElement.WebGLCanvas); if (!this.UIElement.WebGLCanvas) return; var bCreated = false; //是否已经创建了弹幕画法 var barrageData = null; for (var i in this.ExtendChartPaint) { var item = this.ExtendChartPaint[i]; if (item.ClassName === 'BarragePaint') { bCreated = true; barrageData = item.BarrageList; break; } } if (!bCreated) { var chart = new BarragePaint(); chart.Canvas = this.Canvas; chart.ChartBorder = this.Frame.ChartBorder; chart.ChartFrame = this.Frame; chart.HQChart = this; chart.SetOption(option); this.ExtendChartPaint.push(chart); barrageData = chart.BarrageList; } this.EnableAnimation = true; var self = this; this.UIElement.WebGLCanvas.requestAnimationFrame(()=> { this.DrawAnimation(); }); return barrageData; } this.StopAnimation = function () { this.EnableAnimation = false; this.DrawDynamicInfo(); } this.OnMouseMove = function (x, y, e, bFullDraw) { var lastY = this.LastPoint.Y; this.LastPoint.X = x; this.LastPoint.Y = y; var lastCursorIndex = this.CursorIndex; this.CursorIndex = this.Frame.GetXData(x); if ( this.ClassName=="KLineChartContainer" || this.ClassName=="KLineChartHScreenContainer" ) { if (lastCursorIndex == this.CursorIndex && Math.abs(lastY - y) < 1) return; //一个一个数据移动 } else { if (parseInt(lastCursorIndex - 0.5) == parseInt(this.CursorIndex - 0.5) && Math.abs(lastY - y) < 1) return; //一个一个数据移动 } if (bFullDraw) { this.FullDraw(); } else { if (this.IsForceLandscape) this.Draw();//横屏图片太大不让贴,分两张图贴,多次截图的函数是坏的, 直接重画了 else this.DrawDynamicInfo(); } } this.MoveCorssCursor=function(point, e) { var x = point.X; var y = point.Y; this.OnMouseMove(x,y,e,true); } this.OnDoubleClick = function (x, y, e) { //JSConsole.Chart.Log(e); } this.UpdatePointByCursorIndex = function () { this.LastPoint.X = this.Frame.GetXFromIndex(this.CursorIndex); var index = Math.abs(this.CursorIndex - 0.5); index = parseInt(index.toFixed(0)); if (this.ClassName == 'KLineChartContainer') index = this.CursorIndex; var data = this.Frame.Data; if (data.DataOffset + index >= data.Data.length) { return; } var close = data.Data[data.DataOffset + index].Close; this.LastPoint.Y = this.Frame.GetYFromData(close); } this.ResetFrameXYSplit = function () { if (typeof (this.Frame.ResetXYSplit) == 'function') this.Frame.ResetXYSplit(); } this.UpdateFrameMaxMinV2=function() { var mapFrame=new Map(); //key=frameid, value:{ ChartPaint:[] } for(var i=0;irange.Min) item.Min=range.Min; } if (item.Frame.YSpecificMaxMin) //固定坐标 { item.Min=item.Frame.YSpecificMaxMin.Max; item.Max=item.Frame.YSpecificMaxMin.Min; } if (!IFrameSplitOperator.IsNumber(frame.YMaxMin.Max) || frame.YMaxMin.Max!=item.Max) { frame.YMaxMin.Max=item.Max; frame.XYSplit=true; } if (!IFrameSplitOperator.IsNumber(frame.YMaxMin.Min) || frame.YMaxMin.Min!=item.Min) { frame.YMaxMin.Min=item.Min frame.XYSplit=true; } if (frame.XYSplit) { var max=10, min=0; if (item.Max!=null) max=item.Max; if (item.Min!=null) min=item.Min; frame.HorizontalMax=max; frame.HorizontalMin=min; } else { frame.XSplit=true; } //共享Y轴叠加指标坐标同步 for(var j=0;j range.Min) frameItem.Range.Min = range.Min; } else { frameItem = { OverlayFrame:[] }; frameItem.Frame = paint.ChartFrame; frameItem.Range = range; frameMaxMinData.push(frameItem); } } var mapFrame=new Map(); for(var i=0;irange.Min) frameItem.Range.Min=range.Min; } } } for (var i=0; i= data.Data.length) return false; ++data.DataOffset; return true; } this.UpdataDataoffset = function () { var data = null; if (this.Frame.Data) data = this.Frame.Data; else data = this.Frame.SubFrame[0].Frame.Data; if (!data) return; for (var i=0; i { if (this.RightSpaceCount > 0) { if (xPointcount + data.DataOffset >= data.Data.length + this.RightSpaceCount) return false; data.DataOffset += step; if (data.DataOffset + xPointcount >= data.Data.length + this.RightSpaceCount) data.DataOffset = data.Data.length - (xPointcount - this.RightSpaceCount); } else { if (xPointcount + data.DataOffset >= data.Data.length) return false; data.DataOffset += step; if (data.DataOffset + xPointcount >= data.Data.length) data.DataOffset = data.Data.length - xPointcount; } return true; } else //<-- { if (data.DataOffset <= 0) return false; data.DataOffset -= step; if (data.DataOffset < 0) data.DataOffset = 0; return true; } } //获取鼠标在当前子窗口id this.GetSubFrameIndex = function (x, y) { if (!this.Frame.SubFrame || this.Frame.SubFrame.length <= 0) return -1; for (var i in this.Frame.SubFrame) { var frame = this.Frame.SubFrame[i].Frame; var left = frame.ChartBorder.GetLeft(); var top = frame.ChartBorder.GetTop(); var height = frame.ChartBorder.GetHeight(); var width = frame.ChartBorder.GetWidth(); this.Canvas.rect(left, top, width, height); if (this.Canvas.isPointInPath(x, y)) return parseInt(i); } return 0; } //根据X坐标获取数据索引 this.GetDataIndexByPoint = function (x) { var frame = this.Frame; if (this.Frame.SubFrame && this.Frame.SubFrame.length > 0) frame = this.Frame.SubFrame[0].Frame; var data = null; if (this.Frame.Data) data = this.Frame.Data; else data = this.Frame.SubFrame[0].Frame.Data; if (!data || !frame) return; var index = parseInt(frame.GetXData(x)); //JSConsole.Chart.Log('x='+ x +' date='+data.Data[data.DataOffset+index].Date); return data.DataOffset + index; } this.SaveToImage = function (callback) { let width = this.UIElement.Width; let height = this.UIElement.Height;; JSConsole.Chart.Log('[JSChartContainer::SaveToImage]', this.UIElement); wx.canvasToTempFilePath({ x: 0, y: 0, width: width, height: height, canvasId: this.UIElement.ID, success: function (res) { let data = { ImagePath: res.tempFilePath, Width: width, Height: height }; if (typeof (callback) == 'function') callback(data); } }) } //全屏提示信息 { Title:提示信息, Draw:false/true 是否立即重绘, } this.EnableSplashScreen=function(option) { if (!this.ChartSplashPaint) return; if (!option) return; if (IFrameSplitOperator.IsString(option.Title)) this.ChartSplashPaint.SetTitle(option.Title); this.ChartSplashPaint.EnableSplash(true); if (option.Draw===false) return; this.Draw(); } //设置指标窗口属性 windowItem=SetOption.Windows[i], frameItem=SetOption.Frames[i]; this.SetSubFrameAttribute=function(subFrame, windowItem, frameItem) { if (!subFrame || !subFrame.Frame) return; var frame=subFrame.Frame; if (windowItem) { if (IFrameSplitOperator.IsNumber(windowItem.IndexParamSpace)) frame.IndexParamSpace = windowItem.IndexParamSpace; if (IFrameSplitOperator.IsNumber(windowItem.IndexTitleSpace))frame.IndexTitleSpace = windowItem.IndexTitleSpace; if (IFrameSplitOperator.IsBool(windowItem.IsDrawTitleBG)) frame.IsDrawTitleBG=windowItem.IsDrawTitleBG; if (IFrameSplitOperator.IsBool(windowItem.IsShowNameArrow)) frame.IsShowNameArrow=windowItem.IsShowNameArrow; if (IFrameSplitOperator.IsBool(windowItem.IsShowTitleArrow)) frame.IsShowTitleArrow=windowItem.IsShowTitleArrow; } if (frameItem) { if (IFrameSplitOperator.IsNumber(frameItem.SplitCount)) frame.YSplitOperator.SplitCount = frameItem.SplitCount; if (IFrameSplitOperator.IsBool(frameItem.IsShowBorder)) frame.IsShowBorder = frameItem.IsShowBorder; if (IFrameSplitOperator.IsBool(frameItem.IsShowXLine)) frame.IsShowXLine = frameItem.IsShowXLine; if (IFrameSplitOperator.IsBool(frameItem.IsShowYLine)) frame.IsShowYLine=frameItem.IsShowYLine; if (IFrameSplitOperator.IsBool(frameItem.IsShowLeftText)) frame.IsShowYText[0] = frameItem.IsShowLeftText; //显示左边刻度 if (IFrameSplitOperator.IsBool(frameItem.IsShowRightText)) frame.IsShowYText[1] = frameItem.IsShowRightText; //显示右边刻度 } } this.AddNewSubFrame=function(option) { var index=this.Frame.SubFrame.length; var subFrame=this.CreateSubFrameItem(index); this.Frame.SubFrame[index]=subFrame; var titlePaint=new DynamicChartTitlePainting(); titlePaint.Frame=this.Frame.SubFrame[index].Frame; titlePaint.Canvas=this.Canvas; titlePaint.LanguageID=this.LanguageID; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.TitlePaint[index+1]=titlePaint; if (option) { if (option.Window) { var item=option.Window; if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) subFrame.Frame.IsDrawTitleBG=item.IsDrawTitleBG; if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) subFrame.Frame.IsShowNameArrow=item.IsShowNameArrow; } if (IFrameSplitOperator.IsNumber(option.SplitCount)) subFrame.Frame.YSplitOperator.SplitCount=option.SplitCount; if (IFrameSplitOperator.IsNumber(option.TitleHeight)) subFrame.Frame.ChartBorder.TitleHeight=option.TitleHeight; if (IFrameSplitOperator.IsBool(option.IsShowTitleArrow)) subFrame.Frame.IsShowTitleArrow=option.IsShowTitleArrow; if (IFrameSplitOperator.IsBool(option.IsShowIndexName)) subFrame.Frame.IsShowIndexName=option.IsShowIndexName; if (IFrameSplitOperator.IsBool(option.IsShowOverlayIndexName)) subFrame.Frame.IsShowOverlayIndexName=option.IsShowOverlayIndexName; if (IFrameSplitOperator.IsNumber(option.IndexParamSpace)) subFrame.Frame.IndexParamSpace=option.IndexParamSpace; if (IFrameSplitOperator.IsNumber(option.IndexTitleSpace)) subFrame.Frame.IndexTitleSpace=option.IndexTitleSpace; if (IFrameSplitOperator.IsBool(option.IsShowXLine)) subFrame.Frame.IsShowXLine=option.IsShowXLine; if (IFrameSplitOperator.IsBool(option.IsShowYLine)) subFrame.Frame.IsShowYLine=option.IsShowYLine; if (IFrameSplitOperator.IsBool(option.IsShowIndexTitle)) subFrame.Frame.IsShowTitle=option.IsShowIndexTitle; if (IFrameSplitOperator.IsBool(option.IsShowLeftText)) subFrame.Frame.IsShowYText[0] = option.IsShowLeftText; //显示左边刻度 if (IFrameSplitOperator.IsBool(option.IsShowRightText)) subFrame.Frame.IsShowYText[1] = option.IsShowRightText; //显示右边刻度 } //最后一个显示X轴坐标 for(var i=0;i=0) indexData.FloatPrecision=option.FloatPrecision; if (option.StringFormat>0) indexData.StringFormat=option.StringFormat; if (option.Args) indexData.Args=option.Args; } */ this.WindowIndex[index] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args,indexInfo); //脚本执行 if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") var bindData=this.SourceData; else var bindData=this.ChartPaint[0].Data; this.BindIndexData(index,bindData); //执行脚本 } //增加一个自定义指标窗口 this.AddScriptIndexWindow=function(indexInfo, option) { if (!indexInfo || !indexInfo.Script || !indexInfo.Name) return; var index=this.AddNewSubFrame(option); this.WindowIndex[index] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo) if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") var bindData=this.SourceData; else var bindData=this.ChartPaint[0].Data; this.BindIndexData(index,bindData); //执行脚本 } //增加一个远程指标窗口 this.AddAPIIndexWindow=function(indexInfo, option) { if (!indexInfo.API) return; var apiItem = indexInfo.API; var index=this.AddNewSubFrame(option); this.WindowIndex[index] = new APIScriptIndex(apiItem.Name, apiItem.Script, apiItem.Args, indexInfo); if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") var bindData=this.SourceData; else var bindData=this.ChartPaint[0].Data; this.BindIndexData(index,bindData); //执行脚本 } this.SetLanguage=function(language) { var languageID=g_JSChartLocalization.GetLanguageID(language); if (!IFrameSplitOperator.IsNumber(languageID)) { console.warn(`[JSChartContainer::SetLanguage] language=${language} error`); return; } if (this.LanguageID==languageID) return; this.LanguageID=languageID; if (this.ChartCorssCursor && this.ChartCorssCursor.StringFormatY) this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID; for(var i=0; i=this.Frame.SubFrame.length) return; var subFrame=this.Frame.SubFrame[windowIndex]; if (!IFrameSplitOperator.IsNonEmptyArray(subFrame.OverlayIndex)) return; var aryIndexID=[]; for(var i=0; i=0 && windowIndex=0) { data.ChartDrawPicture=item; data.PointIndex=pointIndex; return true; } } return false; } this.SetChartDrawPictureFirstPoint = function (x, y) { var drawPicture = this.CurrentChartDrawPicture; if (!drawPicture) return false; if (!this.Frame.SubFrame || this.Frame.SubFrame.length <= 0) return false; for (var i=0; i=left && x<=right && y>=top && y<=bottom) { drawPicture.Frame = frame; break; } } if (!drawPicture.Frame) return false; drawPicture.Point[0] = new Point(); drawPicture.Point[0].X = x ; drawPicture.Point[0].Y = y; drawPicture.Status = 1; //第1个点完成 return true; } this.SetChartDrawPictureSecondPoint = function (x, y) { var drawPicture = this.CurrentChartDrawPicture; if (!drawPicture) return false; drawPicture.Point[1] = new Point(); drawPicture.Point[1].X = x; drawPicture.Point[1].Y = y; drawPicture.Status = 2; //设置第2个点 return true; } //xStep,yStep 移动的偏移量 this.MoveChartDrawPicture = function (xStep, yStep) { var drawPicture = this.CurrentChartDrawPicture; if (!drawPicture) return false; //JSConsole.Chart.Log("xStep="+xStep+" yStep="+yStep); drawPicture.Move(xStep, yStep); return true; } this.FinishChartDrawPicturePoint = function () { var drawPicture = this.CurrentChartDrawPicture; if (!drawPicture) return false; if (drawPicture.PointCount != drawPicture.Point.length) return false; drawPicture.Status = 10; //完成 drawPicture.PointToValue(); this.ChartDrawPicture.push(drawPicture); this.CurrentChartDrawPicture = null; //通知上层画好了 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FINISH_DRAWPICTURE); //完成画图工具事件 if (event && event.Callback) { let sendData={ DrawPicture: drawPicture }; event.Callback(event,sendData,this); } //单个回调 if (drawPicture.FinishedCallback) drawPicture.FinishedCallback(drawPicture); if (drawPicture.OnFinish) drawPicture.OnFinish(); return true; } this.FinishMoveChartDrawPicture = function () { var drawPicture = this.CurrentChartDrawPicture; if (!drawPicture) return false; if (drawPicture.PointCount != drawPicture.Point.length) return false; drawPicture.Status = 10; //完成 drawPicture.PointToValue(); this.CurrentChartDrawPicture = null; return true; } //清空所有的画线工具 this.ClearChartDrawPicture = function (drawPicture) { if (!drawPicture) { this.ChartDrawPicture = []; this.Draw(); } else { for (var i=0;i=this.Frame.SubFrame.length) return false; if (!option) return false; var frame=this.Frame.SubFrame[windowIndex]; if (option.Delete) { var item=option.Delete; if (item.Window===true) this.DeleteIndexPaint(windowIndex); //删除主指标 if (item.Overlay===true) this.DeleteWindowsOverlayIndex(windowIndex); //清空叠加指标 } //清空标题栏 var titleIndex=windowIndex+1; this.TitlePaint[titleIndex].Data=[]; this.TitlePaint[titleIndex].Title=null; if (option.Window) //主指标 { this.DeleteIndexPaint(windowIndex); //删除主指标 var item=option.Window; if (item.Script) //自定义指标脚本 { this.WindowIndex[windowIndex]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行 } else if (item.API) //后台指标 { var apiItem=item.API; this.WindowIndex[windowIndex]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item); } else { var indexID=item.Index; var indexItem=JSIndexMap.Get(indexID); if (indexItem) { this.WindowIndex[windowIndex]=indexItem.Create(); this.CreateWindowIndex(windowIndex); } else { var systemScript = new JSIndexScript(); var indexInfo = systemScript.Get(indexID); if (indexInfo) { JSIndexScript.ModifyAttribute(indexInfo,item); this.WindowIndex[windowIndex]=new ScriptIndex(indexInfo.Name,indexInfo.Script,indexInfo.Args,indexInfo); //脚本执行 } } } this.SetSubFrameAttribute(frame, item, option.Frame); } //叠加指标 var aryOverlayIndex=[]; if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex)) { this.DeleteWindowsOverlayIndex(windowIndex); //清空叠加指标 for(var i=0;i=0) item.WindowIndex=item.Windows; var overlay=this.CreateOverlayWindowsIndex(item); if (!overlay) continue; aryOverlayIndex.push({ WindowsIndex:item.WindowIndex, Overlay:overlay }); } } //刷新指标 var bindData=this.ChartPaint[0].Data; this.BindIndexData(windowIndex,bindData); //请求主指标 for(var i=0;i 0) { rs = s.length; s += '.'; } while (s.length <= rs + precision) { s += '0'; } return s; } Number.prototype.toFixed2 = Number.prototype.toFixed; //备份下老的 Number.prototype.toFixed = function (precision) { return ToFixed(this, precision) } function Guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } //修正线段有毛刺 function ToFixedPoint(value) { //return value; return parseInt(value) + 0.5; } function ToFixedRect(value) { //return value; // With a bitwise or. //rounded = (0.5 + somenum) | 0; // A double bitwise not. //rounded = ~~ (0.5 + somenum); // Finally, a left bitwise shift. var rounded; return rounded = (0.5 + value) << 0; } function Point() { this.X; this.Y; } function SelectRectData() { this.Data; //主数据 this.JSChartContainer; //行情控件 this.Start; //数据起始位子 this.End; //数据结束位置 this.XStart;//X坐标起始位置 this.XEnd; //X位置结束为止 } //边框信息 function ChartBorder() { this.UIElement; //四周间距 this.Left = 50; this.Right = 80; this.Top = 50; this.Bottom = 50; this.TitleHeight = 15; //标题高度 //上下间距 this.TopSpace = 0; this.BottomSpace = 0; this.LeftExtendWidth=0; //左边扩展图形宽度 this.RightExtendWidth=0; this.GetBorder=function() { var data= { Left:this.Left, LeftEx:this.Left+this.LeftExtendWidth, Right:this.UIElement.Width-this.Right, RightEx:this.UIElement.Width-this.Right-this.RightExtendWidth, Top:this.Top, TopEx:this.Top+this.TitleHeight+this.TopSpace, TopTitle:this.Top+this.TitleHeight, Bottom:this.UIElement.Height-this.Bottom, BottomEx:this.UIElement.Height-this.Bottom-this.BottomSpace, ChartWidth:this.UIElement.Width, ChartHeight:this.UIElement.Height }; return data; } this.GetHScreenBorder=function() { var data= { Left:this.Left, LeftEx:this.Left+this.BottomSpace, Right:this.UIElement.Width-this.Right, RightEx:this.UIElement.Width-this.Right-this.TitleHeight- this.TopSpace, RightTitle:this.UIElement.Width-this.Right-this.TitleHeight, Top:this.Top, TopEx:this.Top+this.LeftExtendWidth, Bottom:this.UIElement.Height-this.Bottom, BottomEx:this.UIElement.Height-this.Bottom-this.RightExtendWidth, ChartWidth:this.UIElement.Width, ChartHeight:this.UIElement.Height }; return data; } this.GetChartWidth = function () { return this.UIElement.Width; } this.GetChartHeight = function () { return this.UIElement.Height; } this.GetLeft = function () { return this.Left; } this.GetRight = function () { return this.UIElement.Width - this.Right; } this.GetTop = function () { return this.Top; } this.GetTopEx = function () //去掉标题,上面间距 { return this.Top + this.TitleHeight + this.TopSpace; } this.GetTopTitle = function () //去掉标题 { return this.Top + this.TitleHeight; } this.GetBottom = function () { return this.UIElement.Height - this.Bottom; } this.GetBottomEx = function () { return this.UIElement.Height - this.Bottom - this.BottomSpace; } this.GetWidth = function () { return this.UIElement.Width - this.Left - this.Right; } this.GetHeight = function () { return this.UIElement.Height - this.Top - this.Bottom; } this.GetHeightEx = function () //去掉标题的高度 上下间距 { return this.UIElement.Height - this.Top - this.Bottom - this.TitleHeight - this.TopSpace - this.BottomSpace; } this.GetRightEx = function () //横屏去掉标题高度的 上面间距 { return this.UIElement.Width - this.Right - this.TitleHeight - this.TopSpace; } this.GetWidthEx = function () //横屏去掉标题宽度 上下间距 { return this.UIElement.Width - this.Left - this.Right - this.TitleHeight - this.TopSpace - this.BottomSpace; } this.GetLeftEx = function () //横屏 { return this.Left + this.BottomSpace; } this.GetRightTitle = function ()//横屏 { return this.UIElement.Width - this.Right - this.TitleHeight; } this.GetTitleHeight = function () { return this.TitleHeight; } } function SubFrameItem() { this.Frame; this.Height; this.OverlayIndex=[]; //叠加指标 } function OverlayIndexItem() { this.Frame; this.ChartPaint=[]; this.Identify=Guid(); this.Scprit; //脚本 this.UpdateFrameMaxMin=function() //调整坐标最大 最小值 { var value={ Max:null, Min:null } if (this.Frame.IsShareY) //共享Y轴坐标 { this.Frame.XYSplit=true; return; } if (this.Frame.YSpecificMaxMin) //固定坐标 { value.Max=this.Frame.YSpecificMaxMin.Max; value.Min=this.Frame.YSpecificMaxMin.Min; } else { for(var i=0; irange.Min) value.Min=range.Min; } } } if (!IFrameSplitOperator.IsNumber(this.Frame.YMaxMin.Max) || this.Frame.YMaxMin.Max!=value.Max) { this.Frame.YMaxMin.Max=value.Max; this.Frame.XYSplit=true; } if (!IFrameSplitOperator.IsNumber(this.Frame.YMaxMin.Min) || this.Frame.YMaxMin.Min!=value.Min) { this.Frame.YMaxMin.Min=value.Min; this.Frame.XYSplit=true; } if (this.Frame.XYSplit) { var max=10, min=0; if (value.Max!=null) max=value.Max; if (value.Min!=null) min=value.Min; this.Frame.HorizontalMax=max; this.Frame.HorizontalMin=min; } else { this.Frame.XYSplit=true; } } } //行情框架 function HQTradeFrame() { this.ClassName='HQTradeFrame'; this.SubFrame = new Array(); //SubFrameItem 数组 this.SizeChange = true; //大小是否改变 this.ChartBorder; this.Canvas; //画布 this.ScreenImagePath; //截图路径 this.ScreenImageData=null; //截图数据 this.Data; //主数据 this.Position; //画布的位置 this.SizeChange = true; this.SnapshotID=0; this.CurrentSnapshotID=0; this.SnapshotStatus=0; //0空闲 1工作 this.AutoLeftBorder=null; //{ Blank:10 留白宽度, MinWidth:最小宽度 } this.AutoRightBorder=null; //{ Blank:10 留白宽度, MinWidth:最小宽度 } this.ZoomWindowsInfo=null; //附图指标缩放,备份信息 this.ZoomStartWindowIndex=1; //允许缩放窗口起始位置 this.CalculateChartBorder = function () //计算每个子框架的边框信息 { if (this.SubFrame.length <= 0) return; var top = this.ChartBorder.GetTop(); var height = this.ChartBorder.GetHeight(); var totalHeight = 0; for (var i=0; ivalue) value=this.AutoLeftBorder.MinWidth; } if (this.IsHScreen) this.ChartBorder.Top=value; else this.ChartBorder.Left=value; for(var i=0; ivalue) value=this.AutoRightBorder.MinWidth; } if (this.IsHScreen) this.ChartBorder.Bottom=value; else this.ChartBorder.Right=value; for(var i=0; i0 && overlayItem.Frame) { overlayItem.Frame.Draw(); } } } this.SizeChange = false; } this.DrawOveraly=function(bDrawFirst) { for(var i=0; i= 4) { var barCount = this.ChartFrame.BarCount; var subBarWidth = dataWidth; var subBarOffset = 0; if (barCount > 0) //多柱子需要把框架柱子宽度的平均分割 { subBarWidth = dataWidth / barCount; subBarOffset = subBarWidth * this.BarID; //JSConsole.Chart.Log('[ChartXYSubBar::Draw] ', subBarWidth, this.BarID, subBarOffset); } xMiddle = ToFixedRect(xMiddle); //调整为整数 for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, yOffset -= (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value == 0) continue; var yBottom = yOffset + subBarOffset; var yTop = yOffset + subBarOffset - dataWidth; if (yBottom < chartTop) break; var x = this.ChartFrame.GetXFromIndex(value); if (value > 0) { this.Canvas.fillStyle = this.UpBarColor; let barWidth = ToFixedRect(Math.abs(x - xMiddle)); let barHeight = subBarWidth; if (Math.abs(chartTop - yBottom) < dataWidth) subBarWidth = Math.abs(chartTop - yBottom); //最后一根柱子可能会超出框架 this.Canvas.fillRect(xMiddle, ToFixedRect(yTop), barWidth, ToFixedRect(barHeight + 0.5)); } else { this.Canvas.fillStyle = this.DownBarColor; //高度调整为整数 let barWidth = ToFixedRect(Math.abs(x - xMiddle)); let barHeight = subBarWidth; if (Math.abs(chartTop - yBottom) < subBarWidth) barHeight = Math.abs(chartTop - yBottom); //最后一根柱子可能会超出框架 this.Canvas.fillRect(xMiddle, ToFixedRect(yTop), -barWidth, ToFixedRect(barHeight + 0.5)); } } } else //太细了 直接画柱子 { for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, yOffset -= (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value == 0) continue; var yBottom = yOffset; var yTop = yOffset - dataWidth; if (yTop < chartTop) break; var x = this.ChartFrame.GetXFromIndex(value); var y = this.ChartFrame.GetYFromData(j); if (value > 0) this.Canvas.strokeStyle = this.UpBarColor; else this.Canvas.strokeStyle = this.DownBarColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(x), y); this.Canvas.lineTo(ToFixedPoint(xMiddle), y); this.Canvas.stroke(); } } } } function ChartSubBar() { this.newMethod = ChartBar; //派生 this.newMethod(); delete this.newMethod; this.BarID = 0; this.Draw = function () { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var xPointCount = this.ChartFrame.XPointCount; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; var yBottom = this.ChartFrame.GetYFromData(0); if (dataWidth >= 4) { var barCount = this.ChartFrame.BarCount; var subBarWidth = dataWidth; var subBarOffset = 0; if (barCount > 0) //多柱子需要把框架柱子宽度的平均分割 { subBarWidth = dataWidth / barCount; subBarOffset = subBarWidth * this.BarID; //JSConsole.Chart.Log('[ChartSubBar::Draw] ', subBarWidth, this.BarID, subBarOffset); } yBottom = ToFixedRect(yBottom); //调整为整数 for (let i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value == 0) continue; var left = xOffset + subBarOffset var right = xOffset + subBarOffset + subBarWidth; if (left > chartright) break; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (value > 0) { this.Canvas.fillStyle = this.UpBarColor; //高度调整为整数 let height = ToFixedRect(Math.abs(yBottom - y)); let barWidth = subBarWidth; if (chartright - left < subBarWidth) barWidth = chartright - left; if (yBottom - y > 0) y = yBottom - height; else y = yBottom + height; this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(barWidth), height); } else { this.Canvas.fillStyle = this.DownBarColor; //高度调整为整数 let height = ToFixedRect(Math.abs(yBottom - y)); let barWidth = subBarWidth; if (chartright - left < subBarWidth) barWidth = chartright - left; if (yBottom - y > 0) y = yBottom - height; else y = yBottom + height; this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(subBarWidth), -height); } } } else //太细了 直接画柱子 { for (let i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value == 0) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (value > 0) this.Canvas.strokeStyle = this.UpBarColor; else this.Canvas.strokeStyle = this.DownBarColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(x), y); this.Canvas.lineTo(ToFixedPoint(x), yBottom); this.Canvas.stroke(); } } } } //柱子 支持横屏 function ChartBar() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.UpBarColor = g_JSChartResource.UpBarColor; this.DownBarColor = g_JSChartResource.DownBarColor; this.Draw = function () { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } var isHScreen = (this.ChartFrame.IsHScreen === true); var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); if (isHScreen) chartright = this.ChartBorder.GetBottom(); var xPointCount = this.ChartFrame.XPointCount; var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0; if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0; var bFirstPoint = true; var drawCount = 0; var yBottom = this.ChartFrame.GetYFromData(0); if (dataWidth >= 4) { yBottom = ToFixedRect(yBottom); //调整为整数 for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value == 0) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (value > 0) { this.Canvas.fillStyle = this.UpBarColor; if (isHScreen) { let height = ToFixedRect(Math.abs(yBottom - y)); //高度调整为整数 y = Math.min(yBottom, y); this.Canvas.fillRect(y, ToFixedRect(left), height, ToFixedRect(dataWidth)); } else { let height = ToFixedRect(Math.abs(yBottom - y)); //高度调整为整数 if (yBottom - y > 0) y = yBottom - height; else y = yBottom + height; this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), height); } } else { this.Canvas.fillStyle = this.DownBarColor; //高度调整为整数 let height = ToFixedRect(Math.abs(yBottom - y)); if (yBottom - y > 0) y = yBottom - height; else y = yBottom + height; this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), -height); } } } else //太细了 直接画柱子 { for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) { var value = this.Data.Data[i]; if (value == null || value == 0) continue; var left = xOffset; var right = xOffset + dataWidth; if (right > chartright) break; var x = this.ChartFrame.GetXFromIndex(j); var y = this.ChartFrame.GetYFromData(value); if (value > 0) this.Canvas.strokeStyle = this.UpBarColor; else this.Canvas.strokeStyle = this.DownBarColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(y, ToFixedPoint(x)); this.Canvas.lineTo(yBottom, ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x), y); this.Canvas.lineTo(ToFixedPoint(x), yBottom); } this.Canvas.stroke(); } } } this.GetMaxMin = function () { var xPointCount = this.ChartFrame.XPointCount; var range = {}; range.Min = 0; range.Max = null; for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j) { var value = this.Data.Data[i]; if (range.Max == null) range.Max = value; if (range.Max < value) range.Max = value; if (range.Min > value) range.Min = value; } return range; } } /* 指标列表 指标信息都在这里,不够后面再加字段 */ function JSIndexMap() { } JSIndexMap.Get = function (id) { var indexMap = new Map( [ //公司自己的指标 ["市场多空", { IsMainIndex: false, Create: function () { return new MarketLongShortIndex() } }], ["市场择时", { IsMainIndex: false, Create: function () { return new MarketTimingIndex() } }], ["市场关注度", { IsMainIndex: false, Create: function () { return new MarketAttentionIndex() } }], ["指数热度", { IsMainIndex: false, Create: function () { return new MarketHeatIndex() } }], ["自定义指数热度", { IsMainIndex: false, Create: function () { return new CustonIndexHeatIndex() }, Name: '自定义指数热度' }], ["财务粉饰", { IsMainIndex: false, Create: function () { return new BenfordIndex() } }], //能图指标 //["能图-趋势", { IsMainIndex: false, Create: function () { return new LighterIndex1() }, Name: '大盘/个股趋势' }], //["能图-位置研判", { IsMainIndex: false, Create: function () { return new LighterIndex2() }, Name: '位置研判' }], //["能图-点位研判", { IsMainIndex: false, Create: function () { return new LighterIndex3() }, Name: '点位研判' }], //["能图-资金分析", { IsMainIndex: false, Create: function () { return new LighterIndex4() }, Name: '资金分析' }], //["能图-市场关注度", { IsMainIndex: false, Create: function () { return new LighterIndex5() }, Name: '市场关注度' }] ] ); return indexMap.get(id); } ///////////////////////////////////////////////////////////////////////////////////////////// // K线图 控件 // this.ChartPaint[0] K线画法 这个不要修改 // // function KLineChartContainer(uielement) { var _self = this; this.newMethod = JSChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName = 'KLineChartContainer'; this.WindowIndex = new Array(); this.ColorIndex; //五彩K线 this.TradeIndex; //交易指标/专家系统 this.Symbol; this.Name; this.Period = 0; //周期 0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 9=季线 10=分笔线 11=120分钟 12=240分钟 this.RightFormula=0 //复权公式 0=简单复权, 1=复权因子复权 this.IsApiPeriod = false; //使用API计算周期 this.Right = 0; //复权 0 不复权 1 前复权 2 后复权 this.SourceData; //原始的历史数据 this.MaxRequestDataCount = 3000; //数据个数 this.MaxRequestMinuteDayCount = 5; //分钟数据请求的天数 this.PageSize = 200; //每页数据个数 this.KLineDrawType = 0; //0=K线 1=收盘价线 2=美国线 this.LoadDataSplashTitle = '下载历史数据'; this.IsAutoUpdate = false; //是否自动更新行情数据 this.AutoUpdateFrequency = 30000; //30秒更新一次数据 this.AutoUpdateTimer=null; //自动定时器 this.RightSpaceCount=1; this.SourceDataLimit = new Map(); //每个周期缓存数据最大个数 key=周期 value=最大个数 this.IsZoomLockRight=false; this.KLineSize=null; //{ DataWidth:, } this.StepPixel = 4; //移动一个数据需要的像素 this.ZoomStepPixel = 5; //放大缩小手势需要的最小像素 this.EnableZoomUpDown=null; //是否手势/键盘/鼠标允许缩放{ Touch:true/false, Mouse:true/false, Keyboard:true/false, Wheel:true/false } this.EnableMoveData=null; //是否可以移动K线 { Touch:true/false } this.DragDownload = { Day: { Enable: false, IsEnd: false, Status: 0 }, //日线数据拖拽下载(暂不支持) Status: 0空闲 1 下载中 Minute: { Enable: false, IsEnd: false, Status: 0 } //分钟数据拖拽下载 }; this.KLineApiUrl = g_JSChartResource.Domain + "/API/KLine2"; //历史K线api地址 this.MinuteKLineApiUrl = g_JSChartResource.Domain + '/API/KLine3'; //历史分钟数据 this.RealtimeApiUrl = g_JSChartResource.Domain + "/API/Stock"; //实时行情api地址 this.KLineMatchUrl = g_JSChartResource.Domain + "/API/KLineMatch"; //形态匹配 this.DragMinuteKLineApiUrl = g_JSChartResource.Domain + '/API/KLine4'; //拖动数据下载 this.DragKLineApiUrl = g_JSChartResource.Domain + '/API/KLine5'; //拖动日K数据下载 this.BeforeBindMainData = null; //function(funcName) 在BindMainData() 调用前回调用 this.AfterBindMainData = null; //function(funcName) 在BindMainData() 调用前后调用 this.ResetDragDownload = function () { this.DragDownload.Day.Status = 0; this.DragDownload.Day.IsEnd=false; this.DragDownload.Minute.Status = 0; this.DragDownload.Minute.IsEnd=false; } this.AddCustomKLine=function(kline, option) { var klineChart=this.ChartPaint[0]; if (!klineChart) return; if (!kline) return; if (!klineChart.CustomKLine) klineChart.CustomKLine=new Map(); if (Array.isArray(kline)) { for(var i=0;i 0) step = obj.Step; if (this.DataMove(step * this.StepPixel, isLeft)) //每次移动一个数据 { this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.ResetFrameXYSplit(); this.Draw(); } else { if (id===JSCHART_OPERATOR_ID.OP_SCROLL_RIGHT && this.DragDownloadData) this.DragDownloadData(); } } else if (id === JSCHART_OPERATOR_ID.OP_ZOOM_IN || id === JSCHART_OPERATOR_ID.OP_ZOOM_OUT) //缩放 { var cursorIndex = {}; cursorIndex.Index = parseInt(Math.abs(this.CursorIndex - 0.5).toFixed(0)); if (id === JSCHART_OPERATOR_ID.OP_ZOOM_IN) { if (!this.Frame.ZoomUp(cursorIndex)) return; } else { if (!this.Frame.ZoomDown(cursorIndex)) return; } this.CursorIndex = cursorIndex.Index; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.Draw(); } else if (id === JSCHART_OPERATOR_ID.OP_GOTO_HOME) //返回最新 { var hisData = this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 var showCount=this.Frame.SubFrame[0].Frame.XPointCount; //获取一屏显示的数据个数 showCount-=this.RightSpaceCount; var index=hisData.Data.length-showCount; hisData.DataOffset=index; this.CursorIndex=0; this.LastPoint.X=null; this.LastPoint.Y=null; JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO_HOME, dataOffset=${hisData.DataOffset} CursorIndex=${this.CursorIndex} PageSize=${showCount}`); this.ChartOperator_Temp_Update(); } else if (id===JSCHART_OPERATOR_ID.OP_GOTO_END) { var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 hisData.DataOffset=0; this.CursorIndex=0; this.LastPoint.X=null; this.LastPoint.Y=null; JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO_END `); this.ChartOperator_Temp_Update(); } else if (id==JSCHART_OPERATOR_ID.OP_GOTO) //{ Date:日期, Time: , PageSize:(可选)} { if (!IFrameSplitOperator.IsNumber(obj.Date)) return; var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 var index=null; if (ChartData.IsDayPeriod(this.Period,true)) { for(var i=0;i=obj.Date) { index=i; break; } } } else if (ChartData.IsMinutePeriod(this.Period,true)) { let findTime=obj.Time; if (IFrameSplitOperator.IsPlusNumber(findTime)) { for(var i=0;iobj.Date || (item.Date==obj.Date && item.Time>=findTime)) { index=i; break; } } } else //只有日期 { for(var i=0;i=obj.Date) { index=i; break; } } } } if (index===null) { JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO can't find date=${obj.Date} time=${obj.Time}`); return; } var oldXPointCount=this.Frame.SubFrame[0].Frame.XPointCount; var xPointCount=oldXPointCount; if (obj.PageSize>0) //调整一屏显示的个数 { xPointCount=obj.PageSize; } if (xPointCount!=oldXPointCount) { //设置X轴显示数据个数 this.Frame.SetXShowCount(xPointCount); } hisData.DataOffset=index; this.CursorIndex=0; this.LastPoint.X=null; this.LastPoint.Y=null; this.ChartOperator_Temp_Update(); } } //内部函数 this.ChartOperator_Temp_GetHistroyData=function() { var hisData=null; if (!this.Frame.Data) hisData=this.Frame.Data; else hisData=this.Frame.SubFrame[0].Frame.Data; if (!hisData) return null; //数据还没有到达 return hisData; } this.ChartOperator_Temp_Update=function() { this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.UpdatePointByCursorIndex(); //更新十字光标位子 } //创建windowCount 窗口个数 this.Create = function (windowCount) { this.UIElement.JSChartContainer = this; //创建十字光标 this.ChartCorssCursor = new ChartCorssCursor(); this.ChartCorssCursor.Canvas = this.Canvas; this.ChartCorssCursor.StringFormatX = g_DivTooltipDataForamt.Create("CorssCursor_XStringFormat"); this.ChartCorssCursor.StringFormatX.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.StringFormatX.LanguageID=this.LanguageID; this.ChartCorssCursor.StringFormatY = g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat"); this.ChartCorssCursor.StringFormatY.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.StringFormatY.LanguageID = this.LanguageID; this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle; this.ChartSplashPaint.HQChart=this; //创建框架容器 this.Frame = new HQTradeFrame(); 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.Frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架 this.ChartSplashPaint.Frame = this.Frame; this.CreateChildWindow(windowCount); this.CreateMainKLine(); //子窗口动态标题 for (var i in this.Frame.SubFrame) { var titlePaint = new DynamicChartTitlePainting(); titlePaint.Frame = this.Frame.SubFrame[i].Frame; titlePaint.Canvas = this.Canvas; titlePaint.LanguageID = this.LanguageID; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.Frame.SubFrame[i].Frame.TitlePaint = titlePaint; this.TitlePaint.push(titlePaint); } this.ChartCorssCursor.StringFormatX.Frame = this.Frame.SubFrame[0].Frame; this.ChartCorssCursor.StringFormatY.Frame=this.Frame; } //创建子窗口 this.CreateChildWindow = function (windowCount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME); for (var i = 0; i < windowCount; ++i) { var border = new ChartBorder(); border.UIElement = this.UIElement; var frame = new KLineFrame(); frame.Canvas = this.Canvas; frame.ChartBorder = border; frame.Identify = i; //窗口序号 frame.RightSpaceCount = this.RightSpaceCount; //右边 frame.HorizontalMax = 20; frame.HorizontalMin = 10; if (i == 0) { frame.YSplitOperator = new FrameSplitKLinePriceY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price'); frame.YSplitOperator.FrameSplitData2 = this.FrameSplitData.get('double'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } border.BottomSpace = 12; //主图上下留空间 border.TopSpace = 12; } else { frame.YSplitOperator = new FrameSplitY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double'); frame.YSplitOperator.LanguageID = this.LanguageID; frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } } frame.YSplitOperator.Frame = frame; frame.YSplitOperator.ChartBorder = border; frame.XSplitOperator = new FrameSplitKLineX(); frame.XSplitOperator.Frame = frame; frame.XSplitOperator.ChartBorder = border; frame.XSplitOperator.GetEventCallback =(id)=> { return this.GetEventCallback(id); } if (i != windowCount - 1) frame.XSplitOperator.ShowText = false; for (var j = frame.HorizontalMin; j <= frame.HorizontalMax; j += 1) { frame.HorizontalInfo[j] = new CoordinateInfo(); frame.HorizontalInfo[j].Value = j; if (i == 0 && j == frame.HorizontalMin) continue; frame.HorizontalInfo[j].Message[1] = j.toString(); frame.HorizontalInfo[j].Font = "14px 微软雅黑"; } var subFrame = new SubFrameItem(); frame.FrameData.SubFrameItem=subFrame; subFrame.Frame = frame; if (i == 0) subFrame.Height = 20; else subFrame.Height = 10; this.Frame.SubFrame[i] = subFrame; if (event && event.Callback) { var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i }; event.Callback(event, sendData, this); } } } this.CreateSubFrameItem = function (id) { var border = new ChartBorder(); border.UIElement = this.UIElement; var frame = new KLineFrame(); frame.Canvas = this.Canvas; frame.ChartBorder = border; frame.Identify = id; //窗口序号 if (this.ModifyIndexDialog) frame.ModifyIndexEvent = this.ModifyIndexDialog.DoModal; //绑定菜单事件 if (this.ChangeIndexDialog) frame.ChangeIndexEvent = this.ChangeIndexDialog.DoModal; frame.HorizontalMax = 20; frame.HorizontalMin = 10; frame.YSplitOperator = new FrameSplitY(); frame.YSplitOperator.LanguageID = this.LanguageID; frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double'); frame.YSplitOperator.Frame = frame; frame.YSplitOperator.ChartBorder = border; frame.XSplitOperator = new FrameSplitKLineX(); frame.XSplitOperator.Frame = frame; frame.XSplitOperator.ChartBorder = border; frame.XSplitOperator.ShowText = false; frame.XSplitOperator.Period=this.Period; frame.XSplitOperator.GetEventCallback =(id)=> { return this.GetEventCallback(id); } //K线数据绑定 var xPointCouont = this.Frame.SubFrame[0].Frame.XPointCount; frame.XPointCount = xPointCouont; frame.Data = this.ChartPaint[0].Data; for (var j = frame.HorizontalMin; j <= frame.HorizontalMax; j += 1) { frame.HorizontalInfo[j] = new CoordinateInfo(); frame.HorizontalInfo[j].Value = j; frame.HorizontalInfo[j].Message[1] = j.toString(); frame.HorizontalInfo[j].Font = "14px 微软雅黑"; } var subFrame = new SubFrameItem(); frame.FrameData.SubFrameItem=subFrame; subFrame.Frame = frame; subFrame.Height = 10; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME); if (event && event.Callback) { var sendData={ SubFrame:subFrame, WindowIndex:id }; event.Callback(event, sendData, this); } return subFrame; } //创建主图K线画法 this.CreateMainKLine = function () { var kline = new ChartKLine(); kline.Canvas = this.Canvas; kline.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder; kline.ChartFrame = this.Frame.SubFrame[0].Frame; kline.Name = "Main-KLine"; kline.DrawType = this.KLineDrawType; kline.GetEventCallback=(id)=>{ return this.GetEventCallback(id); }; this.ChartPaint[0] = kline; this.TitlePaint[0] = new DynamicKLineTitlePainting(); this.TitlePaint[0].Frame = this.Frame.SubFrame[0].Frame; this.TitlePaint[0].Canvas = this.Canvas; this.TitlePaint[0].LanguageID = this.LanguageID; this.TitlePaint[0].HQChart=this; } //绑定主图K线数据 this.BindMainData = function (hisData, showCount) { this.ChartPaint[0].Data = hisData; this.ChartPaint[0].Symbol = this.Symbol; if (this.KLineSize) { if (this.KLineSize.DataWidth==null) { showCount=this.Frame.SubFrame[0].Frame.XPointCount-this.RightSpaceCount; } else { var obj=this.Frame.SetDataWidth(this.KLineSize.DataWidth); showCount=obj.XPointCount-this.RightSpaceCount; this.KLineSize.DataWidth=null; } } for (var i in this.Frame.SubFrame) { var item = this.Frame.SubFrame[i].Frame; item.XPointCount = showCount + this.RightSpaceCount; item.Data = this.ChartPaint[0].Data; item.XSplitOperator.Symbol = this.Symbol; item.XSplitOperator.Period = this.Period; } this.TitlePaint[0].Data = this.ChartPaint[0].Data; //动态标题 this.TitlePaint[0].Symbol = this.Symbol; this.TitlePaint[0].Name = this.Name; this.TitlePaint[0].Period = this.Period; this.ChartCorssCursor.StringFormatX.Data = this.ChartPaint[0].Data; //十字光标 this.Frame.Data = this.ChartPaint[0].Data; for(var i=0; i= hisData.Data.length) this.CursorIndex = hisData.Data.length - 1 - dataOffset; if (this.CursorIndex < 0) this.CursorIndex = 0; //不一定对啊 } this.UpdateMainData = function (hisData, lastDataCount) //更新主图数据(不会放大缩小数据) { var frameHisdata = null; if (!this.Frame.Data) frameHisdata = this.Frame.Data; else if (this.Frame.SubFrame && this.Frame.SubFrame[0]) frameHisdata = this.Frame.SubFrame[0].Frame.Data; if (!frameHisdata) return; var xPointCount=this.Frame.SubFrame[0].Frame.XPointCount; //当前一屏能显示的数据个数 var newDataCount = 0; if (lastDataCount > 0 && hisData.Data.length > lastDataCount) { newDataCount = hisData.Data.length - lastDataCount; JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`); } else if (lastDataCount==0 && hisData.Data.length>xPointCount) //历史数据为空,当前收到数据大于一屏的数据,显示最新数据 { newDataCount=hisData.Data.length-xPointCount; JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] history data is empty. [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`); } this.ChartPaint[0].Data = hisData; this.ChartPaint[0].Symbol = this.Symbol; if (hisData.Data.length>xPointCount) //不满一屏的, 不需要调整索引 this.ChartPaint[0].Data.DataOffset = frameHisdata.DataOffset + newDataCount; //加上数据增加的个数 for (var i in this.Frame.SubFrame) { var item = this.Frame.SubFrame[i].Frame; item.Data = this.ChartPaint[0].Data; if (i==0) { item.YSplitOperator.Symbol = this.Symbol; item.YSplitOperator.Data = this.ChartPaint[0].Data; //K线数据 item.YSplitOperator.Period = this.Period; //周期 } } this.TitlePaint[0].Data = this.ChartPaint[0].Data; //动态标题 this.TitlePaint[0].Symbol = this.Symbol; this.TitlePaint[0].Name = this.Name; this.ChartCorssCursor.StringFormatX.Data = this.ChartPaint[0].Data; //十字光标 this.Frame.Data = this.ChartPaint[0].Data; for (var i=0;i 0 && !this.IsApiPeriod) //复权 { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } if (ChartData.IsDayPeriod(bindData.Period, false) && !this.IsApiPeriod) //周期数据 { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } //绑定数据 this.Symbol = data.symbol; this.Name = data.name; this.BindMainData(bindData, this.PageSize); if (this.AfterBindMainData) this.AfterBindMainData("RecvHistoryData"); this.Frame.SetSizeChage(true); //数据到达通知坐标框架 var firstSubFrame; //主窗口 if (this.Frame.SubFrame[0]) firstSubFrame=this.Frame.SubFrame[0].Frame; if (firstSubFrame && firstSubFrame.YSplitOperator) { firstSubFrame.YSplitOperator.Symbol = this.Symbol; //绑定代码 firstSubFrame.YSplitOperator.Data = this.ChartPaint[0].Data; //K线数据 firstSubFrame.YSplitOperator.Period=this.Period; //周期 } //请求叠加数据 (主数据下载完再下载)) this.ReqeustKLineInfoData({ FunctionName:"RecvHistoryData" }); this.RequestOverlayHistoryData(); //刷新画图 this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.BindInstructionIndexData(bindData); //执行指示脚本 for (var i = 0; i < this.Frame.SubFrame.length; ++i) //执行指标 { this.BindIndexData(i, bindData); } //叠加指标 this.BindAllOverlayIndexData(bindData); if (this.mapEvent.has(JSCHART_EVENT_ID.RECV_HISTROY_DATA)) { var event = this.mapEvent.get(JSCHART_EVENT_ID.RECV_HISTROY_DATA); var data = { HistoryData: bindData, Stock: { Symbol: this.Symbol, Name: this.Name } } event.Callback(event, data, this); } else //老的回调暂时保留 { if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistroyData', this); //单词拼写错误, 请使用下面的回调 if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistoryData', this); } } this.RequestHistoryMinuteData = function () { var self = this; this.CancelAutoUpdate(); this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.ResetDragDownload(); this.Draw(); if (this.NetworkFilter) { var obj = { Name: 'KLineChartContainer::ReqeustHistoryMinuteData', //类名 Explain: '1分钟K线数据', Request: { Url: self.MinuteKLineApiUrl, Type: 'POST', Data: { symbol: self.Symbol, count: self.MaxRequestMinuteDayCount, field: ["name", "symbol", "yclose", "open", "price", "high", "low", "vol"], period:this.Period, right:this.Right } }, Self: this, PreventDefault: false }; this.NetworkFilter(obj, function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMinuteHistoryData(data); self.AutoUpdateEvent(true,"KLineChartContainer::ReqeustHistoryMinuteData"); self.AutoUpdate(); }); if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: this.MinuteKLineApiUrl, data: { "field": ["name","symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestMinuteDayCount }, method: 'POST', dataType: "json", success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMinuteHistoryData(data); self.AutoUpdateEvent(true,"KLineChartContainer::ReqeustHistoryMinuteData"); self.AutoUpdate(); } }); } this.ReqeustHistoryMinuteData=this.RequestHistoryMinuteData; this.RecvMinuteHistoryData = function (recvData) { var data = recvData.data; var aryDayData = KLineChartContainer.JsonDataToMinuteHistoryData(data); //原始数据 var sourceData = new ChartData(); sourceData.Data = aryDayData; sourceData.DataType = 1; //0=日线数据 1=分钟数据 sourceData.Symbol = data.symbol; this.SourceData = sourceData; if (this.BeforeBindMainData) this.BeforeBindMainData("RecvMinuteHistoryData"); //显示的数据 var bindData = new ChartData(); bindData.Data = aryDayData; bindData.Right = this.Right; bindData.Period = this.Period; bindData.DataType = 1; bindData.Symbol = data.symbol; if (bindData.Right>0 && !this.IsApiPeriod && this.RightFormula>=1) //复权 { var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula } ); bindData.Data=rightData; } if (ChartData.IsMinutePeriod(bindData.Period, false) && !this.IsApiPeriod) //周期数据 { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } //绑定数据 this.Symbol = data.symbol; this.Name = data.name; this.BindMainData(bindData, this.PageSize); if (this.AfterBindMainData) this.AfterBindMainData("RecvMinuteHistoryData"); this.Frame.SetSizeChage(true); var firstSubFrame; //主窗口 if (this.Frame.SubFrame[0]) firstSubFrame=this.Frame.SubFrame[0].Frame; if (firstSubFrame && firstSubFrame.YSplitOperator) { firstSubFrame.YSplitOperator.Symbol = this.Symbol; //绑定代码 firstSubFrame.YSplitOperator.Data = this.ChartPaint[0].Data; //K线数据 } for(var i=0; i0) newItem.YClose=this.SourceData.Data[this.SourceData.Data.length-1].YClose; this.SourceData.Data.push(newItem); } else { return; } var bindData = new ChartData(); bindData.Data = this.SourceData.Data; bindData.Period = this.Period; bindData.Right = this.Right; bindData.DataType = this.SourceData.DataType; bindData.Symbol = this.Symbol; if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period,true) && !this.IsApiPeriod) //复权(日线数据才复权) { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } if (!this.IsApiPeriod) { if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理) { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } } //绑定数据 this.UpdateMainData(bindData, lastDataCount); this.UpdateOverlayRealtimeData(data); //更新叠加股票数据 this.Frame.SetSizeChage(true); this.BindInstructionIndexData(bindData); //执行指示脚本 for (var i = 0; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } //刷新画图 this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.SendKLineUpdateEvent(bindData); //叠加指标计算 this.BindAllOverlayIndexData(bindData); } this.UpdateOverlayRealtimeData=function(data) { if (!IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) return; for(var i=0; i0 && MARKET_SUFFIX_NAME.IsSHSZStockA(data.symbol) && !this.IsApiPeriod) //复权数据 ,A股才有有复权 { var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data=rightData; } var aryOverlayData=this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据 bindData.Data=aryOverlayData; if (ChartData.IsDayPeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据 { var periodData=bindData.GetPeriodData(bindData.Period); bindData.Data=periodData; } item.Data=bindData; } } this.GetHistoryDataCount = function () { var frameHisdata = null; if (!this.Frame.Data) frameHisdata = this.Frame.Data; else if (this.Frame.SubFrame && this.Frame.SubFrame[0]) frameHisdata = this.Frame.SubFrame[0].Frame.Data; if (!frameHisdata) return -1; var lastDataCount = frameHisdata.Data.length; //上一个的数据长度 return lastDataCount; } this.RequestMinuteRealtimeData = function () { var self = this; var arySymbol=[self.Symbol]; for(var i=0; i limitCount) { this.SourceData.Data.shift(); --dataOffset; ++removeCount; } if (removeCount > 0) { if (dataOffset < 0) dataOffset = 0; frameHisdata.DataOffset = dataOffset; JSConsole.Chart.Log(`[KLineChartContainer::ReduceSourceData] remove data ${removeCount}, dataOffset=${dataOffset}`); } } this.RecvMinuteRealtimeData = function (recvData) { var data=recvData.data; if (this.IsOnTouch == true) return; //正在操作中不更新数据 if (data.ver == 2.0) { this.RecvMinuteRealtimeDataV2(data); //v2.0数据版本 return; } if (!data.stock || !data.stock[0] || this.Symbol != data.stock[0].symbol) return; var realtimeData = KLineChartContainer.JsonDataToMinuteRealtimeData(data); if (!realtimeData) return; if (this.IsApiPeriod) this.ReduceSourceData(); //减少数据 var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数 var lastSourceDataCount = this.SourceData.Data.length; if (!this.SourceData.MergeMinuteData(realtimeData)) return; JSConsole.Chart.Log(`[KLineChartContainer::RecvMinuteRealtimeData] update kline by 1 minute data [${lastSourceDataCount}->${this.SourceData.Data.length}]`); var bindData = new ChartData(); bindData.Data = this.SourceData.Data; bindData.Period = this.Period; bindData.Right = this.Right; bindData.DataType = this.SourceData.DataType; bindData.Symbol = this.Symbol; if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period,true) && !this.IsApiPeriod) //复权(日线数据才复权) { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } if (!this.IsApiPeriod) { if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理) { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } } //绑定数据 this.UpdateMainData(bindData, lastDataCount); this.Frame.SetSizeChage(true); this.BindInstructionIndexData(bindData); //执行指示脚本 for (var i = 0; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } //刷新画图 this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.SendKLineUpdateEvent(bindData); //叠加指标计算 this.BindAllOverlayIndexData(bindData); } this.RecvMinuteRealtimeDataV2 = function (data) //新版本的 { if (this.IsOnTouch == true) return; //正在操作中不更新数据 var aryMinuteData = KLineChartContainer.JsonDataToMinuteHistoryData(data); if (!aryMinuteData || aryMinuteData.length <= 0) return; if (this.IsApiPeriod) this.ReduceSourceData(); //减少数据 var lastDataCount = this.GetHistoryDataCount(); //保存下上一次的数据个数 if (!this.SourceData.MergeMinuteData(aryMinuteData)) return; JSConsole.Chart.Log(`[KLineChartContainer::RecvMinuteRealtimeDataV2] update kline by 1 minute data [${lastDataCount}->${this.SourceData.Data.length}]`); var bindData = new ChartData(); bindData.Data = this.SourceData.Data; bindData.Period = this.Period; bindData.Right = this.Right; bindData.DataType = this.SourceData.DataType; bindData.Symbol = this.Symbol; if (bindData.Right > 0 && ChartData.IsDayPeriod(bindData.Period, true) && !this.IsApiPeriod) //复权(日线数据才复权) { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } if ((ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) && !this.IsApiPeriod) //周期数据 (0= 日线,4=1分钟线 不需要处理) { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } //绑定数据 this.UpdateMainData(bindData, lastDataCount); this.UpdateOverlayMinuteRealtimeData(data); //更新叠加股票数据 this.Frame.SetSizeChage(true); this.BindInstructionIndexData(bindData); //执行指示脚本 for (var i = 0; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } //刷新画图 this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.SendKLineUpdateEvent(bindData); //更新叠加指标 this.BindAllOverlayIndexData(bindData); } //更新当天的全量分钟数据 this.UpdateOverlayMinuteRealtimeData=function(data) { for(var i=0; i CUSTOM_DAY_PERIOD_START && period <= CUSTOM_DAY_PERIOD_END) { if (this.SourceData.DataType != 0) isDataTypeChange = true; } else if ((period > CUSTOM_MINUTE_PERIOD_START && period <= CUSTOM_MINUTE_PERIOD_END) || (period > CUSTOM_SECOND_PERIOD_START && period <= CUSTOM_SECOND_PERIOD_END)) { if (this.SourceData.DataType != 1) isDataTypeChange = true; } else { switch (period) { case 0: //日线 case 1: //周 case 2: //月 case 3: //年 case 21: //双周 if (this.SourceData.DataType != 0) isDataTypeChange = true; break; case 4: //1分钟 case 5: //5分钟 case 6: //15分钟 case 7: //30分钟 case 8: //60分钟 case 11: //2小时 case 12: //4小时 if (this.SourceData.DataType != 1) isDataTypeChange = true; break; } } } this.Period = period; if (right!=null) this.Right=right; this.ClearCustomKLine(); if (isDataTypeChange == false && !this.IsApiPeriod) { this.Update(); return; } if (ChartData.IsDayPeriod(this.Period, true)) { this.ClearIndexPaint(); this.CancelAutoUpdate(); //先停止更新 this.AutoUpdateEvent(false,"KLineChartContainer::ChangePeriod"); this.ResetOverlaySymbolStatus(); this.Frame.ClearYCoordinateMaxMin(); this.RequestHistoryData(); //请求日线数据 //this.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period)) { this.ClearIndexPaint(); this.CancelAutoUpdate(); //先停止更新 this.AutoUpdateEvent(false,"KLineChartContainer::ChangePeriod"); this.ResetOverlaySymbolStatus(); this.Frame.ClearYCoordinateMaxMin(); this.RequestHistoryMinuteData(); //请求分钟数据 } } //复权切换 this.ChangeRight = function (right) { if (!MARKET_SUFFIX_NAME.IsEnableRight(this.Period,this.Symbol,this.RightFormula)) return; if (right < 0 || right > 2) return; if (this.Right == right) return; this.Right = right; if (!this.IsApiPeriod) { this.Update(); return; } else { if (ChartData.IsDayPeriod(this.Period, true)) { this.CancelAutoUpdate(); //先停止更新 this.AutoUpdateEvent(false,"KLineChartContainer::ChangeRight"); this.RequestHistoryData(); //请求日线数据 //this.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period)) { this.CancelAutoUpdate(); //先停止更新 this.AutoUpdateEvent(false,"KLineChartContainer::ChangeRight"); this.RequestHistoryMinuteData(); //请求分钟数据 } } } //设置第1屏的起始日期 this.SetFirstShowDate=function(obj) { if (!obj || !obj.Date) return; var option={ ID:JSCHART_OPERATOR_ID.OP_GOTO, Date:obj.Date }; if (IFrameSplitOperator.IsNumber(obj.Time)) option.Time=obj.Time; if (IFrameSplitOperator.IsNumber(obj.PageSize)) option.PageSize=obj.PageSize; this.ChartOperator(option); } //删除某一个窗口的指标 bCallDestory=是否调用图形销毁函数 this.DeleteIndexPaint = function (windowIndex, bCallDestroy) { if (!this.Frame.SubFrame[windowIndex]) return; var subFrame=this.Frame.SubFrame[windowIndex].Frame; if (!subFrame) return; var paint=[]; //踢出当前窗口的指标画法 for (var i=0;i= 0) indexData.FloatPrecision = option.FloatPrecision; if (option.StringFormat > 0) indexData.StringFormat = option.StringFormat; if (option.Args) indexData.Args = option.Args; if (IFrameSplitOperator.IsNumber(option.IsShortTitle)) indexData.IsShortTitle=option.IsShortTitle; } return this.ChangeScriptIndex(windowIndex, indexData, option); } //主图指标 if (indexItem.IsMainIndex) { if (windowIndex > 0) windowIndex = 0; //主图指标只能在主图显示 } else { if (windowIndex == 0) windowIndex = 1; //幅图指标,不能再主图显示 } var paint = new Array(); //踢出当前窗口的指标画法 for (var i in this.ChartPaint) { var item = this.ChartPaint[i]; if (i == 0 || item.ChartFrame != this.Frame.SubFrame[windowIndex].Frame) paint.push(item); } //清空指定最大最小值 this.Frame.SubFrame[windowIndex].Frame.YSpecificMaxMin = null; this.Frame.SubFrame[windowIndex].Frame.YSplitScale=null; this.ChartPaint = paint; //清空东条标题 var titleIndex = windowIndex + 1; this.TitlePaint[titleIndex].Data = []; this.TitlePaint[titleIndex].Title = null; this.WindowIndex[windowIndex] = indexItem.Create(); this.CreateWindowIndex(windowIndex); var bindData = this.ChartPaint[0].Data; this.BindIndexData(windowIndex, bindData); this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } this.ChangeKLineDrawType = function (drawType, isDraw) { if (this.KLineDrawType == drawType) return; this.KLineDrawType = drawType; for (var i in this.ChartPaint) { var item = this.ChartPaint[i]; if (i == 0) item.DrawType = this.KLineDrawType; else if (item.ClassName == 'ChartVolStick') item.KLineDrawType = this.KLineDrawType } for(var i=0; i count) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); for(var i=currentLength-1;i>=count;--i) { if (event && event.Callback) { var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i }; event.Callback(event, sendData, this); } } this.Frame.SubFrame.splice(count, currentLength - count); this.WindowIndex.splice(count, currentLength - count); this.TitlePaint.splice(count+1,currentLength-count); } else { for (var i = currentLength; i < count; ++i) //创建新的指标窗口 { var subFrame = this.CreateSubFrameItem(i); this.Frame.SubFrame[i] = subFrame; var titlePaint = new DynamicChartTitlePainting(); titlePaint.Frame = this.Frame.SubFrame[i].Frame; titlePaint.Canvas = this.Canvas; titlePaint.LanguageID = this.LanguageID; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.TitlePaint[i + 1] = titlePaint; } } var systemScript = new JSCommonIndexScript.JSIndexScript(); for (var i = 0; i < count; ++i) { var windowIndex = i; var item=option.Windows[i]; var frameItem=null; if(option.Frame && option.Frame.length>i) frameItem=option.Frame[i]; var titleIndex = windowIndex + 1; this.TitlePaint[titleIndex].Data = []; this.TitlePaint[titleIndex].Title = null; this.DeleteWindowsOverlayIndex(i); //清空叠加指标 if (item.Script) //自定义指标 { this.WindowIndex[i]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行 } else if (item.API) //后台指标 { var apiItem=item.API; this.WindowIndex[i]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item); } else { var indexID = item.Index; var indexItem = JSIndexMap.Get(indexID); if (indexItem) { this.WindowIndex[i] = indexItem.Create(); this.CreateWindowIndex(windowIndex); } else { var indexInfo = systemScript.Get(indexID); if (indexInfo) { JSIndexScript.ModifyAttribute(indexInfo,item); this.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args, indexInfo); //脚本执行 } } } this.SetSubFrameAttribute(this.Frame.SubFrame[i], item, frameItem); } //最后一个显示X轴坐标 for (var i = 0; i < this.Frame.SubFrame.length; ++i) { var item = this.Frame.SubFrame[i].Frame; if (i == this.Frame.SubFrame.length - 1) item.XSplitOperator.ShowText = true; else item.XSplitOperator.ShowText = false; } //叠加指标 var aryOverlayIndex=[]; if (IFrameSplitOperator.IsNonEmptyArray(option.OverlayIndex)) { for(var i=0;i=0) item.WindowIndex=item.Windows; var overlay=this.CreateOverlayWindowsIndex(item); if (!overlay) continue; aryOverlayIndex.push({ WindowsIndex:item.WindowIndex, Overlay:overlay }); } } this.Frame.SetSizeChage(true); if (!bRefreshData) { var bindData = this.ChartPaint[0].Data; for(var i=0; i=this.Frame.SubFrame.length) return; var delFrame=this.Frame.SubFrame[id].Frame; this.DeleteIndexPaint(id, true); var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); if (event && event.Callback) { var sendData={ SubFrame:this.Frame.SubFrame[id], WindowIndex:id }; event.Callback(event, sendData, this); } this.Frame.SubFrame.splice(id,1); this.WindowIndex.splice(id,1); this.TitlePaint.splice(id+1,1); //删除对应的动态标题 for(var i=0;i0) { var aryDrawPicture=[]; for(var i=0;i 0 && ChartData.IsDayPeriod(bindData.Period, true)) //复权(日线数据才复权) { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } else if (bindData.Right>0 && ChartData.IsMinutePeriod(bindData.Period,true) && this.RightFormula>=1) //复权(分钟数据复权, 复权因子模式) { var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data=rightData; } if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 (0= 日线,4=1分钟线 不需要处理)) { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } //绑定数据 this.BindMainData(bindData, this.PageSize); if (this.AfterBindMainData) this.AfterBindMainData("Update"); var firstSubFrame=null; for (var i = 0; i < this.Frame.SubFrame.length; ++i) { if (i==0) firstSubFrame=this.Frame.SubFrame[i].Frame; this.BindIndexData(i, bindData); } //绑定K线数据到Y轴分割 if (firstSubFrame && firstSubFrame.YSplitOperator) { firstSubFrame.YSplitOperator.Symbol=this.Symbol; firstSubFrame.YSplitOperator.Data=this.ChartPaint[0].Data; //K线数据 firstSubFrame.YSplitOperator.Period=this.Period; //周期 } //叠加数据周期调整 for(var i=0; i 0 && MARKET_SUFFIX_NAME.IsSHSZStockA(item.Symbol)) //复权数据 { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } var aryOverlayData = this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据 bindData.Data = aryOverlayData; if (ChartData.IsDayPeriod(bindData.Period, false)) //周期数据 { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } item.Data=bindData; } } this.ReqeustKLineInfoData({FunctionName:"Update"}); //刷新画图 this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); } //切换股票代码 option={ KLine:{Right:, Period: } } this.ChangeSymbol = function (symbol, option) { this.CancelAutoUpdate(); //先停止更新 this.AutoUpdateEvent(false,"KLineChartContainer::ChangeSymbol"); this.ClearCustomKLine(); this.Frame.ClearYCoordinateMaxMin(); this.Symbol = symbol; if (option && option.KLine) { var item=option.KLine; if (IFrameSplitOperator.IsNumber(item.Right)) this.Right=item.Right; if (IFrameSplitOperator.IsNumber(item.Period)) this.Period=item.Period; } if (IsIndexSymbol(symbol)) this.Right = 0; //指数没有复权 this.ClearIndexPaint(); if (ChartData.IsDayPeriod(this.Period, true)) { this.ResetOverlaySymbolStatus(); this.RequestHistoryData(); //请求日线数据 //this.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period)) { this.ResetOverlaySymbolStatus(); this.RequestHistoryMinuteData(); //请求分钟数据 } } this.ReqeustKLineInfoData = function (obj) { if (obj && obj.FunctionName=="RecvDragDayData") //增量更新 { obj.Update=true; } else { if (this.ChartPaint.length > 0) { var klinePaint = this.ChartPaint[0]; klinePaint.InfoData = new Map(); } obj.Update=false; } //信息地雷信息 for (var i in this.ChartInfo) { this.ChartInfo[i].RequestData(this,obj); } } //设置K线信息地雷 this.SetKLineInfo = function (aryInfo, bUpdate) { this.ChartInfo = []; //清空信息地雷 for (var i=0; i result.MaxRequestDataCount) result.MaxRequestDataCount = lCount; } else if (ChartData.IsMinutePeriod(this.Period, true)) { var date=null; var lCount=0; for(var i=0;iresult.MaxRequestMinuteDayCount) result.MaxRequestMinuteDayCount=lCount; } return result; } this.RequestSingleOverlayHistoryData=function(symbol, dataCount, firstDate, item) { var self = this; item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID; if (this.NetworkFilter) { var obj= { Name:'KLineChartContainer::RequestOverlayHistoryData', //类名:: Explain:'叠加股票日K线数据', Request:{ Url:self.KLineApiUrl, Data: { symbol: symbol, count: dataCount.MaxRequestDataCount,"first":{ date: firstDate }, field:["name","symbol","yclose","open","price","high",'vol','amount'] }, Type:'POST' }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID; self.RecvOverlayHistoryData(data,item); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } } this.RequestOverlayHistoryData = function () { if (!this.OverlayChartPaint.length) return; if (!this.SourceData || !this.SourceData.Data) return; //主图数据还没有到完 var dataCount=this.GetRequestDataCount(); var firstDate=this.SourceData.Data[0].Date; for(var i=0;i 0 && !IsIndexSymbol(data.symbol)) //复权数据 ,指数没有复权) { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } var aryOverlayData = this.SourceData.GetOverlayData(bindData.Data); //和主图数据拟合以后的数据 bindData.Data = aryOverlayData; if (ChartData.IsDayPeriod(bindData.Period, false)) //周期数据 { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } paint.Data = bindData; paint.SourceData = sourceData; paint.Title = data.name; paint.Symbol = data.symbol; paint.Status=OVERLAY_STATUS_ID.STATUS_FINISHED_ID; this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType = 1; //调整为百份比坐标 this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); } this.RequestSingleHistoryMinuteData=function(symbol, dataCount, firstDate,firstTime, item) { var self=this; item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID; if (this.NetworkFilter) { var obj= { Name:'KLineChartContainer::RequestOverlayHistoryMinuteData', //类名:: Explain:'叠加股票分钟K线数据', Request:{ Url:self.MinuteKLineApiUrl, Data: { symbol: symbol, count: dataCount.MaxRequestMinuteDayCount,"first":{ date: firstDate, time:firstTime }, field:["name","symbol","yclose","open","price","high",'vol','amount'] }, Type:'POST' }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID; self.RecvOveralyHistoryMinuteData(data,item); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } } this.RequestOverlayHistoryMinuteData=function() { if (!this.OverlayChartPaint.length) return; if (!this.SourceData || !this.SourceData.Data) return; //主图数据还没有到完 var dataCount=this.GetRequestDataCount(); var firstDate=this.SourceData.Data[0].Date; var firstTime=this.SourceData.Data[0].Time; for(var i=0; i0) { var fristKItem=hisData.Data[0]; var aryInfo=[]; for(var i in this.ChartInfo) { var infoItem=this.ChartInfo[i]; for(var j in infoItem.Data) { var item=infoItem.Data[j]; if (item.Date>=fristKItem.Date) //在K线范围内的才显示 aryInfo.push(item); } } aryInfo.sort(function(a,b) { return a.Date-b.Date }); //排序 for(var i=0;i 0) //复权 { var rightData = bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data = rightData; } if (ChartData.IsDayPeriod(bindData.Period, false) || ChartData.IsMinutePeriod(bindData.Period, false)) //周期数据 { var periodData = bindData.GetPeriodData(bindData.Period); bindData.Data = periodData; } } this.WindowIndex[index].BindData(this, index, bindData); this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } //修改参数指标 this.ChangeWindowIndexParam = function (index) { this.WindowIndex[index].Index[0].Param += 1; this.WindowIndex[index].Index[1].Param += 1; this.UpdateWindowIndex(index); } this.OnDoubleClick = function (x, y, e) { var tooltip = new TooltipData(); for (var i in this.ChartPaint) { var item = this.ChartPaint[i]; if (item.GetTooltipData(x, y, tooltip)) break; } if (!tooltip.Data) return; e.data = { Chart: this, Tooltip: tooltip }; } this.CancelAutoUpdate=function() //关闭停止更新 { if (this.AutoUpdateTimer) { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = null; } } //数据自动更新 this.AutoUpdate = function (waitTime) //waitTime 更新时间 { this.CancelAutoUpdate(); if (!this.IsAutoUpdate) return; if (!this.Symbol) return; if (this.IsDestroy) return; var self = this; var marketStatus = MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol); if (marketStatus == 0 || marketStatus == 3) return; //闭市,盘后 var frequency = this.AutoUpdateFrequency; if (marketStatus == 1) //盘前 { this.AutoUpdateTimer=setTimeout(function () { self.AutoUpdate(); }, frequency); } else if (marketStatus == 2) //盘中 { this.AutoUpdateTimer=setTimeout(function () { if (ChartData.IsDayPeriod(self.Period, true)) { self.RequestRealtimeData(); //更新最新行情 //self.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(self.Period, true) || ChartData.IsSecondPeriod(self.Period)) { self.RequestMinuteRealtimeData(); //请求分钟数据 } }, frequency); } } this.GetMaxPageSize = function () { let width = this.Frame.ChartBorder.GetWidth(); let barWidth = (ZOOM_SEED[ZOOM_SEED.length - 1][0] + ZOOM_SEED[ZOOM_SEED.length - 1][1]); let pageSize = parseInt(width / barWidth) - 8; JSConsole.Chart.Log(`[KLineChartContainer::GetMaxPageSize] width=${width} barWidth=${barWidth} pageSize=${pageSize}`); return pageSize } //数据拖拽下载 this.DragDownloadData = function () { var data = null; if (!this.Frame.Data) data = this.Frame.Data; else data = this.Frame.SubFrame[0].Frame.Data; if (!data) return false; if (data.DataOffset > 0) return; if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period)) //下载分钟数据 { JSConsole.Chart.Log(`[KLineChartContainer.DragDownloadData] Minute:[Enable=${this.DragDownload.Minute.Enable}, IsEnd=${this.DragDownload.Minute.IsEnd}, Status=${this.DragDownload.Minute.Status}, Period=${this.Period}]`); if (!this.DragDownload.Minute.Enable) return; if (this.DragDownload.Minute.IsEnd) return; //全部下载完了 if (this.DragDownload.Minute.Status != 0) return; this.RequestDragMinuteData(); } else if (ChartData.IsDayPeriod(this.Period, true)) // 下载日线 { JSConsole.Chart.Log(`[KLineChartContainer.DragDownloadData] Day:[Enable=${this.DragDownload.Minute.Enable}, IsEnd=${this.DragDownload.Minute.IsEnd}, Status=${this.DragDownload.Minute.Status}]`); if (!this.DragDownload.Day.Enable) return; if (this.DragDownload.Day.IsEnd) return; //全部下载完了 if (this.DragDownload.Day.Status != 0) return; this.RequestDragDayData(); } } this.RequestDragMinuteData = function () { var option= { FuncName:'KLineChartContainer::RequestDragMinuteData', FuncExplain:"拖拽分钟|秒K线数据下载", RecvFuncName:"RecvDragMinuteData", Download:this.DragDownload.Minute, Url:this.DragMinuteKLineApiUrl, Count:this.MaxRequestMinuteDayCount, XShowCount:this.Frame.GetXShowCount(), }; this.RequestPreviousMinuteData(option); } this.RequestPreviousMinuteData=function(option) { var funcName=option.FuncName; var funcExplain=option.FuncExplain; var download=option.Download; var url=option.Url; var count=option.Count; //请求数据个数 var self = this; this.AutoUpdateEvent(false, funcName); //停止自动更新 this.CancelAutoUpdate(); download.Status = 1; var firstItem=null; if (IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) firstItem = this.SourceData.Data[0]; //最新的一条数据 else firstItem={Date:null, Time:null}; var postData = { "field": ["name", "symbol", "yclose", "open", "price", "high", "low", "vol"], "symbol": self.Symbol, "enddate": firstItem.Date, "endtime": firstItem.Time, "count": count, "first": { date: firstItem.Date, time: firstItem.Time }, }; if (IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) { postData.overlay=[]; for(var i=0;i=0;--i) { var item=aryDayData[i]; if (firstData.Date>item.Date || (firstData.Date==item.Date && firstData.Time>item.Time)) { endIndex=i; break; } else if (firstData.Date==item.Date && firstData.Time==item.Time) { firstData.YClose=item.YClose; endIndex=i-1; break; } } } else { endIndex=aryDayData.length-1; } if (endIndex==null && endIndex<0) return; for(var i=0;i=0;--i) { var itemData=aryDayData[i]; if (firstData.Date>itemData.Date) { endIndex=i; break; } else if (firstData.Date==itemData.Date && firstData.Time>itemData.Time) { endIndex=i; break; } else if (firstData.Date==itemData.Date && firstData.Time==itemData.Time) { firstData.YClose=itemData.YClose; endIndex=i-1; break; } } if (endIndex==null && endIndex<0) return false; for(var i=0; i=0;--i) { var item=aryDayData[i]; if (firstData.Date>item.Date) { endIndex=i; break; } else if (firstData.Date==item.Date) { firstData.YClose=item.YClose; endIndex=i-1; break; } } } else { var firstData={ Date:null }; endIndex=aryDayData.length-1; } if (endIndex==null && endIndex<0) return; for(var i=0; i=0;--i) { var itemData=aryDayData[i]; if (firstData.Date>itemData.Date) { endIndex=i; break; } else if (firstData.Date==itemData.Date) { firstData.YClose=itemData.YClose; endIndex=i-1; break; } } if (endIndex==null && endIndex<0) return false; for(var i=0; i0 && MARKET_SUFFIX_NAME.IsSHSZStockA(findData.symbol) && !this.IsApiPeriod) //复权数据 ,A股才有有复权 { var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data=rightData; } var aryOverlayData=this.SourceData.GetOverlayData(bindData.Data, this.IsApiPeriod); //和主图数据拟合以后的数据 bindData.Data=aryOverlayData; if (ChartData.IsDayPeriod(bindData.Period,false) && !this.IsApiPeriod) //周期数据 { var periodData=bindData.GetPeriodData(bindData.Period); bindData.Data=periodData; } item.Data=bindData; return true; } //更新叠加数据 this.UpdateOverlayDragDayData=function(data) { if (!IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) return; var aryRecvOverlayData=data.overlay; for(var i=0;i= this.Frame.SubFrame.length) return; var item = this.Frame.SubFrame[windowId]; if (item.Frame) item.Frame.CustomVerticalInfo = data; } this.OnSize=function() { if (!this.Frame) return; if (!this.Frame.OnSize) return; var obj=this.Frame.OnSize(); this.Frame.SetSizeChage(true); if (obj.Changed) { this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); } this.Draw(); } this.AddOverlayIndex=function(obj) { var overlay=this.CreateOverlayWindowsIndex(obj); if (!overlay) return; var bindData=this.ChartPaint[0].Data; this.BindOverlayIndexData(overlay,obj.WindowIndex,bindData); this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } //创建一个叠加指标 this.CreateOverlayWindowsIndex=function(obj) // {WindowIndex:, IndexName:, Identify:, ShowRightText:, API:} { let indexName=obj.IndexName; let windowIndex=obj.WindowIndex; var apiItem=null, indexInfo=null, indexCustom=null; if (obj.API) { apiItem=obj.API; } else if (obj.Script) //动态执行脚本 { indexInfo={ Script:obj.Script, ID:obj.indexName, Name:obj.indexName}; if (obj.Name) indexInfo.Name=obj.Name; } else { let scriptData = new JSCommonIndexScript.JSIndexScript(); indexInfo = scriptData.Get(indexName); //系统指标 if (!indexInfo) { indexCustom=JSIndexMap.Get(indexName); //定制指标 if (!indexCustom) { console.warn(`[KLineChartContainer::CreateOverlayIndex] can not find index[${indexName}]`); return null; } } } var subFrame=this.Frame.SubFrame[windowIndex]; subFrame.Interval=this.OverlayIndexFrameWidth; var overlayFrame=new OverlayIndexItem(); if (obj.Identify) overlayFrame.Identify=obj.Identify; //由外部指定id var frame= this.CreateOverlayFrame(); frame.Canvas=this.Canvas; frame.MainFrame=subFrame.Frame; frame.ChartBorder=subFrame.Frame.ChartBorder; if (IFrameSplitOperator.IsBool(obj.IsShareY)) frame.IsShareY=obj.IsShareY; if (IFrameSplitOperator.IsBool(obj.IsCalculateYMaxMin)) frame.IsCalculateYMaxMin=obj.IsCalculateYMaxMin; //是否计算Y最大最小值 if (IFrameSplitOperator.IsNumber(obj.IsShowMainFrame)) frame.IsShowMainFrame=obj.IsShowMainFrame; frame.YSplitOperator=new FrameSplitY(); frame.YSplitOperator.LanguageID=this.LanguageID; frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double'); frame.YSplitOperator.Frame=frame; frame.YSplitOperator.ChartBorder=frame.ChartBorder; frame.YSplitOperator.SplitCount=subFrame.Frame.YSplitOperator.SplitCount; frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; frame.YSplitOperator.OverlayIdentify=overlayFrame.Identify; overlayFrame.Frame=frame; if (apiItem) { var apiIndex=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,obj, true); apiIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息 overlayFrame.Script=apiIndex; } else if (indexInfo) { JSIndexScript.ModifyAttribute(indexInfo, obj); var scriptIndex=new OverlayScriptIndex(indexInfo.Name,indexInfo.Script,indexInfo.Args,indexInfo); //脚本执行 scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息 overlayFrame.Script=scriptIndex; } else { var scriptIndex=indexCustom.Create(); scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息 scriptIndex.Create(this,windowIndex); overlayFrame.Script=scriptIndex; } subFrame.OverlayIndex.push(overlayFrame); return overlayFrame; } this.DeleteOverlayWindowsIndex=function(identify) //删除叠加指标 { if (!this.DeleteOverlayIndex(identify, null)) return; this.Frame.ResetXYSplit(true); this.Draw(); } this.ChangePriceGap=function(obj) { if (!obj) return; var klineChart=this.ChartPaint[0]; if (!klineChart) return; if (IFrameSplitOperator.IsNumber(obj.Count)) klineChart.PriceGap.Count=obj.Count; if (IFrameSplitOperator.IsBool(obj.Enable)) klineChart.PriceGap.Enable=obj.Enable; this.Draw(); } } //API 返回数据 转化为array[] KLineChartContainer.JsonDataToHistoryData = function (data) { var list = data.data; var aryDayData = new Array(); if (!list) return aryDayData; var upperSymbol = null; if (data.symbol) upperSymbol = data.symbol.toUpperCase(); var isFutures = false; //是否是期货 isFutures = MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol); var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, position = 8; var fclose=9, yfclose=10; //结算价, 前结算价 var bfactor=11, afactor=12; //前, 后复权因子 var colorData=JSCHART_DATA_FIELD_ID.KLINE_COLOR_DATA; var extendDataIndex=JSCHART_DATA_FIELD_ID.KLINE_DAY_EXTENDDATA; //k线扩展数据 for (var i = 0; i < list.length; ++i) { var item = new HistoryData(); var jsData = list[i]; item.Date = jsData[date]; item.Open = jsData[open]; item.YClose = jsData[yclose]; item.Close = jsData[close]; item.High = jsData[high]; item.Low = jsData[low]; item.Vol = jsData[vol]; //原始单位股 item.Amount = jsData[amount]; //可选配置 if (IFrameSplitOperator.IsNumber(jsData[position])) item.Position = jsData[position];//期货持仓 if (IFrameSplitOperator.IsNumber(jsData[fclose])) item.FClose=jsData[fclose]; //期货结算价 if (IFrameSplitOperator.IsNumber(jsData[yfclose])) item.YFClose=jsData[yfclose]; //期货前结算价 if (IFrameSplitOperator.IsNumber(jsData[bfactor])) item.BFactor=jsData[bfactor]; //前复权因子 if (IFrameSplitOperator.IsNumber(jsData[afactor])) item.AFactor=jsData[afactor]; //后复权因子 if (!IFrameSplitOperator.IsNumber(item.Open)) continue; if (jsData[colorData]) item.ColorData=jsData[colorData]; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; aryDayData.push(item); } return aryDayData; } KLineChartContainer.JsonDataToRealtimeData = function (data, symbol) { if (!data) return null; if (!IFrameSplitOperator.IsNonEmptyArray(data.stock)) return null; var stock=null; for(var i=0;i 0) item.Date = jsData.date; else item.Date = date; item.Time = jsData.time; item.YClose = preClose; if (IFrameSplitOperator.IsNumber(jsData.position)) item.Position = jsData.position; //持仓量 if (!IFrameSplitOperator.IsNumber(item.Close)) //当前没有价格 使用上一个价格填充 { item.Close = preClose; item.Open = item.High = item.Low = item.Close; } //价格是0的 都用空 if (!IFrameSplitOperator.IsNumber(item.Open)) item.Open = null; if (!IFrameSplitOperator.IsNumber(item.Close)) item.Close = null; if (!IFrameSplitOperator.IsNumber(item.High)) item.High = null; if (!IFrameSplitOperator.IsNumber(item.Low)) item.Low = null; //上次价格 if (IFrameSplitOperator.IsNumber(jsData.price)) preClose = jsData.price; aryMinuteData[i] = item; } return aryMinuteData; } //API 返回数据 转化为array[] KLineChartContainer.JsonDataToMinuteHistoryData = function (data) { var upperSymbol = null; if (data.symbol) upperSymbol = data.symbol.toUpperCase(); var isSHSZ = false; if (upperSymbol) isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var isFutures = false; //是否是期货 if (upperSymbol) isFutures = MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol); var list = data.data; var aryDayData = new Array(); var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8, position = 9; var fclose=10, yfclose=11; //结算价, 前结算价 var bfactor=12, afactor=13; //前, 后复权因子 var colorData=JSCHART_DATA_FIELD_ID.KLINE_COLOR_DATA; var extendDataIndex=JSCHART_DATA_FIELD_ID.KLINE_MINUTE_EXTENDDATA; //k线扩展数据 for (var i = 0; i < list.length; ++i) { var item = new HistoryData(); var jsData=list[i]; item.Date = jsData[date]; item.Open = jsData[open]; item.YClose = jsData[yclose]; item.Close = jsData[close]; item.High = jsData[high]; item.Low = jsData[low]; item.Vol = jsData[vol]; //原始单位股 item.Amount = jsData[amount]; item.Time = jsData[time]; if (IFrameSplitOperator.IsNumber(jsData[position])) item.Position = jsData[position]; //期货持仓 if (IFrameSplitOperator.IsNumber(jsData[fclose])) item.FClose=jsData[fclose]; //期货结算价 if (IFrameSplitOperator.IsNumber(jsData[yfclose])) item.YFClose=jsData[yfclose]; //期货前结算价 if (IFrameSplitOperator.IsNumber(jsData[bfactor])) item.BFactor=jsData[bfactor]; //前复权因子 if (IFrameSplitOperator.IsNumber(jsData[afactor])) item.AFactor=jsData[afactor]; //后复权因子 if (jsData[colorData]) item.ColorData=jsData[colorData]; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; aryDayData.push(item); } return aryDayData; } /////////////////////////////////////////////////////////////////////////////////////////// // 走势图 // function MinuteChartContainer(uielement) { this.newMethod = JSChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName = 'MinuteChartContainer'; this.WindowIndex = new Array(); this.Symbol; this.Name; this.SourceData; //原始的历史数据 this.OverlaySourceData; //叠加的原始数据 this.IsAutoUpdate = false; //是否自动更新行情数据 this.AutoUpdateFrequency = 30000; //30秒更新一次数据 this.AutoUpdateTimer=null; //更新定时器 this.TradeDate = 0; //行情交易日期 this.LoadDataSplashTitle = '下载分钟数据'; this.UpdateUICallback; //数据到达回调 this.DayCount = 1; //显示几天的数据 this.DayData; //多日分钟数据 this.ZoomStepPixel = 50; //放大缩小手势需要的最小像素 this.MinuteApiUrl = g_JSChartResource.Domain + "/API/Stock"; this.HistoryMinuteApiUrl = g_JSChartResource.Domain + "/API/StockMinuteData"; //历史分钟数据 this.DataStatus={ MultiDay:false, LatestDay:false }; //MultiDay=多日 LatestDay:当天 this.EnableNightDayBG=false; //是否启动夜盘背景色 //手机拖拽 this.ontouchstart = function (e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; this.IsPress=false; this.IsOnTouch = true; this.TouchDrawCount=0; var jsChart = this; if (jsChart.DragMode == 0) return; if (this.IsPhoneDragging(e)) { if (this.TryClickLock || this.TryClickIndexTitle) { var touches = this.GetToucheData(e, this.IsForceLandscape); var x = touches[0].clientX; var y = touches[0].clientY; if (this.TryClickLock && this.TryClickLock(x, y)) return; if (this.TryClickIndexTitle && this.TryClickIndexTitle(x, y)) return; } //长按2秒,十字光标 this.ClearTouchTimer(); var drag = { "Click": {}, "LastMove": {}, //最后移动的位置 }; var touches = this.GetToucheData(e, jsChart.IsForceLandscape); drag.Click.X = touches[0].clientX; drag.Click.Y = touches[0].clientY; drag.LastMove.X = touches[0].clientX; drag.LastMove.Y = touches[0].clientY; this.MouseDrag=drag; this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } }; if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false; this.SelectChartDrawPicture=null; if (this.CurrentChartDrawPicture) //画图工具模式 { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==2) { this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y,true); } else { this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true); //只有1个点 直接完成 if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false}); } return; } else { var pt=this.PointAbsoluteToRelative(touches[0].clientX,touches[0].clientY, true); var drawPictrueData={ X:pt.X, Y:pt.Y, PixelRatio:this.UIElement.PixelRatio }; if (this.GetChartDrawPictureByPoint(drawPictrueData)) { if (drawPictrueData.ChartDrawPicture.EnableMove===true) drawPictrueData.ChartDrawPicture.Status=20; drawPictrueData.ChartDrawPicture.ValueToPoint(); drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex; drawPictrueData.ChartDrawPicture.IsSelected=true; this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture; this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture; let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件 if (event && event.Callback) { let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture }; event.Callback(event,sendData,this); } this.DrawDynamicInfo(); return; } } var T_ShowCorssCursor=()=> { if (this.ChartCorssCursor.IsShow === true) //移动十字光标 { var x = drag.Click.X; var y = drag.Click.Y; if (jsChart.IsForceLandscape) y = jsChart.UIElement.Height - drag.Click.Y; //强制横屏Y计算 jsChart.OnMouseMove(x, y, e); } } if (this.EnableZoomIndexWindow) { this.PhoneDBClick.AddTouchStart(touches[0].clientX, touches[0].clientY, Date.now()); JSConsole.Chart.Log("[MinuteChartContainer::OnTouchStart] PhoneDBClick ", this.PhoneDBClick); } if (this.EnableScrollUpDown==true) { this.TouchTimer=setTimeout(()=> { this.MouseDrag=null; this.IsPress=true; T_ShowCorssCursor(); }, this.PressTime); } var bStartTimer=true; //长按计时开始 if (this.EnableClickModel) { if (this.ClickModel.IsShowCorssCursor==true) bStartTimer=false; else bStartTimer= true; } if (bStartTimer) { this.ClearTouchTimer(); this.TouchTimer = setTimeout(()=>{ jsChart.IsPress=true; if (drag.Click.X == drag.LastMove.X && drag.Click.Y == drag.LastMove.Y) //手指没有移动,出现十字光标 { jsChart.MouseDrag = null; //移动十字光标 var x = drag.Click.X; var y = drag.Click.Y; if (jsChart.EnableClickModel===true) jsChart.ClickModel.IsShowCorssCursor=true; jsChart.OnMouseMove(x, y, e); } }, jsChart.PressTime); } else if (!this.EnableClickModel) { if (this.EnableScrollUpDown==false) T_ShowCorssCursor(); else if (this.IsClickShowCorssCursor) T_ShowCorssCursor(); } this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e); } else if (this.IsPhonePinching(e)) { var phonePinch = { "Start": {}, "Last": {} }; var touches = this.GetToucheData(e, jsChart.IsForceLandscape); phonePinch.Start = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY }; phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY }; jsChart.PhonePinch = phonePinch; } } this.ontouchmove = function (e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var jsChart = this; var drag = jsChart.MouseDrag; var touches = this.GetToucheData(e, jsChart.IsForceLandscape); if (this.IsPhoneDragging(e)) { if (drag == null) { var x = touches[0].clientX; var y = touches[0].clientY; this.LastMovePoint={ X:x, Y:y }; if (this.DrawMoveTimer) return; this.DrawMoveTimer=setTimeout(()=> { if (!this.LastMovePoint) return; this.OnMouseMove(this.LastMovePoint.X, this.LastMovePoint.Y, e); this.DrawMoveTimer=null; }, this.DrawMoveWaitTime); } else { var moveAngle=this.GetMoveAngle(drag.LastMove,{X:touches[0].clientX, Y:touches[0].clientY}); var moveSetp=Math.abs(drag.LastMove.X-touches[0].clientX); var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY); moveSetp=parseInt(moveSetp); if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) { if(moveSetp<5 && moveUpDown<5) return; if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY,true)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==3) { if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY,true)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==20) //画图工具移动 { if(moveSetp<5 && moveUpDown<5) return; if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y,true)) { this.DrawDynamicInfo(); } } drag.LastMove.X=touches[0].clientX; drag.LastMove.Y=touches[0].clientY; } else { if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true ) { //上下滚动 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_TOUCH_SCROLL_UP_DOWN); var isEnd=true; //是否退出 if (event && event.Callback) { var sendData={ DragData:drag, PreventDefault:false }; event.Callback(event, sendData, this); isEnd=(sendData.PreventDefault===false); } if (isEnd) { this.ClearTouchTimer(); return; } } if (drag!=null) { this.ClearTouchTimer(); this.MouseDrag=null; var x = touches[0].clientX; var y = touches[0].clientY; this.OnMouseMove(x,y,e); } } } } else if (this.IsPhonePinching(e)) { var phonePinch = jsChart.PhonePinch; if (!phonePinch) return; if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return; var yHeight = Math.abs(touches[0].pageY - touches[1].pageY); var yLastHeight = Math.abs(phonePinch.Last.Y - phonePinch.Last.Y2); var yStep = yHeight - yLastHeight; var xHeight = Math.abs(touches[0].pageX - touches[1].pageX); var xLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2); var xStep = xHeight - xLastHeight; var minStep=this.ZoomStepPixel; if (Math.abs(yStep) < minStep && Math.abs(xStep) < minStep) return; if (Math.abs(xStep) > minStep) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_MINUTE_TOUCH_ZOOM) if (event && event.Callback) { var data={ XStep:xStep, YStep:yStep, PreventDefault:false }; event.Callback(event,data,this); if (data.PreventDefault) { this.PhonePinch=null; this.ClearTouchTimer(); return; } } } phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY }; } if (this.PhoneTouchInfo) { this.PhoneTouchInfo.End.X=touches[0].clientX; this.PhoneTouchInfo.End.Y=touches[0].clientY; } } //创建 //windowCount 窗口个数 this.Create = function (windowCount) { this.UIElement.JSChartContainer = this; //创建十字光标 this.ChartCorssCursor = new ChartCorssCursor(); this.ChartCorssCursor.Canvas = this.Canvas; this.ChartCorssCursor.StringFormatX = new HQMinuteTimeStringFormat(); this.ChartCorssCursor.StringFormatX.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.StringFormatY = g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat"); this.ChartCorssCursor.StringFormatY.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.StringFormatY.LanguageID = this.LanguageID; this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle; this.ChartSplashPaint.HQChart=this; //创建框架容器 this.Frame = new HQTradeFrame(); this.Frame.ChartBorder = new ChartBorder(); this.Frame.ChartBorder.UIElement = this.UIElement; this.Frame.ChartBorder.Top = 25; this.Frame.ChartBorder.Left = 50; this.Frame.ChartBorder.Bottom = 20; this.Frame.Canvas = this.Canvas; this.Frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.Frame.ZoomStartWindowIndex=2; this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架 this.ChartSplashPaint.Frame = this.Frame; this.CreateChildWindow(windowCount); this.CreateMainKLine(); //子窗口动态标题 for (var i=0; i { return this.GetEventCallback(id); } this.TitlePaint.push(titlePaint); } this.ChartCorssCursor.StringFormatX.Frame = this.Frame.SubFrame[0].Frame; this.ChartCorssCursor.StringFormatY.Frame=this.Frame; } //创建子窗口 this.CreateChildWindow = function (windowCount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME); for (var i = 0; i < windowCount; ++i) { var border = new ChartBorder(); border.UIElement = this.UIElement; var frame = new MinuteFrame(); frame.Canvas = this.Canvas; frame.ChartBorder = border; frame.Identify=i; if (i < 2) frame.ChartBorder.TitleHeight = 0; frame.XPointCount = 243; frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.HQChart=this; var DEFAULT_HORIZONTAL = [9, 8, 7, 6, 5, 4, 3, 2, 1]; frame.HorizontalMax = DEFAULT_HORIZONTAL[0]; frame.HorizontalMin = DEFAULT_HORIZONTAL[DEFAULT_HORIZONTAL.length - 1]; if (i == 0) { frame.YSplitOperator = new FrameSplitMinutePriceY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.HQChart=this; } else { frame.YSplitOperator = new FrameSplitY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double'); frame.YSplitOperator.LanguageID = this.LanguageID; frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } } frame.YSplitOperator.Frame = frame; frame.YSplitOperator.ChartBorder = border; frame.XSplitOperator = new FrameSplitMinuteX(); frame.XSplitOperator.Frame = frame; frame.XSplitOperator.ChartBorder = border; frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (i != windowCount - 1) frame.XSplitOperator.ShowText = false; frame.XSplitOperator.Operator(); for (var j in DEFAULT_HORIZONTAL) { frame.HorizontalInfo[j] = new CoordinateInfo(); frame.HorizontalInfo[j].Value = DEFAULT_HORIZONTAL[j]; if (i == 0 && j == frame.HorizontalMin) continue; frame.HorizontalInfo[j].Message[1] = DEFAULT_HORIZONTAL[j].toString(); frame.HorizontalInfo[j].Font = "14px 微软雅黑"; } var subFrame = new SubFrameItem(); frame.FrameData.SubFrameItem=subFrame; subFrame.Frame = frame; if (i == 0) subFrame.Height = 20; else subFrame.Height = 10; this.Frame.SubFrame[i] = subFrame; if (event && event.Callback) { var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i }; event.Callback(event, sendData, this); } } } this.CreateSubFrameItem=function(id) { var border=new ChartBorder(); border.UIElement=this.UIElement; var frame=new MinuteFrame(); frame.Canvas=this.Canvas; frame.ChartBorder=border; frame.Identify=id; //窗口序号 frame.XPointCount=243; frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; frame.HQChart=this; if (id>=2) { if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.DoModal; //绑定菜单事件 if (this.ChangeIndexDialog) frame.ChangeIndexEvent=this.ChangeIndexDialog.DoModal; } var DEFAULT_HORIZONTAL=[9,8,7,6,5,4,3,2,1]; frame.HorizontalMax=DEFAULT_HORIZONTAL[0]; frame.HorizontalMin=DEFAULT_HORIZONTAL[DEFAULT_HORIZONTAL.length-1]; frame.YSplitOperator=new FrameSplitY(); frame.YSplitOperator.LanguageID=this.LanguageID; frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double'); frame.YSplitOperator.Frame=frame; frame.YSplitOperator.ChartBorder=border; frame.XSplitOperator=new FrameSplitMinuteX(); frame.XSplitOperator.Frame=frame; frame.XSplitOperator.ChartBorder=border; frame.XSplitOperator.ShowText=false; frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //K线数据绑定 var xPointCouont=this.Frame.SubFrame[0].Frame.XPointCount; frame.XPointCount=xPointCouont; frame.Data=this.ChartPaint[0].Data; for(var j in DEFAULT_HORIZONTAL) { frame.HorizontalInfo[j]= new CoordinateInfo(); frame.HorizontalInfo[j].Value=DEFAULT_HORIZONTAL[j]; frame.HorizontalInfo[j].Message[1]=DEFAULT_HORIZONTAL[j].toString(); frame.HorizontalInfo[j].Font="14px 微软雅黑"; } var subFrame=new SubFrameItem(); subFrame.Frame=frame; subFrame.Height=10; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME); if (event && event.Callback) { var sendData={ SubFrame:subFrame, WindowIndex:id }; event.Callback(event, sendData, this); } return subFrame; } this.UpdateXShowText=function() { var bLastFrame=true; for(var i=this.Frame.SubFrame.length-1;i>=0;--i) { var item=this.Frame.SubFrame[i].Frame; var subFrame=this.Frame.SubFrame[i]; if (bLastFrame) { item.XSplitOperator.ShowText=true; if (subFrame.Height>0) bLastFrame=false; } else { item.XSplitOperator.ShowText=false; } } } //删除某一个窗口的指标 bCallDestory=是否调用图形销毁函数 this.DeleteIndexPaint = function (windowIndex, bCallDestroy) { if (!this.Frame.SubFrame[windowIndex]) return; var subFrame=this.Frame.SubFrame[windowIndex].Frame; if (!subFrame) return; var paint=[]; for (var i=0;i= this.Frame.SubFrame.length) windowIndex = 2; if (option) JSIndexScript.ModifyAttribute(indexInfo, option); return this.ChangeScriptIndex(windowIndex, indexInfo); } this.ChangeIndexTemplate=function(option) //切换指标模板 可以设置指标窗口个数 每个窗口的指标, 只能从第3个指标窗口开始设置,前面2个指标窗口固定无法设置 { if (!Array.isArray(option.Windows)) return; var count=option.Windows.length; var currentLength=this.Frame.SubFrame.length; var startWindowIndex=2; count+=startWindowIndex; var dayCount=null; if (IFrameSplitOperator.IsNumber(option.DayCount) && option.DayCount!=this.DayCount) dayCount= option.DayCount; //天数 var bRefreshData= (dayCount!=null); //清空所有的指标图型 for(var i=startWindowIndex;icount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); for(var i=currentLength-1;i>=count;--i) { if (event && event.Callback) { var sendData={ SubFrame:this.Frame.SubFrame[i], WindowIndex:i }; event.Callback(event, sendData, this); } } this.Frame.SubFrame.splice(count,currentLength-count); this.WindowIndex.splice(count,currentLength-count); this.TitlePaint.splice(count+1,currentLength-count); } else { for(var i=currentLength;i { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; this.TitlePaint[i+1]=titlePaint; } } for(var i=0;ii) frameItem=option.Frame[windowIndex]; if (windowIndex>=startWindowIndex) item=option.Windows[windowIndex-startWindowIndex]; var titleIndex=windowIndex+1; this.TitlePaint[titleIndex].Data=[]; this.TitlePaint[titleIndex].Title=null; if (item) { if (item.Script) //自定义指标脚本 { this.WindowIndex[windowIndex]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行 } else if (item.API) //后台指标 { var apiItem=item.API; this.WindowIndex[windowIndex]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item); } else { var indexID=item.Index; var indexItem=JSIndexMap.Get(indexID); if (indexItem) { this.WindowIndex[windowIndex]=indexItem.Create(); this.CreateWindowIndex(windowIndex); } else { var systemScript = new JSIndexScript(); var indexInfo = systemScript.Get(indexID); if (indexInfo) { JSIndexScript.ModifyAttribute(indexInfo, item) this.WindowIndex[windowIndex]=new ScriptIndex(indexInfo.Name,indexInfo.Script, indexInfo.Args,indexInfo); //脚本执行 } } } } this.SetSubFrameAttribute(this.Frame.SubFrame[windowIndex], item, frameItem); } //清空叠加指标 for(var i=0;i=0) item.WindowIndex=item.Windows; var overlay=this.CreateOverlayWindowsIndex(item); if (!overlay) continue; aryOverlayIndex.push({ WindowsIndex:item.WindowIndex, Overlay:overlay }); } } this.Frame.SetSizeChage(true); if (!bRefreshData) { var bindData=this.SourceData; for(var i=0;i=this.Frame.SubFrame.length) return; var delFrame=this.Frame.SubFrame[id].Frame; this.DeleteIndexPaint(id, true); var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); if (event && event.Callback) { var sendData={ SubFrame:this.Frame.SubFrame[id], WindowIndex:id }; event.Callback(event, sendData, this); } this.Frame.SubFrame.splice(id,1); this.WindowIndex.splice(id,1); this.TitlePaint.splice(id+1,1); //删除对应的动态标题 for(var i=0;i=2) this.DeleteIndexPaint(i, true); } } } this.ResetDataStatus=function() { this.DataStatus.MultiDay=false; this.DataStatus.LatestDay=false; } //切换股票代码 this.ChangeSymbol = function (symbol) { this.Symbol = symbol; this.CancelAutoUpdate(); //先停止定时器 this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.ResetDataStatus(); this.ClearIndexPaint(); this.ResetOverlaySymbolStatus(); this.Frame.ClearYCoordinateMaxMin(); this.RequestData(); } this.ChangeDayCount = function (count) { if (count < 0 || count > 10) return; this.DayCount = count; this.CancelAutoUpdate(); //先停止定时器 this.ResetDataStatus(); this.ClearIndexPaint(); this.ResetOverlaySymbolStatus(); this.Frame.ClearYCoordinateMaxMin(); this.RequestData(); } //叠加股票 只支持日线数据 this.OverlaySymbol = function (symbol,option) { var arySymbol=null; if (IFrameSplitOperator.IsString(symbol)) arySymbol=[symbol]; else if (Array.isArray(symbol)) arySymbol=symbol; if (!IFrameSplitOperator.IsNonEmptyArray(arySymbol)) return false; var aryNewSymbol=[]; for(var i=0, j=0;i0 && limitData.min>0) //API里带涨停价格 直接使用 { this.LimitPrice={ Max:limitData.max, Min:limitData.min }; return; } var range=MARKET_SUFFIX_NAME.GetLimitPriceRange(this.Symbol, this.Name); //通过规则获取涨停价格 if (!range) { JSConsole.Chart.Log(`[MinuteChartContainer::CaclutateLimitPrice] ${this.Symbol} no limit price.`) return; } //var yClose=data.stock[0].yclose; if (yClose<=0) return; this.LimitPrice={ Max:yClose*(1+range.Max), Min:yClose*(1+range.Min) }; JSConsole.Chart.Log(`[MinuteChartContainer::CaclutateLimitPrice] ${this.Symbol} yClose:${yClose} max:${this.LimitPrice.Max} min:${this.LimitPrice.Min}`); this.LimitPrice.Max=parseFloat(this.LimitPrice.Max.toFixed(2)); this.LimitPrice.Min=parseFloat(this.LimitPrice.Min.toFixed(2)); JSConsole.Chart.Log(`[MinuteChartContainer::CaclutateLimitPrice] ${this.Symbol} tofixed(2) max:${this.LimitPrice.Max} min:${this.LimitPrice.Min}`); } this.UpdateHistoryMinuteUI = function () { var allMinuteData = this.HistoryMinuteDataToArray(this.DayData); //原始数据 var sourceData = new ChartData(); sourceData.Data = allMinuteData; this.SourceData = sourceData; this.TradeDate = this.DayData[0].Date; this.Frame.SetDayCount(this.DayData.length); var upperSymbol=this.Symbol.toUpperCase(); var yClose=this.DayData[0].YClose; var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); if (IFrameSplitOperator.IsNumber(this.DayData[0].YClearing) && isFutures) yClose=this.DayData[0].YClearing; //期货使用前结算价 this.BindMainData(sourceData, yClose); //if (MARKET_SUFFIX_NAME.IsChinaFutures(this.Symbol)) this.ChartPaint[1].Data = null; //期货均线暂时不用 if (this.Frame.SubFrame.length > 2) { var bindData = new ChartData(); bindData.Data = allMinuteData; for (var i = 2; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } } for (let i in this.Frame.SubFrame) { var item = this.Frame.SubFrame[i]; item.Frame.XSplitOperator.Symbol = this.Symbol; item.Frame.XSplitOperator.DayCount = this.DayData.length; item.Frame.XSplitOperator.DayData = this.DayData; item.Frame.XSplitOperator.Operator(); //调整X轴个数 item.Frame.YSplitOperator.Symbol = this.Symbol; } this.ChartCorssCursor.StringFormatY.Symbol = this.Symbol; this.ChartCorssCursor.StringFormatX.Symbol = this.Symbol; this.TitlePaint[0].IsShowDate = true; this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); } this.HistoryMinuteDataToArray = function (data) //把多日分钟数据转化为单数组 { var result = []; for (var i = data.length - 1; i >= 0; --i) { var item = data[i]; for (var j in item.Data) { result.push(item.Data[j]); } } return result; } this.UpdateLatestMinuteData = function (data, date) //更新最新交易日的分钟数据 { for (var i in this.DayData) { var item = this.DayData[i]; if (item.Date === date) { item.Data = data; break; } } } //请求分钟数据 this.RequestMinuteData = function () { var self = this; var fields = [ "name", "symbol", "yclose", "open", "price", "high", "low", "vol", "amount", "date", "time", "minute", "minutecount" ]; var upperSymbol = this.Symbol.toUpperCase(); if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)) //期货的需要加上结算价 { fields.push("clearing"); fields.push("yclearing"); } if (this.NetworkFilter) { var obj = { Name: 'MinuteChartContainer::RequestMinuteData', //类名::函数名 Explain: '最新分时数据', Request: { Url: self.MinuteApiUrl, Data: { field: fields, symbol: [self.Symbol] }, Type: 'POST' }, Self: this, PreventDefault: false }; this.NetworkFilter(obj, function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMinuteData(data); }); if (obj.PreventDefault == true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: this.MinuteApiUrl, data: { "field": fields, "symbol": [this.Symbol], "start": -1 }, method: "post", dataType: "json", success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMinuteData(data); } }); } this.RecvMinuteData = function (data) { if (data.data && data.data.dataType===1) //增量更新数据模式 { this.RecvUpdateMinuteData(data.data); return; } var aryMinuteData = MinuteChartContainer.JsonDataToMinuteData(data.data); this.DataStatus.LatestDay=true; if (this.DayCount > 1) //多日走势图 { this.UpdateLatestMinuteData(aryMinuteData, data.data.stock[0].date); this.UpdateHistoryMinuteUI(); this.RecvMinuteDataEvent(); this.RequestOverlayMinuteData(); //更新最新叠加数据 this.BindAllOverlayIndexData(this.SourceData); if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this); this.AutoUpdate(); return; } if (this.IsOnTouch==true) //正在操作中不更新数据 { if (this.SourceData && IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) { this.AutoUpdate(); return; } } //原始数据 var sourceData = new ChartData(); sourceData.Data = aryMinuteData; this.TradeDate = data.data.stock[0].date; this.Frame.SetDayCount(1); //单日数据 this.SourceData = sourceData; this.Symbol = data.data.stock[0].symbol; this.Name = data.data.stock[0].name; var yClose = data.data.stock[0].yclose; var upperSymbol = this.Symbol.toUpperCase(); var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol); if (data.data.stock[0].yclearing && isFutures) yClose = data.data.stock[0].yclearing; //期货使用前结算价 this.CaclutateLimitPrice(yClose, data.data.stock[0].limitprice); //计算涨停价格 var extendData = { High: data.data.stock[0].high, Low: data.data.stock[0].low }; this.BindMainData(sourceData, yClose, extendData); for (let i in this.Frame.SubFrame) //把股票代码设置到X轴刻度类里 { var item = this.Frame.SubFrame[i]; item.Frame.XSplitOperator.Symbol = this.Symbol; item.Frame.XSplitOperator.DayCount = 1; item.Frame.XSplitOperator.Operator(); //调整X轴个数 item.Frame.YSplitOperator.Symbol = this.Symbol; } //计算指标 if (this.Frame.SubFrame.length > 2) { var bindData = new ChartData(); bindData.Data = aryMinuteData; for (var i = 2; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } } this.ChartCorssCursor.StringFormatY.Symbol = this.Symbol; this.ChartCorssCursor.StringFormatX.Symbol = this.Symbol; var chartInfo = this.GetChartMinuteInfo(); if (chartInfo) chartInfo.SourceData = this.SourceData; //数据绑定到信息地雷上 this.RecvMinuteDataEvent(); this.RequestMinuteInfoData(); this.RequestOverlayMinuteData();//请求叠加数据 (主数据下载完再下载) this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.BindAllOverlayIndexData(this.SourceData); if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this); this.AutoUpdate(); } this.RecvUpdateMinuteData=function(data) { var minuteData=MinuteChartContainer.JsonDataToUpdateMinuteData(data); if (this.DayCount > 1) //多日走势图 { this.UpdateLatestMinuteDataV2(minuteData); this.UpdateHistoryMinuteUI(); this.RecvMinuteDataEvent(); this.RequestOverlayMinuteData(); //更新最新叠加数据 this.BindAllOverlayIndexData(this.SourceData); if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this); this.AutoUpdate(); return; } this.UpdateLatestMinuteDataV2(minuteData); var sourceData=this.SourceData; var aryMinuteData=this.SourceData.Data; this.Frame.SetDayCount(1); //单日数据 var upperSymbol = this.Symbol.toUpperCase(); var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol); var yClose=minuteData.YClose; if (data.stock[0].yclearing && isFutures) yClose = data.stock[0].yclearing; //期货使用前结算价 this.CaclutateLimitPrice(yClose, data.stock[0].limitprice); //计算涨停价格 var extendData = { High: data.stock[0].high, Low: data.stock[0].low }; this.BindMainData(sourceData, yClose, extendData); for (var i=0;i 2) { var bindData = new ChartData(); bindData.Data = aryMinuteData; for (var i = 2; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } } var chartInfo = this.GetChartMinuteInfo(); if (chartInfo) chartInfo.SourceData = this.SourceData; //数据绑定到信息地雷上 this.RecvMinuteDataEvent(); this.RequestMinuteInfoData(); this.RequestOverlayMinuteData();//请求叠加数据 (主数据下载完再下载) this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); this.BindAllOverlayIndexData(this.SourceData); if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvMinuteData', this); this.AutoUpdate(); } //更新最新的几条数据 this.UpdateLatestMinuteDataV2=function(minuteData) { if (this.DayCount>1) { if (!this.DayData) return; var findItem=null; for(var i=0; i 1) //多日数据 { if (aryMinuteData.length <= 0) return; var minuteData = aryMinuteData[0]; for (var i in this.OverlaySourceData) { var item = this.OverlaySourceData[i]; if (item.Date == minuteData.Date) { this.OverlaySourceData[i] = minuteData; var allMinuteData = this.HistoryMinuteDataToArray(this.OverlaySourceData); var sourceData = new ChartData(); sourceData.Data = allMinuteData; yClose = minuteData.YClose; break; } } if (sourceData == null) return; } else { if (aryMinuteData.length > 0) sourceData = aryMinuteData[0]; else sourceData = new ChartData(); yClose = sourceData.YClose; } paint.Data=sourceData; paint.Title=data.name; paint.Symbol=data.symbol; paint.YClose=yClose; paint.Status=OVERLAY_STATUS_ID.STATUS_FINISHED_ID; var bRedraw=true; if (option && option.Redraw==false) bRedraw=false; if (bRedraw) { this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); } } this.RequestOverlayHistoryMinuteData = function () { if (!IFrameSplitOperator.IsNonEmptyArray(this.DayData)) return; var self = this; var days=[]; for(var i=0; i { return this.GetEventCallback(id); }; frame.YSplitOperator.HQChart=this; frame.YSplitOperator.OverlayIdentify=overlayFrame.Identify; if (obj.Frame) { var item=obj.Frame; if (item.Custom) frame.YSplitOperator.Custom=item.Custom; } overlayFrame.Frame=frame; if (apiItem) { var apiIndex=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,obj, true); apiIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息 overlayFrame.Script=apiIndex; } else if (indexInfo) { let indexData = indexInfo; if (obj.Args) indexData.Args=obj.Args; //外部可以设置参数 var scriptIndex=new OverlayScriptIndex(indexData.Name,indexData.Script,indexData.Args,indexData); //脚本执行 scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息 overlayFrame.Script=scriptIndex; } else { var scriptIndex=indexCustom.Create(); scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame }; //叠加指标信息 scriptIndex.Create(this,windowIndex); overlayFrame.Script=scriptIndex; } subFrame.OverlayIndex.push(overlayFrame); return overlayFrame; } //获取子窗口的所有画法 this.GetChartPaint = function (windowIndex) { var paint = new Array(); for (var i in this.ChartPaint) { if (i < 3) continue; //分钟 均线 成交量 3个线不能改 var item = this.ChartPaint[i]; if (item.ChartFrame == this.Frame.SubFrame[windowIndex].Frame) paint.push(item); } return paint; } //创建指定窗口指标 this.CreateWindowIndex = function (windowIndex) { this.WindowIndex[windowIndex].Create(this, windowIndex); } this.CreateExtendChart = function (name, option) //创建扩展图形 { var chart; switch (name) { case 'MinuteTooltip': if (option.Create && typeof(option.Create)=='function') chart=option.Create(); else chart = new MinuteTooltipPaint(); chart.Canvas = this.Canvas; chart.ChartBorder = this.Frame.ChartBorder; chart.ChartFrame = this.Frame; chart.HQChart = this; option.LanguageID = this.LanguageID; chart.SetOption(option); this.ExtendChartPaint.push(chart); return chart; default: chart=g_ExtendChartPaintFactory.Create(name); if (!chart) return null; chart.Canvas=this.Canvas; chart.ChartBorder=this.Frame.ChartBorder; chart.ChartFrame=this.Frame; chart.HQChart=this; chart.SetOption(option); this.ExtendChartPaint.push(chart); return chart; } } this.SetMinuteInfo = function (aryInfo, bUpdate) { this.ChartInfo = []; //先清空 for (var i in aryInfo) { var infoItem = JSMinuteInfoMap.Get(aryInfo[i]); if (!infoItem) continue; var item = infoItem.Create(); this.ChartInfo.push(item); } if (bUpdate == true) this.RequestMinuteInfoData(); } this.GetChartMinuteInfo = function () { return this.ChartInfoPaint; } this.CreateMinuteInfo = function (option) //在Create()以后 在调用 { var chart = new ChartMinuteInfo(); chart.Canvas = this.Canvas; chart.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder; chart.ChartFrame = this.Frame.SubFrame[0].Frame; chart.ChartMinutePrice = this.ChartPaint[0]; if (option && chart.SetOption) chart.SetOption(option); this.ChartInfoPaint = chart; return chart; } //信息地雷数据请求 this.RequestMinuteInfoData = function () { if (this.ChartInfo.length <= 0) return; var chart = this.GetChartMinuteInfo(); if (!chart) chart = this.CreateMinuteInfo(null); //不存在就创建 chart.SourceData = this.SourceData; //信息地雷信息 for (var i in this.ChartInfo) { this.ChartInfo[i].RequestData(this); } } //更新信息地雷 this.UpdataChartInfo = function () { var chart = this.GetChartMinuteInfo(); if (!chart) return; var infoMap = new Map(); for (var i in this.ChartInfo) { var infoData = this.ChartInfo[i].Data; for (var j in infoData) { var item = infoData[j]; var dateTime = `${item.Date} ${item.Time}`; if (infoMap.has(dateTime)) infoMap.get(dateTime).Data.push(item); else infoMap.set(dateTime, { Data: new Array(item) }); } } chart.Data = infoMap; } this.TryClickIndexTitle=function(x,y) { for(var i=0; i 0) date = jsData.date; //分钟数据中有日期 优先使用 item.DateTime = date.toString() + " " + jsData.time.toString(); item.Date = date; item.Time = jsData.time; if (isFutures || isSHO || isSZO) item.Position = jsData.position; //期货 期权有持仓 if (yClose && item.Close) item.Increase = (item.Close - yClose) / yClose * 100; //涨幅 (最新价格-昨收)/昨收*100 if (isFutures && yClearing && item.Close) item.Increase = (item.Close - yClearing) / yClearing * 100; //涨幅 (最新价格-昨结算价)/昨结算价*100 if (jsData.ExtendData) item.ExtendData=jsData.ExtendData; //扩展数据 aryMinuteData[i] = item; } return aryMinuteData; } //多日日线数据API 转化成array[]; MinuteChartContainer.JsonDataToMinuteDataArray = function (data) { var upperSymbol = data.symbol.toUpperCase(); var isSHSZ = MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var isFutures = MARKET_SUFFIX_NAME.IsFutures(upperSymbol); var isSHO = MARKET_SUFFIX_NAME.IsSHO(upperSymbol); //上海股票期权 var isSZO = MARKET_SUFFIX_NAME.IsSZO(upperSymbol); //深证股票期权 var result = []; var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_MULTI_DAY_EXTENDDATA; //扩展数据序号 for (var i=0; i 0) { item.AvPrice = jsData[7]; //均价 preAvPrice = jsData[7]; } if (!item.Close) //当前没有价格 使用上一个价格填充 { item.Close = preClose; item.Open = item.High = item.Low = item.Close; } if (!item.AvPrice && preAvPrice) item.AvPrice = preAvPrice; if (item.Close && yClose) item.Increase = (item.Close - yClose) / yClose * 100; if (isFutures && item.Close && yClearing) item.Increase = (item.Close - yClearing) / yClearing * 100; item.DateTime = date.toString() + " " + jsData[0].toString(); item.Date = date; item.Time = jsData[0]; if (80) { item.Date=jsData[8]; //日期 item.DateTime=item.Date.toString()+" "+jsData[0].toString(); } if ((isFutures || isSHO || isSZO) && 9 < jsData.length) item.Position = jsData[9]; //持仓 if (j == 0 ) { //if (isSHSZ) item.DateTime = date.toString() + " 0925";//第1个数据 写死9:25 item.IsFristData = true; } if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; minuteData[j] = item; } var newData = new ChartData(); newData.Data = minuteData; newData.YClose = yClose; newData.Close = dayData.close; newData.Date = date; if (IFrameSplitOperator.IsNumber(yClearing)) newData.YClearing=yClearing; result.push(newData); } return result; } //分钟增量数据 stock: [ { date:, yclose:, yclearing: , minute:[ [],]} 0=日期 1=时间 2=开 3=高 4=低 5=收 6=均价 7=量 8=金额 9=涨幅 10=涨跌 11=领先指标 ] MinuteChartContainer.JsonDataToUpdateMinuteData=function(data) { if (!data || !data.stock) return null; var stock=data.stock[0]; if (!IFrameSplitOperator.IsNumber(stock.date)) return null; var symbol=data.stock[0].symbol; var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //国内期货, 纽约期货交易所 var minuteData={ Date:stock.date, Data:[] , Symbol:symbol, Name:stock.name }; var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_DAY_EXTENDDATA; //扩展数据序号 if (IFrameSplitOperator.IsNumber(stock.high)) minuteData.High=stock.high; if (IFrameSplitOperator.IsNumber(stock.low)) minuteData.Low=stock.low; if (IFrameSplitOperator.IsNumber(stock.yclose)) minuteData.YClose=stock.yclose; if (IFrameSplitOperator.IsNumber(stock.YClearing)) minuteData.YClearing=stock.yclearing; if (IFrameSplitOperator.IsNumber(stock.high)) minuteData.High=stock.high; if (IFrameSplitOperator.IsNumber(stock.low)) minuteData.Low=stock.low; if (IFrameSplitOperator.IsNumber(stock.yclose)) minuteData.YClose=stock.yclose; if (IFrameSplitOperator.IsNumber(stock.YClearing)) minuteData.YClearing=stock.yclearing; if (!IFrameSplitOperator.IsNonEmptyArray(stock.minute)) return minuteData; for(var i=0;i 2) { var bindData = new ChartData(); bindData.Data = aryMinuteData; for (var i = 2; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } } this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); //this.AutoUpdata(); } } //API 返回数据 转化为array[] HistoryMinuteChartContainer.JsonDataToMinuteData = function (data) { var aryMinuteData = new Array(); for (var i in data.minute.time) { var item = new MinuteData(); if (data.minute.price[i] <= 0 && i > 0) //当前这一分钟价格为空,使用上一分钟的数据 { item.Close = aryMinuteData[i - 1].Close; item.Open = aryMinuteData[i - 1].Close; item.High = item.Close; item.Low = item.Close; item.Vol = data.minute.vol[i] / 100; //原始单位股 item.Amount = data.minute.amount[i]; item.DateTime = data.date.toString() + " " + data.minute.time[i].toString(); item.Date = data.date; item.Time = data.minute.time[i]; //item.Increate=jsData.increate; //item.Risefall=jsData.risefall; item.AvPrice = aryMinuteData[i - 1].AvPrice; } else { item.Close = data.minute.price[i]; item.Open = data.minute.open[i]; item.High = data.minute.high[i]; item.Low = data.minute.low[i]; item.Vol = data.minute.vol[i] / 100; //原始单位股 item.Amount = data.minute.amount[i]; item.DateTime = data.date.toString() + " " + data.minute.time[i].toString(); item.Date = data.date; item.Time = data.minute.time[i]; //item.Increate=jsData.increate; //item.Risefall=jsData.risefall; item.AvPrice = data.minute.avprice[i]; } //价格是0的 都用空 if (item.Open <= 0) item.Open = null; if (item.Close <= 0) item.Close = null; if (item.AvPrice <= 0) item.AvPrice = null; if (item.High <= 0) item.High = null; if (item.Low <= 0) item.Low = null; aryMinuteData[i] = item; } return aryMinuteData; } ///////////////////////////////////////////////////////////////////////////// // 自定义指数 // function CustomKLineChartContainer(uielement) { this.newMethod = KLineChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName = 'CustomKLineChartContainer'; this.ChangeRight = null; //没有复权设置 this.LoadDataSplashTitle = '计算指数数据'; this.CustomKLineApiUrl = g_JSChartResource.Domain + "/API/IndexCalculate"; //自定义指数计算地址 this.CustomStock; //成分 this.QueryDate = { Start: 20180101, End: 20180627 }; //计算时间区间 this.RequestHistoryData = function () { var self = this; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.Draw(); JSNetwork.HttpRequest({ url: this.CustomKLineApiUrl, data: { "stock": self.CustomStock, "Name": self.Symbol, "date": { "startdate": self.QueryDate.Start, "enddate": self.QueryDate.End } }, method: 'POST', dataType: "json", async: true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvHistoryData(data); } }); } this.RecvHistoryData = function (recvData) { var data = recvData.data; var aryDayData = KLineChartContainer.JsonDataToHistoryData(data); //原始数据 var sourceData = new ChartData(); sourceData.Data = aryDayData; sourceData.DataType = 0; //0=日线数据 1=分钟数据 sourceData.Symbol = data.symbol; //显示的数据 var bindData = new ChartData(); bindData.Data = aryDayData; bindData.Right = 0; //指数没有复权 bindData.Period = this.Period; bindData.DataType = 0; bindData.Symbol = data.symbol; if (ChartData.IsDayPeriod(this.Period, false)) //周期数据 { var periodData = sourceData.GetPeriodData(bindData.Period); bindData.Data = periodData; } //绑定数据 this.SourceData = sourceData; this.Name = data.name; this.BindMainData(bindData, this.PageSize); for (var i = 0; i < this.Frame.SubFrame.length; ++i) { this.BindIndexData(i, bindData); } //this.BindIndexData(0,hisData); //this.BindIndexData(1,hisData); //this.BindIndexData(2,hisData); //刷新画图 this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); if (typeof (this.UpdateUICallback) == 'function') this.UpdateUICallback('RecvHistoryData', this); } } //////////////////////////////////////////////////////////////////////////////// // K线横屏显示 // function KLineChartHScreenContainer(uielement) { this.newMethod = KLineChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName = 'KLineChartHScreenContainer'; this.OnMouseMove = function (x, y, e) { this.LastPoint.X = x; this.LastPoint.Y = y; this.CursorIndex = this.Frame.GetXData(y); this.DrawDynamicInfo(); } //手机拖拽 this.ontouchstart = function (e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var jsChart = this; if (jsChart.DragMode == 0) return; this.IsPress=false; this.IsOnTouch = true; this.PhonePinch = null; this.TouchDrawCount=0; if (this.IsPhoneDragging(e)) { if (jsChart.TryClickLock || this.TryClickIndexTitle) { var touches = this.GetToucheData(e); var x = touches[0].clientX; var y = touches[0].clientY; if (jsChart.TryClickLock && jsChart.TryClickLock(x, y)) return; if (jsChart.TryClickIndexTitle && jsChart.TryClickIndexTitle(x, y)) return; } //长按2秒,十字光标 if (this.TouchTimer != null) clearTimeout(this.TouchTimer); var drag = { "Click": {}, "LastMove": {}, };//最后移动的位置 var touches = this.GetToucheData(e); drag.Click.X = touches[0].clientX; drag.Click.Y = touches[0].clientY; drag.LastMove.X = touches[0].clientX; drag.LastMove.Y = touches[0].clientY; this.MouseDrag = drag; this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } }; if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false; this.SelectChartDrawPicture=null; if (this.CurrentChartDrawPicture) //画图工具模式 { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==2) this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y,true); else { this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true); //只有1个点 直接完成 if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false}); } return; } else { var drawPictrueData={X:touches[0].clientX, Y:touches[0].clientY, PixelRatio:this.UIElement.PixelRatio }; if (this.GetChartDrawPictureByPoint(drawPictrueData)) { drawPictrueData.ChartDrawPicture.Status=20; drawPictrueData.ChartDrawPicture.ValueToPoint(); drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex; drawPictrueData.ChartDrawPicture.IsSelected=true; this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture; this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture; let event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件 if (event && event.Callback) { let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture }; event.Callback(event,sendData,this); } this.DrawDynamicInfo(); return; } } if (this.ChartCorssCursor.IsShow == true) { this.TouchTimer = setTimeout(function () { jsChart.IsPress=true; if (drag.Click.X == drag.LastMove.X && drag.Click.Y == drag.LastMove.Y) //手指没有移动,出现十字光标 { var mouseDrag = jsChart.MouseDrag; jsChart.MouseDrag = null; //移动十字光标 var x = drag.Click.X; var y = drag.Click.Y; jsChart.OnMouseMove(x, y, e); } }, jsChart.PressTime); } } else if (this.IsPhonePinching(e)) { var phonePinch = { "Start": {}, "Last": {}}; var touches = this.GetToucheData(e); phonePinch.Start = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY }; phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY }; this.PhonePinch = phonePinch; this.SelectChartDrawPicture=null; } this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e); } this.ontouchmove = function (e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var jsChart = this; var touches = this.GetToucheData(e); if (this.IsPhoneDragging(e)) { var drag = jsChart.MouseDrag; if (drag == null) { var x = touches[0].clientX; var y = touches[0].clientY; jsChart.OnMouseMove(x, y, e); } else { var moveSetp = Math.abs(drag.LastMove.Y - touches[0].clientY); var moveUpDown=Math.abs(drag.LastMove.X-touches[0].clientX); moveSetp = parseInt(moveSetp); if (this.CurrentChartDrawPicture) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) { if(moveSetp<5 && moveUpDown<5) return; if(this.SetChartDrawPictureSecondPoint(touches[0].clientX,touches[0].clientY)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==3) { if(this.SetChartDrawPictureThirdPoint(touches[0].clientX,touches[0].clientY)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==20) //画图工具移动 { if(moveSetp<5 && moveUpDown<5) return; if(this.MoveChartDrawPicture(touches[0].clientX-drag.LastMove.X,touches[0].clientY-drag.LastMove.Y)) { this.DrawDynamicInfo(); } } drag.LastMove.X=touches[0].clientX; drag.LastMove.Y=touches[0].clientY; } else if (jsChart.DragMode == 1) //数据左右拖拽 { if (moveSetp < 5) return; var isLeft = true; if (drag.LastMove.Y < touches[0].clientY) isLeft = false;//右移数据 if (jsChart.DataMove(moveSetp, isLeft)) { jsChart.UpdataDataoffset(); jsChart.UpdatePointByCursorIndex(); jsChart.UpdateFrameMaxMin(); jsChart.ResetFrameXYSplit(); jsChart.Draw(); } else { if (jsChart.DragDownloadData) jsChart.DragDownloadData(); } drag.LastMove.X = touches[0].clientX; drag.LastMove.Y = touches[0].clientY; } } if (this.PhoneTouchInfo) { this.PhoneTouchInfo.End.X=touches[0].clientX; this.PhoneTouchInfo.End.Y=touches[0].clientY; } } else if (this.IsPhonePinching(e)) { var phonePinch = jsChart.PhonePinch; if (!phonePinch) return; if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return; var yHeight = Math.abs(touches[0].pageX - touches[1].pageX); var yLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2); var yStep = yHeight - yLastHeight; if (Math.abs(yStep) < 5) return; if (yStep > 0) //放大 { var cursorIndex = {}; cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0)); if (!jsChart.Frame.ZoomUp(cursorIndex)) return; jsChart.CursorIndex = cursorIndex.Index; jsChart.UpdatePointByCursorIndex(); jsChart.UpdataDataoffset(); jsChart.UpdateFrameMaxMin(); jsChart.ResetFrameXYSplit(); jsChart.Draw(); } else //缩小 { var cursorIndex = {}; cursorIndex.Index = parseInt(Math.abs(jsChart.CursorIndex - 0.5).toFixed(0)); if (!jsChart.Frame.ZoomDown(cursorIndex)) return; jsChart.CursorIndex = cursorIndex.Index; jsChart.UpdataDataoffset(); jsChart.UpdatePointByCursorIndex(); jsChart.UpdateFrameMaxMin(); jsChart.ResetFrameXYSplit(); jsChart.Draw(); } phonePinch.Last = { "X": touches[0].pageX, "Y": touches[0].pageY, "X2": touches[1].pageX, "Y2": touches[1].pageY }; } } uielement.onmousedown = function (e) //鼠标拖拽 { if (!this.JSChartContainer) return; if (this.JSChartContainer.DragMode == 0) return; if (this.JSChartContainer.TryClickLock) { var x = e.clientX - this.getBoundingClientRect().left; var y = e.clientY - this.getBoundingClientRect().top; if (this.JSChartContainer.TryClickLock(x, y)) return; } var drag = { "Click": {}, "LastMove": {}, //最后移动的位置 }; drag.Click.X = e.clientX; drag.Click.Y = e.clientY; drag.LastMove.X = e.clientX; drag.LastMove.Y = e.clientY; this.JSChartContainer.MouseDrag = drag; document.JSChartContainer = this.JSChartContainer; this.JSChartContainer.SelectChartDrawPicture = null; uielement.ondblclick = function (e) { var x = e.clientX - this.getBoundingClientRect().left; var y = e.clientY - this.getBoundingClientRect().top; if (this.JSChartContainer) this.JSChartContainer.OnDoubleClick(x, y, e); } document.onmousemove = function (e) { if (!this.JSChartContainer) return; //加载数据中,禁用鼠标事件 if (this.JSChartContainer.ChartSplashPaint && this.JSChartContainer.ChartSplashPaint.IsEnableSplash == true) return; var drag = this.JSChartContainer.MouseDrag; if (!drag) return; var moveSetp = Math.abs(drag.LastMove.Y - e.clientY); if (this.JSChartContainer.DragMode == 1) //数据左右拖拽 { if (moveSetp < 5) return; var isLeft = true; if (drag.LastMove.Y < e.clientY) isLeft = false;//右移数据 if (this.JSChartContainer.DataMove(moveSetp, isLeft)) { this.JSChartContainer.UpdataDataoffset(); this.JSChartContainer.UpdatePointByCursorIndex(); this.JSChartContainer.UpdateFrameMaxMin(); this.JSChartContainer.ResetFrameXYSplit(); this.JSChartContainer.Draw(); } drag.LastMove.X = e.clientX; drag.LastMove.Y = e.clientY; } }; document.onmouseup = function (e) { //清空事件 document.onmousemove = null; document.onmouseup = null; //清空数据 this.JSChartContainer.MouseDrag = null; this.JSChartContainer.CurrentChartDrawPicture = null; this.JSChartContainer = null; } } //创建 windowCount 窗口个数 this.Create = function (windowCount) { this.UIElement.JSChartContainer = this; //创建十字光标 this.ChartCorssCursor = new ChartCorssCursor(); this.ChartCorssCursor.Canvas = this.Canvas; this.ChartCorssCursor.StringFormatX = g_DivTooltipDataForamt.Create("CorssCursor_XStringFormat"); this.ChartCorssCursor.StringFormatX.LanguageID=this.LanguageID; this.ChartCorssCursor.StringFormatY = g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat"); this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID; this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.HQChart=this; //创建框架容器 this.Frame = new HQTradeHScreenFrame(); 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.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架 this.ChartSplashPaint.Frame = this.Frame; this.CreateChildWindow(windowCount); this.CreateMainKLine(); //子窗口动态标题 for (var i in this.Frame.SubFrame) { var titlePaint = new DynamicChartTitlePainting(); titlePaint.Frame = this.Frame.SubFrame[i].Frame; titlePaint.Canvas = this.Canvas; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.TitlePaint.push(titlePaint); } } //创建子窗口 this.CreateChildWindow = function (windowCount) { for (var i = 0; i < windowCount; ++i) { var border = new ChartBorder(); border.UIElement = this.UIElement; var frame = new KLineHScreenFrame(); frame.Canvas = this.Canvas; frame.ChartBorder = border; frame.Identify = i; //窗口序号 frame.RightSpaceCount = this.RightSpaceCount; //右边 if (this.ModifyIndexDialog) frame.ModifyIndexEvent = this.ModifyIndexDialog.DoModal; //绑定菜单事件 if (this.ChangeIndexDialog) frame.ChangeIndexEvent = this.ChangeIndexDialog.DoModal; frame.HorizontalMax = 20; frame.HorizontalMin = 10; if (i == 0) { frame.YSplitOperator = new FrameSplitKLinePriceY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price'); frame.YSplitOperator.FrameSplitData2 = this.FrameSplitData.get('double'); //主图上下间距 border.TopSpace = 12; border.BottomSpace = 12; } else { frame.YSplitOperator = new FrameSplitY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double'); //frame.IsLocked = true; } frame.YSplitOperator.Frame = frame; frame.YSplitOperator.ChartBorder = border; frame.XSplitOperator = new FrameSplitKLineX(); frame.XSplitOperator.Frame = frame; frame.XSplitOperator.ChartBorder = border; frame.XSplitOperator.GetEventCallback =(id)=> { return this.GetEventCallback(id); } if (i != windowCount - 1) frame.XSplitOperator.ShowText = false; for (var j = frame.HorizontalMin; j <= frame.HorizontalMax; j += 1) { frame.HorizontalInfo[j] = new CoordinateInfo(); frame.HorizontalInfo[j].Value = j; if (i == 0 && j == frame.HorizontalMin) continue; frame.HorizontalInfo[j].Message[1] = j.toString(); frame.HorizontalInfo[j].Font = "14px 微软雅黑"; } var subFrame = new SubFrameItem(); frame.FrameData.SubFrameItem=subFrame; subFrame.Frame = frame; if (i == 0) subFrame.Height = 20; else subFrame.Height = 10; this.Frame.SubFrame[i] = subFrame; } } } //////////////////////////////////////////////////////////////////////////////// // 走势图横屏显示 // function MinuteChartHScreenContainer(uielement) { this.newMethod = MinuteChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName = 'MinuteChartHScreenContainer'; this.OnMouseMove = function (x, y, e) { this.LastPoint.X = x; this.LastPoint.Y = y; this.CursorIndex = this.Frame.GetXData(y); this.DrawDynamicInfo(); } //创建 windowCount 窗口个数 this.Create = function (windowCount) { this.UIElement.JSChartContainer = this; //创建十字光标 this.ChartCorssCursor = new ChartCorssCursor(); this.ChartCorssCursor.Canvas = this.Canvas; this.ChartCorssCursor.StringFormatX = new HQMinuteTimeStringFormat(); this.ChartCorssCursor.StringFormatY = new HQPriceStringFormat(); this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle; //创建框架容器 this.Frame = new HQTradeHScreenFrame(); this.Frame.ChartBorder = new ChartBorder(); this.Frame.ChartBorder.UIElement = this.UIElement; this.Frame.ChartBorder.Top = 25; this.Frame.ChartBorder.Left = 50; this.Frame.ChartBorder.Bottom = 20; this.Frame.Canvas = this.Canvas; this.ChartCorssCursor.Frame = this.Frame; //十字光标绑定框架 this.ChartSplashPaint.Frame = this.Frame; this.CreateChildWindow(windowCount); this.CreateMainKLine(); //子窗口动态标题 for (var i in this.Frame.SubFrame) { var titlePaint = new DynamicChartTitlePainting(); titlePaint.Frame = this.Frame.SubFrame[i].Frame; titlePaint.Canvas = this.Canvas; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.TitlePaint.push(titlePaint); } this.ChartCorssCursor.StringFormatX.Frame = this.Frame.SubFrame[0].Frame; } //创建子窗口 this.CreateChildWindow = function (windowCount) { for (var i = 0; i < windowCount; ++i) { var border = new ChartBorder(); border.UIElement = this.UIElement; var frame = new MinuteHScreenFrame(); frame.Canvas = this.Canvas; frame.ChartBorder = border; if (i < 2) frame.ChartBorder.TitleHeight = 0; frame.XPointCount = 243; frame.Identify=i; frame.HQChart=this; frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } var DEFAULT_HORIZONTAL = [9, 8, 7, 6, 5, 4, 3, 2, 1]; frame.HorizontalMax = DEFAULT_HORIZONTAL[0]; frame.HorizontalMin = DEFAULT_HORIZONTAL[DEFAULT_HORIZONTAL.length - 1]; if (i == 0) { frame.YSplitOperator = new FrameSplitMinutePriceY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('price'); } else { frame.YSplitOperator = new FrameSplitY(); frame.YSplitOperator.FrameSplitData = this.FrameSplitData.get('double'); } frame.YSplitOperator.Frame = frame; frame.YSplitOperator.ChartBorder = border; frame.XSplitOperator = new FrameSplitMinuteX(); frame.XSplitOperator.Frame = frame; frame.XSplitOperator.ChartBorder = border; frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (i != windowCount - 1) frame.XSplitOperator.ShowText = false; frame.XSplitOperator.Operator(); for (var j in DEFAULT_HORIZONTAL) { frame.HorizontalInfo[j] = new CoordinateInfo(); frame.HorizontalInfo[j].Value = DEFAULT_HORIZONTAL[j]; if (i == 0 && j == frame.HorizontalMin) continue; frame.HorizontalInfo[j].Message[1] = DEFAULT_HORIZONTAL[j].toString(); frame.HorizontalInfo[j].Font = "14px 微软雅黑"; } var subFrame = new SubFrameItem(); frame.FrameData.SubFrameItem=subFrame; subFrame.Frame = frame; if (i == 0) subFrame.Height = 20; else subFrame.Height = 10; this.Frame.SubFrame[i] = subFrame; } } } //////////////////////////////////////////////////////////////////////////////// // K线训练,包含横屏 // function KLineTrainChartContainer(uielement, bHScreen) { if (bHScreen === true) { this.newMethod = KLineChartHScreenContainer; //派生 this.newMethod(uielement); delete this.newMethod; } else { this.newMethod = KLineChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; } this.ClassName2 = 'KLineTrainChartContainer'; this.BuySellPaint; //买卖点画法 this.TrainDataCount = 300; //训练数据个数 this.AutoRunTimer = null; //K线自动前进定时器 this.BuySellData = []; //模拟买卖数据 {Buy:{Price:价格,Date:日期,Time:时间} , Sell:{Price:价格,Date:日期,Time:时间} this.TrainDataIndex; //当前训练的数据索引 this.TrainCallback; //训练回调 (K线每前进一次就调用一次) this.DragMode = 1; this.TrainStartEnd = {}; this.KLineSourceData; //原始K线数据 对应 SourceData this.TrainInfo = { Start: {}, End: {} }; // Index:数据索引, Date:日期 Time:时间 this.CreateBuySellPaint = function () //在主窗口建立以后 创建买卖点 { var chart = new ChartBuySell(); chart.Canvas = this.Canvas; chart.ChartBorder = this.Frame.SubFrame[0].Frame.ChartBorder; chart.ChartFrame = this.Frame.SubFrame[0].Frame; chart.Name = "KLine-Train-BuySell"; this.ChartPaintEx[0] = chart; } this.GetKDataIndexByDateTime = function (kData, dateTime) { if (!dateTime || !kData) return -1; for (var i=0; i= this.TrainStartDate.Date && item.Time >= this.TrainStartDate.Time) return i; } else { if (item.Date >= this.TrainStartDate.Date) return i; } } else if (ChartData.IsDayPeriod(this.Period, true) || ChartData.IsTickPeriod(this.Period)) { if (item.Date >= this.TrainStartDate.Date) return i; } } return -1; } this.AfterBindMainData = function (funcName) { if (!this.ChartPaintEx[0]) this.CreateBuySellPaint(); var hisData = this.ChartPaint[0].Data; this.ChartPaintEx[0].Data = hisData; var showItem = hisData.Data[hisData.Data.length - 1]; //最后一个显示数据 this.TrainInfo.LastShowData = showItem; //最后一个原始数据 this.TrainInfo.LastData = this.SourceData.Data[this.SourceData.Data.length - 1]; if (funcName != 'Update') this.UpdateTrainUICallback("开始"); } this.BeforeBindMainData = function (funcName) { if (funcName == "Update") return; //全量数据 需要过滤 this.KLineSourceData = new ChartData(); this.KLineSourceData.Data = this.SourceData.Data.slice(0); var count = this.SourceData.Data.length; var lEnd = count - this.TrainDataCount - 20; var findIndex = this.GetKDataIndexByDateTime(this.SourceData.Data, this.TrainStartDate); if (findIndex >= 0) { lEnd = findIndex + 1; if (count - lEnd < this.TrainDataCount) this.TrainDataCount = count - lEnd; } //训练起始日期 var index = lEnd - 1; var kItem = this.SourceData.Data[index]; this.TrainInfo.Start.Index = index; this.TrainInfo.Start.Date = kItem.Date; this.TrainInfo.Start.Time = kItem.Time; //训练结束日期 this.TrainInfo.End.Index = index; this.TrainInfo.End.Date = kItem.Date; this.TrainInfo.End.Time = kItem.Time; //最后一个数据 this.TrainInfo.LastData = kItem; //修改数据个数 this.SourceData.Data.length = lEnd; } this.Run = function (option) { if (this.AutoRunTimer) return; if (this.TrainDataCount <= 0) return; var self = this; this.AutoRunTimer = setInterval(function () { if (!self.MoveNextKLineData(option)) clearInterval(self.AutoRunTimer); }, 1000); } this.MoveNextKLineData = function (option) //{PageSize:, Step:} { if (this.TrainDataCount <= 0) return false; var step = 1, moveStep=0; if (option && option.Step > 1) step = option.Step; for (var i = 0; i < step; ++i) { var index = this.TrainInfo.End.Index + 1; if (index >= this.KLineSourceData.Data.length) break; var kItem = this.KLineSourceData.Data[index]; this.SourceData.Data.push(kItem); this.TrainInfo.End.Index = index; this.TrainInfo.End.Date = kItem.Date; this.TrainInfo.End.Time = kItem.Time; --this.TrainDataCount; ++moveStep; if (this.TrainDataCount <= 0) break; } if (moveStep == 0) return false; //使用当前页数据个数移动K线 var pageSize = this.Frame.GetCurrentPageSize(); if (IFrameSplitOperator.IsNumber(pageSize)) this.PageSize = pageSize - this.RightSpaceCount; this.Update(); if (this.TrainDataCount <= 0) { this.FinishTrainData(); this.UpdateTrainUICallback("结束"); return false; } this.UpdateTrainUICallback("训练中"); return true; } this.UpdateTrainUICallback = function (description) { //新的监听事件 if (!this.mapEvent.has(JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP)) return; var item = this.mapEvent.get(JSCHART_EVENT_ID.RECV_TRAIN_MOVE_STEP); if (!item.Callback) return; var data = { TrainDataCount: this.TrainDataCount, BuySellData: this.BuySellData, KLine: { Start: { Index: this.TrainInfo.Start.Index, Date: this.TrainInfo.Start.Date }, End: { Index: this.TrainInfo.End.Index, Date: this.TrainInfo.End.Date } }, LastData: this.TrainInfo.LastData, LastShowData: this.TrainInfo.LastShowData }; if (IFrameSplitOperator.IsNumber(this.TrainInfo.Start.Time)) data.KLine.Start.Time = this.TrainInfo.Start.Time; if (IFrameSplitOperator.IsNumber(this.TrainInfo.End.Time)) data.KLine.End.Time = this.TrainInfo.End.Time; if (description) data.Description = description if (this.TrainDataCount <= 0) { data.Symbol = this.Symbol; data.Name = this.Name; } item.Callback(item, data, this); } this.FinishTrainData = function () { } this.Stop = function () { if (this.AutoRunTimer != null) clearInterval(this.AutoRunTimer); this.AutoRunTimer = null; } this.BuyOrSell = function (obj, bDraw) //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 } bDraw是否立即绘制图标 { var kItem = this.TrainInfo.LastShowData; if (!kItem) return false; var buySellPaint = this.ChartPaintEx[0]; if (!buySellPaint) return false; var hisData = this.ChartPaint[0].Data; if (!hisData || hisData.Data.length <= 0) return false; var index = hisData.Data.length - 1; //数据索引 var buyItem = { Date: this.TrainInfo.End.Date, Time: this.TrainInfo.End.Time, Price: obj.Price, Vol: obj.Vol, Op: 0, ID: obj.ID }; if (obj.Op == 1) buyItem.Op = 1; var key = index; buyItem.Key = key; this.BuySellData.push(buyItem); buySellPaint.AddTradeItem(buyItem); if (bDraw == true) this.Draw(); } this.RestartTrain = function (option) // { Symbol:, Period:周期, Right:复权, Train:{ DataCount:, DateTime: } } { JSConsole.Chart.Log('[KLineTrainChartContainer::RestartTrain] option ', option); this.TrainInfo = { Start: {}, End: {} }; this.BuySellData = []; this.KLineSourceData = null; var buySellPaint = this.ChartPaintEx[0]; if (buySellPaint) { buySellPaint.Data = null; buySellPaint.ClearTradeData(); } if (option.Symbol) this.Symbol = option.Symbol; if (IFrameSplitOperator.IsNumber(option.Period)) this.Period = option.Period; if (IFrameSplitOperator.IsNumber(option.Right)) this.Right = option.Right; if (option.Train) { if (option.Train.DataCount > 1) this.TrainDataCount = option.Train.DataCount; if (option.Train.DateTime) this.TrainStartDate = option.Train.DateTime; } var symbol = this.Symbol; this.ChangeSymbol(symbol); } } /////////////////////////////////////////////////////////////////////////////////// // 简单的K线图, 只计算一次 // ////////////////////////////////////////////////////////////////////////////////// function KLineTrainSimpleChartContainer(uielement, bHScreen) { this.newMethod=KLineTrainChartContainer; //派生 this.newMethod(uielement, bHScreen); delete this.newMethod; this.IsHScreen=bHScreen; this.IsZoomLockRight=true; this.RightSpaceCount=0; this.RecvFlowCapitalData=function(data) { this.Super_RecvFlowCapitalData(data); } this.BeforeBindMainData=function(funcName) { } this.UpdateLastDataIcon=function() { if (!this.ChartPaintEx[0]) return; var chart=this.ChartPaintEx[0]; chart.LastDataIndex=this.TrainInfo.End.Index; } this.AfterBindMainData=function(funcName) { if (!this.ChartPaintEx[0]) { this.CreateBuySellPaint(); this.ChartPaintEx[0].LastDataDrawType=1; } if (funcName!="Update") { var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return false; var count=hisData.Data.length; var lEnd=count-this.TrainDataCount-20; var xPointcount=this.Frame.SubFrame[0].Frame.XPointCount; var findIndex=this.GetKDataIndexByDateTime(hisData.Data, this.TrainStartDate); if (findIndex>=0) { lEnd=findIndex+1; if (count-lEnd1) step=option.Step; var count=hisData.Data.length; var moveStep=0; for(var i=0; i=count) break; var kItem=hisData.Data[index]; this.TrainInfo.End.Index=index; this.TrainInfo.End.Date=kItem.Date; this.TrainInfo.End.Time=kItem.Time; --this.TrainDataCount; ++moveStep; if (this.TrainDataCount<=0) break; } if (moveStep==0) return false; //最后一个显示数据 this.TrainInfo.LastShowData=kItem; this.TrainInfo.LastData = kItem; //调整x轴索引位置 var lEnd=this.TrainInfo.End.Index; var xPointcount=this.Frame.SubFrame[0].Frame.XPointCount; var xOffset=lEnd-xPointcount+1; hisData.DataOffset=xOffset; this.UpdateLastDataIcon(); this.UpdataDataoffset(); this.UpdateFrameMaxMin(); this.Draw(); if (this.TrainDataCount<=0) { this.FinishTrainData(); this.UpdateTrainUICallback("结束"); return false; } this.UpdateTrainUICallback("训练中"); return true; } this.BuyOrSell=function(obj, bDraw) //{ Price:价格, Vol:数量, Op: 买/卖 0=buy 1=sell, ID:单号 } bDraw是否立即绘制图标 { var kItem=this.TrainInfo.LastShowData; if (!kItem) return false; var buySellPaint=this.ChartPaintEx[0]; if (!buySellPaint) return false; var hisData=this.ChartPaint[0].Data; if (!hisData || hisData.Data.length<=0) return false; var index=this.TrainInfo.End.Index; //数据索引 var buyItem={ Date:this.TrainInfo.End.Date, Time:this.TrainInfo.End.Time, Price:obj.Price, Vol:obj.Vol, Op:0, ID:obj.ID }; if (obj.Op==1) buyItem.Op=1; var key=index; buyItem.Key=key; this.BuySellData.push(buyItem); buySellPaint.AddTradeItem(buyItem); if (bDraw==true) this.Draw(); } this.DataMove=function(step,isLeft) { step=parseInt(step/this.StepPixel); if (step<=0) return false; var data = this.ChartOperator_Temp_GetHistroyData(); if (!data) return false; var xPointcount = 0; if (this.Frame.XPointCount) xPointcount = this.Frame.XPointCount; else xPointcount = this.Frame.SubFrame[0].Frame.XPointCount; if (!xPointcount) return false; if (isLeft) //--> { if (this.RightSpaceCount > 0) { //TODO: not support if (xPointcount + data.DataOffset >= data.Data.length + this.RightSpaceCount - 1) return false; data.DataOffset += step; if (data.DataOffset + xPointcount >= data.Data.length + this.RightSpaceCount) data.DataOffset = data.Data.length - (xPointcount - this.RightSpaceCount); } else { var end=this.TrainInfo.End.Index+1; if (xPointcount + data.DataOffset >= end) return false; data.DataOffset += step; if (data.DataOffset + xPointcount >= end) data.DataOffset = end - xPointcount; } return true; } else //<-- { if (data.DataOffset <= 0) return false; data.DataOffset -= step; if (data.DataOffset < 0) data.DataOffset = 0; return true; } } //获取最后一个数据的相对于当前屏的索引 this.GetLastDataIndex=function() { if (!this.ChartPaint[0] || !this.ChartPaint[0].Data || !this.ChartPaint[0].Data.Data) return null; var hisData=this.ChartPaint[0].Data; var dataCount=this.TrainInfo.End.Index+1 if (dataCount>0) return (dataCount-1)-hisData.DataOffset; return null; } } ///////////////////////////////////////////////////////////////////////////////// // 深度图 // function DepthChartContainer(uielement) { this.newMethod=JSChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName="DepthChartContainer"; this.Symbol; //数据 this.MapAsk=new Map(); this.MapBid=new Map(); this.IsAutoUpdate=false; //是否自动更新行情数据 this.AutoUpdateFrequency=30000; //30秒更新一次数据 this.AutoUpdateTimer=null; this.DefaultZoom=0.8; //默认显示80%的盘口 (0 - 1) this.MaxVolRate=1.1; this.Create=function(option) { this.UIElement.JSChartContainer=this; //创建十字光标 this.ChartCorssCursor=new DepthChartCorssCursor(); this.ChartCorssCursor.Canvas=this.Canvas; this.ChartCorssCursor.HQChart=this; //this.ChartCorssCursor.StringFormatX=g_DivTooltipDataForamt.Create("CorssCursor_XStringFormat"); //this.ChartCorssCursor.StringFormatX.LanguageID=this.LanguageID; //this.ChartCorssCursor.StringFormatY=g_DivTooltipDataForamt.Create("CorssCursor_YStringFormat"); //this.ChartCorssCursor.StringFormatY.LanguageID=this.LanguageID; //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SplashTitle = this.LoadDataSplashTitle; //创建框架 this.Frame=new DepthChartFrame(); 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.ChartBorder.TitleHeight=0; this.Frame.Canvas=this.Canvas; this.Frame.Identify=0; var ySplitOper=new FrameSplitY(); ySplitOper.FrameSplitData=this.FrameSplitData.get('double'); ySplitOper.LanguageID=this.LanguageID; ySplitOper.Frame=this.Frame; ySplitOper.SplitCount=5; ySplitOper.IgnoreYValue=[0]; ySplitOper.LineType=3; ySplitOper.ChartBorder=this.Frame.ChartBorder; ySplitOper.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.Frame.YSplitOperator=ySplitOper; var xSplitOper=new FrameSplitXDepth(); xSplitOper.Frame=this.Frame;; xSplitOper.ChartBorder=this.Frame.ChartBorder;; xSplitOper.LanguageID=this.LanguageID; xSplitOper.LineType=3; xSplitOper.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; this.Frame.XSplitOperator=xSplitOper if (this.ChartCorssCursor) this.ChartCorssCursor.Frame=this.Frame; //十字光标绑定框架 this.ChartSplashPaint.Frame = this.Frame; var chartItem=new ChartOrderbookDepth(); chartItem.Canvas=this.Canvas; chartItem.ChartBorder=this.Frame.ChartBorder; chartItem.ChartFrame=this.Frame; chartItem.Name="深度图" this.ChartPaint.push(chartItem); } this.ontouchstart=function(e) { this.IsOnTouch=true; this.TouchDrawCount=0; this.PhonePinch=null; var isSingleTouch=this.IsSingleTouch(e); if (this.EnableScrollUpDown==false || !isSingleTouch) //多点触屏 { } if (this.IsPhoneDragging(e)) { var drag= { "Click":{}, "LastMove":{} //最后移动的位置 }; var touches=this.GetToucheData(e,this.IsForceLandscape); drag.Click.X=touches[0].clientX; drag.Click.Y=touches[0].clientY; drag.LastMove.X=touches[0].clientX; drag.LastMove.Y=touches[0].clientY; this.MouseDrag=drag; var x = drag.Click.X; var y = drag.Click.Y; this.OnMouseMove(x, y, e); } else if (this.IsPhonePinching(e)) { var phonePinch= { "Start":{}, "Last":{} }; var touches=this.GetToucheData(e,this.IsForceLandscape); phonePinch.Start={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY}; phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY}; this.PhonePinch=phonePinch; } } this.ontouchmove=function(e) { var touches=this.GetToucheData(e,false); if (this.IsPhoneDragging(e)) { var drag=this.MouseDrag; if (drag==null) { var x = touches[0].clientX; var y = touches[0].clientY; this.OnMouseMove(x,y,e); } else { this.MouseDrag=null; var x = touches[0].clientX; var y = touches[0].clientY; this.OnMouseMove(x,y,e); } } else if (this.IsPhonePinching(e)) { var phonePinch=this.PhonePinch; if (!phonePinch) return; if (this.EnableZoomUpDown && this.EnableZoomUpDown.Touch===false) return; var yHeight = Math.abs(touches[0].pageY - touches[1].pageY); var yLastHeight = Math.abs(phonePinch.Last.Y - phonePinch.Last.Y2); var yStep = yHeight - yLastHeight; var xHeight = Math.abs(touches[0].pageX - touches[1].pageX); var xLastHeight = Math.abs(phonePinch.Last.X - phonePinch.Last.X2); var xStep = xHeight - xLastHeight; var minStep=this.ZoomStepPixel; if (Math.abs(yStep) 0) //放大 { if (!this.Frame.ZoomUp()) return; this.UpdateFrameMaxMin(); this.Draw(); } else //缩小 { if (!this.Frame.ZoomDown()) return; this.UpdateFrameMaxMin(); this.Draw(); } phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY}; } } this.ontouchend=function(e) { JSConsole.Chart.Log('[DepthChartContainer::OnTouchEnd]',e); this.IsOnTouch = false; this.Draw(); this.TouchDrawCount=0; } this.OnMouseMove = function (x, y, e, bFullDraw) { var lastY = this.LastPoint.Y; this.LastPoint.X = x; this.LastPoint.Y = y; this.FullDraw(); } this.ChangeSymbol=function(symbol) { this.CancelAutoUpdate(); //先停止定时器 this.Symbol=symbol; this.MapBid=new Map(); this.MapAsk=new Map(); this.Frame.VerticalRange.Differ=null; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.Draw(); this.RequestDepthData(); } this.RequestDepthData=function() //全量历史数据 { var self=this; if (this.NetworkFilter) { var obj= { Name:'DepthChartContainer::RequestDepthData', //类名:: Explain:'深度图数据', Request:{ Data: { symbol:self.Symbol } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvDepthData(data); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } } this.RecvDepthData=function(data) { this.UpdateAskAndBid(data); var aryAsk=Array.from(this.MapAsk.values()); //卖 右边 aryAsk.sort((a,b)=> { return a.Price-b.Price; }); var sumVol=0; for(var i in aryAsk) { var item=aryAsk[i]; sumVol+=item.Vol; aryAsk[i]={Price:item.Price, Vol:sumVol }; } var aryBid=Array.from(this.MapBid.values()); //买 左边 aryBid.sort((a,b)=> { return b.Price-a.Price; }); var sumVol=0; for(var i in aryBid) { var item=aryBid[i]; sumVol+=item.Vol; aryBid[i]={Price:item.Price, Vol:sumVol }; } var drawData={ Asks:aryAsk, Bids:aryBid }; var chart=this.ChartPaint[0]; chart.Data=drawData; this.Frame.XSplitOperator.Symbol=this.Symbol; this.ChartCorssCursor.Data=drawData; this.ChartCorssCursor.Symbol=this.Symbol; this.UpdateFramePriceList(); this.UpdateFrameMaxMin(); this.Draw(); } this.UpdateAskAndBid=function(data) //更新数据 { if(data.datatype=="snapshot") //全量数据 { this.MapBid=new Map(); this.MapAsk=new Map(); } for(var i in data.asks) { var item=data.asks[i]; var price=parseFloat(item[0]); var vol=parseFloat(item[1]); if (this.MapAsk.has(price)) { var value=this.MapAsk.get(price); if (vol<=0) this.MapAsk.delete(price); else value.Vol=vol; } else { if (vol>0) this.MapAsk.set(price, { Price:price, Vol:vol}); } } for(var i in data.bids) { var item=data.bids[i]; var price=parseFloat(item[0]); var vol=parseFloat(item[1]); if (this.MapBid.has(price)) { var value=this.MapBid.get(price); if (vol<=0) this.MapBid.delete(price); else value.Vol=vol; } else { if (vol>0) this.MapBid.set(price, { Price:price, Vol:vol}); } } } this.UpdateFramePriceList=function() { var aryAskPrice=Array.from(this.MapAsk.keys()); var aryBidPrice=Array.from(this.MapBid.keys()); aryAskPrice.sort((a,b)=> { return a-b; }); aryBidPrice.sort((a,b)=> { return a-b; }); if (aryAskPrice.length>1 && aryBidPrice.length>1) { var askMin=aryAskPrice[0], askMax=aryAskPrice[aryAskPrice.length-1]; var bidMin=aryBidPrice[0], bidMax=aryBidPrice[aryBidPrice.length-1]; var askDifference=askMax-askMin; //卖差值 var bidDifference=bidMax-bidMin; //买差值 var difference=Math.max(askDifference, bidDifference); //取最大的差值,2边调整 var ask={Min:askMin, Max:askMin+difference}; var bid={Max:bidMax, Min:bidMax-difference}; var range={ Max:ask.Max, Min:bid.Min }; } this.Frame.SetPriceList(aryAskPrice,aryBidPrice); var xRange=this.Frame.VerticalRange; xRange.Max=range.Max; xRange.Center=range.Min+(range.Max-range.Min)/2; xRange.Min=range.Min; xRange.MaxDiffer=difference; //差值 xRange.Ask=ask; xRange.Bid=bid; if (!IFrameSplitOperator.IsNumber(xRange.Differ)) xRange.Differ=difference*this.DefaultZoom; xRange.Min=xRange.Center-xRange.Differ; xRange.Max=xRange.Center+xRange.Differ; } this.UpdateFrameMaxMin=function() { var range=this.ChartPaint[0].GetMaxMin(); this.Frame.HorizontalMax=range.Max*this.MaxVolRate; this.Frame.HorizontalMin=0; this.Frame.XYSplit=true; } this.CancelAutoUpdate=function() //关闭停止更新 { if (this.AutoUpdateTimer) { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = null; } } this.StopAutoUpdate=function() { this.CancelAutoUpdate(); if (!this.IsAutoUpdate) return; this.IsAutoUpdate=false; } this.AutoUpdate=function() //数据自动更新 { this.CancelAutoUpdate(); if (!this.IsAutoUpdate) return; if (!this.Symbol) return; if (this.IsDestroy) return; var self = this; var marketStatus=MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol); if (marketStatus==0 || marketStatus==3) return; //闭市,盘后 var frequency=this.AutoUpdateFrequency; if (marketStatus==1) //盘前 { this.AutoUpdateTimer=setTimeout(function() { self.AutoUpdate(); },frequency); } else if (marketStatus==2) //盘中 { this.AutoUpdateTimer=setTimeout(function() { self.RequestDepthData(); },frequency); } } } //是否是指数代码 function IsIndexSymbol(symbol) { var upperSymbol = symbol.toUpperCase(); if (upperSymbol.indexOf('.SH') > 0) { upperSymbol = upperSymbol.replace('.SH', ''); if (upperSymbol.charAt(0) == '0' && parseInt(upperSymbol) <= 3000) return true; } else if (upperSymbol.indexOf('.SZ') > 0) { upperSymbol = upperSymbol.replace('.SZ', ''); if (upperSymbol.charAt(0) == '3' && upperSymbol.charAt(1) == '9') return true; } else if (upperSymbol.indexOf('.CI') > 0) //自定义指数 { return true; } return false; } //导出统一使用JSCommon命名空间名 var JSCommon= { JSCanvasElement: JSCanvasElement, JSNetwork:JSNetwork, JSChart: JSChart, Guid: Guid, IFrameSplitOperator: IFrameSplitOperator, ChartData: ChartData, DataPlus: DataPlus, KLineTooltipPaint: KLineTooltipPaint, MARKET_SUFFIX_NAME: MARKET_SUFFIX_NAME, JSCommonCoordinateData:JSCommonCoordinateData, FrameSplitKLineX:FrameSplitKLineX, FrameSplitKLinePriceY:FrameSplitKLinePriceY, JSCHART_EVENT_ID:JSCHART_EVENT_ID, JSCHART_DATA_FIELD_ID:JSCHART_DATA_FIELD_ID, JSCHART_OPERATOR_ID:JSCHART_OPERATOR_ID, }; export { JSCommon }; /* module.exports = { JSCommon: { JSCanvasElement: JSCanvasElement, JSChart: JSChart, Guid: Guid, IFrameSplitOperator: IFrameSplitOperator, ChartData: ChartData, DataPlus: DataPlus, KLineTooltipPaint: KLineTooltipPaint, MARKET_SUFFIX_NAME: MARKET_SUFFIX_NAME, JSCommonCoordinateData:JSCommonCoordinateData, FrameSplitKLineX:FrameSplitKLineX, FrameSplitKLinePriceY:FrameSplitKLinePriceY, JSCHART_EVENT_ID:JSCHART_EVENT_ID }, }; */