//日志输出类 var JSConsole= { Chart:{ Log:console.log, Warn:console.warn }, //图形日志 Complier:{ Log:console.log, Warn:console.warn}, //编译器日志 JSTable:{ Log:console.log, Warn:console.warn } //表格日志 }; /* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 系统指标 (H5版本) */ /* 指标数据脚本 系统内置指标都写在这里 Name:指标名字 Description:指标描述信息 Args:参数 { Name:名字, Value=值 } IsMainIndex:是否是主图指标 true=主图指标 false=副图指标 KLineType:K线设置 -1=主图不显示K线(只在主图有效) 0=在副图显示K线 1=在副图显示K线(收盘价线) 2=在副图显示K线(美国线) InstructionType: 1=专家指示 2=五彩K线 FloatPrecision: 小数位数 缺省=2 YSplitScale: Y固定刻度 [1,8,10] YSpecificMaxMin: 固定Y轴最大最小值 { Max: 9, Min: 0, Count: 3 }; StringFormat: 1=带单位万/亿 2=原始格式 Condition: 限制条件 { Symbol:'Index'/'Stock'(只支持指数/股票),Period:[](支持的周期), Include:[](指定支持的股票,代码全部大写包括后缀, Message:"提示信息")} OutName:动态输出变量名字 [{Name:原始变量名, DynamicName:动态名字格式}] 如 {Name:"MA1", DynamicName:"MA{M1}"}; SplitType: Y轴分割类型, YAxis:{ FloatPrecision:小数位数, StringFormat:, EnableRemoveZero, ExcludeValue:不参数Y轴的计算 } //Y轴刻度输出格式 */ //周期条件枚举 var CONDITION_PERIOD= { MINUTE_ID:101, //分钟 走势图 MULTIDAY_MINUTE_ID:102, //多日分钟 走势图 HISTORY_MINUTE_ID:103, //历史分钟 走势图 //K线周期 KLINE_DAY_ID:0, KLINE_WEEK_ID:1, KLINE_TWOWEEK_ID:21, KLINE_MONTH_ID:2, KLINE_QUARTER_ID:9, KLINE_YEAR_ID:3, KLINE_MINUTE_ID:4, KLINE_5_MINUTE_ID:5, KLINE_15_MINUTE_ID:6, KLINE_30_MINUTE_ID:7, KLINE_60_MINUTE_ID:8, }; //自定义的指标脚本 function CustomIndexScript() { this.DataMap=new Map(); //key=指标id, value=data {ID:, Name:指标名字, Description:指标描述信息 Args:参数 ......} this.Get=function(id) { if (!this.DataMap.has(id)) return null; return this.DataMap.get(id); } this.Add=function(data) { this.DataMap.set(data.ID, data); } } var g_CustomIndex=new CustomIndexScript(); function JSIndexScript() { this.DataMap=new Map( [ ['MA', this.MA],['均线', this.MA], ["MA4", this.MA4],["MA5", this.MA5],["MA6", this.MA6],["MA7", this.MA7],["MA8", this.MA8], ['BOLL', this.BOLL],['BOLL副图', this.BOLL2],['BBI', this.BBI], ['DKX', this.DKX],['MIKE', this.MIKE],['PBX', this.PBX], ['ENE', this.ENE],['MACD', this.MACD],['KDJ', this.KDJ],["MACD2", this.MACD2], ['VOL', this.VOL],['VOL2', this.VOL2],["VOL_OVERLAY", this.VOL_OVERLAY], ['RSI', this.RSI],['BRAR', this.BRAR], ['WR', this.WR],['BIAS', this.BIAS],['OBV', this.OBV], ['DMI', this.DMI],['CR', this.CR],['PSY', this.PSY], ['CCI', this.CCI],['DMA', this.DMA],['TRIX', this.TRIX], ['VR', this.VR],['EMV', this.EMV],['ROC', this.ROC], ['MTM', this.MTM],['FSL', this.FSL],['CYR', this.CYR], ['MASS', this.MASS],['WAD', this.WAD],['CHO', this.CHO], ['ADTM', this.ADTM],['HSL', this.HSL],['BIAS36', this.BIAS36], ['BIAS_QL', this.BIAS_QL],['DPO', this.DPO],['OSC', this.OSC], ['ATR', this.ATR],['NVI', this.NVI],['PVI', this.PVI], ['UOS', this.UOS],['CYW', this.CYW],['LON', this.LON], ['NDB', this.NDB],['SKDJ',this.SKDJ],['KD',this.KD],['FKX',this.FKX], ['DKCOL',this.DKCOL],['UDL',this.UDL],['MFI',this.MFI],['LWR',this.LWR], ['MARSI',this.MARSI],['CYD',this.CYD],['CYF',this.CYF],['TAPI',this.TAPI], ['VMACD',this.VMACD],['QACD',this.QACD],['VPT',this.VPT],['WVAD',this.WVAD], ['DBQR',this.DBQR],['JS',this.JS],['CYE',this.CYE],['QR',this.QR],['GDX',this.GDX], ['JLHB',this.JLHB],['PCNT',this.PCNT],['BTX', this.BTX],['AMO',this.AMO], ['VRSI',this.VRSI],['HSCOL',this.HSCOL],['DBQRV',this.DBQRV],['DBLB',this.DBLB], ['ACD',this.ACD],['EXPMA',this.EXPMA],['EXPMA_S',this.EXPMA_S],['HMA',this.HMA], ['LMA',this.LMA],['VMA',this.VMA],['AMV',this.AMV],['BBIBOLL',this.BBIBOLL], ['ALLIGAT',this.ALLIGAT],['ZX',this.ZX],['XS',this.XS],['XS2',this.XS2], ['SG-XDT',this.SG_XDT],['SG-SMX',this.SG_SMX],['SG-LB',this.SG_LB],['SG-PF',this.SG_PF], ['RAD',this.RAD],['SHT',this.SHT],['ZLJC',this.ZLJC],['ZLMM',this.ZLMM],['SLZT',this.SLZT], ['ADVOL',this.ADVOL],['CYC',this.CYC],['CYS',this.CYS],['CYQKL',this.CYQKL], ['SCR',this.SCR],['ASR',this.ASR],['SAR',this.SAR],['TJCJL',this.TJCJL],['量比',this.VOLRate], ['平均K线',this.HeikinAshi], ["ADL", this.ADL],["SQJZ", this.SQJZ],["XT", this.XT],["CFJT", this.CFJT],["CYX",this.CYX], ["WAVE",this.WAVE], ['VOL-TDX',this.VOL_TDX], ['EMPTY', this.EMPTY], //什么都不显示的指标 ['神奇九转', this.NineTurns], ['EMA', this.EMA3], ['EMA4', this.EMA4], ['EMA5', this.EMA5],['EMA6', this.EMA6], ["ICHIMOKU",this.ICHIMOKU],["CDP-STD", this.CDP_STD],["TBP-STD",this.TBP_STD], ["ADX", this.ADX], ["持仓量", this.VOL_POSITION], //成交量+持仓量 //通达信特色指标 ["散户线", this.ShareholderCount],["NXTS", this.NXTS],["FKX", this.FKX],["两融资金", this.Margin4], ["ZSDB",this.ZSDB], ['CJL2', this.CJL], //期货持仓量 ['ASI', this.ASI],['DC', this.DC],['DEMA', this.DEMA],["VWAP", this.VWAP], //指南针 ["ZNZ_CBAND", this.ZNZ_CBAND],["ZNZ_RPY2",this.ZNZ_RPY2],["ZNZ_RPY1", this.ZNZ_RPY1], ['飞龙四式', this.Dragon4_Main],['飞龙四式-附图', this.Dragon4_Fig], ['资金分析', this.FundsAnalysis],['融资占比',this.MarginProportion],['负面新闻', this.NewsNegative], ['涨跌趋势', this.UpDownAnalyze],['北上资金', this.HK2SHSZ],['股东人数', this.ShareHolder], ["两融余额", this.Margin2],["两融余额2", this.Margin3], //外包指标 ['放心股-操盘BS点',this.FXG_BSPoint], ['放心股-涨停多空线',this.FXG_INDEX], ['放心股-涨停吸筹区',this.FXG_INDEX2], ['放心股-量能黄金点',this.FXG_INDEX3], //五彩K线(函数COLOR_开头) ['五彩K线-十字星',this.COLOR_KSTAR1],['五彩K线-早晨之星',this.COLOR_KSTAR2],['五彩K线-黄昏之星',this.COLOR_KSTAR3],['五彩K线-长十字',this.COLOR_SHI1], ['五彩K线-身怀六甲',this.COLOR_K220],['五彩K线-三个白武士',this.COLOR_K300],['五彩K线-三只乌鸦',this.COLOR_K310],['五彩K线-光头阳线',this.COLOR_K380], ['五彩K线-光脚阴线',this.COLOR_K390],['五彩K线-垂死十字',this.COLOR_K134],['五彩K线-早晨十字星',this.COLOR_K140],['五彩K线-黄昏十字星',this.COLOR_K150], ['五彩K线-射击之星',this.COLOR_K160],['五彩K线-倒转锤头',this.COLOR_K165],['五彩K线-锤头',this.COLOR_K170],['五彩K线-吊颈',this.COLOR_K180], ['五彩K线-穿头破脚',this.COLOR_K190],['五彩K线-出水芙蓉',this.COLOR_CSFR],['五彩K线-乌云盖顶',this.COLOR_WYGD],['五彩K线-曙光初现',this.COLOR_SGCJ], ['五彩K线-十字胎',this.COLOR_SZTAI],['五彩K线-剑',this.COLOR_SWORD],['五彩K线-平顶',this.COLOR_PINGDING],['五彩K线-平底',this.COLOR_PINGDI], ['五彩K线-大阳烛',this.COLOR_DAYANZHU],['五彩K线-大阴烛',this.COLOR_DAYINGZHU], ['五彩K线-好友反攻',this.COLOR_HYFG],['五彩K线-跳空缺口',this.COLOR_TKQK], ['五彩K线-双飞乌鸦',this.COLOR_SFWY],['五彩K线-上升三部曲',this.COLOR_SSSBQ],['五彩K线-下跌三部曲',this.COLOR_XDSBQ],['五彩K线-长下影',this.COLOR_CHXY], ['五彩K线-长上影',this.COLOR_CHSY],['五彩K线-分离',this.COLOR_FENLI], //交易系统 ['交易系统-BIAS',this.TRADE_BIAS],['交易系统-CCI',this.TRADE_CCI],['交易系统-DMI',this.TRADE_DMI],['交易系统-KD',this.TRADE_KD], ['交易系统-BOLL',this.TRADE_BOLL],['交易系统-KDJ',this.TRADE_KDJ],['交易系统-MA',this.TRADE_MA],['交易系统-MACD',this.TRADE_MACD], ['交易系统-MTM',this.TRADE_MTM],['交易系统-PSY',this.TRADE_PSY],['交易系统-ROC',this.TRADE_ROC],['交易系统-RSI',this.TRADE_RSI], ['交易系统-VR',this.TRADE_VR],['交易系统-DPSJ',this.TRADE_DPSJ], ['TEST', this.TEST] //测试用 ]); } JSIndexScript.AddIndex=function(aryIndex) //添加自定义指标 { for(var i in aryIndex) { g_CustomIndex.Add(aryIndex[i]); } } //修改指标属性 JSIndexScript.ModifyAttribute=function(indexInfo, attribute) { if (!attribute) return; if (attribute.Args) indexInfo.Args=attribute.Args; //外部可以设置参数 if (IFrameSplitOperator.IsNumber(attribute.FloatPrecision)) indexInfo.FloatPrecision=attribute.FloatPrecision; if (IFrameSplitOperator.IsNumber(attribute.StringFormat)) indexInfo.StringFormat=attribute.StringFormat; if (IFrameSplitOperator.IsBool(attribute.IsSync)) indexInfo.IsSync=attribute.IsSync; if (IFrameSplitOperator.IsBool(attribute.IsShortTitle)) indexInfo.IsShortTitle=attribute.IsShortTitle; if (attribute.TitleFont) indexInfo.TitleFont=attribute.TitleFont; if (attribute.Lock) indexInfo.Lock=attribute.Lock; if (IFrameSplitOperator.IsNumber(attribute.YSplitType)) indexInfo.YSplitType=attribute.YSplitType; if (IFrameSplitOperator.IsBool(attribute.IsShowIndexTitle)) indexInfo.IsShowIndexTitle=attribute.IsShowIndexTitle; if (IFrameSplitOperator.IsNumber(attribute.KLineType)) indexInfo.KLineType=attribute.KLineType; if (attribute.YAxis) { var item=attribute.YAxis; if (!indexInfo.YAxis) indexInfo.YAxis={ }; if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) indexInfo.YAxis.FloatPrecision=item.FloatPrecision; if (IFrameSplitOperator.IsNumber(item.StringFormat)) indexInfo.YAxis.StringFormat=item.StringFormat; if (IFrameSplitOperator.IsBool(item.EnableRemoveZero)) indexInfo.YAxis.EnableRemoveZero=item.EnableRemoveZero; if (IFrameSplitOperator.IsBool(item.ExcludeValue)) indexInfo.YAxis.ExcludeValue=item.ExcludeValue; //不参数Y轴的计算 } } JSIndexScript.prototype.Get=function(id) { var data=g_CustomIndex.Get(id); if (data) return data; var func=this.DataMap.get(id); if (func) { var data= func(); data.ID=id; return data; } return null; } JSIndexScript.prototype.Search=function(name) { var result=[]; var reg = new RegExp(name,'i'); this.DataMap.forEach(function(value,key) { if (key.indexOf('交易系统-')!=0 && key.indexOf('五彩K线-')!=0 && key.search(reg)>=0) result.push(key); }); return result; } JSIndexScript.prototype.MA=function() { let data= { Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2, Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" }], Script: //脚本 'MA1:MA(CLOSE,M1);\n\ MA2:MA(CLOSE,M2);\n\ MA3:MA(CLOSE,M3);' }; return data; } JSIndexScript.prototype.MA4=function() { let data= { Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2, Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20},{ Name:'M4', Value:60} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" } ], Script: //脚本 'MA1:MA(CLOSE,M1);\n\ MA2:MA(CLOSE,M2);\n\ MA3:MA(CLOSE,M3);\n\ MA4:MA(CLOSE,M4);' }; return data; } JSIndexScript.prototype.MA5=function() { let data= { Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2, Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} ,{ Name:'M4', Value:60} ,{ Name:'M5', Value:0}], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" },{Name:'MA5',DynamicName:"MA{M5}" } ], Script: //脚本 'MA1:MA(CLOSE,M1);\n\ MA2:MA(CLOSE,M2);\n\ MA3:MA(CLOSE,M3);\n\ MA4:MA(CLOSE,M4);\n\ MA5:MA(CLOSE,M5);' }; return data; } JSIndexScript.prototype.MA6=function() { let data= { Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} , { Name:'M4', Value:60} , { Name:'M5', Value:0},{ Name:'M6', Value:0} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" }, {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ], Script: //脚本 'MA1:MA(CLOSE,M1);\n\ MA2:MA(CLOSE,M2);\n\ MA3:MA(CLOSE,M3);\n\ MA4:MA(CLOSE,M4);\n\ MA5:MA(CLOSE,M5);\n\ MA6:MA(CLOSE,M6);' }; return data; } JSIndexScript.prototype.MA7=function() { let data= { Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20}, { Name:'M4', Value:60}, { Name:'M5', Value:0},{ Name:'M6', Value:0} ,{ Name:'M7', Value:0 } ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" }, {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ,{ Name:'MA7',DynamicName:"MA{M7}" }], Script: //脚本 'MA1:MA(CLOSE,M1);\n\ MA2:MA(CLOSE,M2);\n\ MA3:MA(CLOSE,M3);\n\ MA4:MA(CLOSE,M4);\n\ MA5:MA(CLOSE,M5);\n\ MA6:MA(CLOSE,M6);\n\ MA7:MA(CLOSE,M7);' }; return data; } JSIndexScript.prototype.MA8=function() { let data= { Name:'MA', Description:'均线', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20}, { Name:'M4', Value:60}, { Name:'M5', Value:0},{ Name:'M6', Value:0} ,{ Name:'M7', Value:0 } ,{ Name:'M8', Value:0 } ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" }, {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ,{ Name:'MA7',DynamicName:"MA{M7}" },{ Name:'MA8',DynamicName:"MA{M8}" }], Script: //脚本 'MA1:MA(CLOSE,M1);\n\ MA2:MA(CLOSE,M2);\n\ MA3:MA(CLOSE,M3);\n\ MA4:MA(CLOSE,M4);\n\ MA5:MA(CLOSE,M5);\n\ MA6:MA(CLOSE,M6);\n\ MA7:MA(CLOSE,M7);\n\ MA8:MA(CLOSE,M8);' }; return data; } JSIndexScript.prototype.EMA3=function() { let data= { Name:'EMA', Description:'指数移动平均值', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" } ], Script: //脚本 'MA1:EMA(CLOSE,M1);\n\ MA2:EMA(CLOSE,M2);\n\ MA3:EMA(CLOSE,M3);' }; return data; } JSIndexScript.prototype.EMA4=function() { let data= { Name:'EMA', Description:'指数移动平均值', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} , { Name:'M4', Value:60} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" } ], Script: //脚本 'MA1:EMA(CLOSE,M1);\n\ MA2:EMA(CLOSE,M2);\n\ MA3:EMA(CLOSE,M3);\n\ MA4:EMA(CLOSE,M4);' }; return data; } JSIndexScript.prototype.EMA5=function() { let data= { Name:'EMA', Description:'指数移动平均值', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} , { Name:'M4', Value:60} , { Name:'M5', Value:0} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" }, {Name:'MA5',DynamicName:"MA{M5}" } ], Script: //脚本 'MA1:EMA(CLOSE,M1);\n\ MA2:EMA(CLOSE,M2);\n\ MA3:EMA(CLOSE,M3);\n\ MA4:EMA(CLOSE,M4);\n\ MA5:EMA(CLOSE,M5);' }; return data; } JSIndexScript.prototype.EMA6=function() { let data= { Name:'EMA', Description:'指数移动平均值', IsMainIndex:true, StringFormat:2, Args: [ { Name:'M1', Value:5}, { Name:'M2', Value:10 }, { Name:'M3', Value:20} , { Name:'M4', Value:60} , { Name:'M5', Value:0},{ Name:'M6', Value:0} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" },{Name:'MA3',DynamicName:"MA{M3}" },{Name:'MA4',DynamicName:"MA{M4}" }, {Name:'MA5',DynamicName:"MA{M5}" } ,{ Name:'MA6',DynamicName:"MA{M6}" } ], Script: //脚本 'MA1:EMA(CLOSE,M1);\n\ MA2:EMA(CLOSE,M2);\n\ MA3:EMA(CLOSE,M3);\n\ MA4:EMA(CLOSE,M4);\n\ MA5:EMA(CLOSE,M5);\n\ MA6:EMA(CLOSE,M6);' }; return data; } JSIndexScript.prototype.BOLL=function() { let data= { Name:'BOLL', Description:'布林线', IsMainIndex:true, Args:[ { Name:'M', Value:20} ], Script: //脚本 'BOLL:MA(CLOSE,M);\n\ UB:BOLL+2*STD(CLOSE,M);\n\ LB:BOLL-2*STD(CLOSE,M);' }; return data; } JSIndexScript.prototype.BOLL2=function() { let data= { Name:'BOLL2', Description:'布林线', IsMainIndex:false, KLineType:0, Args:[ { Name:'M', Value:20} ], Script: //脚本 'BOLL:MA(CLOSE,M);\n\ UB:BOLL+2*STD(CLOSE,M);\n\ LB:BOLL-2*STD(CLOSE,M);' }; return data; } JSIndexScript.prototype.BBI=function() { let data= { Name:'BBI', Description:'多空均线', IsMainIndex:true, Args:[ { Name:'M1', Value:3}, { Name:'M2', Value:6}, { Name:'M3', Value:12}, { Name:'M4', Value:24} ], Script: //脚本 'BBI:(MA(CLOSE,M1)+MA(CLOSE,M2)+MA(CLOSE,M3)+MA(CLOSE,M4))/4;' }; return data; } JSIndexScript.prototype.DKX=function() { let data= { Name:'DKX', Description:'多空线', IsMainIndex:false, Args:[ { Name:'M', Value:10} ], Script: //脚本 'MID:=(3*CLOSE+LOW+OPEN+HIGH)/6;\n\ DKX:(20*MID+19*REF(MID,1)+18*REF(MID,2)+17*REF(MID,3)+\n\ 16*REF(MID,4)+15*REF(MID,5)+14*REF(MID,6)+\n\ 13*REF(MID,7)+12*REF(MID,8)+11*REF(MID,9)+\n\ 10*REF(MID,10)+9*REF(MID,11)+8*REF(MID,12)+\n\ 7*REF(MID,13)+6*REF(MID,14)+5*REF(MID,15)+\n\ 4*REF(MID,16)+3*REF(MID,17)+2*REF(MID,18)+REF(MID,20))/210;\n\ MADKX:MA(DKX,M);' }; return data; } JSIndexScript.prototype.MIKE=function() { let data= { Name:'MIKE', Description:'麦克支撑压力', IsMainIndex:true, Args:[ { Name:'N', Value:10} ], Script: //脚本 'HLC:=REF(MA((HIGH+LOW+CLOSE)/3,N),1);\n\ HV:=EMA(HHV(HIGH,N),3);\n\ LV:=EMA(LLV(LOW,N),3);\n\ STOR:EMA(2*HV-LV,3);\n\ MIDR:EMA(HLC+HV-LV,3);\n\ WEKR:EMA(HLC*2-LV,3);\n\ WEKS:EMA(HLC*2-HV,3);\n\ MIDS:EMA(HLC-HV+LV,3);\n\ STOS:EMA(2*LV-HV,3);' }; return data; } JSIndexScript.prototype.PBX=function() { let data= { Name:'PBX', Description:'瀑布线', IsMainIndex:true, Args:[ { Name:'M1', Value:4}, { Name:'M2', Value:6}, { Name:'M3', Value:9}, { Name:'M4', Value:13},{ Name:'M5', Value:18},{ Name:'M6', Value:24} ], Script: //脚本 'PBX1:(EMA(CLOSE,M1)+MA(CLOSE,M1*2)+MA(CLOSE,M1*4))/3;\n\ PBX2:(EMA(CLOSE,M2)+MA(CLOSE,M2*2)+MA(CLOSE,M2*4))/3;\n\ PBX3:(EMA(CLOSE,M3)+MA(CLOSE,M3*2)+MA(CLOSE,M3*4))/3;\n\ PBX4:(EMA(CLOSE,M4)+MA(CLOSE,M4*2)+MA(CLOSE,M4*4))/3;\n\ PBX5:(EMA(CLOSE,M5)+MA(CLOSE,M5*2)+MA(CLOSE,M5*4))/3;\n\ PBX6:(EMA(CLOSE,M6)+MA(CLOSE,M6*2)+MA(CLOSE,M6*4))/3;' }; return data; } JSIndexScript.prototype.ENE=function() { let data= { Name:'ENE', Description:'轨道线', IsMainIndex:true, Args:[ { Name:'N', Value:25}, { Name:'M1', Value:6}, { Name:'M2', Value:6} ], Script: //脚本 'UPPER:(1+M1/100)*MA(CLOSE,N);\n\ LOWER:(1-M2/100)*MA(CLOSE,N);\n\ ENE:(UPPER+LOWER)/2;' }; return data; } JSIndexScript.prototype.MACD=function() { let data= { Name:'MACD', Description:'平滑异同平均', IsMainIndex:false, Args:[ { Name:'SHORT', Value:12}, { Name:'LONG', Value:26}, { Name:'MID', Value:9} ], Script: //脚本 'DIF:EMA(CLOSE,SHORT)-EMA(CLOSE,LONG);\n\ DEA:EMA(DIF,MID);\n\ MACD:(DIF-DEA)*2,COLORSTICK;' }; return data; } //上下柱子 JSIndexScript.prototype.MACD2=function() { let data= { Name:'MACD', Description:'平滑异同平均', IsMainIndex:false, Args:[ { Name:'SHORT', Value:12}, { Name:'LONG', Value:26}, { Name:'MID', Value:9} ], Script: //脚本 'DIF2:=EMA(CLOSE,SHORT)-EMA(CLOSE,LONG);\n\ DEA2:=EMA(DIF2,MID);\n\ MACD:(DIF2-DEA2)*2,COLORSTICK,LINETHICK50;\n\ DIF:DIF2;\n\ DEA:DEA2;' }; return data; } JSIndexScript.prototype.KDJ=function() { let data= { Name:'KDJ', Description:'随机指标', IsMainIndex:false, Args:[ { Name:'N', Value:9}, { Name:'M1', Value:3}, { Name:'M2', Value:3} ], Script: //脚本 'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\ K:SMA(RSV,M1,1);\n\ D:SMA(K,M2,1);\n\ J:3*K-2*D;' }; return data; } JSIndexScript.prototype.VOL=function() { let data= { Name:'VOL', Description:'成交量', IsMainIndex:false,FloatPrecision:0, Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" }], Script: //脚本 'VOL:VOL,VOLSTICK;\n\ MA1:MA(VOL,M1);\n\ MA2:MA(VOL,M2);' }; return data; } JSIndexScript.prototype.VOL2=function() { let data= { Name:'VOL', Description:'成交量', IsMainIndex:false,FloatPrecision:0, Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10} ], OutName:[ {Name:'MA1',DynamicName:"MA{M1}" }, {Name:'MA2',DynamicName:"MA{M2}" }], Script: //脚本 'VOL:VOL,VOLSTICK,STICKTYPE(1);\n\ MA1:MA(VOL,M1);\n\ MA2:MA(VOL,M2);' }; return data; } JSIndexScript.prototype.VOL_OVERLAY=function() { let data= { Name:'VOL', Description:'成交量', IsMainIndex:false,FloatPrecision:0, Script: //脚本 'VOL:VOL,VOLSTICK,UPCOLOR(RGBA(255,0,0,0.3)),DOWNCOLOR(RGBA(0,255,0,0.3));' }; return data; } JSIndexScript.prototype.VOL_TDX=function() { let data= { Name:'VOL-TDX', Description:'成交量(虚拟)', IsMainIndex:false,FloatPrecision:0, Args:[ { Name:'M1', Value:5}, { Name:'M2', Value:10} ], Script: //脚本 'TOTAL:=IF(PERIOD=1,5,IF(PERIOD=2,15,IF(PERIOD=3,30,IF(PERIOD=4,60,IF(PERIOD=5,TOTALFZNUM,1)))));\n\ MTIME:=MOD(FROMOPEN,TOTAL);\n\ CTIME:=IF(MTIME<0.5,TOTAL,MTIME);\n\ VVOL:IF((CURRBARSCOUNT=1 AND DYNAINFO(8)>1),VOL*(TOTAL+3)/(CTIME+3),DRAWNULL),NODRAW;\n\ STICKLINE((CURRBARSCOUNT=1 AND DYNAINFO(8)>1),VVOL,0,-1,-1),COLORYELLOW;\n\ VOLUME:VOL,VOLSTICK;\n\ MAVOL1:MA(VOLUME,M1);\n\ MAVOL2:MA(VOLUME,M2);' }; return data; } JSIndexScript.prototype.RSI=function() { let data= { Name:'RSI', Description:'相对强弱指标', IsMainIndex:false, Args:[ { Name:'N1', Value:6}, { Name:'N2', Value:12}, { Name:'N3', Value:24} ], Script: //脚本 'LC:=REF(CLOSE,1);\n\ RSI1:SMA(MAX(CLOSE-LC,0),N1,1)/SMA(ABS(CLOSE-LC),N1,1)*100;\n\ RSI2:SMA(MAX(CLOSE-LC,0),N2,1)/SMA(ABS(CLOSE-LC),N2,1)*100;\n\ RSI3:SMA(MAX(CLOSE-LC,0),N3,1)/SMA(ABS(CLOSE-LC),N3,1)*100;' }; return data; } JSIndexScript.prototype.BRAR=function() { let data= { Name:'BRAR', Description:'情绪指标', IsMainIndex:false, Args:[ { Name:'N', Value:26} ], Script: //脚本 'BR:SUM(MAX(0,HIGH-REF(CLOSE,1)),N)/SUM(MAX(0,REF(CLOSE,1)-LOW),N)*100;\n\ AR:SUM(HIGH-OPEN,N)/SUM(OPEN-LOW,N)*100;' }; return data; } JSIndexScript.prototype.WR=function() { let data= { Name:'WR', Description:'威廉指标', IsMainIndex:false, Args:[ { Name:'N', Value:10}, { Name:'N1', Value:6} ], Script: //脚本 'WR1:100*(HHV(HIGH,N)-CLOSE)/(HHV(HIGH,N)-LLV(LOW,N));\n\ WR2:100*(HHV(HIGH,N1)-CLOSE)/(HHV(HIGH,N1)-LLV(LOW,N1));' }; return data; } JSIndexScript.prototype.BIAS=function() { let data= { Name:'BIAS', Description:'乖离率', IsMainIndex:false, Args:[ { Name:'N1', Value:6}, { Name:'N2', Value:12}, { Name:'N3', Value:24} ], Script: //脚本 'BIAS1 :(CLOSE-MA(CLOSE,N1))/MA(CLOSE,N1)*100;\n\ BIAS2 :(CLOSE-MA(CLOSE,N2))/MA(CLOSE,N2)*100;\n\ BIAS3 :(CLOSE-MA(CLOSE,N3))/MA(CLOSE,N3)*100;' }; return data; } JSIndexScript.prototype.OBV=function() { let data= { Name:'OBV', Description:'累积能量线', IsMainIndex:false, Args:[ { Name:'M', Value:30} ], Script: //脚本 'VA:=IF(CLOSE>REF(CLOSE,1),VOL,-VOL);\n\ OBV:SUM(IF(CLOSE==REF(CLOSE,1),0,VA),0);\n\ MAOBV:MA(OBV,M);' }; return data; } JSIndexScript.prototype.DMI=function() { let data= { Name:'DMI', Description:'趋向指标', IsMainIndex:false, Args:[ { Name:'N', Value:14}, { Name:'MM', Value:6} ], Script: //脚本 'MTR:=EXPMEMA(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(REF(CLOSE,1)-LOW)),N);\n\ HD :=HIGH-REF(HIGH,1);\n\ LD :=REF(LOW,1)-LOW;\n\ DMP:=EXPMEMA(IF(HD>0&&HD>LD,HD,0),N);\n\ DMM:=EXPMEMA(IF(LD>0&&LD>HD,LD,0),N);\n\ PDI: DMP*100/MTR;\n\ MDI: DMM*100/MTR;\n\ ADX: EXPMEMA(ABS(MDI-PDI)/(MDI+PDI)*100,MM);\n\ ADXR:EXPMEMA(ADX,MM);' }; return data; } JSIndexScript.prototype.CR=function() { let data= { Name:'CR', Description:'带状能量线', IsMainIndex:false, Args:[ { Name:'N', Value:26}, { Name:'M1', Value:10},{ Name:'M2', Value:20},{ Name:'M3', Value:40},{ Name:'M4', Value:62} ], Script: //脚本 'MID:=REF(HIGH+LOW,1)/2;\n\ CR:SUM(MAX(0,HIGH-MID),N)/SUM(MAX(0,MID-LOW),N)*100;\n\ MA1:REF(MA(CR,M1),M1/2.5+1);\n\ MA2:REF(MA(CR,M2),M2/2.5+1);\n\ MA3:REF(MA(CR,M3),M3/2.5+1);\n\ MA4:REF(MA(CR,M4),M4/2.5+1);' }; return data; } JSIndexScript.prototype.PSY=function() { let data= { Name:'PSY', Description:'心理线', IsMainIndex:false, Args:[ { Name:'N', Value:12}, { Name:'M', Value:6} ], Script: //脚本 'PSY:COUNT(CLOSE>REF(CLOSE,1),N)/N*100;\r\ PSYMA:MA(PSY,M);' }; return data; } JSIndexScript.prototype.CCI=function() { let data= { Name:'CCI', Description:'商品路径指标', IsMainIndex:false, Args:[ { Name:'N', Value:14} ], Script: //脚本 'TYP:=(HIGH+LOW+CLOSE)/3;\n\ CCI:(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));' }; return data; } JSIndexScript.prototype.DMA=function() { let data= { Name:'DMA', Description:'平均差', IsMainIndex:false, Args:[ { Name:'N1', Value:10},{ Name:'N2', Value:50},{ Name:'M', Value:10} ], Script: //脚本 'DIF:MA(CLOSE,N1)-MA(CLOSE,N2);\n\ DIFMA:MA(DIF,M);' }; return data; } JSIndexScript.prototype.TRIX=function() { let data= { Name:'TRIX', Description:'三重指数平均线', IsMainIndex:false, Args:[ { Name:'N', Value:12},{ Name:'M', Value:9} ], Script: //脚本 'MTR:=EMA(EMA(EMA(CLOSE,N),N),N);\n\ TRIX:(MTR-REF(MTR,1))/REF(MTR,1)*100;\n\ MATRIX:MA(TRIX,M) ;' }; return data; } JSIndexScript.prototype.VR=function() { let data= { Name:'VR', Description:'成交量变异率', IsMainIndex:false, Args:[ { Name:'N', Value:26},{ Name:'M', Value:6} ], Script: //脚本 'TH:=SUM(IF(CLOSE>REF(CLOSE,1),VOL,0),N);\n\ TL:=SUM(IF(CLOSEREF(CLOSE,1),MIDA,MIDB),0);\n\ MAWAD:MA(WAD,M);' }; return data; } JSIndexScript.prototype.CHO=function() { let data= { Name:'CHO', Description:'佳庆指标', IsMainIndex:false, Args:[ { Name:'N1', Value:10}, { Name:'N2', Value:20}, { Name:'M', Value:6}], Script: //脚本 'MID:=SUM(VOL*(2*CLOSE-HIGH-LOW)/(HIGH+LOW),0);\n\ CHO:MA(MID,N1)-MA(MID,N2);\n\ MACHO:MA(CHO,M);' }; return data; } JSIndexScript.prototype.ADTM=function() { let data= { Name:'ADTM', Description:'动态买卖气指标', IsMainIndex:false, Args:[ { Name:'N', Value:23}, { Name:'M', Value:8}], Script: //脚本 'DTM:=IF(OPEN<=REF(OPEN,1),0,MAX((HIGH-OPEN),(OPEN-REF(OPEN,1))));\n\ DBM:=IF(OPEN>=REF(OPEN,1),0,MAX((OPEN-LOW),(OPEN-REF(OPEN,1))));\n\ STM:=SUM(DTM,N);\n\ SBM:=SUM(DBM,N);\n\ ADTM:IF(STM>SBM,(STM-SBM)/STM,IF(STM==SBM,0,(STM-SBM)/SBM));\n\ MAADTM:MA(ADTM,M);' }; return data; } JSIndexScript.prototype.HSL=function() { let data= { Name:'HSL', Description:'换手线', IsMainIndex:false, Args:[ { Name:'N', Value:5} ], Script: //脚本 'HSL:IF((SETCODE==0||SETCODE==1),100*VOL,VOL)/(FINANCE(7)/100);\n\ MAHSL:MA(HSL,N);' }; return data; } JSIndexScript.prototype.BIAS36=function() { let data= { Name:'BIAS36', Description:'三六乖离', IsMainIndex:false, Args:[ { Name:'M', Value:6} ], Script: //脚本 'BIAS36:MA(CLOSE,3)-MA(CLOSE,6);\n\ BIAS612:MA(CLOSE,6)-MA(CLOSE,12);\n\ MABIAS:MA(BIAS36,M);' }; return data; } JSIndexScript.prototype.BIAS_QL=function() { let data= { Name:'BIAS_QL', Description:'乖离率-传统版', IsMainIndex:false, Args:[ { Name:'N', Value:6}, { Name:'M', Value:6} ], Script: //脚本 'BIAS :(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100;\n\ BIASMA :MA(BIAS,M);' }; return data; } JSIndexScript.prototype.DPO=function() { let data= { Name:'DPO', Description:'区间震荡线', IsMainIndex:false, Args:[ { Name:'N', Value:20}, { Name:'M', Value:6} ], Script: //脚本 'DPO:CLOSE-REF(MA(CLOSE,N),N/2+1);\n\ MADPO:MA(DPO,M);' }; return data; } JSIndexScript.prototype.OSC=function() { let data= { Name:'OSC', Description:'变动速率线', IsMainIndex:false, Args:[ { Name:'N', Value:20}, { Name:'M', Value:6} ], Script: //脚本 'OSC:100*(CLOSE-MA(CLOSE,N));\n\ MAOSC:EXPMEMA(OSC,M);' }; return data; } JSIndexScript.prototype.ATR=function() { let data= { Name:'ATR', Description:'真实波幅', IsMainIndex:false, Args:[ { Name:'N', Value:14}], Script: //脚本 'MTR:MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));\n\ ATR:MA(MTR,N);' }; return data; } JSIndexScript.prototype.NVI=function() { let data= { Name:'ATR', Description:'负成交量', IsMainIndex:false, Args:[ { Name:'N', Value:72} ], Script: //脚本 'NVI:100*MULAR(IF(VREF(V,1),C/REF(C,1),1),0);\n\ MANVI:MA(NVI,N);' }; return data; } JSIndexScript.prototype.UOS=function() { let data= { Name:'UOS', Description:'终极指标', IsMainIndex:false, Args:[ { Name:'N1', Value:7} ,{ Name:'N2', Value:14},{ Name:'N3', Value:28},{ Name:'M', Value:6}], Script: //脚本 'TH:=MAX(HIGH,REF(CLOSE,1));\n\ TL:=MIN(LOW,REF(CLOSE,1));\n\ ACC1:=SUM(CLOSE-TL,N1)/SUM(TH-TL,N1);\n\ ACC2:=SUM(CLOSE-TL,N2)/SUM(TH-TL,N2);\n\ ACC3:=SUM(CLOSE-TL,N3)/SUM(TH-TL,N3);\n\ UOS:(ACC1*N2*N3+ACC2*N1*N3+ACC3*N1*N2)*100/(N1*N2+N1*N3+N2*N3);\n\ MAUOS:EXPMEMA(UOS,M);' }; return data; } JSIndexScript.prototype.CYW=function() { let data= { Name:'CYW', Description:'主力控盘', IsMainIndex:false, Args:[ ], Script: //脚本 'VAR1:=CLOSE-LOW;\n\ VAR2:=HIGH-LOW;\n\ VAR3:=CLOSE-HIGH;\n\ VAR4:=IF(HIGH>LOW,(VAR1/VAR2+VAR3/VAR2)*VOL,0);\n\ CYW: SUM(VAR4,10)/10000, COLORSTICK;' }; return data; } JSIndexScript.prototype.LON=function() { let data= { Name:'LON', Description:'龙系长线', IsMainIndex:false, Args:[ { Name:'N', Value:10} ], Script: //脚本 'LC := REF(CLOSE,1);\n\ VID := SUM(VOL,2)/(((HHV(HIGH,2)-LLV(LOW,2)))*100);\n\ RC := (CLOSE-LC)*VID;\n\ LONG := SUM(RC,0);\n\ DIFF := SMA(LONG,10,1);\n\ DEA := SMA(LONG,20,1);\n\ LON : DIFF-DEA;\n\ LONMA : MA(LON,10);\n\ LONT : LON, COLORSTICK;' }; return data; } JSIndexScript.prototype.NDB = function () { let data = { Name: 'NDB', Description: '脑电波', IsMainIndex: false, Args: [{ Name: 'P1', Value: 5 }, { Name: 'P2', Value: 10 }], Script: //脚本 'HH:=IF(C/REF(C,1)>1.098 AND L>REF(H,1),2*C-REF(C,1)-H,2*C-H-L);\n\ V1:= BARSCOUNT(C) - 1;\n\ V2:= 2 * REF(C, V1) - REF(H, V1) - REF(L, V1);\n\ DK: SUM(HH, 0) + V2;\n\ MDK5: MA(DK, P1);\n\ MDK10: MA(DK, P2);' }; return data; } JSIndexScript.prototype.SKDJ = function () { let data = { Name: 'SKDJ', Description: '慢速随机指标', IsMainIndex: false, Args: [{ Name: 'N', Value: 9 }, { Name: 'M', Value: 3 }], Script: //脚本 'LOWV:=LLV(LOW,N);\n\ HIGHV:=HHV(HIGH,N);\n\ RSV:=EMA((CLOSE-LOWV)/(HIGHV-LOWV)*100,M);\n\ K:EMA(RSV,M);\n\ D:MA(K,M);' }; return data; } JSIndexScript.prototype.KD = function () { let data = { Name: 'KD', Description: '随机指标KD', IsMainIndex: false, Args: [{ Name: 'N', Value: 9 }, { Name: 'M1', Value: 3 },{ Name: 'M2', Value: 3 }], Script: //脚本 'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\ K:SMA(RSV,M1,1);\n\ D:SMA(K,M2,1);' }; return data; } JSIndexScript.prototype.FKX=function() { let data= { Name:'FKX', Description:'反K线', IsMainIndex:true, Args:[ ], Script: //脚本 'DRAWKLINE(-LOW, -OPEN, -HIGH, -CLOSE);' }; return data; } JSIndexScript.prototype.DKCOL = function () { let data = { Name: 'DKCOL', Description: '多空能量柱(适用于分时主图)', IsMainIndex: true, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 'FF:=(C-REF(C,N))/REF(C,N);\n\ STICKLINE(FF>0,DYNAINFO(3),DYNAINFO(3)*(1+FF),0.5,0),COLORRED;\n\ STICKLINE(FF<0,DYNAINFO(3),DYNAINFO(3)*(1+FF),0.5,0),COLORGREEN;' }; return data; } JSIndexScript.prototype.UDL = function () { let data = { Name: 'UDL', Description: '引力线', IsMainIndex: false, Args: [{ Name: 'N1', Value: 3 },{ Name: 'N2', Value: 5 },{ Name: 'N3', Value: 10 },{ Name: 'N4', Value: 20 },{ Name: 'M', Value: 6 }], Script: //脚本 'UDL:(MA(CLOSE,N1)+MA(CLOSE,N2)+MA(CLOSE,N3)+MA(CLOSE,N4))/4;\n\ MAUDL:MA(UDL,M);' }; return data; } JSIndexScript.prototype.MFI = function () { let data = { Name: 'MFI', Description: '资金流量指标', IsMainIndex: false, Args: [{ Name: 'N', Value: 14 },{ Name: 'N2', Value: 6 }], Script: //脚本 'TYP := (HIGH + LOW + CLOSE)/3;\n\ V1:=SUM(IF(TYP>REF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYP=0,DIF,0);\n\ VD:=IF(DIF<0,-DIF,0);\n\ MAU1:=MEMA(VU,M1);\n\ MAD1:=MEMA(VD,M1);\n\ MAU2:=MEMA(VU,M2);\n\ MAD2:=MEMA(VD,M2);\n\ RSI10:MA(100*MAU1/(MAU1+MAD1),M1);\n\ RSI6:MA(100*MAU2/(MAU2+MAD2),M2);' }; return data; } JSIndexScript.prototype.CYD = function () { let data = { Name: 'CYD', Description: '承接因子', IsMainIndex: false, Args: [{ Name: 'N', Value: 21 }], Script: //脚本 'CYDS:WINNER(CLOSE)/(VOL/CAPITAL);\n\ CYDN:WINNER(CLOSE)/MA(VOL/CAPITAL,N);' }; return data; } JSIndexScript.prototype.CYF = function () { let data = { Name: 'CYF', Description: '市场能量', IsMainIndex: false, Args: [{ Name: 'N', Value: 21 }], Script: //脚本 'CYF:100-100/(1+EMA(HSL,N));' }; return data; } JSIndexScript.prototype.TAPI = function () { let data = { Name: 'TAPI', Description: '加权指数成交值', IsMainIndex: false, Args: [{ Name: 'M', Value: 6 }], Script: //脚本 'TAPI:AMOUNT/INDEXC;\n\ MATAIP:MA(TAPI,M);' }; return data; } JSIndexScript.prototype.VMACD = function () { let data = { Name: 'VMACD', Description: '量平滑异同平均', IsMainIndex: false, Args: [{ Name: 'SHORT', Value: 12 },{ Name: 'LONG', Value: 26 },{ Name: 'MID', Value: 9 }], Script: //脚本 'DIF:EMA(VOL,SHORT)-EMA(VOL,LONG);\n\ DEA:EMA(DIF,MID);\n\ MACD:DIF-DEA,COLORSTICK;' }; return data; } JSIndexScript.prototype.QACD = function () { let data = { Name: 'QACD', Description: '快速异同平均', IsMainIndex: false, Args: [{ Name: 'N1', Value: 12 },{ Name: 'N2', Value: 26 },{ Name: 'M', Value: 9 }], Script: //脚本 'DIF:EMA(CLOSE,N1)-EMA(CLOSE,N2);\n\ MACD:EMA(DIF,M);\n\ DDIF:DIF-MACD;' }; return data; } JSIndexScript.prototype.VPT = function () { let data = { Name: 'VPT', Description: '量价曲线', IsMainIndex: false, Args: [{ Name: 'N', Value: 51 },{ Name: 'M', Value: 6 }], Script: //脚本 'VPT:SUM(VOL*(CLOSE-REF(CLOSE,1))/REF(CLOSE,1),N);\n\ MAVPT:MA(VPT,M);' }; return data; } JSIndexScript.prototype.WVAD = function () { let data = { Name: 'WVAD', Description: '威廉变异离散量', IsMainIndex: false, Args: [{ Name: 'N', Value: 24 },{ Name: 'M', Value: 6 }], Script: //脚本 'WVAD:SUM((CLOSE-OPEN)/(HIGH-LOW)*VOL,N)/10000;\n\ MAWVAD:MA(WVAD,M);' }; return data; } JSIndexScript.prototype.DBQR = function () { let data = { Name: 'WVAD', Description: '对比强弱', IsMainIndex: false, Args: [{ Name: 'N', Value: 5 },{ Name: 'M1', Value: 10 },{ Name: 'M2', Value: 20 },{ Name: 'M3', Value: 60 }], Script: //脚本 'ZS:(INDEXC-REF(INDEXC,N))/REF(INDEXC,N);\n\ GG:(CLOSE-REF(CLOSE,N))/REF(CLOSE,N);\n\ MADBQR1:MA(GG,M1);\n\ MADBQR2:MA(GG,M2);\n\ MADBQR3:MA(GG,M3);' }; return data; } JSIndexScript.prototype.JS = function () { let data = { Name: 'JS', Description: '加速线', IsMainIndex: false, Args: [{ Name: 'N', Value: 5 },{ Name: 'M1', Value: 5 },{ Name: 'M2', Value: 10 },{ Name: 'M3', Value: 20 }], Script: //脚本 'JS:100*(CLOSE-REF(CLOSE,N))/(N*REF(CLOSE,N));\n\ MAJS1:MA(JS,M1);\n\ MAJS2:MA(JS,M2);\n\ MAJS3:MA(JS,M3);' }; return data; } JSIndexScript.prototype.CYE = function () { let data = { Name: 'CYE', Description: '市场趋势', IsMainIndex: false, Args: [ ], Script: //脚本 'MAL:=MA(CLOSE,5);\n\ MAS:=MA(MA(CLOSE,20),5);\n\ CYEL:(MAL-REF(MAL,1))/REF(MAL,1)*100;\n\ CYES:(MAS-REF(MAS,1))/REF(MAS,1)*100;' }; return data; } JSIndexScript.prototype.QR = function () { let data = { Name: 'QR', Description: '强弱指标', IsMainIndex: false, Args: [{ Name: 'N', Value: 21 } ], Script: //脚本 '个股: (CLOSE-REF(CLOSE,N))/REF(CLOSE,N)*100; \n\ 大盘: (INDEXC-REF(INDEXC,N))/REF(INDEXC,N)*100; \n\ 强弱值:EMA(个股-大盘,2),COLORSTICK;' }; return data; } JSIndexScript.prototype.GDX = function () { let data = { Name: 'GDX', Description: '轨道线', IsMainIndex: false, Args: [{ Name: 'N', Value: 30 } ,{ Name: 'M', Value: 9 }], Script: //脚本 'AA:=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,N))/MA(CLOSE,N); \n\ 轨道:DMA(CLOSE,AA);\n\ 压力线:(1+M/100)*轨道; \n\ 支撑线:(1-M/100)*轨道;' }; return data; } JSIndexScript.prototype.JLHB = function () { let data = { Name: 'JLHB', Description: '绝路航标', IsMainIndex: false, Args: [{ Name: 'N', Value: 7 } ,{ Name: 'M', Value: 5 }], Script: //脚本 'VAR1:=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*80; \n\ B:SMA(VAR1,N,1); \n\ VAR2:SMA(B,M,1); \n\ 绝路航标:IF(CROSS(B,VAR2) AND B<40,50,0);' }; return data; } JSIndexScript.prototype.PCNT = function () { let data = { Name: 'PCNT', Description: '幅度比', IsMainIndex: false, Args: [{ Name: 'M', Value: 5 }], Script: //脚本 'PCNT:(CLOSE-REF(CLOSE,1))/CLOSE*100;\n\ MAPCNT:EXPMEMA(PCNT,M);' }; return data; } JSIndexScript.prototype.BTX = function () { let data = { Name: 'BTX', Description: '宝塔线', IsMainIndex: false, Args: [], Script: //脚本 'B1:=REF(C,1);\n\ B2:= REF(C, 2);\n\ SS:= IF(C > REF(C, 1) AND REF(C, 1) >= REF(C, 2), 1, IF(C < REF(C, 1) AND REF(C, 1) <= REF(C, 2), -1, IF(C > REF(C, 2) AND REF(C, 2) > REF(C, 1), 2, IF(C < REF(C, 2) AND REF(C, 2) < REF(C, 1), -2, 0))));\n\ SM:= IF(REF(SS, 1) <> 0, REF(SS, 1), IF(REF(SS, 2) <> 0, REF(SS, 2), IF(REF(SS, 3) <> 0, REF(SS, 3), IF(REF(SS, 5) <> 0, REF(SS, 5), IF(REF(SS, 6) <> 0, REF(SS, 6), IF(REF(SS, 7) <> 0, REF(SS, 7), 0))))));\n\ MC:= IF(REF(SS, 1) <> 0, B2, IF(SM > 0, MIN(B1, B2), MAX(B1, B2)));\n\ TOW1:= IF(C > REF(C, 1), C, REF(C, 1));\n\ TOW2:= IF((SS == -1 OR SS == -2) AND SM > 0, B2, TOW1);\n\ TOWER:= IF(TOW1 > TOW2, TOW1, TOW2);\n\ STICKLINE(SS == 1 OR SM >= 1 AND SS == 0, B1, C, 10, 1), COLORRED;\n\ STICKLINE(SS == -1 OR SM <= -1 AND SS == 0, B1, C, 10, 0), COLORCYAN;\n\ STICKLINE(SS == 2, B2, C, 10, 1), COLORRED;\n\ STICKLINE(SS == -2, B2, C, 10, 0), COLORCYAN;\n\ STICKLINE((SS == -1 OR SS == -2) AND SM > 0, B2, B1, 10, 1), COLORRED;\n\ STICKLINE((SS == 1 OR SS == 2) AND SM < 0, B2, B1, 10, 0), COLORCYAN;' }; return data; } JSIndexScript.prototype.AMO = function () { let data = { Name: 'AMO', Description: '成交金额', IsMainIndex: false, StringFormat:2, YAxis:{ FloatPrecision:0, StringFormat:2 }, Args: [{ Name: 'M1', Value: 5 },{ Name: 'M2', Value: 10 }], Script: //脚本 'AMOW:AMOUNT/10000.0,VOLSTICK;\n\ AMO1:MA(AMOW,M1);\n\ AMO2:MA(AMOW,M2);' }; return data; } JSIndexScript.prototype.VRSI = function () { let data = { Name: 'VRSI', Description: '相对强弱量', IsMainIndex: false, Args: [{ Name: 'N1', Value: 6 },{ Name: 'N2', Value: 12 },{ Name: 'N3', Value: 24 }], Script: //脚本 'LC:=REF(VOL,1);\n\ RSI1:SMA(MAX(VOL-LC,0),N1,1)/SMA(ABS(VOL-LC),N1,1)*100;\n\ RSI2:SMA(MAX(VOL-LC,0),N2,1)/SMA(ABS(VOL-LC),N2,1)*100;\n\ RSI3:SMA(MAX(VOL-LC,0),N3,1)/SMA(ABS(VOL-LC),N3,1)*100;' }; return data; } JSIndexScript.prototype.HSCOL = function () { let data = { Name: 'HSCOL', Description: '换手柱', IsMainIndex: false, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 'HSCOL:IF((SETCODE==0||SETCODE==1),100*VOL,VOL)/(FINANCE(7)/100),VOLSTICK;\n\ MAHSL:MA(HSCOL,N);' }; return data; } JSIndexScript.prototype.DBQRV = function () { let data = { Name: 'DBQRV', Description: '对比强弱量(需下载日线)', IsMainIndex: false, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 'ZS:(INDEXV-REF(INDEXV,N))/REF(INDEXV,N);\n\ GG:(VOL-REF(VOL,N))/REF(VOL,N);' }; return data; } JSIndexScript.prototype.DBLB = function () { let data = { Name: 'DBLB', Description: '对比量比(需下载日线)', IsMainIndex: false, Args: [{ Name: 'N', Value: 5 },{ Name: 'M', Value: 5 }], Script: //脚本 'GG:=VOL/SUM(REF(VOL,1),N);\n\ ZS:=INDEXV/SUM(REF(INDEXV,1),N);\n\ DBLB:GG/ZS;\n\ MADBLB:MA(DBLB,M);' }; return data; } JSIndexScript.prototype.ACD = function () { let data = { Name: 'ACD', Description: '升降线', IsMainIndex: false, Args: [{ Name: 'M', Value: 20 }], Script: //脚本 'LC:=REF(CLOSE,1);\n\ DIF:=CLOSE-IF(CLOSE>LC,MIN(LOW,LC),MAX(HIGH,LC));\n\ ACD:SUM(IF(CLOSE==LC,0,DIF),0);\n\ MAACD:EXPMEMA(ACD,M);' }; return data; } JSIndexScript.prototype.EXPMA = function () { let data = { Name: 'EXPMA', Description: '指数平均线', IsMainIndex: true, Args: [{ Name: 'M1', Value: 12 },{ Name: 'M2', Value: 50 }], Script: //脚本 'EXP1:EMA(CLOSE,M1);\n\ EXP2:EMA(CLOSE,M2);' }; return data; } JSIndexScript.prototype.EXPMA_S = function () { let data = { Name: 'EXPMA_S', Description: '指数平均线-副图', IsMainIndex: false, Args: [{ Name: 'M1', Value: 12 },{ Name: 'M2', Value: 50 }], Script: //脚本 'EXP1:EMA(CLOSE,M1);\n\ EXP2:EMA(CLOSE,M2);' }; return data; } JSIndexScript.prototype.HMA = function () { let data = { Name: 'HMA', Description: '高价平均线', IsMainIndex: true, Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }], Script: //脚本 'HMA1:MA(HIGH,M1);\n\ HMA2:MA(HIGH,M2);\n\ HMA3:MA(HIGH,M3);\n\ HMA4:MA(HIGH,M4);\n\ HMA5:MA(HIGH,M5);' }; return data; } JSIndexScript.prototype.LMA = function () { let data = { Name: 'LMA', Description: '低价平均线', IsMainIndex: true, Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }], Script: //脚本 'LMA1:MA(LOW,M1);\n\ LMA2:MA(LOW,M2);\n\ LMA3:MA(LOW,M3);\n\ LMA4:MA(LOW,M4);\n\ LMA5:MA(LOW,M5);' }; return data; } JSIndexScript.prototype.VMA = function () { let data = { Name: 'VMA', Description: '变异平均线', IsMainIndex: true, Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }], Script: //脚本 'VV:=(HIGH+OPEN+LOW+CLOSE)/4;\n\ VMA1:MA(VV,M1);\n\ VMA2:MA(VV,M2);\n\ VMA3:MA(VV,M3);\n\ VMA4:MA(VV,M4);\n\ VMA5:MA(VV,M5);' }; return data; } JSIndexScript.prototype.AMV = function () { let data = { Name: 'AMV', Description: '成本价均线', IsMainIndex: false, Args: [{ Name: 'M1', Value: 6 },{ Name: 'M2', Value: 12 },{ Name: 'M3', Value: 30 },{ Name: 'M4', Value: 72 },{ Name: 'M5', Value: 144 }], Script: //脚本 'AMOV:=VOL*(OPEN+CLOSE)/2;\n\ AMV1:SUM(AMOV,M1)/SUM(VOL,M1);\n\ AMV2:SUM(AMOV,M2)/SUM(VOL,M2);\n\ AMV3:SUM(AMOV,M3)/SUM(VOL,M3);\n\ AMV4:SUM(AMOV,M4)/SUM(VOL,M4);' }; return data; } JSIndexScript.prototype.BBIBOLL = function () { let data = { Name: 'BBIBOLL', Description: '多空布林线', IsMainIndex: true, Args: [{ Name: 'N', Value: 11 },{ Name: 'M', Value: 6 }], Script: //脚本 'CV:=CLOSE;\n\ BBIBOLL:(MA(CV,3)+MA(CV,6)+MA(CV,12)+MA(CV,24))/4;\n\ UPR:BBIBOLL+M*STD(BBIBOLL,N);\n\ DWN:BBIBOLL-M*STD(BBIBOLL,N);' }; return data; } JSIndexScript.prototype.ALLIGAT = function () { let data = { Name: 'ALLIGAT', Description: '鳄鱼线', IsMainIndex: true, Args: [], Script: //脚本 'NN:=(H+L)/2;\n\ 上唇:REF(MA(NN,5),3),COLOR40FF40;\n\ 牙齿:REF(MA(NN,8),5),COLOR0000C0;\n\ 下颚:REF(MA(NN,13),8),COLORFF4040;' }; return data; } JSIndexScript.prototype.ZX = function () { let data = { Name: 'ZX', Description: '重心线', IsMainIndex: false, Args: [], Script: //脚本 'AV:0.01*AMOUNT/VOL;' }; return data; } JSIndexScript.prototype.XS = function () { let data = { Name: 'XS', Description: '薛斯通道', IsMainIndex: true, Args: [{ Name: 'N', Value: 13 }], Script: //脚本 'VAR2:=CLOSE*VOL;\n\ VAR3:=EMA((EMA(VAR2,3)/EMA(VOL,3)+EMA(VAR2,6)/EMA(VOL,6)+EMA(VAR2,12)/EMA(VOL,12)+EMA(VAR2,24)/EMA(VOL,24))/4,N);\n\ SUP:1.06*VAR3;\n\ SDN:VAR3*0.94;\n\ VAR4:=EMA(CLOSE,9);\n\ LUP:EMA(VAR4*1.14,5);\n\ LDN:EMA(VAR4*0.86,5);' }; return data; } JSIndexScript.prototype.XS2 = function () { let data = { Name: 'XS2', Description: '薛斯通道II', IsMainIndex: true, Args: [{ Name: 'N', Value: 102 },{ Name: 'M', Value: 7 }], Script: //脚本 'AA:=MA((2*CLOSE+HIGH+LOW)/4,5); \n\ 通道1:AA*N/100; \n\ 通道2:AA*(200-N)/100; \n\ CC:=ABS((2*CLOSE+HIGH+LOW)/4-MA(CLOSE,20))/MA(CLOSE,20); \n\ DD:=DMA(CLOSE,CC); \n\ 通道3:(1+M/100)*DD; \n\ 通道4:(1-M/100)*DD;' }; return data; } JSIndexScript.prototype.SG_XDT = function () { let data = { Name: 'SG-XDT', Description: '心电图(需下载日线)', IsMainIndex: false, Args: [{ Name: 'P1', Value: 5 },{ Name: 'P2', Value: 10 }], Script: //脚本 'QR:CLOSE/INDEXC*1000;\n\ MQR1:MA(QR,5);\n\ MQR2:MA(QR,10);' }; return data; } JSIndexScript.prototype.SG_SMX = function () { let data = { Name: 'SG-SMX', Description: '生命线(需下载日线)', IsMainIndex: false, Args: [{ Name: 'N', Value: 50 }], Script: //脚本 'H1:=HHV(HIGH,N);\n\ L1:=LLV(LOW,N);\n\ H2:=HHV(INDEXH,N);\n\ L2:=LLV(INDEXL,N);\n\ ZY:=CLOSE/INDEXC*2000;\n\ ZY1:EMA(ZY,3);\n\ ZY2:EMA(ZY,17);\n\ ZY3:EMA(ZY,34);' }; return data; } JSIndexScript.prototype.SG_LB = function () { let data = { Name: 'SG-LB', Description: '量比(需下载日线)', IsMainIndex: false, Args: [], Script: //脚本 'ZY2:=VOL/INDEXV*1000;\n\ 量比:ZY2;\n\ MA5:MA(ZY2,5);\n\ MA10:MA(ZY2,10);' }; return data; } JSIndexScript.prototype.SG_PF = function () { let data = { Name: 'SG-PF', Description: '强势股评分(需下载日线)', IsMainIndex: false, Args: [], Script: //脚本 'ZY1:=CLOSE/INDEXC*1000;\n\ A1:=IF(ZY1>HHV(ZY1,3),10,0);\n\ A2:=IF(ZY1>HHV(ZY1,5),15,0);\n\ A3:=IF(ZY1>HHV(ZY1,10),20,0);\n\ A4:=IF(ZY1>HHV(ZY1,2),10,0);\n\ A5:=COUNT(ZY1>REF(ZY1,1) ,9)*5;\n\ 强势股评分:A1+A2+A3+A4+A5;' }; return data; } JSIndexScript.prototype.RAD = function () { let data = { Name: 'RAD', Description: '威力雷达(需下载日线)', IsMainIndex: false, Args: [{ Name: 'D', Value: 3 },{ Name: 'S', Value: 30 },{ Name: 'M', Value: 30 }], Script: //脚本 'SM:=(OPEN+HIGH+CLOSE+LOW)/4;\n\ SMID:=MA(SM,D);\n\ IM:=(INDEXO+INDEXH+INDEXL+INDEXC)/4;\n\ IMID:=MA(IM,D);\n\ SI1:=(SMID-REF(SMID,1))/SMID;\n\ II:=(IMID-REF(IMID,1))/IMID;\n\ RADER1:SUM((SI1-II)*2,S)*1000;\n\ RADERMA:SMA(RADER1,M,1);' }; return data; } JSIndexScript.prototype.SHT = function () { let data = { Name: 'SHT', Description: '龙系短线', IsMainIndex: false, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 'VAR1:=MA((VOL-REF(VOL,1))/REF(VOL,1),5);\n\ VAR2:=(CLOSE-MA(CLOSE,24))/MA(CLOSE,24)*100;\n\ MY: VAR2*(1+VAR1);\n\ SHT: MY, COLORSTICK;\n\ SHTMA: MA(SHT,N);' }; return data; } JSIndexScript.prototype.ZLJC = function () { let data = { Name: 'ZLJC', Description: '主力进出', IsMainIndex: false, Args: [], Script: //脚本 'VAR1:=(CLOSE+LOW+HIGH)/3; \n\ VAR2:=SUM(((VAR1-REF(LOW,1))-(HIGH-VAR1))*VOL/100000/(HIGH-LOW),0); \n\ VAR3:=EMA(VAR2,1); \n\ JCS:VAR3; \n\ JCM:MA(VAR3,12); \n\ JCL:MA(VAR3,26);' }; return data; } JSIndexScript.prototype.ZLMM = function () { let data = { Name: 'ZLMM', Description: '主力买卖', IsMainIndex: false, Args: [], Script: //脚本 'LC :=REF(CLOSE,1);\n\ RSI2:=SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100;\n\ RSI3:=SMA(MAX(CLOSE-LC,0),18,1)/SMA(ABS(CLOSE-LC),18,1)*100;\n\ MMS:MA(3*RSI2-2*SMA(MAX(CLOSE-LC,0),16,1)/SMA(ABS(CLOSE-LC),16,1)*100,3);\n\ MMM:EMA(MMS,8);\n\ MML:MA(3*RSI3-2*SMA(MAX(CLOSE-LC,0),12,1)/SMA(ABS(CLOSE-LC),12,1)*100,5);' }; return data; } JSIndexScript.prototype.SLZT = function () { let data = { Name: 'SLZT', Description: '神龙在天', IsMainIndex: false, Args: [], Script: //脚本 '白龙: MA(CLOSE,125);\n\ 黄龙: 白龙+2*STD(CLOSE,170);\n\ 紫龙: 白龙-2*STD(CLOSE,145);\n\ 青龙: SAR(125,1,7), LINESTICK;\n\ VAR2:=HHV(HIGH,70);\n\ VAR3:=HHV(HIGH,20);\n\ 红龙: VAR2*0.83;\n\ 蓝龙: VAR3*0.91;' }; return data; } JSIndexScript.prototype.ADVOL = function () { let data = { Name: 'ADVOL', Description: '龙系离散量', IsMainIndex: false, Args: [], Script: //脚本 'A:=SUM(((CLOSE-LOW)-(HIGH-CLOSE))*VOL/10000/(HIGH-LOW),0);\n\ ADVOL:A;\n\ MA1:MA(A,30);\n\ MA2:MA(MA1,100);' }; return data; } JSIndexScript.prototype.CYC = function () { let data = { Name: 'CYC', Description: '成本均线', IsMainIndex: true, Args: [{ Name: 'P1', Value: 5 },{ Name: 'P2', Value: 13 },{ Name: 'P3', Value: 34 }], Script: //脚本 'JJJ:=IF(DYNAINFO(8)>0.01,0.01*DYNAINFO(10)/DYNAINFO(8),DYNAINFO(3));\n\ DDD:=(DYNAINFO(5)<0.01 || DYNAINFO(6)<0.01);\n\ JJJT:=IF(DDD,1,(JJJ<(DYNAINFO(5)+0.01) && JJJ>(DYNAINFO(6)-0.01)));\n\ CYC1:IF(JJJT,0.01*EMA(AMOUNT,P1)/EMA(VOL,P1),EMA((HIGH+LOW+CLOSE)/3,P1));\n\ CYC2:IF(JJJT,0.01*EMA(AMOUNT,P2)/EMA(VOL,P2),EMA((HIGH+LOW+CLOSE)/3,P2));\n\ CYC3:IF(JJJT,0.01*EMA(AMOUNT,P3)/EMA(VOL,P3),EMA((HIGH+LOW+CLOSE)/3,P3));\n\ CYC4:IF(JJJT,DMA(AMOUNT/(100*VOL),100*VOL/FINANCE(7)),EMA((HIGH+LOW+CLOSE)/3,120));' }; return data; } JSIndexScript.prototype.CYS = function () { let data = { Name: 'CYS', Description: '市场盈亏', IsMainIndex: false, Args: [], Script: //脚本 'CYC13:EMA(AMOUNT,13)/EMA(VOL,13);\n\ CYS:(CLOSE-CYC13)/CYC13*100;' }; return data; } JSIndexScript.prototype.CYQKL = function () { let data = { Name: 'CYQKL', Description: '博弈K线长度', IsMainIndex: false, Args: [], Script: //脚本 'KL:100*(WINNER(CLOSE)-WINNER(OPEN));' }; return data; } JSIndexScript.prototype.SCR = function () { let data = { Name: 'SCR', Description: '筹码集中度', IsMainIndex: false, Args: [{ Name: 'P1', Value: 90 }], Script: //脚本 'A:=P1+(100-P1)/2;\n\ B:=(100-P1)/2;\n\ CC:=COST(A);\n\ DD:=COST(B);\n\ SCR:(CC-DD)/(CC+DD)*100/2;' }; return data; } JSIndexScript.prototype.ASR = function () { let data = { Name: 'ASR', Description: '浮筹比例', IsMainIndex: false, Args: [], Script: //脚本 'ASR:(WINNER(C*1.1)-WINNER(C*0.9))/WINNER(HHV(H,0))*100;' }; return data; } JSIndexScript.prototype.SAR = function () { let data = { Name: 'SAR', Description: '抛物转向', IsMainIndex: true, Args: [{ Name: 'P', Value: 10 },{ Name: 'STEP', Value: 2 },{ Name: 'MAXP', Value: 20 }], Script: //脚本 'S:SAR(P,STEP,MAXP),UPDOWNDOT;' }; return data; } JSIndexScript.prototype.TJCJL = function () { let data = { Name: '太极成交量', Description: '太极成交量', IsMainIndex: true, Args: [], Script: //脚本 '总手:VOL,NODRAW;\n\ DRAWTEXT_FIX(ISLASTBAR,0,0,0,"说明: 红色柱为吸货量,绿色为出货量,黄色为天量,蓝色为地量"),COLORGRAY;\n\ ZZ:=IF(REF(C,1)>REF(O,1) AND O>REF(C,1)*1.014 AND CV5*1.2 AND V>V12*1.2 AND ZZ>2 AND C>H*0.975,0,VOL,3,0),COLORRED;\n\ STICKLINE(CROSS(C6,C) AND V>V5*1.2 AND V>V12*1.2,0,VOL,3,0),COLORGREEN;\n\ STICKLINE(VOL>MA(VOL,5)*2 AND V>V34*3 AND CMA(VOL,5)*2 AND V>V34*3 AND CV5*1.2 AND V>V12*1.2 AND ZZ>2 AND C>H*0.975,VOL*0.5,0,3,0),COLORRED;\n\ STICKLINE(VOL>MA(VOL,5)*2 AND V>V34*3 AND CV5*1.2 AND V>V12*1.2,VOL*0.5,0,3,0),COLORRED;' }; return data; } /* 飞龙四式-主图 */ JSIndexScript.prototype.Dragon4_Main = function () { let data = { Name: '飞龙四式', Description: '飞龙四式', IsMainIndex: true, Args: [{ Name: 'N1', Value: 5 }, { Name: 'N2', Value: 10 }, { Name: 'N3', Value: 50 }, { Name: 'N4', Value: 60 }], Script: //脚本 '蜻蜓点水:=EMA(CLOSE,N1),COLORGRAY;\n\ 魔界:=EMA(CLOSE,N2),COLORGREEN;\n\ 水:=EMA(CLOSE,N3),COLORRED;\n\ DRAWKLINE(HIGH,OPEN,LOW,CLOSE);\n\ 生命线:MA(CLOSE,N4),COLORBLUE,LINETHICK2;\n\ DRAWBAND(魔界,\'RGB(186,225,250)\',水,\'RGB(253,194,124)\');\n\ DRAWBAND(蜻蜓点水,\'RGB(128,138,135)\',魔界,\'RGB(0,0,255)\');' }; return data; } JSIndexScript.prototype.Dragon4_Fig=function() { let data = { Name: '飞龙四式', Description: '飞龙四式', IsMainIndex: false, Args: [], Script: //脚本 '倍:VOL>=REF(V,1)*1.90 AND C>REF(C,1),COLORYELLOW;\n\ 低:VOLREF(V,1),3)==3 AND COUNT(C>O,3)==3,COLORBROWN;\n\ 缩量涨:COUNT(C>REF(C,1),2)==2 AND COUNT(V=REF(C,1),V,0,2,0),COLORRED;\n\ STICKLINE(C=2038 AND MONTH>=1,0,1); VAR2:=REF(LOW,1)*VAR1; VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1; VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1; VAR5:=LLV(LOW,30)*VAR1; VAR6:=HHV(VAR4,30)*VAR1; VAR7:=IF(MA(CLOSE,58),1,0)*VAR1; VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1; 吸筹A:IF(VAR8>100,100,VAR8)*VAR1,COLORRED; 吸筹B:STICKLINE(吸筹A>-150,0,吸筹A,8,0),COLORRED; 散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORFFFF00,LINETHICK2; RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100; K:=SMA(RSV,3,1); D:=SMA(K,3,1); J:=3*K-2*D; 主力线:EMA(J,5),COLORFF00FF,LINETHICK2; DRAWICON(CROSS(主力线,散户线),主力线,1); DRAWICON(CROSS(散户线,主力线),主力线,2); */ JSIndexScript.prototype.FundsAnalysis=function() { let data = { Name: '资金分析', Description: '资金分析', IsMainIndex: false, Args: [{ Name: 'M', Value: 55 }, { Name: 'N', Value: 34 }], Script: //脚本 'LC:=REF(CLOSE,1);\n\ RSI:=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);\n\ FF:=EMA(CLOSE,3);\n\ MA15:=EMA(CLOSE,21); DRAWTEXT(CROSS(85,RSI),75,\'▼\'),COLORGREEN;\n\ VAR1:=IF(YEAR>=2038 AND MONTH>=1,0,1);\n\ VAR2:=REF(LOW,1)*VAR1;\n\ VAR3:=SMA(ABS(LOW-VAR2),3,1)/SMA(MAX(LOW-VAR2,0),3,1)*100*VAR1;\n\ VAR4:=EMA(IF(CLOSE*1.3,VAR3*10,VAR3/10),3)*VAR1;\n\ VAR5:=LLV(LOW,30)*VAR1;\n\ VAR6:=HHV(VAR4,30)*VAR1;\n\ VAR7:=IF(MA(CLOSE,58),1,0)*VAR1;\n\ VAR8:=EMA(IF(LOW<=VAR5,(VAR4+VAR6*2)/2,0),3)/618*VAR7*VAR1;\n\ 吸筹A:IF(VAR8>100,100,VAR8)*VAR1,COLORFB2F3B;\n\ {吸筹B}STICKLINE(吸筹A>-150,0,吸筹A,8,0),COLORFB2F3B;\n\ \n\ 散户线: 100*(HHV(HIGH,M)-CLOSE)/(HHV(HIGH,M)-LLV(LOW,M)),COLORAA89BD,LINETHICK2;\n\ RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\ K:=SMA(RSV,3,1);\n\ D:=SMA(K,3,1);\n\ J:=3*K-2*D;\n\ 主力线:EMA(J,5),COLORF39800,LINETHICK2;\n\ DRAWICON(CROSS(主力线,散户线),主力线,1);\n\ DRAWICON(CROSS(散户线,主力线),主力线,2);' }; return data; } JSIndexScript.prototype.MarginProportion=function() { let data = { Name: '融资占比(%)', Description: '融资占比', IsMainIndex: false, Condition: { Period:[CONDITION_PERIOD.KLINE_DAY_ID] }, Args: [], Script: //脚本 '占比:MARGIN(2);' }; return data; } JSIndexScript.prototype.Margin2=function() { let data = { Name: '两融余额', Description: '融资融券余额', IsMainIndex: false, Condition: { Period:[CONDITION_PERIOD.KLINE_DAY_ID] }, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 'T1:MARGIN(1);\n\ T2:MA(MARGIN(1),N);' }; return data; } JSIndexScript.prototype.Margin3=function() { let data = { Name: '两融余额', Description: '融资融券余额', IsMainIndex: false, Condition: { Period:[CONDITION_PERIOD.KLINE_DAY_ID] }, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 'T1:=MARGIN(1);\n\ T2:=MA(MARGIN(1),N);\n\ STICKLINE(T1-T2>=0,0,T1-T2,50,T1>T2),COLORRED;\n\ STICKLINE(T1-T2<0,T1-T2,0,50,T1>T2),COLORGREEN;' }; return data; } JSIndexScript.prototype.FXG_BSPoint=function() { let data = { Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true, Args: [], Script: //脚本 'MA5:MA(CLOSE,5);\n\ MA13:MA(CLOSE,13);\n\ MA21:MA(CLOSE,21);\n\ MA34:MA(CLOSE,34);\n\ {MA55:MA(CLOSE,55),COLOR0000FF;}\n\ {MA120:=MA(CLOSE,120),COLORFFFF00;}\n\ 天使:=EMA(C,2),COLOR000000;\n\ 魔鬼:=EMA(SLOPE(C,21)*20+C,42),COLOR000000;\n\ 买:=CROSS(天使,魔鬼);\n\ 卖:=CROSS(魔鬼,天使);\n\ DRAWICON(买,L*0.97,13);\n\ DRAWICON(卖,H*1.03,14);\n\ DRAWKLINE_IF(天使>=魔鬼,HIGH,CLOSE,LOW,OPEN),COLORRED;\n\ DRAWKLINE_IF(天使<魔鬼,HIGH,CLOSE,LOW,OPEN),COLORBLUE;\n\ DRAWKLINE_IF(CROSS(天使,魔鬼),HIGH,CLOSE,LOW,OPEN),COLORYELLOW;\n\ DRAWKLINE_IF(CROSS(魔鬼,天使),HIGH,CLOSE,LOW,OPEN),COLORBLACK;' }; return data; } JSIndexScript.prototype.FXG_INDEX=function() { let data = { Name: '涨停多空线', Description: '涨停多空线', IsMainIndex: false, Args: [], Script: //脚本 '做多能量线: SMA((CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100,5,1)-8,COLORRED,LINETHICK3;\n\ 做空能量线: SMA((HHV(HIGH,36)-CLOSE)/(HHV(HIGH,36)-LLV(LOW,36))*100,2,1),COLORGREEN,LINETHICK3;\n\ 20,POINTDOT,COLORF00FF0;\n\ 50,POINTDOT,COLORGREEN;\n\ 80,POINTDOT,COLORLIBLUE;' }; return data; } JSIndexScript.prototype.FXG_INDEX2=function() { let data = { Name: '涨停吸筹区', Description: '涨停吸筹区', IsMainIndex: false, Args: [], Script: //脚本 'VAR0:=EMA(HHV(HIGH,500),21); \n\ VAR1:=EMA(HHV(HIGH,250),21);\n\ VAR2:=EMA(HHV(HIGH,90),21); \n\ VAR3:=EMA(LLV(LOW,500),21); \n\ VAR4:=EMA(LLV(LOW,250),21); \n\ VAR5:=EMA(LLV(LOW,90),21);\n\ \n\ VAR6:=EMA((VAR3*0.96+VAR4*0.96+VAR5*0.96+VAR0*0.558+VAR1*0.558+VAR2*0.558)/6,21); \n\ VAR7:=EMA((VAR3*1.25+VAR4*1.23+VAR5*1.2+VAR0*0.55+VAR1*0.55+VAR2*0.65)/6,21); \n\ VAR8:=EMA((VAR3*1.3+VAR4*1.3+VAR5*1.3+VAR0*0.68+VAR1*0.68+VAR2*0.68)/6,21); \n\ VAR9:=EMA((VAR6*3+VAR7*2+VAR8)/6*1.738,21); \n\ VAR10:=REF(LOW,1); \n\ VAR11:=SMA(ABS(LOW-VAR10),3,1)/SMA(MAX(LOW-VAR10,0),3,1)*100; \n\ VAR12:=EMA(IFF(CLOSE*1.35<=VAR9,VAR11*10,VAR11/10),3); \n\ VAR13:=LLV(LOW,30); \n\ VAR14:=HHV(VAR12,30); \n\ VAR15:=IFF(MA(CLOSE,58),1,0); \n\ VAR16:=EMA(IFF(LOW<=VAR13,(VAR12+VAR14*2)/2,0),3)/618*VAR15;\n\ \n\ 资金入场:IFF(VAR16>0,VAR16,0),LINETHICK,LINETHICK2, COLORFF0000; \n\ \n\ A1:IFF(资金入场>0,资金入场*1.2,0),STICK,LINETHICK5, COLORFF0000;\n\ A2:IFF(资金入场>0,资金入场*0.8,0),STICK,LINETHICK5, COLORFF6600;\n\ A3:IFF(资金入场>0,资金入场*0.6,0),STICK,LINETHICK5, COLORFF9900;\n\ A4:IFF(资金入场>0,资金入场*0.4,0) ,STICK,LINETHICK5,COLORFFCC00;\n\ A5:IFF(资金入场>0,资金入场*0.2,0) ,STICK,LINETHICK5,COLORFFFF00;' }; return data; } JSIndexScript.prototype.FXG_INDEX3=function() { let data = { Name: '量能黄金点', Description: '量能黄金点', IsMainIndex: false,FloatPrecision:0, Args: [], Script: //脚本 'A:=IFF((CLOSE>126.32),VOL,VOL); \n\ 主力:=MA(A,4),COLORRED;\n\ 游资:=MA(A,8),COLORYELLOW;\n\ 大户:=MA(A,16),COLORF0F000;\n\ 散户:=MA(A,32),COLOR00FF00;\n\ 主比:=ABS(((主力)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORRED;\n\ 游比:=ABS(((游资)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORYELLOW;\n\ 大比:=ABS(((大户)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLORF0F000;\n\ 散比:=ABS(((散户)/(主力 + 游资 + 大户 + 散户))*(100)),LINESTICK,COLOR00FF00;\n\ 警戒线:MA(A,180),COLORFF66FF;\n\ STICKLINE((主力 > 0),0,主力,2.5,0),COLOR1020BB;\n\ STICKLINE((主力 > 0),0,主力,0.7,0),COLORRED;\n\ STICKLINE((游资 > 0),0,游资,2.5,0),COLOR009CFF;\n\ STICKLINE((游资 > 0),0,游资,0.7,0),COLORYELLOW;\n\ STICKLINE((大户 > 0),0,大户,2.5,0),COLORFF8800;\n\ STICKLINE((大户 > 0),0,大户,0.7,0),COLORLIBLUE;\n\ STICKLINE((散户 > 0),0,散户,2.5,0),COLOR00CA00;\n\ STICKLINE((散户 > 0),0,散户,0.7,0),COLORGREEN;' }; return data; } JSIndexScript.prototype.NewsNegative=function() { let data= { Name: '负面新闻', Description: '负面新闻统计', IsMainIndex: false,FloatPrecision:0, Args: [{ Name: 'N', Value: 5 }, { Name: 'N2', Value: 10 }], Script: //脚本 '负面:NEWS(1);\n\ MA1:MA(负面,N);\n\ MA2:MA(负面,N2);' }; return data; } JSIndexScript.prototype.UpDownAnalyze=function() { let data= { Name: '涨跌趋势', Description: '涨跌趋势', IsMainIndex: false,FloatPrecision:0, Condition: { Period:[CONDITION_PERIOD.MINUTE_ID, CONDITION_PERIOD.MULTIDAY_MINUTE_ID, CONDITION_PERIOD.KLINE_DAY_ID] }, Args: [], Script: //脚本 "上涨家数:UPCOUNT('CNA.CI'),COLORRED;\n\ 下跌家数:DOWNCOUNT('CNA.CI'),COLORGREEN;" }; return data; } JSIndexScript.prototype.HK2SHSZ=function() { let data= { Name: '北上资金', Description: '北上资金', IsMainIndex: false,FloatPrecision:0, Condition: { Period:[CONDITION_PERIOD.MINUTE_ID,CONDITION_PERIOD.MULTIDAY_MINUTE_ID,CONDITION_PERIOD.KLINE_DAY_ID] }, Args: [], Script: //脚本 "净流入:HK2SHSZ(1),COLORSTICK;" }; return data; } JSIndexScript.prototype.ShareHolder=function() { let data= { Name: '股东人数', Description: '股东人数', IsMainIndex: false,FloatPrecision:0, Condition: { Period:[ CONDITION_PERIOD.KLINE_DAY_ID, CONDITION_PERIOD.KLINE_MONTH_ID, CONDITION_PERIOD.KLINE_WEEK_ID, CONDITION_PERIOD.KLINE_YEAR_ID] }, Args: [], Script: //脚本 "人数:FINANCE(100);" }; return data; } JSIndexScript.prototype.VOLRate=function() { let data= { Name: '量比', Description: '量比', IsMainIndex: false, Condition: { Period:[CONDITION_PERIOD.MINUTE_ID, CONDITION_PERIOD.MULTIDAY_MINUTE_ID ] }, Args: [], Script: //脚本 "LIANGBI:VOLR;" }; return data; } //////////////////////////////////////////////////////////////////////////////////////////////// //五彩K线 JSIndexScript.prototype.COLOR_KSTAR1=function() { let data= { Name: '十字星', Description: '十字星', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:CLOSE==OPEN&&HIGH>LOW;' }; return data; } JSIndexScript.prototype.COLOR_KSTAR2=function() { let data= { Name: '早晨之星', Description: '早晨之星', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:(REF(CLOSE,2)/REF(OPEN,2)<0.95) && (REF(OPEN,1) < REF(CLOSE,2)) && (ABS(REF(OPEN,1)-REF(CLOSE,1))/REF(CLOSE,1)<0.03) && CLOSE/OPEN>1.05 && CLOSE>REF(CLOSE,2);' }; return data; } JSIndexScript.prototype.COLOR_KSTAR3=function() { let data= { Name: '黄昏之星', Description: '黄昏之星', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:REF(CLOSE,2)/REF(OPEN,2)>1.05 && REF(OPEN,1)>REF(CLOSE,2) && ABS(REF(OPEN,1)-REF(CLOSE,1))/REF(CLOSE,1)<0.03 && CLOSE/OPEN<0.95 && CLOSE1.03;' }; return data; } JSIndexScript.prototype.COLOR_K220=function() { let data= { Name: '身怀六甲', Description: '身怀六甲', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:ABS(REF(CLOSE,1)-REF(OPEN,1))/REF(CLOSE,1)>0.04&&\n\ ABS(CLOSE-OPEN)/CLOSE<0.005&&\n\ MAX(CLOSE,OPEN)MIN(REF(CLOSE,1),REF(OPEN,1));' }; return data; } JSIndexScript.prototype.COLOR_K300=function() { let data= { Name: '三个白武士', Description: '三个白武士', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:UPNDAY(CLOSE,3)&&NDAY(CLOSE,OPEN,3);' }; return data; } JSIndexScript.prototype.COLOR_K310=function() { let data= { Name: '三只乌鸦', Description: '三只乌鸦', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:DOWNNDAY(CLOSE,3)&&NDAY(OPEN,CLOSE,3);' }; return data; } JSIndexScript.prototype.COLOR_K380=function() { let data= { Name: '光头阳线', Description: '光头阳线', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:HIGH==CLOSE&&HIGH>LOW;' }; return data; } JSIndexScript.prototype.COLOR_K390=function() { let data= { Name: '光脚阴线', Description: '光脚阴线', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:LOW==CLOSE&&HIGH>LOW;' }; return data; } JSIndexScript.prototype.COLOR_K134=function() { let data= { Name: '垂死十字', Description: '垂死十字', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:CLOSE==OPEN&&CLOSE==LOW&&CLOSE1.05&&CLOSE>REF(CLOSE,2);' }; return data; } JSIndexScript.prototype.COLOR_K150=function() { let data= { Name: '黄昏十字星', Description: '黄昏十字星', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:REF(CLOSE,2)/REF(OPEN,2)>1.05&&\n\ REF(OPEN,1)>REF(CLOSE,2)&&\n\ REF(OPEN,1)=REF(CLOSE,1)&&\n\ CLOSE/OPEN<0.95&&CLOSE3*(MAX(OPEN,CLOSE)-LOW)&&\n\ CLOSE>MA(CLOSE,5);' }; return data; } JSIndexScript.prototype.COLOR_K165=function() { let data= { Name: '倒转锤头', Description: '倒转锤头', IsMainIndex: true, InstructionType:2, Script: //脚本 'KSTAR:MIN(OPEN,CLOSE)==LOW&&\n\ HIGH-LOW>3*(MAX(OPEN,CLOSE)-LOW)&&\n\ CLOSE3*(HIGH-MIN(OPEN,CLOSE))&&\n\ CLOSE3*(HIGH-MIN(OPEN,CLOSE))&&\n\ CLOSE>MA(CLOSE,5);' }; return data; } JSIndexScript.prototype.COLOR_K190=function() { let data= { Name: '穿头破脚', Description: '穿头破脚', IsMainIndex: true, InstructionType:2, Script: //脚本 'OUT:(REF(CLOSE,1)/REF(OPEN,1)>1.03&&\n\ CLOSE/OPEN<0.96&&\n\ CLOSEREF(CLOSE,1))||\n\ (REF(CLOSE,1)/REF(OPEN,1)<0.97&&\n\ CLOSE/OPEN>1.04&&\n\ CLOSE>REF(OPEN,1)&&OPENREF(VOL,1)||VOL>(CAPITAL*0.1);\n\ BB:=OPEN>=(REF(HIGH,1))&&REF(HIGH,1)>(REF(HIGH,2)*1.06);\n\ CC:=CLOSE>(REF(CLOSE,1))-(REF(CLOSE,1)*0.01);\n\ DD:=CLOSE<(HIGH*0.965) && HIGH>(OPEN*1.05);\n\ EE:=LOW(REF(CLOSE,1)*1.06);\n\ FF:=(HIGH-(MAX(OPEN,CLOSE)))/2>(MIN(OPEN,CLOSE))-LOW;\n\ GG:=(ABS(OPEN-CLOSE))/2<(MIN(OPEN,CLOSE)-LOW);\n\ SWORDO:AA&&BB&&CC&&DD&&EE&&FF&&GG;' }; return data; } JSIndexScript.prototype.COLOR_CSFR=function() { let data= { Name: '出水芙蓉', Description: '出水芙蓉', IsMainIndex: true, InstructionType:2, Script: //脚本 'A:=CLOSE>OPEN;\n\ B:=A&&CLOSE>MA(CLOSE,S)&&CLOSE>MA(CLOSE,M)&&CLOSE>MA(CLOSE,LL);\n\ CC:=B&&OPEN0.0618*CLOSE;' }; return data; } JSIndexScript.prototype.COLOR_WYGD=function() { let data= { Name: '乌云盖顶', Description: '乌云盖顶', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( \n\ REF(CLOSE,1)/REF(OPEN,1)>1.03 AND \n\ CLOSE/OPEN<0.97 AND \n\ OPEN>REF(CLOSE,1) AND CLOSE1.03 AND \n\ OPENREF(CLOSE,1), 3);' }; return data; } JSIndexScript.prototype.COLOR_SZTAI=function() { let data= { Name: '十字胎', Description: '十字胎', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( ABS(REF(CLOSE,1)-REF(OPEN,1))/REF(CLOSE,1) > 0.04 AND \n\ CLOSE==OPEN AND CLOSE < MAX(REF(CLOSE,1),REF(OPEN,1)) AND \n\ CLOSE > MIN(REF(CLOSE,1),REF(OPEN,1)), 2);' }; return data; } JSIndexScript.prototype.COLOR_PINGDING=function() { let data= { Name: '平顶', Description: '平顶', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET(ABS(HIGH-REF(HIGH,1))/HIGH<0.001,2);' }; return data; } JSIndexScript.prototype.COLOR_PINGDI=function() { let data= { Name: '平底', Description: '平底', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET((ABS(LOW-REF(LOW,1))/LOW<0.001 AND \n\ ABS(REF(LOW,1)-REF(LOW,2))/REF(LOW,1)<=0.001),2);' }; return data; } JSIndexScript.prototype.COLOR_DAYANZHU=function() { let data= { Name: '大阳烛', Description: '大阳烛', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:CLOSE/OPEN>1.05 AND HIGH/LOW < CLOSE/OPEN+0.018;' }; return data; } JSIndexScript.prototype.COLOR_DAYINGZHU=function() { let data= { Name: '大阴烛', Description: '大阴烛', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:OPEN/CLOSE > 1.05 AND HIGH/LOW < OPEN/CLOSE+0.018;' }; return data; } JSIndexScript.prototype.COLOR_HYFG=function() { let data= { Name: '好友反攻', Description: '好友反攻', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( (REF(CLOSE,1)OPEN AND ABS(CLOSE-REF(CLOSE,1))/CLOSE<0.002),2);' }; return data; } JSIndexScript.prototype.COLOR_TKQK=function() { let data= { Name: '跳空缺口', Description: '跳空缺口', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( HIGHREF(HIGH,1),2);' }; return data; } JSIndexScript.prototype.COLOR_SFWY=function() { let data= { Name: '双飞乌鸦', Description: '双飞乌鸦', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( REF(CLOSE,1)1.03 AND \n\ REF(CLOSE,3)REF(HIGH,3) AND \n\ REF(HIGH,4)>REF(HIGH,2) AND \n\ REF(HIGH,4)>REF(HIGH,1) AND \n\ CLOSE/OPEN>1.03 AND \n\ CLOSE>REF(CLOSE,4), 5);' }; return data; } JSIndexScript.prototype.COLOR_XDSBQ=function() { let data= { Name: '下跌三部曲', Description: '下跌三部曲', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( \n\ REF(CLOSE,4)/REF(OPEN,4)<0.97 AND \n\ REF(CLOSE,3)>REF(OPEN,3) AND \n\ REF(CLOSE,2)>REF(OPEN,2) AND \n\ REF(CLOSE,1)>REF(OPEN,1) AND \n\ REF(LOW,4)REF(HIGH,3) AND \n\ REF(HIGH,4)>REF(HIGH,2) AND \n\ REF(HIGH,4)>REF(HIGH,1) AND \n\ CLOSE/OPEN<0.97 AND \n\ CLOSE0.667;' }; return data; } JSIndexScript.prototype.COLOR_CHSY=function() { let data= { Name: '长上影', Description: '长上影', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR2:(HIGH-MAX(CLOSE,OPEN))/(HIGH-LOW)>0.667,COLORBLUE;' }; return data; } JSIndexScript.prototype.COLOR_FENLI=function() { let data= { Name: '分离', Description: '分离', IsMainIndex: true, InstructionType:2, Script: //脚本 'VAR1:BACKSET( OPEN==REF(OPEN,1) AND (CLOSE-OPEN)*(REF(CLOSE,1)-REF(OPEN,1))<0,2);' }; return data; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //交易系统 JSIndexScript.prototype.TRADE_BIAS = function () { let data = { Name: 'BIAS', Description: '乖离率专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 12 }, { Name: 'LL', Value: 6 },{ Name: 'LH', Value: 6 }], Script: //脚本 'BIAS:=(CLOSE-MA(CLOSE,N))/MA(CLOSE,N)*100;\n\ ENTERLONG:CROSS(-LL,BIAS);\n\ EXITLONG:CROSS(BIAS,LH);' }; return data; } JSIndexScript.prototype.TRADE_CCI = function () { let data = { Name: 'CCI', Description: 'CCI专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 14 }], Script: //脚本 'TYP:=(HIGH+LOW+CLOSE)/3;\n\ CCI:=(TYP-MA(TYP,N))/(0.015*AVEDEV(TYP,N));\n\ INDEX:=CCI;\n\ ENTERLONG:CROSS(INDEX,-100);\n\ EXITLONG:CROSS(100,INDEX);' }; return data; } JSIndexScript.prototype.TRADE_DMI = function () { let data = { Name: 'DMI', Description: '趋向专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 14 }], Script: //脚本 'MTR:=SUM(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(LOW-REF(CLOSE,1))),N);\n\ HD :=HIGH-REF(HIGH,1);\n\ LD :=REF(LOW,1)-LOW;\n\ PDM:=SUM(IF(HD>0&&HD>LD,HD,0),N);\n\ MDM:=SUM(IF(LD>0&&LD>HD,LD,0),N);\n\ PDI:=PDM*100/MTR;\n\ MDI:=MDM*100/MTR;\n\ ENTERLONG:CROSS(PDI,MDI);\n\ EXITLONG:CROSS(MDI,PDI);' }; return data; } JSIndexScript.prototype.TRADE_KD = function () { let data = { Name: 'KD', Description: 'KD指标专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 9 },{ Name: 'M1', Value: 3 },{ Name: 'M2', Value: 3 }], Script: //脚本 'WRSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\ WK:=SMA(WRSV,M1,1);\n\ D:=SMA(WK,M2,1);\n\ ENTERLONG:CROSS(WK,D)&&WK<20;\n\ EXITLONG:CROSS(D,WK)&&WK>80;' }; return data; } JSIndexScript.prototype.TRADE_BOLL = function () { let data = { Name: 'BOLL', Description: '布林带专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 20 }], Script: //脚本 'MID :=MA(CLOSE,N);\n\ UPPER:=MID+2*STD(CLOSE,N);\n\ LOWER:=MID-2*STD(CLOSE,N);\n\ ENTERLONG:CROSS(CLOSE,LOWER);\n\ EXITLONG:CROSS(CLOSE,UPPER);' }; return data; } JSIndexScript.prototype.TRADE_KDJ = function () { let data = { Name: 'KDJ', Description: 'KDJ专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 9 },{ Name: 'M1', Value: 3 }], Script: //脚本 'RSV:=(CLOSE-LLV(LOW,N))/(HHV(HIGH,N)-LLV(LOW,N))*100;\n\ K:=SMA(RSV,M1,1);\n\ D:=SMA(K,M1,1);\n\ J:=3*K-2*D;\n\ ENTERLONG:CROSS(J,0);\n\ EXITLONG:CROSS(100,J);' }; return data; } JSIndexScript.prototype.TRADE_MA = function () { let data = { Name: 'MA', Description: '均线专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'SHORT', Value: 5 },{ Name: 'LONG', Value: 20 }], Script: //脚本 'ENTERLONG:CROSS(MA(CLOSE,SHORT),MA(CLOSE,LONG));\n\ EXITLONG:CROSS(MA(CLOSE,LONG),MA(CLOSE,SHORT));' }; return data; } JSIndexScript.prototype.TRADE_MACD = function () { let data = { Name: 'MACD', Description: 'MACD专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'LONG', Value: 26 }, { Name: 'SHORT', Value: 12 }, { Name: 'M', Value: 9 }], Script: //脚本 'DIFF:=EMA(CLOSE,SHORT) - EMA(CLOSE,LONG);\n\ DEA := EMA(DIFF,M);\n\ MACD := 2*(DIFF-DEA);\n\ ENTERLONG:CROSS(MACD,0);\n\ EXITLONG:CROSS(0,MACD);' }; return data; } JSIndexScript.prototype.TRADE_MTM = function () { let data = { Name: 'MTM', Description: '动力指标专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 6 }], Script: //脚本 'WMTM:=C-REF(C,N);\n\ ENTERLONG:CROSS(WMTM,0);\n\ EXITLONG:CROSS(0,WMTM);' }; return data; } JSIndexScript.prototype.TRADE_PSY = function () { let data = { Name: 'PSY', Description: 'PSY心理线专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 12 },{ Name: 'LL', Value: 10 },{ Name: 'LH', Value: 85 }], Script: //脚本 'MYPSY:=COUNT(CLOSE>REF(CLOSE,1),N)/N*100;\n\ ENTERLONG:CROSS(LL,MYPSY);\n\ EXITLONG:CROSS(MYPSY,LH);' }; return data; } JSIndexScript.prototype.TRADE_ROC = function () { let data = { Name: 'ROC', Description: '变动速率专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 12 },{ Name: 'M', Value: 6 }], Script: //脚本 'WROC:=MA(100*(CLOSE-REF(CLOSE,N))/REF(CLOSE,N),M);\n\ ENTERLONG:CROSS(WROC,0);\n\ EXITLONG:CROSS(0,WROC);' }; return data; } JSIndexScript.prototype.TRADE_RSI = function () { let data = { Name: 'RSI', Description: '相对强弱专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 6 },{ Name: 'LL', Value: 20 },{ Name: 'LH', Value: 80 }], Script: //脚本 'LC:=REF(CLOSE,1);\n\ WRSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1)*100;\n\ ENTERLONG:CROSS(WRSI,LL);\n\ EXITLONG:CROSS(LH,WRSI);' }; return data; } JSIndexScript.prototype.TRADE_VR = function () { let data = { Name: 'VR', Description: 'VR容量比率专家系统', IsMainIndex: true, InstructionType:1, Args: [{ Name: 'N', Value: 26 },{ Name: 'LL', Value: 70 },{ Name: 'LH', Value: 250 }], Script: //脚本 'WVR := SUM((IF(CLOSE>OPEN,VOL,0)+IF(CLOSE=OPEN,VOL/2,0)),N)/SUM((IF(CLOSEX_3 AND X_2>X_4,X_2+X_3/2+X_5/4,IF(X_3>X_4 AND X_3>X_2,X_3+X_2/2+X_5/4,X_4+X_5/4));\n\ X_7:=CLOSE-X_1+(CLOSE-OPEN)/2+X_1-REF(OPEN,1);\n\ X_8:=8*X_7/X_6*MAX(X_2,X_3);\n\ ASI:SUM(X_8,0),LINETHICK2;\n\ MASI:MA(ASI,N1),LINETHICK2;" }; return data; } /* History The Donchian Channels (DC) indicator was created by the famous commodities trader Richard Donchian. Donchian would become known as The Father of Trend Following. Calculation For this example, a 20 day period is used which is a very commonly used timeframe. Upper Channel = 20 Day High Lower Channel = 20 Day Low Middle Channel = (20 Day High + 20 Day Low)/2 */ JSIndexScript.prototype.DC = function () { let data = { Name: 'DC', Description: '唐奇安通道', IsMainIndex: true, Args: [{ Name: 'N1', Value: 20 }], Script: //脚本 "UPPER:HHV(H,N1),COLORBLUE,LINETHICK2;\n\ LOWER:LLV(L,N1),COLORBLUE,LINETHICK2;\n\ MIDDLE:(UPPER+LOWER)/2,COLORRED,LINETHICK3;" }; return data; } /* 双重指数移动均线(DEMA)由Patrick Mulloy开发并于1994年2月在"股票与商品期货的技术分析"杂志中出版。 用于平滑价格系列并被直接应用到金融证券的价格图表中。此外,它还用于平滑其他指标的价值。 DEMA的优势是在锯齿状的价格移动中清除错误信号并允许趋势强劲时保持仓位。 计算 该指标基于指数移动平均线 (EMA). 从EMA值中查看价格偏差错误: err(i) = Price(i) - EMA(Price, N, i) 此处: err(i) ― 当前EMA误差; Price(i) ― 当前价格; EMA(Price, N, i) ― 价格系列的以N为周期的EMA的当前值。 添加指数平均线错误值到价格指数移动平均数值,可以获得EDMA; DEMA(i) = EMA(Price,N,i)+ EMA(err,N,i) = EMA(Price,N,i)+EMA(Price-EMA(Price,N,i),N,i) = = 2*EMA(Price,N,i)-EMA(Price-EMA(Price,N,i),N,i)=2*EMA(Price,N,i)-EMA2(Price,N,i) 此处: EMA(err, N, i) ― 误差err的指数均线的当前值; EMA2(Price, N, i) ― 价格的二重连续平滑的当前值。 */ JSIndexScript.prototype.DEMA = function () { let data = { Name: 'DEMA', Description: '双重指数移动均线', IsMainIndex: true, Args: [{ Name: 'N1', Value: 10 }], Script: //脚本 "ERR:=C-EMA(C,N1);\n\ DEMA:EMA(C,10)+EMA(ERR,N1);" }; return data; } /* Calculation There are five steps in calculating VWAP: Calculate the Typical Price for the period. [(High + Low + Close)/3)] Multiply the Typical Price by the period Volume. (Typical Price x Volume) Create a Cumulative Total of Typical Price. Cumulative(Typical Price x Volume) Create a Cumulative Total of Volume. Cumulative(Volume) Divide the Cumulative Totals. VWAP = Cumulative(Typical Price x Volume) / Cumulative(Volume) */ JSIndexScript.prototype.VWAP = function () { let data = { Name: 'VWAP', Description: '成交量加权平均价', IsMainIndex: true, Args: [{ Name: 'N1', Value: 10 }], Script: //脚本 "PRICE:=(H+L+C)/3;\n\ T2:=VOL*PRICE;\n\ VWAP:SUM(T2,0)/SUM(VOL,0);" }; return data; } JSIndexScript.prototype.SQJZ = function () { let data = { Name: 'SQJZ', Description: '神奇九转', IsMainIndex: true, Script: //脚本 "B:=C=9 AND REFXV(COUNT(B,9),8)=9);\n\ DRAWNUMBER(B1 AND REF(B,1)=0,L,1),COLORMAGENTA;\n\ B2:=(N=5 AND REFXV(COUNT(B,6),4)=6) OR (N=6 AND REFXV(COUNT(B,7),5)=7) OR (N=7 AND REFXV(COUNT(B,8),6)=8) OR (N>=8 AND REFXV(COUNT(B,9),7)=9);\n\ DRAWNUMBER(B2 AND REF(B,2)=0,L,2),COLORMAGENTA;\n\ B8:=(N=1 AND COUNT(B,8)=8) OR (N>=2 AND REFXV(COUNT(B,9),1)=9);\n\ DRAWNUMBER(B8 AND REF(B,8)=0,L,8),COLORMAGENTA;\n\ B9:=(N>=1 AND COUNT(B,9)=9);\n\ DRAWNUMBER(B9 AND REF(B,9)=0,L,9),COLORBROWN;\n\ S:=C>REF(C,4);\n\ S1:=(N=6 AND REFXV(COUNT(S,6),5)=6) OR (N=7 AND REFXV(COUNT(S,7),6)=7) OR (N=8 AND REFXV(COUNT(S,8),7)=8) OR (N>=9 AND REFXV(COUNT(S,9),8)=9);\n\ DRAWNUMBER(S1 AND REF(S,1)=0,H,1),COLORMAGENTA,DRAWABOVE;\n\ S2:=(N=5 AND REFXV(COUNT(S,6),4)=6) OR (N=6 AND REFXV(COUNT(S,7),5)=7) OR (N=7 AND REFXV(COUNT(S,8),6)=8) OR (N>=8 AND REFXV(COUNT(S,9),7)=9);\n\ DRAWNUMBER(S2 AND REF(S,2)=0,H,2),COLORMAGENTA,DRAWABOVE;\n\ S8:=(N=1 AND COUNT(S,8)=8) OR (N>=2 AND REFXV(COUNT(S,9),1)=9);\n\ DRAWNUMBER(S8 AND REF(S,8)=0,H,8),COLORMAGENTA,DRAWABOVE;\n\ S9:=(N>=1 AND COUNT(S,9)=9);\n\ DRAWNUMBER(S9 AND REF(S,9)=0,H,9),COLORGREEN,DRAWABOVE;" }; return data; } JSIndexScript.prototype.XT = function () { let data = { Name: 'XT', Description: '箱体', IsMainIndex: true, Args: [{ Name: 'N', Value: 10 }], Script: //脚本 "【箱顶】:PEAK(CLOSE,N,1)*0.98;\n\ 【箱底】:TROUGH(CLOSE,N,1)*1.02;\n\ 【箱高】:100*(【箱顶】-【箱底】)/【箱底】,NODRAW;" }; return data; } JSIndexScript.prototype.CFJT = function () { let data = { Name: 'CFJT', Description: '财富阶梯', IsMainIndex: true, Script: //脚本 "突破:=REF(EMA(C,14),1);\n\ A1X:=(EMA(C,10)-突破)/突破*100;\n\ 多方:=IF(A1X>=0,REF(EMA(C,10),BARSLAST(CROSS(A1X,0))+1),DRAWNULL);\n\ 空方:=IF(A1X<0,REF(EMA(C,10),BARSLAST(CROSS(0,A1X))+1),DRAWNULL);\n\ STICKLINE(A1X>=0,多方,突破,110,0),COLORRED;\n\ STICKLINE(A1X<0,空方,突破,110,0),COLORGREEN;" }; return data; } JSIndexScript.prototype.CYX = function () { let data = { Name: 'CYX', Description: '撑压线', IsMainIndex: true, Args: [{ Name: 'N', Value: 7 }], Script: //脚本 "Z1:=STRCAT(HYBLOCK,' ');\n\ Z2:=STRCAT(Z1,DYBLOCK);\n\ Z3:=STRCAT(Z2,' ');\n\ DRAWTEXT_FIX(ISLASTBAR,0,0,0,STRCAT(Z3,GNBLOCK)),COLOR00C0C0;\n\ A1:=REF(H,N)=HHV(H,2*N+1);\n\ B1:=FILTER(A1,N);\n\ C1:=BACKSET(B1,N+1);\n\ D1:=FILTER(C1,N);\n\ A2:=REF(L,N)=LLV(L,2*N+1);\n\ B2:=FILTER(A2,N);\n\ C2:=BACKSET(B2,N+1);\n\ D2:=FILTER(C2,N);\n\ E1:=(REF(LLV(L,2*N),1)+REF(HHV(H,2*N),1))/2;\n\ E2:=(H+L)/2;\n\ H1:=(D1 AND NOT(D2 AND E1>=E2)) OR ISLASTBAR OR BARSCOUNT(C)=1;\n\ L1:=(D2 AND NOT(D1 AND E1=E2);\n\ X1:=REF(BARSLAST(H1),1)+1;\n\ F1:=BACKSET(H1 AND COUNT(L1,X1)>0,LLVBARS(IF(L1,L,10000),X1));\n\ G1:=F1>REF(F1,1);\n\ I1:=BACKSET(G1,2);\n\ LD:=I1>REF(I1,1);\n\ L2:=LD OR ISLASTBAR OR BARSCOUNT(C)=1;\n\ X2:=REF(BARSLAST(L2),1)+1;\n\ F2:=BACKSET(L2 AND COUNT(H2,X2)>0,HHVBARS(IF(H2,H,0),X2));\n\ G2:=F2>REF(F2,1);\n\ I2:=BACKSET(G2,2);\n\ HD:=I2>REF(I2,1);\n\ R1:=BACKSET(ISLASTBAR,BARSLAST(HD)+1);\n\ S1:=R1>REF(R1,1);\n\ T1:=BACKSET(ISLASTBAR,BARSLAST(LD)+1);\n\ U1:=T1>REF(T1,1);\n\ R2:=BACKSET(S1,REF(BARSLAST(HD),1)+2);\n\ S2:=R2>REF(R2,1);\n\ T2:=BACKSET(U1,REF(BARSLAST(LD),1)+2);\n\ U2:=T2>REF(T2,1);\n\ DRAWLINE(S2,H,S1,H,1),LINETHICK2,COLORRED;\n\ DRAWLINE(U2,L,U1,L,1),LINETHICK2,COLORGREEN;" }; return data; } JSIndexScript.prototype.WAVE = function () { let data = { Name: 'WAVE', Description: '波浪分析', IsMainIndex: true, Args: [{ Name: 'N', Value: 5 }], Script: //脚本 "ZIG(3,N);" }; return data; } JSIndexScript.prototype.ShareholderCount=function() { let data = { Name: '散户线', Description: '散户线', IsMainIndex: false, Script: //脚本 "GPJYVALUE(1,1,1);" }; return data; } JSIndexScript.prototype.NXTS=function() { let data = { Name: 'NXTS', Description: '牛熊天数', IsMainIndex: false, Args: [{ Name: 'N', Value: 20 }], Script: //脚本 "Z:=ZIG(C,N);\n\ 高点:=Z>REF(Z,1) AND Z>REFX(Z,1);\n\ 低点:=ZND OR COUNT(高点,0)=0) AND ND>0 AND (HHV(C,ND)-REF(C,ND))/REF(C,ND)>(N/100);\n\ N2:=NG0 AND (LLV(C,NG)-REF(C,NG))/REF(C,NG)>=-(N/100);\n\ N3:=NG(N/100);\n\ N5:=COUNT(低点,0)=0 AND NG>0 AND (LLV(C,NG)-REF(C,NG))/REF(C,NG)>=-(N/100);\n\ N6:=COUNT(低点,0)=0 AND NG=0;\n\ X1:=(NG0 AND (LLV(C,NG)-REF(C,NG))/REF(C,NG)<-(N/100);\n\ X2:=NG>ND AND ND>0 AND (HHV(C,ND)-REF(C,ND))/REF(C,ND)<=(N/100);\n\ X3:=NG>ND AND ND=0;\n\ X4:=COUNT(高点 OR 低点,0)=0 AND (LLV(C,0)-REF(C,BARSSINCE(C)))/REF(C,BARSSINCE(C))<-(N/100);\n\ X5:=COUNT(高点,0)=0 AND ND>0 AND (HHV(C,ND)-REF(C,ND))/REF(C,ND)<=(N/100);\n\ X6:=COUNT(高点,0)=0 AND ND=0;\n\ 牛市天数:IF(N4 OR N5 OR N6,D0,IF(N1 OR N2 OR N3,DD,0)),COLORRED;\n\ 熊市天数:IF(X4 OR X5 OR X6,D0,IF(X1 OR X2 OR X3,DG,0)),COLORGREEN;" }; return data; } JSIndexScript.prototype.FKX=function() { let data = { Name: 'FKX', Description: '反K线', IsMainIndex: false, Script: //脚本 "DRAWKLINE(-LOW, -OPEN, -HIGH, -CLOSE);" }; return data; } JSIndexScript.prototype.Margin4=function() { let data = { Name: '两融资金', Description: '两融资金', IsMainIndex: false, Script: //脚本 "TMPV:=IF(FINANCE(3)==0,REF(SCJYVALUE(1,1,1),1),REF(GPJYVALUE(3,1,1),1));\n\ TMPV1:=IF(FINANCE(3)==0,SCJYVALUE(1,1,0),GPJYVALUE(3,1,0));\n\ 两融:IF(TMPV==0 OR TMPV1==0,DRAWNULL,IF(FINANCE(3)==0,(SCJYVALUE(1,1,1)-REF(SCJYVALUE(1,1,1),1))/10000-(SCJYVALUE(1,2,1)-REF(SCJYVALUE(1,2,1),1))/10000,((GPJYVALUE(3,1,1)-REF(GPJYVALUE(3,1,1),1))-((GPJYVALUE(3,2,1)*C/10000-(REF(GPJYVALUE(3,2,1),1)*REF(C,1)/10000)))))),NODRAW;\n\ STICKLINE(两融>0,0,两融,2,0),COLORRED;\n\ STICKLINE(两融<0,0,两融,2,0),COLORCYAN;" }; return data; } JSIndexScript.prototype.ZSDB=function() { let data = { Name: 'ZSDB', Description: '指数对比(副图,需下载日线)', IsMainIndex: false, Script: //脚本 "A:=REF(INDEXC,1);\n\ 指数涨幅:IF(A>0,(INDEXC-A)*100/A,0),NODRAW;\n\ DRAWKLINE(INDEXH,INDEXO,INDEXL,INDEXC);" }; return data; } JSIndexScript.prototype.NineTurns=function() { let data = { Name: '神奇九转', Description: '九转指标', IsMainIndex: true, Script: //脚本 "A1:=C>REF(C,4);\n\ A2:=CREF(C,4);\n\ D1:=B2 AND REF(B1,1);\n\ D2:=B2 AND REF(D1,1);\n\ D3:=B2 AND REF(D2,1);\n\ D4:=B2 AND REF(D3,1);\n\ D5:=B2 AND REF(D4,1);\n\ D6:=B2 AND REF(D5,1);\n\ D7:=B2 AND REF(D6,1);\n\ D8:=B2 AND REF(D7,1);\n\ D9:=B2 AND REF(D8,1);\n\ D10:=B2 AND REF(D9,1);\n\ D11:=B2 AND REF(D10,1);\n\ D12:=B2 AND REF(D11,1);\n\ D13:=B2 AND REF(D12,1);\n\ D14:=B2 AND REF(D13,1);\n\ DRAWTEXT(D1,H*1.010,'1'),COLORBLUE;\n\ DRAWTEXT(D2,H*1.010,'2'),COLORBLUE;\n\ DRAWTEXT(D3,H*1.010,'3'),COLORBLUE;\n\ DRAWTEXT(D4,H*1.010,'4'),COLORBLUE;\n\ DRAWTEXT(D5,H*1.010,'5'),COLORBLUE;\n\ DRAWTEXT(D6,H*1.010,'6'),COLORBLUE;\n\ DRAWTEXT(D7,H*1.010,'7'),COLORBLUE;\n\ DRAWTEXT(D8,H*1.010,'8'),COLORBLUE;\n\ DRAWTEXT(D9,H*1.010,'9'),COLORGREEN;" }; return data; } JSIndexScript.prototype.ICHIMOKU=function() { let data = { Name: 'ICHIMOKU', Description: '一目均衡图', IsMainIndex: true, Args: [{ Name: 'SHORT', Value: 7 },{ Name: 'MID', Value: 22 },{ Name: 'LONG', Value: 44 }], Script: //脚本 "转换线:(HHV(H,SHORT)+LLV(L,SHORT))/2,COLORRED,LINETHICK2;\n\ 基准线:(HHV(H,MID)+LLV(L,MID))/2,COLORFF8040,LINETHICK2;\n\ 迟行带:REFXV(C,MID),COLORGRAY,LINETHICK2;\n\ A:=REF((转换线+基准线)/2,MID);\n\ B:=REF((HHV(H,LONG)+LLV(L,LONG))/2,MID);\n\ STICKLINE(A=B,A,B,2,1),COLOR0033CC;\n\ 先行带A:PLOYLINE(1,A),COLORBROWN;\n\ 先行带B:PLOYLINE(1,B),COLORLIGREEN;" }; return data; } JSIndexScript.prototype.CDP_STD=function() { let data = { Name: 'CDP-STD', Description: '逆势操作', IsMainIndex: true, Script: //脚本 "CH:=REF(H,1);\n\ CL:=REF(L,1);\n\ CC:=REF(C,1);\n\ CDP:(CH+CL+CC)/3;\n\ AH:2*CDP+CH-2*CL;\n\ NH:CDP+CDP-CL;\n\ NL:CDP+CDP-CH;\n\ AL:2*CDP-2*CH+CL;" }; return data; } JSIndexScript.prototype.TBP_STD=function() { let data = { Name: 'TBP-STD', Description: '趋势平衡点', IsMainIndex: true, Script: //脚本 "APX:=(H+L+C)/3;\n\ TR0:=MAX(H-L,MAX(ABS(H-REF(C,1)),ABS(L-REF(C,1))));\n\ MF0:=C-REF(C,2);\n\ MF1:=REF(MF0,1);\n\ MF2:=REF(MF0,2);\n\ DIRECT1:=BARSLAST(MF0>MF1 AND MF0>MF2);\n\ DIRECT2:=BARSLAST(MF050,MIN(MF0,MF1),MAX(MF0,MF1)),1);\n\ 多头获利:REF(IF(DIRECT0>50,APX*2-L,DRAWNULL),1),NODRAW;\n\ 多头停损:REF(IF(DIRECT0>50,APX-TR0,DRAWNULL),1),NODRAW;\n\ 空头回补:REF(IF(DIRECT0<-50,APX*2-H,DRAWNULL),1),NODRAW;\n\ 空头停损:REF(IF(DIRECT0<-50,APX+TR0,DRAWNULL),1),NODRAW;" }; return data; } JSIndexScript.prototype.ADX = function () { let data = { Name: 'ADX', Description: '均趋向指标', IsMainIndex: false, Args: [{ Name: 'N', Value: 14 }], Script: //脚本 `TR1:=SMA(MAX(MAX(HIGH-LOW,ABS(HIGH-REF(CLOSE,1))),ABS(LOW-REF(CLOSE,1))),N,1); HD:=HIGH-REF(HIGH,1); LD:=REF(LOW,1)-LOW; DMP:=SMA(IF(HD>0 AND HD>LD,HD,0),N,1); DMM:=SMA(IF(LD>0 AND LD>HD,LD,0),N,1); PDI:DMP*100/TR1,COLORRED,DOTLINE; MDI:DMM*100/TR1,COLORGREEN,DOTLINE; ADX:SMA(ABS(MDI-PDI)/(MDI+PDI)*100,N,1),COLORYELLOW,LINETHICK2; 20; 40;` }; return data; } JSIndexScript.prototype.ZNZ_CBAND = function() { let data = { Name: 'ZNZ_CBAND', Description: '优化成本布林带宽', IsMainIndex: false, Args: [{ Name: 'N', Value: 20 }], Script: //脚本 `A:=AMOUNT/(100*VOL); BBI1:=MA(A,N); UPR0:=BBI1+STD(A,N); DWN0:=BBI1-STD(A,N); UPR1:=BBI1+1.7*STD(A,N); DWN1:=BBI1-1.7*STD(A,N); 优化成本布林带宽:100*1.7*STD(A,N);` }; return data; } JSIndexScript.prototype.ZNZ_RPY2 = function() { let data = { Name: 'ZNZ_RPY2', Description: '两年相对价位', IsMainIndex: false, Script: //脚本 `A:=REF(HHV(CLOSE,480),1); B:=REF(LLV(CLOSE,480),1); 100*(CLOSE-B)/(A-B);` }; return data; } JSIndexScript.prototype.ZNZ_RPY1 = function() { let data = { Name: 'ZNZ_RPY1', Description: '年相对价位', IsMainIndex: false, Args: [{ Name: 'N', Value: 240 }], Script: //脚本 `A:=REF(HHV(CLOSE,N),1); B:=REF(LLV(CLOSE,N),1); 100*(CLOSE-B)/(A-B);` }; return data; } JSIndexScript.prototype.TEST = function () { let data = { Name: 'TEST', Description: '测试脚本', IsMainIndex: false, Args: [{ Name: 'N', Value: 10 }], Script: //脚本 "DRAWCHANNEL(OPEN>C,H,L, 'RGB(255,94,102)', 2 ,'5,5','RGBA(58,20,62,0.3)' );" }; return data; } /* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装行情类图形控件 (H5版本) */ //日志输出类 if (!JSConsole) { var JSConsole= { Chart:{ Log:console.log, Warn:console.warn }, //图形日志 Complier:{ Log:console.log, Warn:console.warn } //编译器日志 }; } function JSChart(divElement, bOffscreen, bCacheCanvas) { this.DivElement=divElement; this.DivToolElement=null; //工具条 this.JSChartContainer; //画图控件 this.ResizeListener; //h5 canvas this.CanvasElement=document.createElement("canvas"); this.CanvasElement.className='jschart-drawing'; this.CanvasElement.id=Guid(); this.CanvasElement.setAttribute("tabindex",0); if (this.CanvasElement.style) { this.CanvasElement.style.outline='none'; //this.CanvasElement.style.position="absolute"; //外部自己设置 } if(divElement.hasChildNodes()) { JSConsole.Chart.Log("[JSChart::JSChart] divElement hasChildNodes", divElement.childNodes); } divElement.appendChild(this.CanvasElement); //离屏 this.OffscreenCanvasElement; if (bOffscreen==true) this.OffscreenCanvasElement=document.createElement("canvas"); //图形缓存 this.CacheCanvasElement=null; if (bCacheCanvas) this.CacheCanvasElement=document.createElement("canvas"); //改参数div this.ModifyIndexDialog=new ModifyIndexDialog(divElement); //额外的画布 this.MapExtraCanvasElement=new Map(); //key=画布名字, value={ Element:, Canvas:} this.CreateExtraCanvasElement=function(name, option) { if (this.MapExtraCanvasElement.has(name)) return this.MapExtraCanvasElement.get(name); var element=document.createElement("canvas"); element.className='jschart-drawing-extra'; element.id=Guid(); if (name==JSChart.CorssCursorCanvasKey) element.setAttribute("tabindex",5); else element.setAttribute("tabindex",1); if (element.style) { element.style.outline='none'; element.style.position="absolute"; element.style.left='0px'; element.style.top='0px'; element.style["pointer-events"]="none"; } if (option) { if (IFrameSplitOperator.IsNumber(option.TabIndex)) element.setAttribute("tabindex",option.TabIndex); if (IFrameSplitOperator.IsNumber(option.ZIndex)) element.style["z-index"]=option.ZIndex; } if (this.CanvasElement) { element.height=this.CanvasElement.height; element.width=this.CanvasElement.width; if (element.style) { element.style.width=this.CanvasElement.style.width; element.style.height=this.CanvasElement.style.height } } divElement.appendChild(element); var item={ Element:element, Canvas:null }; this.MapExtraCanvasElement.set(name, item); } this.GetExtraCanvas=function(name) { if (!this.MapExtraCanvasElement.has(name)) return null; var item=this.MapExtraCanvasElement.get(name); if (!item.Element) return null; if (!item.Canvas) item.Canvas=item.Element.getContext("2d"); return item; } /* { Type: 1=K线柱子宽度不变 2=K线全部显示 Redraw:是否重绘, XYSplit:是否重新计算分割线 } */ this.OnSize=function(option) { //画布大小通过div获取 如果有style里的大小 使用style里的 var height=this.DivElement.offsetHeight; var width=this.DivElement.offsetWidth; if (this.DivElement.style.height && this.DivElement.style.width) { if (this.DivElement.style.height.includes("px")) height=parseInt(this.DivElement.style.height.replace("px","")); if (this.DivElement.style.width.includes("px")) width=parseInt(this.DivElement.style.width.replace("px","")); } if (this.ToolElement) { //TODO调整工具条大小 height-=this.ToolElement.style.height.replace("px",""); //减去工具条的高度 } this.CanvasElement.height=height; this.CanvasElement.width=width; this.CanvasElement.style.width=this.CanvasElement.width+'px'; this.CanvasElement.style.height=this.CanvasElement.height+'px'; var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.CanvasElement.height*=pixelTatio; this.CanvasElement.width*=pixelTatio; if (this.OffscreenCanvasElement) { this.OffscreenCanvasElement.height=this.CanvasElement.height; this.OffscreenCanvasElement.width=this.CanvasElement.width; } if (this.CacheCanvasElement) { this.CacheCanvasElement.height=this.CanvasElement.height; this.CacheCanvasElement.width=this.CanvasElement.width; } for(var mapItem of this.MapExtraCanvasElement) { var item=mapItem[1]; var element=item.Element; if (!element) continue; element.height=this.CanvasElement.height; element.width=this.CanvasElement.width; element.style.width=this.CanvasElement.style.width; element.style.height=this.CanvasElement.style.height; } JSConsole.Chart.Log(`[JSChart::OnSize] devicePixelRatio=${window.devicePixelRatio}, height=${this.CanvasElement.height}, width=${this.CanvasElement.width}`); if (option && option.Redraw==false) return; if (this.JSChartContainer) { if (option && option.XYSplit===true) this.JSChartContainer.ResetFrameXYSplit(); if (this.JSChartContainer.OnSize && option && option.Type==1) //K线宽度不变 { this.JSChartContainer.OnSize(); } else if (this.JSChartContainer.ShowAllKLine && option && option.Type==2) { this.JSChartContainer.ShowAllKLine(); } else { if (this.JSChartContainer.Frame) this.JSChartContainer.Frame.SetSizeChage(true); this.JSChartContainer.Draw(); } } } //手机屏需要调整 间距 this.AdjustChartBorder=function(chart) { var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 chart.Frame.ChartBorder.Left*=pixelTatio; chart.Frame.ChartBorder.Right*=pixelTatio; chart.Frame.ChartBorder.Top*=pixelTatio; chart.Frame.ChartBorder.Bottom*=pixelTatio; if (chart.Frame.AutoLeftBorder) { var item=chart.Frame.AutoLeftBorder; if (IFrameSplitOperator.IsNumber(item.MinWidth)) item.MinWidth*=pixelTatio; if (IFrameSplitOperator.IsNumber(item.Blank)) item.Blank*=pixelTatio; } if (chart.Frame.AutoRightBorder) { var item=chart.Frame.AutoRightBorder; if (IFrameSplitOperator.IsNumber(item.MinWidth)) item.MinWidth*=pixelTatio; if (IFrameSplitOperator.IsNumber(item.Blank)) item.Blank*=pixelTatio; } } this.AdjustTitleHeight=function(chart) { var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 for(var i=0;i{ return this.GetExtraCanvas(name); } var extraElement=this.GetExtraCanvas(JSChart.CorssCursorCanvasKey); if (extraElement) chart.SetCorssCursorElement(extraElement); if (option.EventCallback) this.SetEventCallback(chart, option.EventCallback); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; //创建改参数div chart.ModifyIndexDialog=this.ModifyIndexDialog; var pixelRatio=GetDevicePixelRatio(); //右键菜单 if (IFrameSplitOperator.IsBool(option.IsShowRightMenu)) chart.IsShowRightMenu=option.IsShowRightMenu; if (option.ScriptError) chart.ScriptErrorCallback=option.ScriptError; if (option.EnableScrollUpDown==true) chart.EnableScrollUpDown=option.EnableScrollUpDown; if (option.DisableMouse==true) chart.DisableMouse=option.DisableMouse; if (option.TouchMoveMinAngle) chart.TouchMoveMinAngle=option.TouchMoveMinAngle; if (option.EnableZoomUpDown) chart.EnableZoomUpDown=option.EnableZoomUpDown; if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle=option.SplashTitle; if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow; if (IFrameSplitOperator.IsBool(option.IsDrawPictureXY)) chart.IsDrawPictureXY=option.IsDrawPictureXY; if (IFrameSplitOperator.IsNumber(option.CtrlMoveStep)) chart.CtrlMoveStep=option.CtrlMoveStep; if (IFrameSplitOperator.IsBool(option.EnableIndexChartDrag)) chart.EnableIndexChartDrag=option.EnableIndexChartDrag; if (IFrameSplitOperator.IsBool(option.EnableVerifyRecvData)) chart.EnableVerifyRecvData=option.EnableVerifyRecvData; if (option.GlobalOption) { var item=option.GlobalOption; if (IFrameSplitOperator.IsBool(item.IsValueFullRange)) chart.GlobalOption.IsValueFullRange=item.IsValueFullRange; if (item.SelectedBorder) { var subItem=item.SelectedBorder; if (IFrameSplitOperator.IsNumber(subItem.Mode)) chart.GlobalOption.SelectedBorder.Mode=subItem.Mode; } } if (option.EnableYDrag) { var item=option.EnableYDrag; if (IFrameSplitOperator.IsBool(item.Left)) chart.EnableYDrag.Left=item.Left; if (IFrameSplitOperator.IsBool(item.Right)) chart.EnableYDrag.Right=item.Right; if (IFrameSplitOperator.IsBool(item.Wheel)) chart.EnableYDrag.Wheel=item.Wheel; if (IFrameSplitOperator.IsNumber(item.WheelYMove)) chart.EnableYDrag.WheelYMove=item.WheelYMove; } if (option.KLineTooltip) { var item=option.KLineTooltip; if (IFrameSplitOperator.IsBool(item.Enable)) chart.KLineTooltipConfig.Enable=item.Enable; if (IFrameSplitOperator.IsBool(item.EnableKeyDown)) chart.KLineTooltipConfig.EnableKeyDown=item.EnableKeyDown; } if (option.KLine) //k线图的属性设置 { var item=option.KLine; 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.MaxReqeustDataCount>0) chart.MaxRequestDataCount=option.KLine.MaxReqeustDataCount; //兼容老版本 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 (IFrameSplitOperator.IsBool(item.IsShowTooltip)) chart.IsShowTooltip=item.IsShowTooltip; if (option.KLine.MaxRequestMinuteDayCount>0) chart.MaxRequestMinuteDayCount=option.KLine.MaxRequestMinuteDayCount; if (option.KLine.DrawType) chart.KLineDrawType=option.KLine.DrawType; if (option.KLine.FirstShowDate>19910101) chart.CustomShow={ Date:option.KLine.FirstShowDate, PageSize:option.KLine.PageSize }; //!!已弃用 新的格式"CustomShow" if (option.KLine.RightSpaceCount>0) chart.RightSpaceCount=option.KLine.RightSpaceCount; if (option.KLine.ZoomType>0) chart.ZoomType=option.KLine.ZoomType; if (option.KLine.DataWidth>=1) chart.KLineSize={ DataWidth:option.KLine.DataWidth }; if (IFrameSplitOperator.IsNumber(option.KLine.RightFormula)) chart.RightFormula=option.KLine.RightFormula; } //自定义显示位置 if (option.CustomShow && IFrameSplitOperator.IsPlusNumber(option.CustomShow.Date)) { var item=option.CustomShow; chart.CustomShow={ Date:item.Date }; if (IFrameSplitOperator.IsNumber(item.Time)) chart.CustomShow.Time=item.Time; if (IFrameSplitOperator.IsPlusNumber(item.PageSize)) chart.CustomShow.PageSize=item.PageSize; } if (option.EnableFlowCapital) { var item=option.EnableFlowCapital; if (item.BIT==true) chart.EnableFlowCapital.BIT=item.BIT; } if (IFrameSplitOperator.IsBool(option.EnableBorderDrag)) { chart.EnableBorderDrag=option.EnableBorderDrag; } if (option.Page) { if (option.Page.Day && option.Page.Day.Enable==true) chart.Page.Day.Enable=true; if (option.Page.Minute && option.Page.Minute.Enable==true) chart.Page.Minute.Enable=true; } 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.ZoomDownload) { if (option.ZoomDownload.Day && IFrameSplitOperator.IsBool(option.ZoomDownload.Day.Enable)) chart.ZoomDownload.Day.Enable=option.ZoomDownload.Day.Enable; if (option.ZoomDownload.Minute && IFrameSplitOperator.IsBool(option.ZoomDownload.Minute.Enable)) chart.ZoomDownload.Minute.Enable=option.ZoomDownload.Minute.Enable; } 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.DrawPicture) //画图工具 { if (option.DrawPicture.StorageKey && chart.ChartDrawStorage) chart.ChartDrawStorage.Load(option.DrawPicture.StorageKey); } if (option.DrawTool) //画图工具 { if (option.DrawTool.StorageKey && chart.ChartDrawStorage) chart.ChartDrawStorage.Load(option.DrawTool.StorageKey); } if (IFrameSplitOperator.IsNumber(option.StepPixel)) chart.StepPixel=option.StepPixel; if (option.ZoomStepPixel>0) chart.ZoomStepPixel=option.ZoomStepPixel; if (option.IsApiPeriod==true) chart.IsApiPeriod=option.IsApiPeriod; //图形选中 if (option.SelectedChart) { var item=option.SelectedChart; if (IFrameSplitOperator.IsBool(item.EnableSelected)) chart.SelectedChart.EnableSelected=item.EnableSelected; if (IFrameSplitOperator.IsBool(item.EnableMoveOn)) chart.SelectedChart.EnableMoveOn=item.EnableMoveOn; } if (!option.Windows || option.Windows.length<=0) return null; //K线扩展计算方法配置 if (IFrameSplitOperator.IsNonEmptyArray(option.KLineCalcOption)) { for(var i=0;i 0) //一屏显示的数据个数 { let pageSize = chart.GetMaxMinPageSize(); if (pageSize.Max>10 && pageSize.Max < option.KLine.PageSize) chart.PageSize = pageSize.Max; else if (pageSize.Min>10 && pageSize.Min> option.KLine.PageSize) chart.PageSize=pageSize.Min; else chart.PageSize = option.KLine.PageSize; } } //取消显示十字光标刻度信息 if (option.IsCorssOnlyDrawKLine===true) chart.ChartCorssCursor.IsOnlyDrawKLine=option.IsCorssOnlyDrawKLine; if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (option.IsClickShowCorssCursor==true) chart.IsClickShowCorssCursor=option.IsClickShowCorssCursor; 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.IsBool(item.IsOnlyDrawKLine)) chart.ChartCorssCursor.IsOnlyDrawKLine = item.IsOnlyDrawKLine; //Y轴显示收盘价 if (option.CorssCursorInfo.PressTime) chart.PressTime=option.CorssCursorInfo.PressTime; //长按显示十字光标的时间 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.VLineType)) chart.ChartCorssCursor.VLineType=item.VLineType; if (option.CorssCursorInfo.DateFormatType>0) chart.ChartCorssCursor.StringFormatX.DateFormatType=option.CorssCursorInfo.DateFormatType; if (IFrameSplitOperator.IsBool(item.IsDrawXRangeBG)) chart.ChartCorssCursor.IsDrawXRangeBG=item.IsDrawXRangeBG; if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime; if (IFrameSplitOperator.IsNumber(item.TextHeight)) chart.ChartCorssCursor.TextHeight=item.TextHeight; if (item.RightButton) { if (IFrameSplitOperator.IsBool(item.RightButton.Enable)) chart.ChartCorssCursor.RightButton.Enable=item.RightButton.Enable; } if (IFrameSplitOperator.IsNumber(item.PriceFormatType)) chart.ChartCorssCursor.StringFormatY.PriceFormatType=item.PriceFormatType; if (IFrameSplitOperator.IsNumber(item.DataFormatType)) chart.ChartCorssCursor.StringFormatY.DataFormatType=item.DataFormatType; if (IFrameSplitOperator.IsBool(item.EnableKeyboard)) chart.ChartCorssCursor.EnableKeyboard=item.EnableKeyboard; } //保存十字光标文字高度 option.CorssCursor={}; option.CorssCursor.TitleHeight=chart.ChartCorssCursor.TextHeight; if (IFrameSplitOperator.IsNumber(option.SplashTitlePosition)) { if (chart.ChartSplashPaint) chart.ChartSplashPaint.Position=option.SplashTitlePosition; } if (option.Frame) { for(var i=0;i=0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace=item.TopSpace*pixelRatio; if (item.BottomSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace=item.BottomSpace*pixelRatio; if (item.RightTextPosition>0) chart.Frame.SubFrame[i].Frame.YTextPosition[1]=item.RightTextPosition; if (item.LeftTextPosition>0) chart.Frame.SubFrame[i].Frame.YTextPosition[0]=item.LeftTextPosition; 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 (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline; if (item.YCoordinateType>0) chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=item.YCoordinateType; if (item.IsYReverse==true) chart.Frame.SubFrame[0].Frame.CoordinateType=1; //反转坐标 if (IFrameSplitOperator.IsNumber(item.PercentageTextFormat)) subFrame.YSplitOperator.PercentageTextFormat=item.PercentageTextFormat; //百分比坐标格式 if (item.DefaultYMaxMin) chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultYMaxMin=item.DefaultYMaxMin; if (IFrameSplitOperator.IsBool(item.EnableRemoveZero)) chart.Frame.SubFrame[i].Frame.YSplitOperator.EnableRemoveZero=item.EnableRemoveZero; if (IFrameSplitOperator.IsPlusNumber(item.MinYDistance)) chart.Frame.SubFrame[i].Frame.MinYDistance=item.MinYDistance; if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine; if (IFrameSplitOperator.IsBool(item.IsShowIndexTitle)) chart.Frame.SubFrame[i].Frame.IsShowIndexTitle=item.IsShowIndexTitle; if (IFrameSplitOperator.IsBool(item.IsDrawTitleBottomLine)) subFrame.IsDrawTitleBottomLine=item.IsDrawTitleBottomLine; if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) chart.Frame.SubFrame[i].Frame.IsShowNameArrow=item.IsShowNameArrow; if (item.ClientBGColor) subFrame.ClientBGColor=item.ClientBGColor; } } if (option.KLine) { var item=option.KLine; var klineChart=chart.ChartPaint[0]; if (option.KLine.ShowKLine == false) klineChart.IsShow = false; if (option.KLine.InfoPosition>0) klineChart.InfoPosition=option.KLine.InfoPosition; if (IFrameSplitOperator.IsBool(item.IsShowMaxMinPrice)) klineChart.IsShowMaxMinPrice=item.IsShowMaxMinPrice; if (IFrameSplitOperator.IsNumber(item.OneLimitBarType)) klineChart.OneLimitBarType=item.OneLimitBarType; 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(IFrameSplitOperator.IsBool(item.IsTitleShowLatestData)) chart.IsTitleShowLatestData=item.IsTitleShowLatestData; } //叠加股票 if (option.Overlay) { for(var i=0;i0) chart.WindowIndex[i].StringFormat=item.StringFormat; if (item.FloatPrecision>=0) chart.WindowIndex[i].FloatPrecision=item.FloatPrecision; } } var frame=chart.Frame.SubFrame[i].Frame; if (IFrameSplitOperator.IsBool(item.Modify)) frame.ModifyIndex=item.Modify; if (IFrameSplitOperator.IsBool(item.Change)) frame.ChangeIndex=item.Change; if (IFrameSplitOperator.IsBool(item.Close)) frame.CloseIndex=item.Close; if (IFrameSplitOperator.IsBool(item.Overlay)) frame.OverlayIndex=item.Overlay; if (IFrameSplitOperator.IsBool(item.Export)) frame.ExportData=item.Export; if (IFrameSplitOperator.IsBool(item.MaxMin)) chart.Frame.SubFrame[i].Frame.MaxMinWindow=item.MaxMin; if (IFrameSplitOperator.IsBool(item.TitleWindow)) chart.Frame.SubFrame[i].Frame.TitleWindow=item.TitleWindow; if (item.IsDrawTitleBG==true) chart.Frame.SubFrame[i].Frame.IsDrawTitleBG=item.IsDrawTitleBG; if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) chart.Frame.SubFrame[i].Frame.IsShowNameArrow=item.IsShowNameArrow; if (IFrameSplitOperator.IsNumber(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight=item.TitleHeight; else item.TitleHeight=chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight; if (IFrameSplitOperator.IsBool(item.IsShowTitleArrow)) frame.IsShowTitleArrow=item.IsShowTitleArrow; if (IFrameSplitOperator.IsNumber(item.TitleArrowType)) frame.TitleArrowType=item.TitleArrowType; if (item.IsShowIndexName==false) chart.Frame.SubFrame[i].Frame.IsShowIndexName=false; if (item.IsShowOverlayIndexName==false) chart.Frame.SubFrame[i].Frame.IsShowOverlayIndexName=false; if (IFrameSplitOperator.IsNumber(item.IndexParamSpace)) chart.Frame.SubFrame[i].Frame.IndexParamSpace=item.IndexParamSpace; if (IFrameSplitOperator.IsNumber(item.IndexTitleSpace)) chart.Frame.SubFrame[i].Frame.IndexTitleSpace=item.IndexTitleSpace; if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) frame.HorizontalReserved=item.HorizontalReserved; if (item.OverlayIndexType) { if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.Position)) chart.Frame.SubFrame[i].Frame.OverlayIndexType.Position=item.OverlayIndexType.Position; if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.LineSpace)) chart.Frame.SubFrame[i].Frame.OverlayIndexType.LineSpace=item.OverlayIndexType.LineSpace; } } //叠加指标宽度 if (option.OverlayIndexFrameWidth>40) chart.Frame.FixedRightWidth.Overlay=option.OverlayIndexFrameWidth; //叠加指标 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); } } this.AdjustTitleHeight(chart); return chart; } //自定义指数历史K线图 this.CreateCustomKLineChartContainer=function(option) { var chart=new CustomKLineChartContainer(this.CanvasElement); //创建改参数div chart.ModifyIndexDialog=this.ModifyIndexDialog; //右键菜单 if (IFrameSplitOperator.IsBool(option.IsShowRightMenu)) chart.IsShowRightMenu=option.IsShowRightMenu; 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.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 (!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 (option.IsShowCorssCursorInfo==false) //取消显示十字光标刻度信息 { chart.ChartCorssCursor.IsShowText=option.IsShowCorssCursorInfo; } if (option.Frame) { for(var i=0;i{ return this.GetExtraCanvas(name); } if (option.EventCallback) this.SetEventCallback(chart, option.EventCallback); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; chart.ModifyIndexDialog=this.ModifyIndexDialog; var pixelRatio=GetDevicePixelRatio(); var windowsCount=2; if (option.Windows && option.Windows.length>0) windowsCount+=option.Windows.length; //指标窗口从第3个窗口开始 if (option.EnableScrollUpDown==true) chart.EnableScrollUpDown=option.EnableScrollUpDown; if (option.DisableMouse==true) chart.DisableMouse=option.DisableMouse; if (option.ScriptError) chart.ScriptErrorCallback=option.ScriptError; //指标执行错误回调 if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle=option.SplashTitle; if (IFrameSplitOperator.IsBool(option.EnableSelectRect)) chart.EnableSelectRect=option.EnableSelectRect; //是否启用区间选择 if (IFrameSplitOperator.IsBool(option.EnableZoomIndexWindow)) chart.EnableZoomIndexWindow=option.EnableZoomIndexWindow; if (IFrameSplitOperator.IsBool(option.IsDrawPictureXY)) chart.IsDrawPictureXY=option.IsDrawPictureXY; if (IFrameSplitOperator.IsBool(option.EnableNewIndex)) chart.EnableNewIndex=option.EnableNewIndex; if (IFrameSplitOperator.IsBool(option.EnableIndexChartDrag)) chart.EnableIndexChartDrag=option.EnableIndexChartDrag; if (IFrameSplitOperator.IsBool(option.EnableVerifyRecvData)) chart.EnableVerifyRecvData=option.EnableVerifyRecvData; if (IFrameSplitOperator.IsBool(option.EnableNightDayBG)) chart.EnableNightDayBG=option.EnableNightDayBG; if (option.GlobalOption) { var item=option.GlobalOption; if (IFrameSplitOperator.IsBool(item.IsValueFullRange)) chart.GlobalOption.IsValueFullRange=item.IsValueFullRange; if (IFrameSplitOperator.IsNumber(item.XDateFormat)) chart.GlobalOption.XDateFormat=item.XDateFormat; } if (option.DisplayLatest) { var item=option.DisplayLatest; if (IFrameSplitOperator.IsBool(item.Enable)) chart.DisplayLatestOption.Enable=item.Enable; if (IFrameSplitOperator.IsNumber(item.DelayTime)) chart.DisplayLatestOption.DelayTime=item.DelayTime; } if (option.DrawDynamicInfo) { var item=option.DrawDynamicInfo; if (IFrameSplitOperator.IsBool(item.Enable)) chart.DrawDynamicInfoOption.Enable=item.Enable; if (IFrameSplitOperator.IsNumber(item.DelayTime)) chart.DrawDynamicInfoOption.DelayTime=item.DelayTime; } if (option.Minute) //分钟走势图属性设置 { if (option.Minute.IsShowTooltip==false) chart.IsShowTooltip=false; if (option.Minute.DragMode>=0) chart.DragMode=option.Minute.DragMode; } if (option.Language) { var value=g_JSChartLocalization.GetLanguageID(option.Language); if (IFrameSplitOperator.IsNumber(value)) chart.LanguageID=value; } if (option.Info && option.Info.length>0) chart.SetMinuteInfo(option.Info,false); if (option.DrawTool) //画图工具 { if (option.DrawTool.StorageKey && chart.ChartDrawStorage) chart.ChartDrawStorage.Load(option.DrawTool.StorageKey); } if (option.BeforeOpen) //集合竞价 { var item=option.BeforeOpen; if (IFrameSplitOperator.IsBool(item.IsShow)) chart.IsShowBeforeData=item.IsShow; if (IFrameSplitOperator.IsNumber(item.Width)) chart.ExtendWidth.Left=item.Width; if (IFrameSplitOperator.IsBool(item.IsShowMultiDay)) chart.IsShowMultiDayBeforeData=item.IsShowMultiDay; if (IFrameSplitOperator.IsNumber(item.MulitiDayWidth)) chart.MultiDayExtendWidth.Left=item.MulitiDayWidth; } if (option.AfterClose) //收盘集合竞价 { var item=option.AfterClose; if (IFrameSplitOperator.IsBool(item.IsShow)) chart.IsShowAfterData=item.IsShow; if (IFrameSplitOperator.IsNumber(item.ShareVol)) chart.ShareAfterVol=item.ShareVol; if (IFrameSplitOperator.IsNumber(item.Width)) chart.ExtendWidth.Right=item.Width; if (IFrameSplitOperator.IsBool(item.IsShowMultiDay)) chart.IsShowMultiDayAfterData=item.IsShowMultiDay; if (IFrameSplitOperator.IsNumber(item.MulitiDayWidth)) chart.MultiDayExtendWidth.Right=item.MulitiDayWidth; } //图形选中 if (option.SelectedChart) { var item=option.SelectedChart; if (IFrameSplitOperator.IsBool(item.EnableSelected)) chart.SelectedChart.EnableSelected=item.EnableSelected; if (IFrameSplitOperator.IsBool(item.EnableMoveOn)) chart.SelectedChart.EnableMoveOn=item.EnableMoveOn; } if (chart.ClassName=="MinuteChartContainer") { if (!option.DragSelectRect) { option.DragSelectRect={ Enable:true }; //默认开启区间选中画布 } if (option.DragSelectRect) { var item=option.DragSelectRect; var zindex=10; if (IFrameSplitOperator.IsNumber(item.ZIndex)) zindex=item.ZIndex; if (item.Enable) this.CreateExtraCanvasElement(JSChart.RectDragCanvasKey, { ZIndex:zindex }); //创建独立的区间选择画布 } } //分页 if (option.PageInfo) chart.SetPageInfo(option.PageInfo); chart.Create(windowsCount,option); //创建子窗口 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 (option.CorssCursorInfo.RightTextFormat>0) chart.ChartCorssCursor.TextFormat.Right=option.CorssCursorInfo.RightTextFormat; if (option.CorssCursorInfo.IsOnlyDrawMinute == true) chart.ChartCorssCursor.IsOnlyDrawMinute = option.CorssCursorInfo.IsOnlyDrawMinute; //Y轴显示收盘价 if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime; if (item.RightButton) { if (IFrameSplitOperator.IsBool(item.RightButton.Enable)) chart.ChartCorssCursor.RightButton.Enable=item.RightButton.Enable; } 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.HPenType)) chart.ChartCorssCursor.HPenType=item.HPenType; if (IFrameSplitOperator.IsNumber(item.VPenType)) chart.ChartCorssCursor.VPenType=item.VPenType; if (IFrameSplitOperator.IsBool(item.EnableKeyboard)) chart.ChartCorssCursor.EnableKeyboard=item.EnableKeyboard; } if (option.MinuteInfo) chart.CreateMinuteInfo(option.MinuteInfo); if (IFrameSplitOperator.IsBool(option.IsShowRightMenu)) chart.IsShowRightMenu=option.IsShowRightMenu; if (IFrameSplitOperator.IsNumber(option.DayCount)) chart.DayCount=option.DayCount; this.SetChartBorder(chart, option); if (option.SplashTitle) chart.ChartSplashPaint.SplashTitle=option.SplashTitle; if (IFrameSplitOperator.IsBool(option.EnableBorderDrag)) { chart.EnableBorderDrag=option.EnableBorderDrag; } this.AdjustChartBorder(chart); 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 (item.RightTextFormat>0) chart.Frame.SubFrame[i].Frame.YSplitOperator.RightTextFormat=item.RightTextFormat; if (IFrameSplitOperator.IsNumber(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight=item.TitleHeight; if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine; if (IFrameSplitOperator.IsBool(item.EnableRemoveZero)) chart.Frame.SubFrame[i].Frame.YSplitOperator.EnableRemoveZero=item.EnableRemoveZero; if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) chart.Frame.SubFrame[i].Frame.YSplitOperator.FloatPrecision=item.FloatPrecision; 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 (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline; if (IFrameSplitOperator.IsBool(item.IsShowIndexTitle)) chart.Frame.SubFrame[i].Frame.IsShowIndexTitle=item.IsShowIndexTitle; if (item.TopSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace=item.TopSpace*pixelRatio; if (item.BottomSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace=item.BottomSpace*pixelRatio; //是否显示关闭集合竞价按钮 if (IFrameSplitOperator.IsNumber(item.CloseBeforeButton)) chart.Frame.SubFrame[i].Frame.IsShowCloseButton=item.CloseBeforeButton; if (item.ClientBGColor) subFrame.ClientBGColor=item.ClientBGColor; if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) subFrame.HorizontalReserved=item.HorizontalReserved; } chart.UpdateXShowText(); } if (option.ExtendChart) { for(var i=0;i0) chart.Frame.SubFrame[0].Frame.YSplitOperator.SplitType=option.MinuteLine.SplitType; } if (option.MinuteVol) { var item=option.MinuteVol; if (IFrameSplitOperator.IsNumber(item.BarColorType)) chart.ChartPaint[2].BarColorType=item.BarColorType; } if(option.MinuteTitle) { var item=option.MinuteTitle; if(IFrameSplitOperator.IsBool(item.IsShowName)) chart.TitlePaint[0].IsShowName=item.IsShowName; if(IFrameSplitOperator.IsBool(item.IsShowDate)) chart.TitlePaint[0].IsShowDate=item.IsShowDate; if(IFrameSplitOperator.IsBool(item.IsShowTime)) chart.TitlePaint[0].IsShowTime=item.IsShowTime; if(IFrameSplitOperator.IsBool(item.IsTitleShowLatestData)) chart.IsTitleShowLatestData=item.IsTitleShowLatestData; if(IFrameSplitOperator.IsBool(item.IsAlwaysShowLastData)) chart.TitlePaint[0].IsAlwaysShowLastData=item.IsAlwaysShowLastData; if(IFrameSplitOperator.IsNumber(item.ShowLastDataFormat)) chart.TitlePaint[0].ShowLastDataFormat=item.ShowLastDataFormat; if (IFrameSplitOperator.IsNumber(item.TitleBaseLine)) chart.TitlePaint[0].TitleBaseLine=item.TitleBaseLine; if (item.TimeFormat) chart.TitlePaint[0].TimeFormat=item.TimeFormat; } if (IFrameSplitOperator.IsBool(option.CorssCursorTouchEnd)) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (IFrameSplitOperator.IsBool(option.IsClickShowCorssCursor)) chart.IsClickShowCorssCursor=option.IsClickShowCorssCursor; if (option.IsShowBeforeData===true) chart.IsShowBeforeData=option.IsShowBeforeData; //分钟数据指标从第3个指标窗口设置 if (IFrameSplitOperator.IsNonEmptyArray(option.Windows)) { let scriptData = new JSIndexScript(); for(var i=0;i0) chart.WindowIndex[index].StringFormat=item.StringFormat; if (item.FloatPrecision>=0) chart.WindowIndex[index].FloatPrecision=item.FloatPrecision; } } var frame=chart.Frame.SubFrame[index].Frame; if (IFrameSplitOperator.IsBool(item.Modify)) frame.ModifyIndex=item.Modify; if (IFrameSplitOperator.IsBool(item.Change)) frame.ChangeIndex=item.Change; if (IFrameSplitOperator.IsBool(item.Close)) frame.CloseIndex=item.Close; if (IFrameSplitOperator.IsBool(item.Overlay)) frame.OverlayIndex=item.Overlay; if (IFrameSplitOperator.IsBool(item.Export)) frame.ExportData=item.Export; if (IFrameSplitOperator.IsBool(item.MaxMin)) frame.MaxMinWindow=item.MaxMin; if (IFrameSplitOperator.IsBool(item.TitleWindow)) frame.TitleWindow=item.TitleWindow; if (IFrameSplitOperator.IsNumber(item.YSplitType)) chart.Frame.SubFrame[index].Frame.YSplitOperator.SplitType=item.YSplitType; if (IFrameSplitOperator.IsNumber(item.FilterType)) chart.Frame.SubFrame[index].Frame.YSplitOperator.FilterType=item.FilterType; 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)) frame.IsShowTitleArrow=item.IsShowTitleArrow; if (IFrameSplitOperator.IsNumber(item.TitleArrowType)) frame.TitleArrowType=item.TitleArrowType; if (item.IsShowIndexName==false) chart.Frame.SubFrame[index].Frame.IsShowIndexName=false; if (item.IsShowOverlayIndexName==false) chart.Frame.SubFrame[index].Frame.IsShowOverlayIndexName=false; if (!IFrameSplitOperator.IsUndefined(item.HorizontalReserved)) frame.HorizontalReserved=item.HorizontalReserved; } } this.AdjustTitleHeight(chart); //叠加指标 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.CreateMinMinuteChartContainer=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.BeforeOpen) //集合竞价 { var item=option.BeforeOpen; if (IFrameSplitOperator.IsBool(item.IsShow)) chart.IsShowBeforeData=item.IsShow; if (IFrameSplitOperator.IsNumber(item.Width)) chart.ExtendWidth.Left=item.Width; if (IFrameSplitOperator.IsBool(item.IsShowMultiDay)) chart.IsShowMultiDayBeforeData=item.IsShowMultiDay; if (IFrameSplitOperator.IsNumber(item.MulitiDayWidth)) chart.MultiDayExtendWidth.Left=item.MulitiDayWidth; } if (option.AfterClose) //收盘集合竞价 { var item=option.AfterClose; if (IFrameSplitOperator.IsBool(item.IsShow)) chart.IsShowAfterData=item.IsShow; if (IFrameSplitOperator.IsNumber(item.ShareVol)) chart.ShareAfterVol=item.ShareVol; if (IFrameSplitOperator.IsNumber(item.Width)) chart.ExtendWidth.Right=item.Width; if (IFrameSplitOperator.IsBool(item.IsShowMultiDay)) chart.IsShowMultiDayAfterData=item.IsShowMultiDay; if (IFrameSplitOperator.IsNumber(item.MulitiDayWidth)) chart.MultiDayExtendWidth.Right=item.MulitiDayWidth; } if (!option.Listener) option.Listener={ KeyDown:false, Wheel:false }; chart.Create(windowsCount,option.Listener); //创建子窗口 if (option.CorssCursorInfo) { var item=option.CorssCursorInfo; if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.Left)) chart.ChartCorssCursor.ShowTextMode.Left=option.CorssCursorInfo.Left; if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.Right)) chart.ChartCorssCursor.ShowTextMode.Right=option.CorssCursorInfo.Right; if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.Bottom)) chart.ChartCorssCursor.ShowTextMode.Bottom=option.CorssCursorInfo.Bottom; if (option.CorssCursorInfo.IsShowCorss===false) chart.ChartCorssCursor.IsShowCorss=option.CorssCursorInfo.IsShowCorss; if (option.CorssCursorInfo.RightTextFormat>0) chart.ChartCorssCursor.TextFormat.Right=option.CorssCursorInfo.RightTextFormat; if (option.CorssCursorInfo.IsOnlyDrawMinute == true) chart.ChartCorssCursor.IsOnlyDrawMinute = option.CorssCursorInfo.IsOnlyDrawMinute; //Y轴显示收盘价 if (IFrameSplitOperator.IsBool(option.CorssCursorInfo.IsFixXLastTime)) chart.ChartCorssCursor.IsFixXLastTime=option.CorssCursorInfo.IsFixXLastTime; if (item.RightButton) { if (IFrameSplitOperator.IsBool(item.RightButton.Enable)) chart.ChartCorssCursor.RightButton.Enable=item.RightButton.Enable; } 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(option.CorssCursorInfo.HPenType)) chart.ChartCorssCursor.HPenType=option.CorssCursorInfo.HPenType; if (IFrameSplitOperator.IsNumber(option.CorssCursorInfo.VPenType)) chart.ChartCorssCursor.VPenType=option.CorssCursorInfo.VPenType; } if (IFrameSplitOperator.IsNumber(option.DayCount)) chart.DayCount=option.DayCount; this.SetChartBorder(chart, option); if (option.SplashTitle) chart.ChartSplashPaint.SplashTitle=option.SplashTitle; if (IFrameSplitOperator.IsBool(option.EnableVerifyRecvData)) chart.EnableVerifyRecvData=option.EnableVerifyRecvData; chart.TitlePaint[0].IsShow=false; //主窗口 隐藏刻度 var mainFrame=chart.Frame.SubFrame[0]; mainFrame.Frame.IsShowYText[0]=false; mainFrame.Frame.IsShowYText[1]=false; mainFrame.Frame.IsShowXLine=false; mainFrame.Frame.IsShowYLine=false; mainFrame.Frame.BorderLine=0; chart.Frame.SubFrame[1].Height=0; //隐藏成交量 chart.EnableBorderDrag=false; 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 (item.RightTextFormat>0) chart.Frame.SubFrame[i].Frame.YSplitOperator.RightTextFormat=item.RightTextFormat; if (IFrameSplitOperator.IsNumber(item.TitleHeight)) chart.Frame.SubFrame[i].Frame.ChartBorder.TitleHeight=item.TitleHeight; if (IFrameSplitOperator.IsNumber(item.BorderLine)) chart.Frame.SubFrame[i].Frame.BorderLine=item.BorderLine; if (IFrameSplitOperator.IsBool(item.EnableRemoveZero)) chart.Frame.SubFrame[i].Frame.YSplitOperator.EnableRemoveZero=item.EnableRemoveZero; if (IFrameSplitOperator.IsNumber(item.FloatPrecision)) chart.Frame.SubFrame[i].Frame.YSplitOperator.FloatPrecision=item.FloatPrecision; 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 (IFrameSplitOperator.IsNumber(item.YTextBaseline)) chart.Frame.SubFrame[i].Frame.YTextBaseline=item.YTextBaseline; } } chart.UpdateXShowText(); if (option.MinuteLine) { if (option.MinuteLine.IsDrawAreaPrice==false) chart.ChartPaint[0].IsDrawArea=false; if (option.MinuteLine.IsShowLead==false) chart.IsShowLead=false; if (option.MinuteLine.IsShowAveragePrice==false) { chart.ChartPaint[1].IsShow=false; chart.TitlePaint[0].IsShowAveragePrice=false; //标题栏均线也不显示 for(var i=0;i0) chart.Frame.SubFrame[0].Frame.YSplitOperator.SplitType=option.MinuteLine.SplitType; } this.AdjustTitleHeight(chart); if (option.DisableMouseEvent===true) { //取消鼠标事件 this.CanvasElement.onmousemove=(e)=>{ } this.CanvasElement.oncontextmenu=(e)=> { } this.CanvasElement.ondblclick=(e)=>{ } this.CanvasElement.onmousedown=(e)=> { } this.CanvasElement.onmouseout=(e)=>{ } this.CanvasElement.onmouseleave=(e)=>{ } } if (option.ExtendChart) { for(var i=0;i0) 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; } let scriptData = new JSIndexScript(); if (option.Windows) { for(var i=0;i=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 (IFrameSplitOperator.IsNumber(option.KLine.RightSpaceCount) && !isSimpleTrain) chart.RightSpaceCount=option.KLine.RightSpaceCount; } 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); this.AdjustChartBorder(chart); if (option.IsShowCorssCursorInfo==false) chart.ChartCorssCursor.IsShowText=option.IsShowCorssCursorInfo; //取消显示十字光标刻度信息 if (option.IsCorssOnlyDrawKLine===true) chart.ChartCorssCursor.IsOnlyDrawKLine=option.IsCorssOnlyDrawKLine; if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; if (option.IsClickShowCorssCursor==true) chart.IsClickShowCorssCursor=option.IsClickShowCorssCursor; if (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 (option.CorssCursorInfo.IsShowClose == true) chart.ChartCorssCursor.IsShowClose = option.CorssCursorInfo.IsShowClose; //Y轴显示收盘价 if (option.CorssCursorInfo.PressTime) chart.PressTime=option.CorssCursorInfo.PressTime; //长按显示十字光标的时间 if (option.CorssCursorInfo.HPenType>0) chart.ChartCorssCursor.HPenType=option.CorssCursorInfo.HPenType; if (option.CorssCursorInfo.VPenType>0) chart.ChartCorssCursor.VPenType=option.CorssCursorInfo.VPenType; } //保存十字光标文字高度 option.CorssCursor={}; option.CorssCursor.TitleHeight=chart.ChartCorssCursor.TextHeight; if (option.Frame) { for(var i=0;i0) chart.Frame.SubFrame[i].Height = item.Height; if (item.IsShowLeftText==false) chart.Frame.SubFrame[i].Frame.YSplitOperator.IsShowLeftText=item.IsShowLeftText; //显示左边刻度 if (item.IsShowRightText==false) chart.Frame.SubFrame[i].Frame.YSplitOperator.IsShowRightText=item.IsShowRightText; //显示右边刻度 } } if (option.KLine) { if (option.KLine.ShowKLine == false) chart.ChartPaint[0].IsShow = false; if (option.KLine.InfoPosition>0) chart.ChartPaint[0].InfoPosition=option.KLine.InfoPosition; if (option.KLine.IsShowMaxMinPrice == false) chart.ChartPaint[0].IsShowMaxMinPrice=option.KLine.IsShowMaxMinPrice; } if(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 (IFrameSplitOperator.IsNonEmptyArray(option.Overlay)) //叠加股票 { for(var i=0;i0) chart.ZoomStepPixel=option.ZoomStepPixel; if (IFrameSplitOperator.IsString(option.SplashTitle)) chart.LoadDataSplashTitle=option.SplashTitle; if (IFrameSplitOperator.IsBool(option.EnableVerifyRecvData)) chart.EnableVerifyRecvData=option.EnableVerifyRecvData; 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; } this.AdjustChartBorder(chart); 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.YLineType)) chart.Frame.YSplitOperator.LineType=item.YLineType; if (IFrameSplitOperator.IsNumber(item.XLineType)) chart.Frame.XSplitOperator.LineType=item.XLineType; 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; //X轴刻度个数 半边的 } return chart; } //根据option内容绘制图形 this.SetOption=function(option) { //toolbar按钮风格 if (IFrameSplitOperator.IsNumber(option.ToolbarButtonStyle)) g_JSChartResource.ToolbarButtonStyle=option.ToolbarButtonStyle; 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.CreateMinMinuteChartContainer(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; chart.DivElement=this.DivElement; if (option.EnableResize==true) this.CreateResizeListener(); if (option.DefaultCursor) chart.DefaultCursor=option.DefaultCursor; if (option.OnCreatedCallback) option.OnCreatedCallback(chart); //是否自动更新 if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate; if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; //内置菜单 if (option.EnablePopMenuV2===true) chart.InitalPopMenu(); //画图工具 if (option.EnableDrawToolDialogV2===true) chart.InitalDrawToolDialog(); if (option.EnableModifyDrawDialogV2===true) chart.InitalModifyDrawDialog(); //K线tooltip if (option.TooltipDialog && option.TooltipDialog.Enable) chart.InitalTooltipDialog(option.TooltipDialog); if (option.FloatTooltip && option.FloatTooltip.Enable) chart.InitalFloatTooltip(option.FloatTooltip); if (option.SelectRectDialog && option.SelectRectDialog.Enable) chart.InitalSelectRectDialog(option.SelectRectDialog); if (option.SearchIndexDialog && option.SearchIndexDialog.Enable) chart.InitalSearchIndexDialog(option.SearchIndexDialog); //注册事件 if (option.EventCallback) { for(var i=0;i{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } this.OnDivResize=function(entries) { JSConsole.Chart.Log("[JSChart::OnDivResize] entries=", entries); this.OnSize( {Type:1} ); } //创建工具条 this.CreateToolbar=function(option) { } //创建设置div窗口 this.CreateSettingDiv=function(option) { } this.Focus=function() { if (this.CanvasElement) this.CanvasElement.focus(); } //切换股票代码接口 this.ChangeSymbol=function(symbol, option) { if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol,option); } //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); } 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.ChangeScriptIndex=function(windowIndex,indexData,option) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeScriptIndex)=='function') this.JSChartContainer.ChangeScriptIndex(windowIndex,indexData,option); } this.ChangePyScriptIndex=function(windowIndex, indexData) //切换py指标 { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangePyScriptIndex)=='function') this.JSChartContainer.ChangePyScriptIndex(windowIndex,indexData); } this.GetIndexInfo=function() { if (this.JSChartContainer && typeof(this.JSChartContainer.GetIndexInfo)=='function') return this.JSChartContainer.GetIndexInfo(); else return []; } this.ChangeInstructionIndex=function(indexName, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeInstructionIndex)=='function') this.JSChartContainer.ChangeInstructionIndex(indexName, option); } this.ChangeInstructionScriptIndex=function(indexData) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeInstructionIndex)=='function') this.JSChartContainer.ChangeInstructionScriptIndex(indexData); } this.CancelInstructionIndex=function() { if (this.JSChartContainer && typeof(this.JSChartContainer.CancelInstructionIndex)=='function') this.JSChartContainer.CancelInstructionIndex(); } //K线周期切换 this.ChangePeriod=function(period, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangePeriod)=='function') this.JSChartContainer.ChangePeriod(period, option); } //K线复权切换 this.ChangeRight=function(right) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeRight)=='function') this.JSChartContainer.ChangeRight(right); } //叠加股票 this.OverlaySymbol=function(symbol,option) { if (this.JSChartContainer && typeof(this.JSChartContainer.OverlaySymbol)=='function') this.JSChartContainer.OverlaySymbol(symbol,option); } //删除一个叠加股票 this.DeleteOverlaySymbol=function(symbol) { if (this.JSChartContainer && typeof(this.JSChartContainer.DeleteOverlaySymbol)=='function') this.JSChartContainer.DeleteOverlaySymbol(symbol); } //设置当前屏的起始日期 { 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线 4=面积图 5=订单流 this.ChangeKLineDrawType=function(drawType, isDraw, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.ChangeKLineDrawType)=='function') this.JSChartContainer.ChangeKLineDrawType(drawType,isDraw, option); } //指标窗口个数 this.ChangeIndexWindowCount = function(count, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ChangeIndexWindowCount) == 'function') { this.JSChartContainer.ChangeIndexWindowCount(count,option); } } //取消叠加 this.ClearOverlaySymbol = function(){ if(this.JSChartContainer && typeof(this.JSChartContainer.ClearOverlaySymbol) == 'function'){ this.JSChartContainer.ClearOverlaySymbol(); } } this.DeleteKLineInfo=function(infoName) { if(this.JSChartContainer && typeof(this.JSChartContainer.DeleteKLineInfo) == 'function') { this.JSChartContainer.DeleteKLineInfo(infoName); } } this.ClearKLineInfo=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.ClearKLineInfo) == 'function') { this.JSChartContainer.ClearKLineInfo(); } } this.AddKLineInfo=function(infoName, bUpdate) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddKLineInfo) == 'function') { this.JSChartContainer.AddKLineInfo(infoName,bUpdate); } } this.AddOverlayIndex=function(obj) //{WindowIndex:窗口ID, IndexName:指标ID, Identify:叠加指标ID(可选), API} { if (this.JSChartContainer && typeof(this.JSChartContainer.AddOverlayIndex)=='function') this.JSChartContainer.AddOverlayIndex(obj); } this.MoveOverlayIndex=function(src, dest, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.MoveOverlayIndex)=='function') this.JSChartContainer.MoveOverlayIndex(src, dest, option); } this.MoveOverlayIndexToNewWindow=function(src, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.MoveOverlayIndexToNewWindow)=='function') this.JSChartContainer.MoveOverlayIndexToNewWindow(src, option); } this.DeleteOverlayWindowsIndex=function(identify) { if (this.JSChartContainer && typeof(this.JSChartContainer.DeleteOverlayWindowsIndex)=='function') this.JSChartContainer.DeleteOverlayWindowsIndex(identify); } this.StopAutoUpdate=function() { if (this.JSChartContainer && typeof(this.JSChartContainer.StopAutoUpdate)=='function') this.JSChartContainer.StopAutoUpdate(); } this.ChartDestroy=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestroy) == 'function') { this.JSChartContainer.ChartDestroy(); } } this.ChartDestory=this.ChartDestroy; //版本写错了,继续使用 //设置深度图数据 depthData=[ {ID:深度图ID, Data:数据},] option={ Draw: true/false } this.SetDepthMapData=function(depthData, option) { if (this.JSChartContainer && typeof(this.JSChartContainer.SetDepthMapData)=='function') this.JSChartContainer.SetDepthMapData(depthData, 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, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ChangeDayCount)=='function') { JSConsole.Chart.Log('[JSChart:ChangeDayCount] count', count); this.JSChartContainer.ChangeDayCount(count,option); } } //集合竞价显示/隐藏 this.ShowCallAuctionData=function(obj, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ShowCallAuctionData)=='function') { JSConsole.Chart.Log('[JSChart:ShowCallAuctionData] obj, option ', obj, option); this.JSChartContainer.ShowCallAuctionData(obj, option); } } //返回弹幕数据类 this.StartAnimation=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.StartAnimation)=='function') { JSConsole.Chart.Log('[JSChart:StartAnimation] start.'); return this.JSChartContainer.StartAnimation(option); } } this.StopAnimation=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.StopAnimation)=='function') { JSConsole.Chart.Log('[JSChart:StopAnimation] start.'); return this.JSChartContainer.StopAnimation(); } } this.SaveToImage = function (format,colorGB) //format=保存的文件格式, colorGB=背景色 { if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImage) == 'function') return this.JSChartContainer.SaveToImage(format,colorGB); } this.SaveToImageUrl=function(obj, callback) { if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImageUrl) == 'function') return this.JSChartContainer.SaveToImageUrl(obj, callback); } //事件回调 this.AddEventCallback=function(obj) { 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.ChangeIndexTemplate=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ChangeIndexTemplate)=='function') { JSConsole.Chart.Log('[JSChart:ChangeIndexTemplate] ', option); this.JSChartContainer.ChangeIndexTemplate(option); } } //画图工具 this.SetChartDrawOption=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.SetChartDrawOption)=='function') { JSConsole.Chart.Log('[JSChart:SetChartDrawOption] ', option); this.JSChartContainer.SetChartDrawOption(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); } } this.AddChartDrawPicture=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddChartDrawPicture)=='function') { JSConsole.Chart.Log('[JSChart:AddChartDrawPicture] ', obj); return this.JSChartContainer.AddChartDrawPicture(obj); } } //删除画图工具 this.ClearChartDrawPicture=function(drawPicture, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ClearChartDrawPicture)=='function') { //JSConsole.Chart.Log('[JSChart:ClearChartDrawPicture] ', drawPicture); this.JSChartContainer.ClearChartDrawPicture(drawPicture, option); } } //复制一个画图 this.PasteChartDrawPicture=function(data, frameID, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.PasteChartDrawPicture)=='function') { JSConsole.Chart.Log('[JSChart:PasteChartDrawPicture] ', data, frameID, option); return this.JSChartContainer.PasteChartDrawPicture(data, frameID, option); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } this.EnableSplashScreen=function(enable, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.EnableSplashScreen)=='function') { JSConsole.Chart.Log('[JSChart:EnableSplashScreen] '); this.JSChartContainer.EnableSplashScreen(enable, option); } } this.Draw=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.Draw)=='function') { JSConsole.Chart.Log('[JSChart:Draw] '); this.JSChartContainer.Draw(); } } this.SetFocus=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.SetFocus)=='function') { JSConsole.Chart.Log('[JSChart:SetFocus] '); this.JSChartContainer.SetFocus(); } } //数据导出, option={ Start:{ Date, Time:可选}, End:{Date: Time:可选} } this.ExportData=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ExportData)=='function') { JSConsole.Chart.Log('[JSChart:ExportData] '); return this.JSChartContainer.ExportData(option); } } this.ChangePriceGap=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ChangePriceGap)=='function') { JSConsole.Chart.Log('[JSChart:ChangePriceGap] '); return this.JSChartContainer.ChangePriceGap(option); } } this.PopupMenuByTab=function(menuData, rtTab) { if(this.JSChartContainer && typeof(this.JSChartContainer.PopupMenuByTab)=='function') { JSConsole.Chart.Log('[JSChart:PopupMenuByTab] '); return this.JSChartContainer.PopupMenuByTab(menuData, rtTab); } } this.PopupMenuByDrapdown=function(menuData, rtButton) { if(this.JSChartContainer && typeof(this.JSChartContainer.PopupMenuByDrapdown)=='function') { JSConsole.Chart.Log('[JSChart:PopupMenuByDrapdown] '); return this.JSChartContainer.PopupMenuByDrapdown(menuData, rtButton); } } } JSChart.LastVersion=null; //最新的版本号 JSChart.EnableCanvasWillReadFrequently=false; //https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequently JSChart.CorssCursorCanvasKey="hqchart_corsscursor"; JSChart.TooltipCursorCanvasKey="hqchart_tooltip"; JSChart.RectDragCanvasKey="hqchart_drag_rect"; //初始化 JSChart.Init=function(divElement,bScreen,bCacheCanvas) { var jsChartControl=new JSChart(divElement,bScreen,bCacheCanvas); jsChartControl.OnSize(); return jsChartControl; } JSChart.SetDomain=function(domain,cacheDomain) { if (domain) g_JSChartResource.Domain=domain; if (cacheDomain) g_JSChartResource.CacheDomain=cacheDomain; } JSChart.SetPyIndexDomain=function(domain) //设置py指标计算api域名 { if (domain) g_JSChartResource.PyIndexDomain=domain; } //自定义风格 JSChart.SetStyle=function(option) { if (option) g_JSChartResource.SetStyle(option); } //value { EN:'', CH:'' } JSChart.SetTextResource=function(key,value) { g_JSChartLocalization.SetTextResource(key,value); } //获取本地化资源 JSChart.GetLocalization=function() { return g_JSChartLocalization; } //获取设备分辨率比 JSChart.GetDevicePixelRatio=function() { return GetDevicePixelRatio(); } JSChart.CreateGuid=function() { return Guid(); } JSChart.GetResource=function() //获取颜色配置 (设置配必须啊在JSChart.Init()之前) { return g_JSChartResource; } JSChart.GetMinuteTimeStringData=function() { return g_MinuteTimeStringData; } JSChart.GetMinuteCoordinateData=function() { return g_MinuteCoordinateData; } JSChart.GetKLineZoom=function() //K线缩放配置 { return ZOOM_SEED; } JSChart.SetKLineZoom=function(aryZoom) //设置K线缩放比例 { ZOOM_SEED=aryZoom; } JSChart.GetDivTooltipDataFormat=function() //div tooltip数据格式化 { return g_DivTooltipDataForamt; } JSChart.GetKLineCustomCalulate=function() //K线额外计算 { return g_KLineCustomCalulate; } JSChart.SetUSATimeType=function(type) //设置 0=标准时间 1=夏令时间 3=美国时间 { g_NYMEXTimeData.TimeType=type; g_COMEXTimeData.TimeType=type; g_NYBOTTimeData.TimeType=type; g_CBOTTimeData.TimeType=type; } JSChart.GetChinaFuturesTimeData=function() //获取国内期货交易时间配置 { return g_FuturesTimeData; } JSChart.AddPeriodCallback=function(obj) //添加自定义周期方法 { Period:周期ID, Callback:回调 } { g_DataPlus.AddPeriodCallback(obj); } JSChart.RemovePeriodCallback=function(obj) //添加自定义周期方法 { Period:周期ID, } { g_DataPlus.RemovePeriodCallback(obj); } //注册一个新的画图工具 {Name:中文名字, ClassName:类名, Create:function()} JSChart.RegisterDrawPicture=function(obj) { return IChartDrawPicture.RegisterDrawPicture(obj); } //注册一个新图标 {Name:, Text: , Color:, Family:} JSChart.RegisterDrawPictureIonFont=function(obj) { return IChartDrawPicture.RegisterIonFont(obj); } JSChart.GetInternalTimeData=function(name) //内置品种交易时间 { switch(name) { case "NYMEXTimeData": return g_NYMEXTimeData; case "COMEXTimeData": return g_COMEXTimeData; case "NYBOTTimeData": return g_NYBOTTimeData; case "CBOTTimeData": return g_CBOTTimeData; case "LMETimeData": return g_LMETimeData; case "FuturesTimeData": return g_FuturesTimeData; case "TOCOMTimeData": //东京商品交易所(TOCOM return g_TOCOMTimeData; case "IPETimeData": return g_IPETimeData; //美国洲际交易所 default: return null; } } //注册外部扩展图形 //option:{ Create:创建类方法 } JSChart.RegisterExtendChartClass=function(name, option) { return g_ExtendChartPaintFactory.Add(name,option); } JSChart.AddExtendCallbackDraw=function(className) { return g_ExtendChartPaintFactory.AddCallbackDrawClassName(className); } //注册外部图形类 //option:{ Create:创建类方法 } JSChart.RegisterChartPaintClass=function(name, option) { return g_ChartPaintFactory.Add(name, option); } //注册外部指标图形 JSChart.RegisterScriptIndexChart=function(name, option) { return g_ScriptIndexChartFactory.Add(name, option); } //注册设置对话框类 //option:{ Create:创建类方法 } JSChart.RegisterDialogClass=function(name, option) { return g_DialogFactory.Add(name, option); } //注册框架类 JSChart.RegisterChartFrameClass=function(name, option) { return g_ChartFrameFactory.Add(name, option); } //一些公共函数 JSChart.ToFixedPoint=function(value) { return ToFixedPoint(value); } JSChart.ToFixedPoint2=function(width, value) { return ToFixedPoint2(width, value); } JSChart.ToFixedRect=function(value) { return ToFixedRect(value); } JSChart.GetScrollPosition=function() { return GetScrollPosition(); } //品种小数位数 JSChart.GetfloatPrecision=function(symbol) { return GetfloatPrecision(symbol); } var JSCHART_EVENT_ID= { //RECV_KLINE_MATCH:1, //接收到形态匹配 RECV_INDEX_DATA:2, //接收指标数据 RECV_HISTROY_DATA:3,//接收到历史数据 RECV_TRAIN_MOVE_STEP:4, //接收K线训练,移动一次K线 CHART_STATUS:5, //每次Draw() 以后会调用 BARRAGE_PLAY_END:6, //单个弹幕播放完成 RECV_OVERLAY_INDEX_DATA:7,//接收叠加指标数据 DBCLICK_KLINE:8, //双击K线图 RECV_START_AUTOUPDATE:9, //开始自动更新 RECV_STOP_AUTOUPDATE:10, //停止自动更新 ON_CONTEXT_MENU:11, //右键菜单事件 ON_TITLE_DRAW:12, //标题信息绘制事件 ON_SELECT_RECT:13, //区间选择事件通知 RECV_MINUTE_DATA:14, //分时图数据到达 ON_CLICK_INDEXTITLE:15, //点击指标标题事件 RECV_KLINE_UPDATE_DATA:16, //K线日,分钟更新数据到达 ON_CLICK_DRAWPICTURE:17, //点击画图工具 ON_FINISH_DRAWPICTURE:18, //完成画图工具 ON_INDEXTITLE_DRAW:19, //指标标题重绘事件 ON_CUSTOM_VERTICAL_DRAW:20, //自定义X轴绘制事件 RECV_KLINE_MANUAL_UPDATE_DATA:21, //手动更新K线事件 ON_ENABLE_SPLASH_DRAW:22, //开启/关闭过场动画事件 ON_CLICK_CHART_PAINT:23, //点击图形 ON_DRAW_MINUTE_LAST_POINT:24, //分时图绘制回调事件, 返回最后一个点的坐标 ON_DRAW_DEPTH_TOOLTIP:25, //绘制深度图tooltip事件 ON_CLICK:26, //点击事件 ON_PHONE_TOUCH:27, //手势点击事件 包含 TouchStart 和 TouchEnd ON_CLICKUP_CHART_PAINT:28, //点击图形鼠标抬起 ON_SPLIT_YCOORDINATE:29, //分割Y轴及格式化刻度文字 ON_DBCLICK:30, ON_SPLIT_XCOORDINATE:31, //分割X轴及格式化刻度文字 ON_KEYDOWN_SELECT_RECT:32, //键盘空格区间选择完成事件 ON_DRAG_SELECT_RECT:33, //区间选择区域变动 ON_DRAG_SELECT_RECT_MOUSEUP:34, //区间选择区域变动鼠标松开 ON_DRAW_KLINE_LAST_POINT:35, //K线图绘制回调事件,返回最后一个点的坐标 ON_CLICK_CROSSCURSOR_RIGHT:36, //十字光标右边按钮 ON_PLAY_SOUND:37, //播放声音 { Name:, Data: } ON_CALCULATE_INDEX_OX:38, //创建OX指标回调 ON_LOAD_DRAWPICTURE:39, //加载画图工具 //ON_SAVE_DRAWPICTURE:40 //画图工具存盘 ON_DRAW_COUNTDOWN:41, //倒计时回调 ON_BIND_DRAWICON:42, //小程序用到,h5无效 ON_DRAW_DEAL_VOL_COLOR:43, //成交明细 成交量颜色 ON_DRAW_DEAL_TEXT:44, //成交明细 自定义字段 ON_FILTER_DEAL_DATA:45, //成交明细 数据过滤回调 ON_FILTER_REPORT_DATA:46, //报价列表 数据过滤回调 ON_CLICK_REPORT_ROW:47, //点击报价列表 ON_REPORT_MARKET_STATUS:48, //报价列表交易状态 ON_DBCLICK_REPORT_ROW:49, //双击报价列表 ON_RCLICK_REPORT_ROW:50, //右键点击列表 ON_CLICK_REPORT_HEADER:51, //单击表头 ON_RCLICK_REPORT_HEADER:52, //右键点击表头 ON_REPORT_LOCAL_SORT:53, //报价列表本地排序 ON_DRAW_REPORT_NAME_COLOR:54, //报价列表股票名称列颜色 ON_DRAW_CUSTOM_TEXT:55, //报价列表自定义列 ON_CLICK_REPORT_TAB:56, //报价列表标签点击 ON_CLICK_REPORT_TABMENU:57, //报价列表标签菜单点击 ON_DRAW_REPORT_FIXEDROW_TEXT:58, //报价列表固定行绘制 ON_CLICK_REPORT_FIXEDROW:59, //点击报价列表点击固定行 ON_RCLICK_REPORT_FIXEDROW:60, //点击报价列表右键点击固定行 ON_KEYDOWN_SELECT_RECT_FIRST:61, //区间选择第1个位置事件 ON_CLICK_FRAME_TOOLBAR:62, //指标标题工具栏 ON_REPORT_DRAG_ROW:63, //自选股行拖拽 ON_MOUSE_MOVE:64, //鼠标移动 ON_MINUTE_PAGE_CHANGED:65, //分时图翻页事件 ON_DRAG_SUB_SELECT_RECT:66, //拖拽区间选择子区域 ON_DRAG_SUB_SELECT_RECT_MOUSEUP:67, //拖拽区间选择子区域鼠标松开 ON_KEYBOARD_SELECTED:68, //键盘精灵选中回车 ON_KEYBOARD_MOUSEUP:69, ON_CLICK_DRAWPICTURE_BUTTON:70, //画图工具按钮 ON_FINISH_MOVE_DRAWPICTURE:71, //画图工具移动完成 ON_CLICK_EXTENDCHART_BUTTON:72, ON_SCROLLBAR_SLIDER_CHANGED:73, //滚动条拖动 ON_DISPLAY_LATEST:74, //显示最新数据 ON_FORMAT_CORSSCURSOR_Y_TEXT:75, //格式化十字光标Y轴文字 ON_FORMAT_INDEX_OUT_TEXT:76, //格式化指标标题文字 ON_FORMAT_CORSSCURSOR_X_TEXT:77, //格式化十字光标X轴文字 ON_REPORT_MOUSE_MOVE:78, //鼠标移动 { x,y, Cell:单元格} ON_REPORT_DRAG_HEADER_TOOLTIP:88, //表头拖动提示信息 ON_REPORT_DRAW_CUSTOM_ICON:89, //表格自定义图标 ON_REPORT_DRAW_KLINE:90, //表格绘制K线 ON_DBCLICK_REPORT_DRAG_COLUMN_WIDTH:91, //双击表头拖动宽度 ON_REPORT_FORMAT_DRAW_INFO:92, //单元格输出信息 ON_FORMAT_INDEX_Y_LABEL:93, //格式化指标右侧Y轴刻度输出 ON_FORMAT_OVERLAY_INDEX_Y_LABEL:94, //格式化叠加指标右侧Y轴刻度输出 ON_CUSTOM_UNCHANGE_KLINE_COLOR:95, //定制平盘K线颜色 ON_CLICK_TITLE_BUTTON:96, //指标标题按钮 ON_CUSTOM_LEFT_TOOLBAR:97, ON_CUSTOM_RIGHT_TOOLBAR:98, ON_REPORT_DRAG_COLUMN_WIDTH:99, //拖动列宽 ON_CUSTOM_UNCHANGE_KLINE_TITLE_COLOR:100, //定制平盘K线标题颜色 ON_CHANGE_KLINE_PERIOD:101, //切换周期 ON_MINUTE_TOUCH_ZOOM:102, //分时图手势缩放 ON_RELOAD_INDEX_CHART_RESOURCE:103, //加载指标图形额外资源 ON_RELOAD_OVERLAY_INDEX_CHART_RESOURCE:104, //加载叠加指标图形额外资源 ON_CREATE_FRAME:105, ON_DELETE_FRAME:106, ON_SIZE_FRAME:107, ON_TOUCH_SCROLL_UP_DOWN:108, //页面上下滚动 手机端 ON_RECV_REALTIME_DATA:109, //实时数据 ON_CUSTOM_OVERLAY_TOOLBAR:110, //自定义叠加指标按钮 //绘图之前的事件 ON_BEFORE_DRAW:111, ON_BEFORE_DRAW_DYNAMIC_INFO:112, //自定义图形拖拽 ON_CUSTOM_DRAG_MOUSE_DOWN:113, ON_CUSTOM_DRAG_DOC_MOUSE_MOVE:114, ON_CUSTOM_DRAG_DOC_MOUSE_UP:115, ON_CUSTOM_DRAG_MOUSE_MOVE:116, ON_KEYDOWN:117, ON_CREATE_OVERLAY_FRAME:118, //创建叠加框架回调 ON_CREATE_CUSTOM_Y_COORDINATE:119, //自定义Y轴刻度 ON_BEFORE_DRAW_SPLASH_SCREEN:120, //T型报价 ON_TREPORT_MARKET_STATUS:121, //T型报价列表交易状态 ON_DBCLICK_TREPORT_ROW:122, //双击T型报报价列表 ON_RCLICK_TREPORT_ROW:123, //右键点击T型报价列表 ON_CLICK_TREPORT_HEADER:124, //单击T型报价表头 ON_RCLICK_TREPORT_HEADER:125, //右键点击T型报价表头 ON_TREPORT_LOCAL_SORT:126, //T型报价列表本地排序 ON_CLICK_TREPORT_ROW:127, //左键点击点击T型报价列表 ON_MOVE_SELECTED_TREPORT_ROW:128, //选中行变动 ON_DRAW_REPORT_ROW_BG:140, //报价列表整行背景 ON_CLICK_REPORT_CHECKBOX:141, //报价列表checkbox ON_CLICK_REPORT_BUTTON:142, //报价列表按钮 ON_CLICK_REPORT_LINK:143, //报价列表 链接 ON_CREATE_REPORT_HEADER_MENU:144, //报价列表 表头菜单 ON_CHANGE_INDEX:150, //切换指标 ON_MENU_COMMAND:151, //菜单事件回调 ON_CREATE_RIGHT_MENU:152, //创建右键菜单 ON_FORMAT_CALL_AUCTION_INDEX_TITLE:153, //集合竞价指标窗口标题内容 ON_FORMAT_KLINE_HIGH_LOW_TITLE:154, //K线最高最低价格式化内容 ON_CUSTOM_CORSSCURSOR_POSITION:155, //自定义十字光标X轴的输出的位置 ON_CUSTOM_MINUTE_NIGHT_DAY_X_INDEX:156, //日盘夜盘的分界线 ON_CUSTOM_MINUTE_BG:157, //自定义分时图背景颜色 ON_CLICK_HORIZONTAL_LABEL:158, //点击Y轴刻度标签 ON_FORMAT_DIALOG_TOOLTIP:159, //格式化Tooltip对话框显示文字 ON_CHANGE_KLINE_RIGHT:160, //切换复权 ON_FORMAT_KLINE_FLOAT_TOOLTIP:161, //格式化k线浮动框显示文字 ON_FORMAT_KLINE_INFO_FLOAT_TOOLTIP:162, //格式化信息地雷显示文字 } var JSCHART_OPERATOR_ID= { OP_SCROLL_LEFT:1, //往左移动 OP_SCROLL_RIGHT:2, //往右移动 OP_ZOOM_OUT:3, //缩小 OP_ZOOM_IN:4, //放大 OP_GOTO_HOME:5, //最新一天数据 OP_GOTO_END:6, //第1天的数据 OP_LEFT_ZOOM_OUT:7, //左边缩小 OP_LEFT_ZOOM_IN:8, //左右放大 OP_RIGHT_ZOOM_OUT:9, //右边缩小 OP_RIGHT_ZOOM_IN:10, //右边放大 OP_SCROLL_GOTO:11, //滚动条移动到某一个位置 OP_SET_SELECTRECT:12, //区间选择 OP_SET_SUB_SELECTRECT:13, //区间选择子区域 OP_CORSSCURSOR_GOTO:14, //十字光标移动某一个时刻点 OP_SCROOLBAR_SLIDER_CHANGED:15, //滑块变动 OP_GOTO:16, //移动到某一个天或某一个分钟 OP_GOTO_BY_DATAINDEX:17, //的移动到某一个数据起始位置 } var JSCHART_DRAG_ID= { DISABLE_DRAG_ID:0, CLICK_TOUCH_MODE_ID:3 //长按十字光标显示保留/点击十字光标消失 (使用TouchStatus) } var JSCHART_BUTTON_ID= { CLOSE_BEFOREOPEN_ID:1, //关闭集合竞价 CLOSE_OVERLAY_INDEX:2, //关闭叠加指标 MODIFY_INDEX_PARAM:3, //改指标参数 CHANGE_INDEX:4, //换指标 CLOSE_INDEX_WINDOW:5, //关闭指标窗口 OVERLAY_INDEX:6, //叠加指标 MODIFY_OVERLAY_INDEX_PARAM:7, //改叠加指标参数 CHIP_DEFULT:8, CHIP_LONG:9, CHIP_RECENT:10, MAX_MIN_WINDOW:11, //指标窗口最大最小化 TITLE_WINDOW:12, //指标窗口只显示标题 //画图工具 DRAW_PICTURE_DELETE:13, DRAW_PICTURE_SETTING:14, EXTEND_CHART_BUTTON_ID:15, //扩展画法按钮事件 EXPORT_DATA:16, //画图工具 按钮预留18个 DRAW_PICTURE_BUTTON_1:17, DRAW_PICTURE_BUTTON_2:18, DRAW_PICTURE_BUTTON_3:19, DRAW_PICTURE_BUTTON_4:20, DRAW_PICTURE_BUTTON_5:21, DRAW_PICTURE_BUTTON_6:22, DRAW_PICTURE_BUTTON_7:23, DRAW_PICTURE_BUTTON_8:24, DRAW_PICTURE_BUTTON_9:25, DRAW_PICTURE_BUTTON_10:26, DRAW_PICTURE_BUTTON_11:27, DRAW_PICTURE_BUTTON_12:28, DRAW_PICTURE_BUTTON_13:29, DRAW_PICTURE_BUTTON_14:30, DRAW_PICTURE_BUTTON_15:31, DRAW_PICTURE_BUTTON_16:32, DRAW_PICTURE_BUTTON_17:33, DRAW_PICTURE_BUTTON_18:34, //弹出菜单 POP_MENU_1:40, POP_MENU_2:41, POP_MENU_3:42, INDEX_NAME_BUTTON:43 } var JSCHART_DATA_FIELD_ID= { KLINE_ORDERFLOW:99, MINUTE_MULTI_DAY_EXTENDDATA:21, //多日分时图扩展数据序号 MINUTE_DAY_EXTENDDATA:21, MINUTE_BEFOREOPEN_EXTENDDATA:21, MINUTE_AFTERCLOSE_EXTENDDATA:21, KLINE_COLOR_DATA:66, //K线自定义颜色数据 KLINE_DAY_EXTENDDATA:25, KLINE_MINUTE_EXTENDDATA:25, //OrderBook Heatmap KLINE_HEATMAP:67, } var JSCHART_WORKER_MESSAGE_ID= { EXECUTE_SCRIPT:1, //工作线程执行脚本 FINISH_EXECUTE_SCRIPT:2, //脚本执行完成 ERROR_EXECUTE_SCRIPT:3, } var JSCHART_MENU_ID= { CMD_CHANGE_PERIOD_ID:1, //切换周期 CMD_CHANGE_WINDOW_COUNT_ID:2, //窗口个数 CMD_CHANGE_RIGHT_ID:3, //复权 CMD_CHANGE_INDEX_ID:4, //切换指标 CMD_CHANGE_COLOR_INDEX_ID:5, //五彩K线指标 CMD_CHANGE_TRADE_INDEX_ID:6, //专家系统(交易指标) CMD_DELETE_COLOR_INDEX_ID:7, //删除五彩K线指标 CMD_DELETE_TRADE_INDEX_ID:8, //删除专家系统(交易指标) CMD_CHANGE_KLINE_TYPE_ID:9, //切换K线类型 CMD_CHANGE_PRICE_GAP_ID:10, //缺口提示 CMD_OVERLAY_SYMBOL_ID:11, //叠加品种 CMD_DELETE_ALL_OVERLAY_SYMBOL_ID:12, //删除所有叠加品种 CMD_CHANGE_COORDINATETYPE_ID:13, //切换坐标类型 CMD_CHANGE_KLINE_INFO_ID:14, //切换信息地雷 CMD_DELETE_ALL_KLINE_INFO_ID:15, //清空信息地雷 CMD_CHANGE_DRAG_MODE_ID:16, //切换拖动模式 CMD_CHANGE_BG_SPLIT_ID:17, //背景分割 CMD_SHOW_DRAWTOOL_ID:18, //画图工具 CMD_HIDE_DRAWTOOL_ID:19, CMD_SHOW_STOCKCHIP_ID:20, //筹码分布 CMD_HIDE_STOCKCHIP_ID:21, CMD_ENABLE_SELECT_RECT_ID:22, //启动区间选择 CMD_CHANGE_DAY_COUNT_ID:23, //切换天数 CMD_SHOW_BEFORE_DATA_ID:24, //显示|隐藏集合竞价 CMD_SELECTED_ZOOM_ID:25, //选中放大 CMD_SELECTED_SUMMARY_ID:26, //区间统计 CMD_SHOW_INDEX_ID:27, //显示隐藏指标 CMD_SHOW_OVERLAY_INDEX_ID:28, //显示隐藏叠加指标 CMD_DELETE_OVERLAY_INDEX_ID:29, //删除叠加指标 CMD_SHOW_OVERLAY_Y_AXIS_ID:30, //显示隐藏Y轴叠加指标 CMD_ENABLE_OVERLAY_SHARE_Y_ID:31, //和主图指标共享Y轴坐标 CMD_CHANGE_DEFAULTCURSOR_ID:32, //修改鼠标形状 CMD_CHANGE_API_INDEX_ID:33, //切换后台接口指标 CMD_CHANGE_SCRIPT_INDEX_ID:34, //切换成自定义的脚本指标 CMD_CHANGE_BASELINE_ID:35, //分时图切换基准线 CMD_ADD_OVERLAY_INDEX_ID:36, //添加叠加指标 CMD_CHANGE_LANGUAGE_ID:37, //语言切换 CMD_CHANGE_DRAG_RECT_SHOW_MODE_ID:38, CMD_SHOW_CORSS_LINE_ID:39, //显示十字光标线 CMD_ENABLE_POP_MINUTE_CHART_ID:40, //双击弹分时图 CMD_CHANGE_INFO_POSITION_ID:41, //修改信息地雷位置 CMD_REPORT_CHANGE_BLOCK_ID:60, //报价列表 切换板块ID CMD_REPORT_COLUMN_SORT_ID:61, //报价列表 表头排序 Arg[列序号, 排序方向] CMD_REPORT_COLUMN_DEL_ID:62, //报价列表 删除列 CMD_REPORT_COLUMN_MOVE_ID:63, //报价列表 列移动 CMD_REPORT_COLUMN_FILTER_ID:64, //报价列表 筛选 CMD_DIALOG_TOOLTIP_ATTRIBUTE:65, //修改K线信息框属性 Ary:[{ Enable:, Style:}, ] CMD_KLINE_TOOLTIP_ATTRIBUTE:66, //修改K线提示框属性 Ary:[{ Enable:true/false, EnableKeyDown:true/false}] } function PhoneDBClick() { this.Start=[]; this.Clear=function() { this.Start=[]; } this.AddTouchStart=function(x, y, time) { if (this.Start.length>0) { var item=this.Start[this.Start.length-1]; var spanTime=time-item.Time; if (spanTime>0 && spanTime<300) { this.Start.push({ X:x, Y:y, Time:time }); } else { this.Start=[]; } } else { this.Start.push({ X:x, Y:y, Time:time }); } } this.IsVaildDBClick=function() { if (this.Start.length==2) return true; return false; } this.AddTouchEnd=function(time) { if (this.Start.length<=0) return; var item=this.Start[this.Start.length-1]; var spanTime=time-item.Time; if (spanTime>=0 && spanTime<150) { } else { this.Start=[]; } } } /* 图形控件 */ function JSChartContainer(uielement, OffscreenElement, cacheElement) { this.ClassName='JSChartContainer'; var _self = this; this.Frame; //框架画法 this.ChartPaint=new Array(); //图形画法 this.ChartPaintEx=[]; //图形扩展画法 this.ChartInfo=new Array(); //K线|走势图上信息地雷 this.ChartInfoPaint; //信息地理 this.ExtendChartPaint=new Array(); //扩展画法 this.TitlePaint=new Array(); //标题画法 this.OverlayChartPaint=new Array(); //叠加信息画法 this.ChartDrawPicture=new Array(); //画图工具 this.ChartDrawStorage; //画图工具保存 this.ChartDrawOption={ IsLockScreen:false, Zoom:1, Magnet:null }; //画图工具设置 { IsLockScreen://是否锁住屏幕, Zoom: //线段|点放大倍数, Magnet:磁吸 {Enable:, Type, Distance,} } this.CurrentChartDrawPicture=null; //当前的画图工具 this.SelectChartDrawPicture=null; //当前选中的画图 this.MoveOnChartDrawPicture=null; //鼠标在画图上 this.EnableEraseChartDrawPicture=false; //擦除画图 this.IsDrawPictureXY=false; //选中的画图工具是否显示X,Y轴对应数值 this.EnableShowCorssCursor={ DrawPicture:true }; //DrawPicture=画图是否显示十字光标 this.ChartPictureMenu; //画图工具 单个图形设置菜单 this.ChartCorssCursor; //十字光标 this.ChartDragSelectRect; //选择区间选中 this.IsClickShowCorssCursor=false; //手势点击显示十字光标 this.ChartSplashPaint=null; //等待提示 this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息 this.DefaultCursor="default"; //crosshair , default 默认手型 //绘图缓存 this.CacheCanvas=null; this.CacheElement=null; if (cacheElement) { this.CacheElement=cacheElement; this.CacheCanvas=cacheElement.getContext("2d"); } if (OffscreenElement) { this.Canvas=OffscreenElement.getContext("2d"); this.OffscreenCanvasElement=OffscreenElement; this.ShowCanvas=uielement.getContext("2d"); } else { if (JSChart.EnableCanvasWillReadFrequently===true) { let contextAttr={ willReadFrequently:true }; this.Canvas=uielement.getContext("2d",contextAttr); //画布 } else { this.Canvas=uielement.getContext("2d"); //画布 } this.ShowCanvas=null; } //十字光标层 this.CorssCursorElement; this.CorssCursorCanvas; this.UIElement=uielement; this.MouseDrag; this.PhoneTouchInfo; //手机手势信息 this.DragMode=1; //拖拽模式 0 禁止拖拽 1 数据拖拽 2 区间选择 3(CLICK_TOUCH_MODE_ID)=长按十字光标显示保留/点击十字光标消失 (使用TouchStatus) this.EnableBorderDrag=true; //是否可以拖拽边框调整指标框高度 this.BorderDrag; //{ Index:, } this.YDrag; //{Index: } //y轴拖拽放大缩小 this.TouchStatus={ CorssCursorShow:false }, //十字光标是否显示 this.DragTimer; this.EnableScrollUpDown=false; //是否可以上下滚动图形(手机端才有) this.ClickChartTimer=null; //点击图形定时器,解决双击和单击K线事件 this.CursorIndex=0; //十字光标X轴索引 this.LastPoint=new Point(); //鼠标位置 this.IsForceLandscape=false; //是否强制横屏 this.CorssCursorTouchEnd = false; //手离开屏幕自动隐藏十字光标 this.IsTitleShowLatestData=false; //十字/手势不在K线图上,标题显示最新一个数据 this.StepPixel=4; //移动一个数据需要的像素 0=自动模式(根据K线宽度+间距) this.ZoomStepPixel=5; //放大缩小手势需要的最小像素 this.TouchMoveMinAngle=70; //左右移动最小角度 this.EnableAnimation=false; //是否开启动画 //tooltip提示信息 this.Tooltip=document.createElement("div"); this.Tooltip.className='jschart-tooltip'; this.Tooltip.style.background=g_JSChartResource.TooltipBGColor; this.Tooltip.style.opacity=g_JSChartResource.TooltipAlpha; this.Tooltip.style["pointer-events"]="none"; this.Tooltip.id=Guid(); uielement.parentNode.appendChild(this.Tooltip); this.IsShowTooltip=true; //是否显示K线tooltip this.KLineTooltipConfig={ EnableKeyDown:true, Enable:true }; //K线鼠标移动上去提示信息配置 this.TooltipCache={ Type:null, IsShow:false, X:null, Y:null, Data:null, InnerHTML:null }; //缓存tooltip数据 //坐标轴风格方法 double-更加数值型分割 price-更加股票价格分割 this.FrameSplitData=new Map(); this.FrameSplitData.set("double",new SplitData()); this.FrameSplitData.set("price",new PriceSplitData()); //事件回调 this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} this.PhonePinch=null; //手机双指操作信息 this.IsOnTouch = false; //是否再操作数据 this.TouchDrawCount = 0; //手势绘制次数 this.DisableMouse=false; //禁止鼠标事件 this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; this.PressTime=500; this.IsPress=false; //是否长按 this.NetworkFilter; //网络请求回调 function(data, callback); this.LastMouseStatus={ MouseOnToolbar:null }; // MouseOnToolbar={ Rect:{}, Title: } this.ClickDownPoint; //鼠标点击坐标 {X, Y}, 鼠标放开以后清空为null this.IsDestroy=false; //是否已经销毁了 this.EnableYDrag= { Left:false, Right:false, //是否可以拖拽缩放Y轴最大最小值 Wheel:false, WheelYMove:5 //是否可以滚轴缩放Y轴最大最小值 }; this.EnableZoomIndexWindow=false; //是否支持双击缩放附图窗口 this.EnableVerifyRecvData=false; //是否检测接收到的数据 this.PhoneDBClick=new PhoneDBClick(); this.SelectedChart={ EnableSelected:false, EnableMoveOn:false, Selected:{ Identify:null }, MoveOn:{ Identify:null } }; //选中图形 this.IndexChartDrag; //拖拽指标图形 this.EnableIndexChartDrag=false; this.GlobalOption= { IsValueFullRange:false , IsDisplayLatest:false, SelectedBorder:{ Mode:0, SelFrame:0 }, //边框选中模式 Mode:0=禁用 1=右侧标记选中 2=指标窗口标记选中 SelectedXBorder: { Mode:0, Date:null } //X边框选中模式 Mode:0=禁用 分时图图有效 //XDateFormat (多日分时图x轴底部日期格式) }; this.VerticalDrag; //通过X轴左右拖动数据(手势才有) this.EnableVerticalDrag=false; //十字光标长留(手势才有) this.ClickModel={ IsShowCorssCursor:false }; this.EnableClickModel=false; //标题栏显示最新数据 this.DisplayLatestOption={ Timer:null, Enable: false, DelayTime:60*1000*3, LastPoint:null }; this.DrawDynamicInfoOption={ Timer:null, Enable:false , DelayTime:10 }; this.CustomChartDrag; //自定义图形的拖拽操作 { Type:, Data: } this.StockCache={ Data:null }; //扩展数据缓存数据 this.JSPopMenu; //内置菜单 this.IsShowRightMenu=true; //显示右键菜单 this.DialogDrawTool; //画图工具 this.DialogModifyDraw; //画图修改 this.DialogTooltip; //tooltip信息 this.DialogSelectRect; //区间统计 this.FloatTooltip; //浮动tooltip信息 this.DialogSearchIndex; //指标搜索 this.ClearStockCache=function() { this.StockCache.Data=null; } this.InitalPopMenu=function() //初始化弹出窗口 { if (this.JSPopMenu) return; this.JSPopMenu=new JSPopMenu(); //内置菜单 this.JSPopMenu.Inital(); } this.InitalDrawToolDialog=function() { if (this.DialogDrawTool) return; this.DialogDrawTool=new JSDialogDrawTool(); this.DialogDrawTool.Inital(this); this.DialogDrawTool.Create(); } this.InitalTooltipDialog=function(option) { if (this.DialogTooltip) return; this.DialogTooltip=new JSDialogTooltip(); this.DialogTooltip.Inital(this, option); this.DialogTooltip.Create(); } this.InitalFloatTooltip=function(option) { if (this.FloatTooltip) return; this.FloatTooltip=new JSFloatTooltip(); this.FloatTooltip.Inital(this, option); this.FloatTooltip.Create(); } this.InitalModifyDrawDialog=function() { if ( this.DialogModifyDraw) return; this.DialogModifyDraw=new JSDialogModifyDraw(); this.DialogModifyDraw.Inital(this); this.DialogModifyDraw.Create(); } this.InitalSelectRectDialog=function(option) { if (this.DialogSelectRect) return; this.DialogSelectRect=new JSDialogSelectRect(); this.DialogSelectRect.Inital(this, option); this.DialogSelectRect.Create(); } this.InitalSearchIndexDialog=function(option) { if (this.DialogSearchIndex) return; this.DialogSearchIndex=new JSDialogSearchIndex(); this.DialogSearchIndex.Inital(this, option); this.DialogSearchIndex.Create(); } this.ShowChangeIndexDialog=function(data) { if (!data) return; if (!this.DialogSearchIndex) return; data.Title=`切换指标 [窗口${data.WindowIndex+1}]`; this.DialogSearchIndex.SetOpData(data); this.DialogSearchIndex.Show(); } this.ShowAddOverlayIndexDialog=function(data) { if (!data) return; if (!this.DialogSearchIndex) return; data.Title=`添加叠加指标 [窗口${data.WindowIndex+1}]`; this.DialogSearchIndex.SetOpData(data); this.DialogSearchIndex.Show(); } this.DrawSelectRectDialog=function() { } this.IsShowSelectRectDialog=function() { if (!this.DialogSelectRect) return false; return this.DialogSelectRect.IsShow(); } this.ShowDrawToolDialog=function(x,y) { if (!this.DialogDrawTool) return; var rtClient=this.UIElement.getBoundingClientRect(); var rtScroll=GetScrollPosition(); var top=this.UIElement.offsetTop+15; var left=this.UIElement.offsetWidth-this.DialogDrawTool.DivDialog.offsetWidth-15; left+=rtClient.left+rtScroll.Left; top+=rtClient.top+rtScroll.Top; this.DialogDrawTool.Show(left,top); } this.IsShowDrawToolDialog=function() { if (!this.DialogDrawTool) return false; return this.DialogDrawTool.IsShow(); } this.ShowModifyDrawDialog=function(chart, x,y) { if (!this.DialogModifyDraw) return; this.DialogModifyDraw.SetChartPicture(chart); if (this.DialogModifyDraw.IsShow()) return; var rtClient=this.UIElement.getBoundingClientRect(); var rtScroll=GetScrollPosition(); var top=this.UIElement.offsetTop+15; var left=(this.UIElement.offsetWidth-this.DialogModifyDraw.DivDialog.offsetWidth)/2; left+=rtClient.left+rtScroll.Left; top+=rtClient.top+rtScroll.Top; this.DialogModifyDraw.Show(left, top); } this.CloseModifyDrawDialog=function() { if (!this.DialogModifyDraw) return; this.DialogModifyDraw.Close(); } this.IsShowTooltipDialog=function() { if (!this.DialogTooltip) return false; return this.DialogTooltip.IsShow(); } this.CloseTooltipDialog=function() { if (!this.DialogTooltip) return; this.DialogTooltip.Close(); } this.HideFloatTooltip=function() { if (!this.FloatTooltip) return; this.FloatTooltip.Hide(); } this.DestroyTooltipDialog=function() { if (!this.DialogTooltip) return; this.DialogTooltip.Destroy(); this.DialogTooltip=null; } this.DestroyFloatTooltip=function() { if (!this.FloatTooltip) return; this.FloatTooltip.Destroy(); this.FloatTooltip=null; } this.DestroySearchIndexDialog=function() { if (!this.DialogSearchIndex) return; this.DialogSearchIndex.Destroy(); this.DialogSearchIndex=null; } //obj={ Element:, Canvas: } this.SetCorssCursorElement=function(obj) { if (!obj || !obj.Element || !obj.Canvas) return; this.CorssCursorElement=obj.Element; this.CorssCursorCanvas=obj.Canvas; } this.StopDisplayLatest=function() { this.GlobalOption.IsDisplayLatest=false; if (this.DisplayLatestOption.Timer) { clearTimeout(this.DisplayLatestOption.Timer); this.DisplayLatestOption.Timer=null; } } this.StartStopDisplayLatest=function() { this.StopDisplayLatest(); if (!this.DisplayLatestOption.Enable) return; this.DisplayLatestOption.Timer=setTimeout(()=> { if (this.DisplayLatest) { JSConsole.Chart.Log('[JSChartContainer:StartStopDisplayLatest] call this.DisplayLatest()'); this.DisplayLatest(); } },this.DisplayLatestOption.DelayTime); } this.StopDrawDynamicInfo=function() { if (this.DrawDynamicInfoOption.Timer) { clearTimeout(this.DrawDynamicInfoOption.Timer); this.DrawDynamicInfoOption.Timer=null; } } this.ChartDestroy=function() //销毁 { this.IsDestroy=true; this.StopAutoUpdate(); this.DestroyTooltipDialog(); this.DestroyFloatTooltip(); this.DestroySearchIndexDialog(); } this.ChartDestory=this.ChartDestroy; //老版本写错了,需要兼容下 //设置焦点 this.SetFocus=function() { if (this.UIElement) this.UIElement.focus(); } //设置事件回调 //{event:事件id, callback:回调函数} this.AddEventCallback=function(object) { if (!object || !object.event || !object.callback) return; var data={Callback:object.callback, Source:object}; this.mapEvent.set(object.event,data); } this.RemoveEventCallback=function(eventid) { if (!this.mapEvent.has(eventid)) return; this.mapEvent.delete(eventid); } this.GetEventCallback=function(id) //获取事件回调 { if (!this.mapEvent.has(id)) return null; var item=this.mapEvent.get(id); return item; } //接收指标数据 this.GetIndexEvent=function() { return this.GetEventCallback(JSCHART_EVENT_ID.RECV_INDEX_DATA); } this.GetOverlayIndexEvent=function() { return this.GetEventCallback(JSCHART_EVENT_ID.RECV_OVERLAY_INDEX_DATA); } //鼠标事件绑定 uielement.onmousemove=(e)=>{ this.UIOnMouseMove(e);} uielement.oncontextmenu=(e)=> { return this.UIOnContextMenu(e); } uielement.ondblclick=(e)=>{ this.UIOnDblClick(e); } uielement.onmousedown=(e)=> { this.UIOnMouseDown(e); } uielement.onmouseout=(e)=>{ this.UIOnMounseOut(e); } uielement.onmouseleave=(e)=>{ this.UIOnMouseleave(e); } this.UIOnMouseMove=function(e) { //JSConsole.Chart.Log('[JSChartContainer.UIOnMouseMove] e.clientX, e.clientY, left, top ',e.clientX, e.clientY, this.getBoundingClientRect().left,this.getBoundingClientRect().top); var pixelTatio = GetDevicePixelRatio(); //鼠标移动坐标是原始坐标 需要乘以放大倍速 var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; this.StopDisplayLatest(); //加载数据中,禁用鼠标事件 this.MoveOnChartDrawPicture=null; if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; if (this.DisableMouse==true) return; if (this.BorderDrag) return; if (this.YDrag) return; if (this.IndexChartDrag) return; if (this.CustomChartDrag) return; //if (this.RectSelectDrag) return; /* if (this.CurrentChartDrawPicture) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.PointCount<=2) return; JSConsole.Chart.Log("[JSChartContainer::UIOnMouseMove] Status", drawPicture.Status); } */ //鼠标离开 if (e && e.type=="mouseout" && e.buttons==0) { x=y=-1; } //保存最后一次鼠标移动信息 var MoveStatus={ X:x, Y:y, IsInClient: this.IsMouseOnClient(x,y) }; this.LastMouseStatus.OnMouseMove=MoveStatus; this.LastMouseStatus.MoveOnPoint={X:x, Y:y}; //鼠标移动的位置 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_MOUSE_MOVE); var titleChart=this.TitlePaint[0]; if (event && titleChart) titleChart.OnMouseMoveEvent=event; this.MoveOnPoint={X:x, Y:y}; this.OnMouseMove(x,y,e); //this.LastMouseStatus.MoveOnPoint=null; if (titleChart) titleChart.OnMouseMoveEvent=null; this.StartStopDisplayLatest(); } this.IsMouseOnClient=function(x,y) { var rect={ Left:this.Frame.ChartBorder.GetLeft(), Top:this.Frame.ChartBorder.GetTop(), Width:this.Frame.ChartBorder.GetWidth(), Height:this.Frame.ChartBorder.GetHeight() }; rect.Right=rect.Left+rect.Width; rect.Bottom=rect.Top+rect.Height; if (x>=rect.Left && x<=rect.Right && y>=rect.Top && y<=rect.Bottom) return true; return false; } this.UIOnContextMenu=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; if (!this.IsShowRightMenu) return; var x = e.clientX-this.UIElement.getBoundingClientRect().left; var y = e.clientY-this.UIElement.getBoundingClientRect().top; if(typeof(this.OnRightMenu)=='function') this.OnRightMenu(x,y,e); //右键菜单事件 return false; } this.UIOnDblClick=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; this.OnDoubleClick(x,y,e); } //是否在拖拽Y轴上 this.TryYDrag=function(x,y) { if (!this.EnableYDrag) return null; if (!this.EnableYDrag.Left && !this.EnableYDrag.Right) return null; if (!this.Frame || !this.Frame.PtInFrameY) return null; var dragY=this.Frame.PtInFrameY(x,y); if (!dragY || dragY.Index<0 ) return null; if (dragY.IsOverlay===true) { if (!dragY.Right || !this.EnableYDrag.Right) return null; if (this.Frame.IsEnableOverlayDragY(dragY.Index, dragY.OverlayIndex)) return dragY; return null; } if (dragY.Left && this.EnableYDrag.Left && this.Frame.IsEnableDragY(dragY.Index)) { return dragY; } if (dragY.Right && this.EnableYDrag.Right && this.Frame.IsEnableDragY(dragY.Index)) { return dragY; } return null; } //是否可以上下拖拽 this.TryUpDownDrag=function(x,y) { var windowIndex=this.Frame.PtInFrame(x,y); if (windowIndex<0) return null; var item=this.Frame.SubFrame[windowIndex]; if (!item || !item.Frame) return null; var frame=item.Frame; if (!frame.YSplitOperator || !frame.YSplitOperator.FixedYMaxMin) return null; return { Index:windowIndex, X:x, Y:y }; } this.TryRectSelectDrag=function(x,y) { var paint=this.GetRectSelectPaint(); if (!paint) return null; if (paint.GetPointCount()<=0) return null; var item=paint.PtInPaint(x,y); return { Item:item, X:x, Y:y }; } this.TryClickCrossCursor=function(x,y,e) { if (!this.ChartCorssCursor) return; var button=this.ChartCorssCursor.PtInButton(x,y); if (!button) return false; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_CROSSCURSOR_RIGHT); if (event && event.Callback) { var sendData={ Button:button, e }; event.Callback(event,sendData,this); } return true; } this.TryClickButton=function(x, y, e) { var button=this.Frame.PtInButtons(x,y); if (button && this.ClickFrameButton) { this.ClickFrameButton(button, e); return true; } button=this.PtInExtendChartButtons(x,y); if (button && this.ClickExtendChartButton) { this.ClickExtendChartButton(button, e); return true; } button=this.PtInDrawPictureButtons(x,y); if (button && this.ClickDrawPictureButton) { this.ClickDrawPictureButton(button, e); return true; } button=this.PtInTitleButtons(x,y); if (button && this.ClickTitleButton) { this.ClickTitleButton(button, e); return true; } var label=this.Frame.PtInHorizontalLabel(x,y); if (label && this.ClickHorizontalLabel) { this.ClickHorizontalLabel(label, e); return true; } return false; } this.TryMouseMove_CustomChartDrag=function(sendData) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_DRAG_MOUSE_MOVE); if (!event || !event.Callback) return false; return event.Callback(event, sendData, this); } this.TryClick_CustomChartDrag=function(sendData) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_DRAG_MOUSE_DOWN); if (!event || !event.Callback) return false; sendData.ChartDrag=null; sendData.Cusrsor=null; event.Callback(event, sendData, this); this.CustomChartDrag=sendData.ChartDrag; this.SetCursor(sendData); } this.TryDragMove_CustomChartDrag=function(sendData) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_DRAG_DOC_MOUSE_MOVE); if (!event || !event.Callback) return; var e=sendData.e; var drag=sendData.Drag; if(Math.abs(drag.LastMove.Y-e.clientY)<2 && Math.abs(drag.LastMove.X-e.clientX)<2) return; if (event.Callback(event, sendData, this)) { drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } } this.TryMouseUp_CustomChartDrag=function(sendData) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_DRAG_DOC_MOUSE_UP); if (!event || !event.Callback) return; event.Callback(event, sendData, this); } this.UIOnMouseDown=function(e) { this.MoveOnChartDrawPicture=null; if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; this.ClickDownPoint={ X:e.clientX, Y:e.clientY }; this.IsOnTouch=true; this.BorderDrag=null; this.YDrag=null; this.UpDownDrag=null; this.RectSelectDrag=null; this.IndexChartDrag=null; this.CustomChartDrag=null; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.TryClickButton(x,y,e)) { this.IsOnTouch=false; return; } var bDrawDynamicInfo=false; if (this.GlobalOption.SelectedBorder && this.GlobalOption.SelectedBorder.Mode>=1) { var item=this.GlobalOption.SelectedBorder; var frameId=this.Frame.PtInFrame(x,y); if (frameId>=0 && frameId!=item.SelFrame) { item.SelFrame=frameId; bDrawDynamicInfo=true; } } var bRedraw=false; if (this.GlobalOption.SelectedXBorder && this.GlobalOption.SelectedXBorder.Mode>=1) { if (this.PtInMulitDayMinute) { var item=this.GlobalOption.SelectedXBorder; var selectedDate=this.PtInMulitDayMinute(x,y); if (item.Date!=selectedDate) { item.Date=selectedDate bRedraw=true; } } } if (this.TryClickCrossCursor(x,y, e)) { this.IsOnTouch=false; return; } if (this.TryClickChartTooltipData && this.TryClickChartTooltipData(x,y,e)) //预留给外部点击图标什么用的 { this.IsOnTouch=false; return; } if (this.TryClickLock) { //JSConsole.Chart.Log('[uielement.onmousedown] left, top ',e.clientX, e.clientY, this.getBoundingClientRect().left,this.getBoundingClientRect().top); if (this.TryClickLock(x,y)) return; } this.HideSelectRect(); this.ClearDragSelectRect(); if (this.ChartPictureMenu) this.ChartPictureMenu.Hide(); var paint=this.GetRectSelectPaint(); if (paint && paint.GetPointCount()>0) { var item=paint.PtInPaint(x,y); if (item) { if (item.Type==4) { //this.UIElement.style.cursor="pointer"; this.SetCursor({Cursor:"pointer"}); var obj={ X:e.clientX }; if (this.GetXDataIndex(obj)) { this.RectSelectDrag={ DataIndex:obj.DataIndex, Type:item.Type, X:e.clientX }; JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] drag sub rect select ", obj); } } else { //this.UIElement.style.cursor="ew-resize"; this.SetCursor({Cursor:"ew-resize"}); this.RectSelectDrag={ Index:item.PointIndex, Type:item.Type }; JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] drag rect select ",item); } } } if (!this.IsShowSelectRectDialog()) //区间统计框存在,不清空区间背景色 { if (!this.RectSelectDrag && this.ClearRectSelect(false)) this.Draw(); } if (this.EnableBorderDrag && this.Frame) { var dragBorder=this.Frame.PtInFrameBorder(x,y); if (dragBorder && dragBorder.Index>=0) { //this.UIElement.style.cursor="n-resize"; this.SetCursor({Cursor:"n-resize"}); this.BorderDrag={ Index:dragBorder.Index }; JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] DragBorder ",dragBorder); } } //拖拽Y轴缩放 if (!this.BorderDrag) { var dragY=this.TryYDrag(x,y); if (dragY) { //this.UIElement.style.cursor=dragY.Position==0 ? "n-resize":"row-resize"; var cursor=dragY.Position==0 ? "n-resize":"row-resize"; this.SetCursor({Cursor:cursor}); this.YDrag=dragY; JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] dragY ",dragY); } else { var dragUpDown=this.TryUpDownDrag(x,y); if (dragUpDown) { //this.UIElement.style.cursor="pointer"; this.SetCursor({Cursor:"pointer"}); this.UpDownDrag=dragUpDown; JSConsole.Chart.Log("[JSChartContainer::UIOnMouseDown] dragUpDown ",dragUpDown); } } } var sendData={ X:x, Y:y, e:e }; if (this.TryClick_CustomChartDrag(sendData)) { } if(this.DragMode==0) return; var drag= { "Click":{}, "LastMove":{}, //最后移动的位置 CurrentMove:{}, //当前的移动 }; drag.Click.X=e.clientX; drag.Click.Y=e.clientY; drag.Click.IsInFrameBottom=this.Frame.PtInFrameBottom(x,y); //是否点击在X轴上 drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; this.MouseDrag=drag; var drawPictureActive=this.GetActiveDrawPicture(); //上一次选中的 var selectedChart={ Chart:this.SelectedChart.Selected.Chart, Identify:this.SelectedChart.Selected.Identify }; //上一次选中的图形 this.SelectChartDrawPicture=null; if (this.BorderDrag) { } else if (this.YDrag || this.RectSelectDrag || this.CustomChartDrag) { } else if (this.CurrentChartDrawPicture) //画图工具模式 { this.UpDownDrag=null; //画图优先 var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==2) this.SetChartDrawPictureThirdPoint(drag.Click.X,drag.Click.Y); else { this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y); //只有1个点 直接完成 if (this.FinishChartDrawPicturePoint()) { if (drawPicture.IsDrawMain) this.Draw(); else this.DrawDynamicInfo(); } } if (drawPictureActive.Select.Guid && ( !this.CurrentChartDrawPicture ||drawPictureActive.Select.Guid!=this.CurrentChartDrawPicture.Guid)) { if (drawPictureActive.Select.Chart.IsDrawMain) this.Draw(); } } else //是否在画图工具上 { var drawPictrueData={}; drawPictrueData.X=(e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; drawPictrueData.Y=(e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.GetChartDrawPictureByPoint(drawPictrueData)) { if (this.EnableEraseChartDrawPicture) //擦掉画线 { this.CurrentChartDrawPicture=null; this.SelectChartDrawPicture=null; this.ClearChartDrawPicture(drawPictrueData.ChartDrawPicture); } else { this.UpDownDrag=null; //画图优先 this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture; this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture; //当前已有选中的,需要刷下 var bDraw=false; if (drawPictureActive.Select.Guid && drawPictureActive.Select.Chart && drawPictureActive.Select.Chart.IsDrawMain) bDraw=true; else if (drawPictrueData.ChartDrawPicture.IsDrawMain) bDraw=true; if (bDraw) this.Draw(); if (drawPictrueData.ChartDrawPicture.EnableMove==true) drawPictrueData.ChartDrawPicture.Status=20; drawPictrueData.ChartDrawPicture.ValueToPoint(); drawPictrueData.ChartDrawPicture.MovePointIndex=drawPictrueData.PointIndex; //this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture; //this.SelectChartDrawPicture=drawPictrueData.ChartDrawPicture; this.SelectChartDrawPicture.DragInfo={Click:{X:e.clientX,Y:e.clientY}}; } var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件 if (event && event.Callback) { var sendData={ DrawPicture: drawPictrueData.ChartDrawPicture }; event.Callback(event,sendData,this); } else { this.OnSelectChartPicture(drawPictrueData.ChartDrawPicture); //选中画图工具事件 } } else { if (this.ClickChartTimer!=null) { clearTimeout(this.ClickChartTimer); this.ClickChartTimer=null; } var self=this; var ptClick={ X:this.ClickDownPoint.X, Y:this.ClickDownPoint.Y }; this.ClickChartTimer = setTimeout(function() { self.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICK_CHART_PAINT,ptClick,e); }, 250); var bSelectedChartChanged=false; if (this.SelectedChart.EnableSelected) { var selectChart=this.PtInChart(x,y); if (selectChart) { if (this.SelectedChart.Selected.Identify!=selectChart.Identify) { this.SelectedChart.Selected.Identify=selectChart.Identify; this.SelectedChart.Selected.Chart=selectChart.Chart; bSelectedChartChanged=true; } if (this.EnableIndexChartDrag) { this.IndexChartDrag={ SelectedChart:selectChart, LastMove:{X:x, Y:y}, Click:{X:x, Y:y } }; this.IndexChartDrag.Info=this.GetSelectedChartInfo(selectChart); if (this.IndexChartDrag.Info) this.IndexChartDrag.Info.FrameID=this.Frame.PtInFrame(x,y); } } else { if (this.SelectedChart.Selected.Identify) { this.SelectedChart.Selected.Identify=null; this.SelectedChart.Selected.Chart=null; bSelectedChartChanged=true; } } } else { if (this.SelectedChart.Selected.Identify) { this.SelectedChart.Selected.Identify=null; bSelectedChartChanged=true; } } if ((drawPictureActive.Select.Guid!=null && this.SelectChartDrawPicture==null) || bSelectedChartChanged) { var drawType=0; if (drawPictureActive.Select.Guid && drawPictureActive.Select.Chart && drawPictureActive.Select.Chart.IsDrawMain) drawType=1; if (bSelectedChartChanged) { var chart=selectedChart.Chart; if (chart && chart.SetSelectedStatus) { chart.SetSelectedStatus(0); drawType=1; } chart=this.SelectedChart.Selected.Chart; if (chart &&chart.SetSelectedStatus) { chart.SetSelectedStatus(1); drawType=1; } } if (drawType==1) this.Draw(); else this.DrawDynamicInfo(); } else if (bRedraw) { this.Draw(); } else if (bDrawDynamicInfo) { this.DrawDynamicInfo(); } } } if (!this.SelectChartDrawPicture) this.CloseModifyDrawDialog(); //当前没有选中画图 隐藏画图修改框 document.onmousemove=(e)=>{ this.DocOnMouseMove(e); } document.onmouseup=(e)=> { this.DocOnMouseUp(e); } } this.DocOnMouseMove=function(e) { //加载数据中,禁用鼠标事件 if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return; var drag=this.MouseDrag; if (!drag) return; var moveSetp=Math.abs(drag.LastMove.X-e.clientX); var moveSetpY=Math.abs(drag.LastMove.Y-e.clientY); var isDragSelectRect=(this.RectSelectDrag && this.RectSelectDrag.Index>=0); var isDragSubSelectRect=(this.RectSelectDrag && this.RectSelectDrag.Type==4); if (drag.CurrentMove) { drag.CurrentMove.X=e.clientX; drag.CurrentMove.Y=e.clientY; } if (this.BorderDrag && this.BorderDrag.Index>=0) //边框拖动 { if(Math.abs(drag.LastMove.Y-e.clientY)<5) return; var yMove=e.clientY-drag.LastMove.Y; this.OnMoveFromeBorder(this.BorderDrag.Index, yMove); drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } else if (this.YDrag && this.YDrag.Index>=0) //Y轴缩放 { if(moveSetpY<5) return; var yMove=e.clientY-drag.LastMove.Y; //this.UIElement.style.cursor="n-resize"; JSConsole.Chart.Log("[JSChartContainer::DocOnMouseMove] YDrag ",this.YDrag,yMove); this.OnZoomUpDownFrameY(this.YDrag, yMove); drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } else if (this.IndexChartDrag && this.IndexChartDrag.SelectedChart) { if(Math.abs(drag.LastMove.Y-e.clientY)<2 && Math.abs(drag.LastMove.X-e.clientX)<2) return; var chartMove=this.GetExtendChartByClassName("DragMovePaint"); if (chartMove && chartMove.Chart) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; chartMove.Chart.Point={X:x, Y:y}; chartMove.Chart.IsShow=true; chartMove.Chart.Info=this.IndexChartDrag.Info; this.DrawDynamicInfo(); } this.IndexChartDrag.LastMove.X=x; this.IndexChartDrag.LastMove.Y=y; drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } else if (this.CustomChartDrag) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var sendData={X:x, Y:y, e:e, ChartDrag:this.CustomChartDrag, Drag:drag }; this.TryDragMove_CustomChartDrag(sendData); } else if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) { if(Math.abs(drag.LastMove.X-e.clientX)<5 && Math.abs(drag.LastMove.Y-e.clientY)<5) return; if(this.SetChartDrawPictureSecondPoint(e.clientX,e.clientY)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==3) { if(this.SetChartDrawPictureThirdPoint(e.clientX,e.clientY)) { this.DrawDynamicInfo(); } } else if (drawPicture.Status==20) //画图工具移动 { if(Math.abs(drag.LastMove.X-e.clientX)<5 && Math.abs(drag.LastMove.Y-e.clientY)<1) return; if (this.SelectChartDrawPicture) { if (this.SelectChartDrawPicture.EnableCtrlMove) { if (!e.ctrlKey) return; } } if (this.SelectChartDrawPicture && this.SelectChartDrawPicture.DragInfo) this.SelectChartDrawPicture.DragInfo.Move={X:e.clientX, Y:e.client}; if(this.MoveChartDrawPicture(e.clientX-drag.LastMove.X,e.clientY-drag.LastMove.Y,false,drag)) { this.DrawDynamicInfo(); } } drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } else if (this.DragMode==1 || isDragSelectRect || isDragSubSelectRect) //数据上下左右拖拽 { this.OnDragMode_One({X:moveSetp, Y:moveSetpY}, e); } else if (this.DragMode==2) //区间选择 { var yMoveSetp=Math.abs(drag.LastMove.Y-e.clientY); if (moveSetp<5 && yMoveSetp<5) return; this.SetCursor({Cursor:"default"}); var ptStart=this.PointAbsoluteToRelative(drag.Click.X, drag.Click.Y); var ptEnd=this.PointAbsoluteToRelative(e.clientX, e.clientY); this.ShowDragSelectRect(ptStart, ptEnd); drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } } this.OnDragMode_One=function(moveData, e) { var moveSetp=moveData.X; var moveSetpY=moveData.Y; var drag=this.MouseDrag; if (moveSetp<5 && moveSetpY<5) return; var bNeedDraw=false; var bUpDownY=false; if (moveSetpY>=5) { if (this.UpDownDrag && this.UpDownDrag.Index>=0) { var yMove=e.clientY-drag.LastMove.Y; JSConsole.Chart.Log("[JSChartContainer::OnDragMode_One] UpDownDrag ",this.UpDownDrag,yMove); //this.UIElement.style.cursor="pointer"; this.SetCursor({Cursor:"pointer"}); if (this.OnUpDonwFrameY(this.UpDownDrag, yMove)) { bNeedDraw=true; bUpDownY=true; } drag.LastMove.Y=e.clientY; } } if (moveSetp>=5) { if (this.RectSelectDrag) { if (this.RectSelectDrag.Index>=0) { var obj={ X:e.clientX, Y:e.clientY, PointIndex:this.RectSelectDrag.Index, Name:"MoveRectSelectLine" }; if (this.MoveRectSelectPoint(obj)) bNeedDraw=true; } else if (this.RectSelectDrag.Type===4) { var obj={ X:e.clientX }; if (!this.GetXDataIndex(obj)) return; if (obj.DataIndex==this.RectSelectDrag.DataIndex) return; var step=obj.DataIndex-this.RectSelectDrag.DataIndex; var isLeft=true; if (step>0) isLeft=false; if (!this.MoveSubRectSelect({ Step:Math.abs(step), IsLeft:isLeft, X:e.clientX, Y:e.clientY })) return; this.RectSelectDrag.DataIndex=obj.DataIndex; this.RectSelectDrag.X=e.clientX; bNeedDraw=true; } } else { var isLeft=true; if (drag.LastMove.X=kData.Data.length) dataIndex=kData.Data.length-1; var item = kData.Data[dataIndex]; obj.DataIndex=dataIndex; obj.Item=item; //JSConsole.Chart.Log("[JSChartContainer::GetXDataIndex] point, item", obj.PointIndex, item); return true; } this.DocOnMouseUp=function(e) { //清空事件 document.onmousemove=null; document.onmouseup=null; var IsMinuteChart=(this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") ? true:false; var isDragSelectRect=(this.RectSelectDrag && this.RectSelectDrag.Index>=0); var isDragSubSelectRect=(this.RectSelectDrag && this.RectSelectDrag.Type==4); 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(); } } else if (this.IndexChartDrag && this.IndexChartDrag.SelectedChart) { var chartMove=this.GetExtendChartByClassName("DragMovePaint"); if (chartMove && chartMove.Chart) chartMove.Chart.Clear(); if (!this.OnDragChart(this.IndexChartDrag)) this.DrawDynamicInfo(); //this.UIElement.style.cursor="default"; this.SetCursor({Cursor:"default"}); } else if (this.CustomChartDrag) { var sendData={ e:e, ChartDrag:this.CustomChartDrag, Drag:this.MouseDrag }; this.TryMouseUp_CustomChartDrag(sendData); } else if (isDragSelectRect) //区间选择拖动范围 { if (this.OnDragSelectRectMouseUp) this.OnDragSelectRectMouseUp(e); } else if (isDragSubSelectRect) { if (this.OnDragSubSelectRectMouseUp) this.OnDragSubSelectRectMouseUp(e); } else if (IsMinuteChart) { if (this.OnMinuteSelectRectMouseUp) this.OnMinuteSelectRectMouseUp(e); } else if (this.DragMode==2) //区间选择 { var drag=this.MouseDrag; drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; var selectData=new SelectRectData(); var pixelTatio = GetDevicePixelRatio(); //区间起始位置 结束位子 selectData.XStart=(drag.Click.X-uielement.getBoundingClientRect().left)*pixelTatio; selectData.YStart=(drag.Click.Y-uielement.getBoundingClientRect().top)*pixelTatio; selectData.XEnd=(drag.LastMove.X-uielement.getBoundingClientRect().left)*pixelTatio; selectData.YEnd=(drag.LastMove.Y-uielement.getBoundingClientRect().top)*pixelTatio; selectData.JSChartContainer=this; selectData.Stock={Symbol:this.Symbol, Name:this.Name}; if (this.ChartDragSelectRect.Enable && !this.BorderDrag && this.GetSelectRectData(selectData)) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SELECT_RECT); var paint=this.GetRectSelectPaint(); var isShowMenu=true; if (event && event.Callback) { var data= { X:drag.LastMove.X-uielement.getBoundingClientRect().left, Y:drag.LastMove.Y-uielement.getBoundingClientRect().top, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint, //区间选择背景 IsShowMenu:true, e,e }; event.Callback(event,data,this); isShowMenu=data.IsShowMenu; } if (IsMinuteChart) //分时图直接显示显示区间选择 { this.HideSelectRect(); this.UpdateSelectRect(selectData.Start,selectData.End); } else { if (isShowMenu) { var data= { Chart:this, X:drag.LastMove.X-uielement.getBoundingClientRect().left, Y:drag.LastMove.Y-uielement.getBoundingClientRect().top, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; e.data=data; this.PopupSelectRectMenuV2(data, e); } } } else { this.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICKUP_CHART_PAINT,this.ClickDownPoint,e); } } else { this.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICKUP_CHART_PAINT,this.ClickDownPoint,e); this.ClickEvent(e); } //清空数据 JSConsole.Chart.Log('[KLineChartContainer::document.onmouseup]',e); if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.DragInfo=null; //this.UIElement.style.cursor="default"; this.SetCursor({Cursor:"default"}); this.MouseDrag=null; this.ClickDownPoint=null; this.IsOnTouch=false; if (this.EnableEraseChartDrawPicture==true) { this.EnableEraseChartDrawPicture=false; //更改画图工具对话框橡皮状态 if (this.DialogDrawTool && this.DialogDrawTool.SetEraseChartButtonStatus) this.DialogDrawTool.SetEraseChartButtonStatus(false); } if (this.BorderDrag && this.BorderDrag.Index>=0) this.Frame.SaveSubFrameHeightRate(); //拖拽指标窗口高度以后保存 this.BorderDrag=null; this.YDrag=null; this.UpDownDrag=null; this.RectSelectDrag=null; this.IndexChartDrag=null; this.CustomChartDrag=null; if (bClearDrawPicture===true) this.CurrentChartDrawPicture=null; } this.UIOnMounseOut=function(e) { JSConsole.Chart.Log('[KLineChartContainer::UIOnMounseOut]',e); this.UIOnMouseMove(e); } this.UIOnMouseleave=function(e) { JSConsole.Chart.Log('[KLineChartContainer::UIOnMouseleave]',e); //this.UIOnMouseMove(e); } this.OnDragChart=function(drag) { if (!drag) return false; var info=drag.Info; var lastMove=drag.LastMove; var startFrameID=info.FrameID; var endFrameID=this.Frame.PtInFrame(lastMove.X,lastMove.Y); if (endFrameID<0) { if (endFrameID==-3) //底部 移动到新的窗口 return this.MoveIndexToNewWindow({ WindowIndex:startFrameID, IndexID:info.IndexID }, { Operator:0 }); return false; } if (startFrameID==endFrameID) return false; //移动指标 return this.MoveIndex({ WindowIndex:startFrameID, IndexID:info.IndexID }, { WindowIndex:endFrameID, }, { Operator:0 }); } //获取选中图形信息 this.GetSelectedChartInfo=function(selectedChart) { if (!selectedChart) return null; var result={ Type:0 }; var id=selectedChart.Identify; if (id=="Main-KLine") { result.Name=this.Name; result.Symbol=this.Symbol; result.Type=JSCHART_DRAGCHART_TYPE_ID.MAIN_KLINE; } else if (id.indexOf("Overlay-KLine-")==0) { result.Name=selectedChart.Chart.Title; result.Symbol=selectedChart.Chart.Symbol; result.Type=JSCHART_DRAGCHART_TYPE_ID.OVERLAY_KLINE; } else if (id.indexOf("Overlay-Minute-")==0) { result.Name=selectedChart.Chart.Title; result.Symbol=selectedChart.Chart.Symbol; result.Type=JSCHART_DRAGCHART_TYPE_ID.OVERLAY_MINUTE; } else if (id=="Minute-Line") { result.Name=this.Name; result.Symbol=this.Symbol; result.Type=JSCHART_DRAGCHART_TYPE_ID.MAIN_MINUTE; } else if (id=="Minute-Average-Line") { result.Name=this.Name; result.Symbol=this.Symbol; result.Type=JSCHART_DRAGCHART_TYPE_ID.MAIN_AVERAGE_MINUTE; } else if (id=="Minute-Vol-Bar") { result.Name=this.Name; result.Symbol=this.Symbol; result.Type=JSCHART_DRAGCHART_TYPE_ID.MAIN_MINUTE_VOL; } else if (id.indexOf("guid")==0) { for(var i=0;i0) break; } } return result; } //点击事件 this.ClickEvent=function(e) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK); if (!event || !event.Callback) return false; if (this.ClickDownPoint.X!=e.clientX || this.ClickDownPoint.Y!=e.clientY) return false; var pixelTatio = GetDevicePixelRatio(); var x=(e.clientX-uielement.getBoundingClientRect().left)*pixelTatio; var y=(e.clientY-uielement.getBoundingClientRect().top)*pixelTatio; var data= { X:e.clientX, Y:e.clientY, FrameID:-1 }; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); if (isInClient) { 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.DBClickEvent=function(dbClickInfo, e) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DBCLICK); if (!event || !event.Callback) return false; var pixelTatio = GetDevicePixelRatio(); var x=(e.clientX-uielement.getBoundingClientRect().left)*pixelTatio; var y=(e.clientY-uielement.getBoundingClientRect().top)*pixelTatio; var data= { X:e.clientX, Y:e.clientY, FrameID:-1 , ClientPos:-1 }; var clientPos=this.PtInClient(x,y); data.ClientPos=clientPos; if (clientPos>0) { 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 } ; if (this.GetDataItem) data.Data.Item=this.GetDataItem({ClientPos:clientPos, Index:xValue, Point:{ X:x, Y:y } }); } } //选中图形 if (dbClickInfo && dbClickInfo.SelectedChart) { data.SelectedChart=this.GetSelectedChartInfo(dbClickInfo.SelectedChart); } event.Callback(event, data, this); return true; } this.PtInChartPaintTooltip=function(x,y, toolTip) { for(var i=0;i { this.OnTouchStart(e); } uielement.ontouchmove=(e)=> {this.OnTouchMove(e); } uielement.ontouchend=(e)=> {this.OnTouchEnd(e); } this.AddPhoneDBClickInfo=function(x,y,time) { var item={ X:x, Y:y, Time:time }; this.PhoneDBClickInfo.Start.push(item); } this.ClearPhoneDBClickInfo=function() { this.PhoneDBClickInfo.Start=[]; } this.IsShortPhoneClick=function(x,y,time) { } this.OnTouchStart=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; this.IsPress=false; this.IsOnTouch=true; this.TouchDrawCount=0; this.PhonePinch=null; this.StopDragTimer(); var isSingleTouch=this.IsSingleTouch(e); if (this.EnableScrollUpDown==false || !isSingleTouch || //多点触屏 (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID && this.TouchStatus.CorssCursorShow==true)) //十字光标显示,不能滚动页面 { if (e.cancelable) e.preventDefault(); } if (this.IsPhoneDragging(e)) { var touches = this.GetToucheData(e, this.IsForceLandscape); var pt=this.PointAbsoluteToRelative(touches[0].clientX, touches[0].clientY, true); if (this.TryClickLock || this.TryClickIndexTitle) //指标枷锁区域 , 指标标题点击 { var x = pt.X; var y = pt.Y; if (this.TryClickLock && this.TryClickLock(x, y)) return; if (this.TryClickIndexTitle && this.TryClickIndexTitle(x,y)) return; } if (this.ClickFrameButton) { var button=this.Frame.PtInButtons(pt.X,pt.Y); if (button) { this.ClickFrameButton(button, e); return; } } if (this.EnableVerticalDrag ) { this.VerticalDrag={ IsDrag:false }; if (this.Frame.PtInFrameVertical(pt.X, pt.Y)) this.VerticalDrag.IsDrag=true; } var bStartTimer=true; if (this.ChartDrawOption.IsLockScreen) { bStartTimer=false; } else if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) { if (this.TouchStatus.CorssCursorShow==true) bStartTimer=false; } else if (this.DragMode==JSCHART_DRAG_ID.DISABLE_DRAG_ID) { bStartTimer=false; } else { if (!isSingleTouch) bStartTimer=false; } if (this.VerticalDrag) bStartTimer=false; if (this.EnableClickModel && this.ClickModel.IsShowCorssCursor==true) bStartTimer=false; 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 drawPictureActive=this.GetActiveDrawPicture(); //上一次选中的 var selectedChart={ Chart:this.SelectedChart.Selected.Chart, Identify:this.SelectedChart.Selected.Identify }; //上一次选中的图形 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; var isDrawPictrue=false; 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()) { if (drawPicture.IsDrawMain) this.Draw(); else this.DrawDynamicInfo( {Corss:false, Tooltip:false} ); } } if (e.cancelable) e.preventDefault(); return; } else { var pt=this.PointAbsoluteToRelative(touches[0].clientX,touches[0].clientY, true); var drawPictrueData={ X:pt.X, Y:pt.Y }; var pixelTatio = GetDevicePixelRatio(); //鼠标移动坐标是原始坐标 需要乘以放大倍速 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; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件 if (event && event.Callback) { let sendData={ DrawPicture: drawPictrueData.ChartDrawPicture }; event.Callback(event,sendData,this); } var drawType=0; if (drawPictrueData.ChartDrawPicture.IsDrawMain) drawType=1; else if (drawPictureActive.Select.Guid && drawPictureActive.Select.Chart && drawPictureActive.Select.Chart.IsDrawMain) drawType=1; if (drawType==1) this.Draw(); if (e.cancelable) e.preventDefault(); return; } } if (bStartTimer) { //长按2秒,十字光标 var self=this; this.DragTimer=setTimeout(function() { self.IsPress=true; if (drag.Click.X==drag.LastMove.X && drag.Click.Y==drag.LastMove.Y) //手指没有移动,出现十字光标 { var mouseDrag=self.MouseDrag; self.MouseDrag=null; if (self.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) self.TouchStatus.CorssCursorShow=true; //十字显示 if (self.EnableClickModel===true) self.ClickModel.IsShowCorssCursor=true; self.MoveCorssCursor(drag.Click,e);//移动十字光标 } }, self.PressTime); } if (this.EnableZoomIndexWindow) { this.PhoneDBClick.AddTouchStart(touches[0].clientX, touches[0].clientY, Date.now()); JSConsole.Chart.Log("[JSChartContainer::OnTouchStart] PhoneDBClick ", this.PhoneDBClick); } if (this.ChartDrawOption.IsLockScreen) { this.MouseDrag=null; } else if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) { } else if (this.DragMode==JSCHART_DRAG_ID.DISABLE_DRAG_ID) { this.MouseDrag=null; this.MoveCorssCursor(drag.Click,e); } else if (this.EnableClickModel) { //if (this.ClickModel.IsShowCorssCursor===true) this.MoveCorssCursor(drag.Click,e) } else if (this.VerticalDrag) { if (!this.VerticalDrag.IsDrag) this.MoveCorssCursor(drag.Click,e); //没有点击X轴, 就显示十字光标 } else if (this.IsClickShowCorssCursor) { this.MoveCorssCursor(drag.Click,e); } this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchStart"}, e); var drawType=0; if (drawPictureActive.Select.Guid!=null) { if (drawPictureActive.Select.Guid && drawPictureActive.Select.Chart) drawType=1; } if (drawType==1) this.Draw(); } 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.SelectChartDrawPicture=null; } } this.OnTouchMove=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var touches=this.GetToucheData(e,this.IsForceLandscape); if (this.IsPhoneDragging(e)) { var drag=this.MouseDrag; if (drag==null) { if (this.IsForceLandscape) y=uielement.getBoundingClientRect().width-touches[0].clientY; //强制横屏Y计算 if (!this.ChartDrawOption.IsLockScreen) this.MoveCorssCursor({X:touches[0].clientX, Y:touches[0].clientY},e); } 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); var isMoveCorssCursor=(this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID && this.TouchStatus.CorssCursorShow==true); //是否移动十字光标 if (this.VerticalDrag) { if (this.VerticalDrag.IsDrag===true) isMoveCorssCursor=false; else isMoveCorssCursor=true; } if (this.EnableClickModel) { if (this.ClickModel.IsShowCorssCursor===true) isMoveCorssCursor=true; else isMoveCorssCursor=false; } //JSConsole.Chart.Log(`[JSChartContainer::OnTouchMove] moveAngle=${moveAngle} , moveUpDown=${moveUpDown}, moveSetp=${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 (isMoveCorssCursor) //点击模式下 十字光标显示 左右移动十字光标 { var mouseDrag=this.MouseDrag; this.MouseDrag=null; this.MoveCorssCursor(drag.Click,e); //移动十字光标 } else if (this.DragMode==1 || isMoveCorssCursor==false) //数据左右拖拽 { if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true ) { this.StopDragTimer(); return; } if (moveSetp<5 || moveAngle<=this.TouchMoveMinAngle) { this.PreventTouchEvent(e); return; } if (this.EnableVerticalDrag) { if (!this.VerticalDrag) return; if (!this.VerticalDrag.IsDrag) return; } var isLeft=true; if (drag.LastMove.X0) //放大 { var cursorIndex={ IsLockRight:this.IsZoomLockRight }; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (!this.Frame.ZoomUp(cursorIndex)) return; phonePinch.Operator="ZoomUp"; this.CursorIndex=cursorIndex.Index; this.UpdatePointByCursorIndex(); this.UpdataDataoffset(); this.UpdateFrameMaxMin(); //this.ResetFrameXSplit(); this.Draw(); this.ShowTooltipByKeyDown(); this.StopDragTimer(); } else //缩小 { var cursorIndex={ IsLockRight:this.IsZoomLockRight }; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (!this.Frame.ZoomDown(cursorIndex)) return; phonePinch.Operator="ZoomDown"; this.CursorIndex=cursorIndex.Index; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); //this.ResetFrameXSplit(); this.Draw(); this.ShowTooltipByKeyDown(); this.StopDragTimer(); } phonePinch.Last={ X:touches[0].pageX, Y:touches[0].pageY, X2:touches[1].pageX, Y2:touches[1].pageY }; } this.PreventTouchEvent(e); } this.OnTouchEnd=function(e) { JSConsole.Chart.Log('[KLineChartContainer:OnTouchEnd]',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.VerticalDrag=null; if (bClearDrawPicture===true) this.CurrentChartDrawPicture=null; this.StopDragTimer(); this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchEnd"}, e); this.OnTouchFinished(); this.TouchDrawCount=0; this.PhonePinch=null; } this.OnTouchDBClick=function(points) { var pt=this.PointAbsoluteToRelative(points[0].X, points[0].Y, true); var x=pt.X, y=pt.Y; JSConsole.Chart.Log(`[KLineChartContainer:OnTouchDBClick] Phone dbclick absolute [${x},${y}], soruce [${points[0].X},${points[0].Y}]`); var frameId=this.Frame.PtInFrame(x,y); JSConsole.Chart.Log("[KLineChartContainer::OnTouchDBClick] frameId",frameId); if (frameId>=this.Frame.ZoomStartWindowIndex) { if (this.ZoomIndexWindow(frameId, {X:x, Y:y})) { this.Frame.SetSizeChage(true); this.Draw(); return true; } } } //手势事件 this.TouchEvent=function(obj,e) { var eventID=obj.EventID; var event=this.GetEventCallback(eventID); if (!event || !event.Callback) return false; var drag=this.PhoneTouchInfo if (!drag || !drag.Start || !drag.End ) return false; var pixelTatio = GetDevicePixelRatio(); var clientX=drag.End.X/pixelTatio; var clientY=drag.End.Y/pixelTatio; var x=drag.End.X-this.UIElement.getBoundingClientRect().left*pixelTatio; var y=drag.End.Y-this.UIElement.getBoundingClientRect().top*pixelTatio; var data= { X:clientX, Y:clientY, FrameID:-1, FunctionName:obj.FunctionName, Drag: { Start:{ X:drag.Start.X/pixelTatio, Y:drag.Start.Y/pixelTatio }, End:{ X:drag.End.X/pixelTatio, Y:drag.End.Y/pixelTatio } } }; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); if (isInClient) { 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.MoveCorssCursor=function(point,e) { var pixelTatio = GetDevicePixelRatio(); var x = point.X-this.UIElement.getBoundingClientRect().left*pixelTatio; var y = point.Y-this.UIElement.getBoundingClientRect().top*pixelTatio; if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) this.TouchStatus.CorssCursorShow=true; //十字显示 this.OnMouseMove(x,y,e,true); } this.DrawEmpty=function() { if (this.UIElement.width<=0 || this.UIElement.height<=0) return; this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); if (this.Frame) { this.Frame.ScreenImageData=null; this.Frame.Draw(); } } this.PtInChart=function(x,y) { var result=null; for(var i=0;i { this.BeforeDrawXYCoordinate(frame); }); } this.Frame.Draw(); if (this.Frame.DrawCustomVertical) { var eventCVericalDraw=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_VERTICAL_DRAW); this.Frame.DrawCustomVertical(eventCVericalDraw); } this.Frame.CalculateLock(); for(var i=0;i=0 对应的指标窗口中ID if (this.LastPoint.X!=null || this.LastPoint.Y!=null) { if (this.ChartCorssCursor) { this.ChartCorssCursor.LastPoint=this.LastPoint; this.ChartCorssCursor.CursorIndex=this.CursorIndex; if (this.EnableNewIndex) { this.ChartCorssCursor.CorssCursorIndex=this.CorssCursorIndex; this.ChartCorssCursor.EnableNewIndex=this.EnableNewIndex; } var bRestoreCanvas=false; if (this.CorssCursorCanvas) //独立的十字光标层 { this.ChartCorssCursor.Canvas=this.CorssCursorCanvas; this.ChartCorssCursor.Canvas.clearRect(0,0,this.CorssCursorElement.width,this.CorssCursorElement.height) bRestoreCanvas=true; } var button=this.PtInButton(this.LastPoint.X,this.LastPoint.Y); if (button) //鼠标在按钮上 不显示十字光标 { } else if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) { //点击手势模式下 if (this.TouchStatus.CorssCursorShow==true) this.ChartCorssCursor.Draw(); } else if (this.EnableClickModel) { if (this.ClickModel.IsShowCorssCursor===true) this.ChartCorssCursor.Draw(); } else if (!(this.CorssCursorTouchEnd===true && this.MouseDrag) && !(this.CorssCursorTouchEnd==true && this.IsOnTouch==false)) { //移动端 拖拽数据的时候 不显示十字光标, 没有按屏的时候也不显示十字光标 this.ChartCorssCursor.Draw(); } if (bRestoreCanvas) { this.ChartCorssCursor.Canvas=this.Canvas; } bDrawDialogTooltip=true; } ptPosition=this.Frame.PtInFrame(this.LastPoint.X, this.LastPoint.Y); } var drawStatus=this.GetDrawStatus(); drawStatus.DrawName="Draw"; var eventTitleDraw=this.GetEventCallback(JSCHART_EVENT_ID.ON_TITLE_DRAW); var eventIndexTitleDraw=this.GetEventCallback(JSCHART_EVENT_ID.ON_INDEXTITLE_DRAW); for(var i=0;iendKLine.Open) info.LineColor=g_JSChartResource.FrameLatestPrice.UpBarColor; else if (endKLine.Close=0 对应的指标窗口中ID if (option && option.Point && (option.ParentFunction=='OnMouseMove' || option.ParentFunction=='MoveCorssCursorIndex')) { ptPosition=this.Frame.PtInFrame(option.Point.X, option.Point.Y); } var drawStatus=this.GetDrawStatus(); drawStatus.DrawName="DrawDynamicInfo"; for(var i=0;i=0) //在K线内部移动,调整K线索引 this.CursorIndex=this.Frame.GetXData(x); if (this.EnableBorderDrag && this.Frame && !this.CurrentChartDrawPicture) { var dragBorder=this.Frame.PtInFrameBorder(x,y); if (dragBorder && dragBorder.Index>=0) { mouseStatus={ Cursor:"n-resize", Name:"DragBorder"}; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] drag border ",dragBorder); } } if (this.EnableYDrag && this.Frame && !this.CurrentChartDrawPicture) { var dragY=this.TryYDrag(x,y); if (dragY) { mouseStatus={ Cursor:dragY.Position==0 ? "n-resize":"row-resize", Name:"DragY"}; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] drag y ",dragY); } } if (!this.CurrentChartDrawPicture) { button=this.PtInButton(x,y); if (button) { mouseStatus={ Cursor:"pointer", Name:button.Name}; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] frame button ", button); } } if (this.ChartCorssCursor) { var crossButton=this.ChartCorssCursor.PtInButton(x,y); if (crossButton) { mouseStatus={ Cursor:"pointer", Name:"CorssCursorButton"}; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] cross cursor button ", crossButton); } } if (this.ClassName=="KLineChartContainer" && this.Frame.PtInFrameBottom(x,y)) { mouseStatus={ Cursor:"ew-resize", Name:"FrameButtom"}; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] frame bottom "); } if (this.Frame.PtInHorizontalLabel && this.Frame.PtInHorizontalLabel(x,y)) { mouseStatus={ Cursor:"pointer", Name:"HorizontalLabel"}; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] frame Horizontal Label "); } if (this.SelectedChart.EnableMoveOn && this.PtInChart && !this.CurrentChartDrawPicture) { var chartInfo=this.PtInChart(x,y); if (chartInfo && chartInfo.Identify) { mouseStatus={ Cursor:"pointer", Name:"PtInChart"}; this.SelectedChart.MoveOn.Identify=chartInfo.Identify; this.SelectedChart.MoveOn.Identify=null; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] Point in chart ", chartInfo); } else { this.SelectedChart.MoveOn.Identify=null; } } else { this.SelectedChart.MoveOn.Identify=null; } //区间选择 var paint=this.GetRectSelectPaint(); if (paint && paint.GetPointCount()>0) { var item=paint.PtInPaint(x,y); if (item) { if (item.Type==4) mouseStatus={ Cursor:"pointer", Name:"DragRectSelect"}; //子区域选中 else mouseStatus={ Cursor:"ew-resize", Name:"DragRectSelect" }; JSConsole.Chart.Log("[JSChartContainer::OnMouseMove] drag rect select ",item); } } var sendData={ MouseStatus:null, X:x, Y:y, FrameID:frameID, e:e }; if (this.TryMouseMove_CustomChartDrag(sendData)) { if (sendData.MouseStatus) mouseStatus=sendData.MouseStatus; } var bDrawPicture=false; //是否正在画图 if (this.CurrentChartDrawPicture) { var index=this.Frame.PtInChartFrame(x,y); if (this.CurrentChartDrawPicture.Status!=20) { var bDrawValid=false; //是否在有效绘图区域里面 if (IFrameSplitOperator.IsNumber(this.CurrentChartDrawPicture.LimitFrameID)) { if (index>=0 && index==this.CurrentChartDrawPicture.LimitFrameID) bDrawValid=true; } else { if (index>=0) bDrawValid=true; } mouseStatus={ Cursor:bDrawValid ? "crosshair":"not-allowed", Name:"CurrentChartDrawPicture"}; } if (this.CurrentChartDrawPicture.SetLastPoint) this.CurrentChartDrawPicture.SetLastPoint({X:x,Y:y}); bDrawPicture=true; } else { var drawPictrueData={}; drawPictrueData.X=x; drawPictrueData.Y=y; if (this.GetChartDrawPictureByPoint(drawPictrueData) && drawPictrueData.ChartDrawPicture) { if (this.EnableEraseChartDrawPicture) { this.SetCursor({Cursor:"grabbing"}); } else { if (drawPictrueData.ChartDrawPicture.EnableMove==true) { if (drawPictrueData.PointIndex===100) { if (drawPictrueData.Cursor) this.SetCursor(drawPictrueData); //this.UIElement.style.cursor=drawPictrueData.Cursor; else this.SetCursor({Cursor:"move"}); //this.UIElement.style.cursor="move"; } else { if (drawPictrueData.Cursor) this.SetCursor(drawPictrueData); //this.UIElement.style.cursor=drawPictrueData.Cursor else this.SetCursor({Cursor:"pointer"}); //this.UIElement.style.cursor="pointer"; } bDrawPicture=true; } } this.MoveOnChartDrawPicture=drawPictrueData.ChartDrawPicture; } else { if (!this.MouseDrag) this.SetCursor({Cursor:"default"}); //this.UIElement.style.cursor="default"; } } var clientPos=this.PtInClient(x,y); var option={ ParentFunction:'OnMouseMove', Point:{X:x, Y:y}, IsPhone:isPhone===true, ClientPos:clientPos }; if ((e && (e.type=="mouseout" || e.type=="mouseleave")) || button) option.Corss=false; //鼠标移开,在按钮上,不显示十字光标 if (this.SetCorssCursorIndex) this.SetCorssCursorIndex(option); if (this.DrawDynamicInfoOption.Enable) { this.DrawDynamicInfoOption.Timer=setTimeout(()=> { this.DrawDynamicInfo(option); },this.DrawDynamicInfoOption.DelayTime); } else { this.DrawDynamicInfo(option); } this.SetCursor(mouseStatus); if (this.IsShowTooltip && bDrawPicture==false) { var toolTip=this.GetChartTooltipData(x,y); if (toolTip && toolTip.Data) { if (isPhone===true) { var touche=e.touches[0]; var xTooltip = touche.clientX-this.UIElement.getBoundingClientRect().left; var yTooltip = touche.clientY-this.UIElement.getBoundingClientRect().top; } else { var xTooltip = e.clientX-this.UIElement.getBoundingClientRect().left; var yTooltip = e.clientY-this.UIElement.getBoundingClientRect().top; } this.ShowTooltip(xTooltip,yTooltip,toolTip); } else { this.HideTooltip(); } } } //设置鼠标形状 {Cursor:鼠标形状 } this.SetCursor=function(obj) { if (!obj || !obj.Cursor) return; if (obj.Cursor=="default") this.UIElement.style.cursor=this.DefaultCursor; else this.UIElement.style.cursor=obj.Cursor; } this.OnKeyDown=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; //回调事件 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYDOWN); if (event && event.Callback) { var sendData={ e:e, PreventDefault:false }; event.Callback(event, sendData, this); if (sendData.PreventDefault) return; } var keyID = e.keyCode ? e.keyCode :e.which; var draw=false; if (this.ChartCorssCursor && this.ChartCorssCursor.OnKeyDown) //十字光标 隐藏显示 { var sendData={ e:e, KeyID:keyID, Draw:false, PreventDefault:false }; this.ChartCorssCursor.OnKeyDown(sendData); draw=sendData.Draw; } switch(keyID) { case 37: //left if (e.ctrlKey && this.OnCustomKeyDown) { if (this.OnCustomKeyDown(keyID, e)) break; } if (this.CursorIndex<=0.99999) { if (!this.DataMoveLeft()) { //左移数据到头了 触发下载新数据 if (this.DragDownloadData) this.DragDownloadData(); break; } this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.ResetFrameXSplit(); this.Draw(); this.ShowTooltipByKeyDown(); this.OnKLinePageChange("keydown"); } else { --this.CursorIndex; this.UpdatePointByCursorIndex(); this.DrawDynamicInfo(); this.ShowTooltipByKeyDown(); } break; case 39: //right if (e.ctrlKey && this.OnCustomKeyDown) { if (this.OnCustomKeyDown(keyID, e)) break; } var xPointcount=0; if (this.Frame.XPointCount) xPointcount=this.Frame.XPointCount; else xPointcount=this.Frame.SubFrame[0].Frame.XPointCount; if (this.CursorIndex+1>=xPointcount) { if (!this.DataMoveRight()) break; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.ResetFrameXSplit(); this.Draw(); this.ShowTooltipByKeyDown(); this.OnKLinePageChange("keydown"); } else { //判断是否在最后一个数据上 var data=null; if (this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; if (!data) break; if (this.CursorIndex+data.DataOffset+1>=data.Data.length) break; ++this.CursorIndex; this.UpdatePointByCursorIndex(); this.DrawDynamicInfo(); this.ShowTooltipByKeyDown(); } break; case 38: //up if (this.EnableZoomUpDown && this.EnableZoomUpDown.Keyboard===false) break; var cursorIndex={ ZoomType:this.ZoomType, IsLockRight:this.IsZoomLockRight }; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (!this.Frame.ZoomUp(cursorIndex)) break; this.CursorIndex=cursorIndex.Index; this.UpdatePointByCursorIndex(); this.UpdataDataoffset(); this.UpdateFrameMaxMin(); this.ResetFrameXSplit(); this.Draw(); this.ShowTooltipByKeyDown(); this.OnKLinePageChange("keydown"); break; case 40: //down if (this.EnableZoomUpDown && this.EnableZoomUpDown.Keyboard===false) break; var cursorIndex={ ZoomType:this.ZoomType ,IsLockRight:this.IsZoomLockRight }; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (!this.Frame.ZoomDown(cursorIndex, { ZoomDownloadDataCallback:(requestData)=>{ this.ZoomDownloadData(requestData) } })) break; this.CursorIndex=cursorIndex.Index; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.ResetFrameXSplit(); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) { } else { this.Draw(); } this.ShowTooltipByKeyDown(); this.OnKLinePageChange("keydown"); break; case 46: //del if (this.SelectChartDrawPicture) { var drawPicture=this.SelectChartDrawPicture; JSConsole.Chart.Log("[JSChartContainer::OnKeyDown] delete draw picture."); this.SelectChartDrawPicture=null; if (this.ChartPictureMenu) this.ChartPictureMenu.Hide(); this.ClearChartDrawPicture(drawPicture); //删除选中的画图工具 this.CloseModifyDrawDialog(); } else if (this.SelectedChart && this.SelectedChart.Selected.Identify) { var selectedInfo=this.GetSelectedChartInfo(this.SelectedChart.Selected); if (selectedInfo) { if (selectedInfo.Type==JSCHART_DRAGCHART_TYPE_ID.OVERLAY_INDEX) this.DeleteOverlayWindowsIndex(selectedInfo.IndexID); else if (selectedInfo.Type==JSCHART_DRAGCHART_TYPE_ID.OVERLAY_KLINE) this.DeleteOverlaySymbol(selectedInfo.Symbol); } } break; case 32: //space this.OnMarkRectSelect(e); break; case 27: //ESCAPE 取消画布工具 if (this.CurrentChartDrawPicture) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status!=20) //画布移动的时候不能取消 this.CurrentChartDrawPicture=null; } break; default: return; } if (draw) this.DrawDynamicInfo(); //不让滚动条滚动 if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnDoubleClick=function(x,y,e) { //JSConsole.Chart.Log(e); } this.ZoomIndexWindow=function(frameID, option) //最大化/最小化指标窗口 { if (frameID<0 || frameID>=this.Frame.SubFrame.length) return false; return this.Frame.ZoomIndexWindow(frameID, option); } this.ShowIndexTitleOnly=function(frameID, option) //只显示指标的标题 { if (frameID<0 || frameID>=this.Frame.SubFrame.length) return false; return this.Frame.ShowIndexTitleOnly(frameID, option); } this.RemoveMinSizeWindows=function() //清空最小化窗口 { if (!this.Frame.ZoomWindowsInfo) return; var aryDeleteIndex=[], aryIndex=[]; //删除的索引, 保留的索引 for(var i=0;i10) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { this.Canvas.rect(border.Left,border.Top,border.Right-border.Left,border.TopEx-border.Top); } else { this.Canvas.rect(border.Left,border.Top,border.LeftEx-border.Left,border.Bottom-border.Top); } if (this.Canvas.isPointInPath(x,y)) return 2; } if (this.Frame.ChartBorder.RightExtendWidth>10) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { this.Canvas.rect(border.Left,border.BottomEx,border.Right-border.Left,border.Bottom-border.BottomEx); } else { this.Canvas.rect(border.RightEx,border.Top,border.Right-border.RightEx,border.Bottom-border.Top); } if (this.Canvas.isPointInPath(x,y)) return 3; } return -1; } this.OnMoveFromeBorder=function(index, yMove) { if (!this.Frame) return; if (!this.Frame.OnMoveFromeBorder(index,yMove)) return ; //this.Frame.SetSizeChage(true); this.Frame.SetFrameBorderSizeChange(); this.Frame.ReDrawToolbar(); this.Draw(); } this.OnZoomUpDownFrameY=function(obj, yMove) { if (!this.Frame) return; if (!this.Frame.OnZoomUpDownFrameY(obj,yMove)) return ; this.Frame.SetSizeChage(true); this.Draw(); } this.OnUpDonwFrameY=function(obj, yMove) { if (!this.Frame) return false; if (!this.Frame.OnUpDonwFrameY(obj,yMove)) return false; this.Frame.SetSizeChage(true); return true; } this.CancelZoomUpDownFrameY=function(obj) { if (!this.Frame) return; if (!this.Frame.CancelZoomUpDownFrameY(obj)) return ; this.UpdateFrameMaxMin(); this.Frame.SetSizeChage(true); this.Draw(); } this.IsKLineContainer=function() { if (this.ClassName=='KLineChartContainer' || this.ClassName=='KLineChartHScreenContainer' || this.ClassName=="KLineTrainChartContainer" || this.ClassName=="CustomKLineChartContainer" ) return true; return false; } this.IsMinuteContainer=function() { if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") return true; return false; } this.UpdatePointByCursorIndex=function(type) //type 1=根据十字光标更新 2=强制取消十字光标 { var pt={X:null, Y:null}; pt.X=this.Frame.GetXFromIndex(this.CursorIndex); var index=Math.abs(this.CursorIndex-0.5); if (this.IsKLineContainer()) index=this.CursorIndex; var data=this.Frame.Data; if (data.DataOffset+index { return this.GetEventCallback(id); } if (!format.Operator()) return; var textHeight=format.LineCount*25; //每行的行高25 if (format.Height>0) textHeight=format.Height; //新版本高度有格式化类计算完成 var width=format.Width; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =textHeight+"px"; //JSConsole.Chart.Log(`[JSChartContainer::ShowTooltip] left=${left} top=${top} xMove=${xMove}` ); //if (toolTip.ChartPaint.Name=="Overlay-KLine") this.Tooltip.style.height =220+"px"; this.Tooltip.style.position = "absolute"; //JSConsole.Chart.Log('[JSChartContainer::ShowTooltip] getBoundingClientRect() ',this.UIElement.getBoundingClientRect()) if (left+width>this.UIElement.getBoundingClientRect().width) this.Tooltip.style.left = (left-width) + "px"; else this.Tooltip.style.left = left + "px"; if (top+xMove+textHeight>this.UIElement.getBoundingClientRect().height-5) this.Tooltip.style.top = (top-textHeight)+ "px"; else this.Tooltip.style.top = (top + xMove)+ "px"; this.Tooltip.className='jschart-tooltip'; this.Tooltip.innerHTML=format.Text; this.Tooltip.style.display = "block"; this.TooltipCache.IsShow=true; this.TooltipCache.Data={ Date:toolTip.Data.Date, Time:toolTip.Data.Time }; this.TooltipCache.InnerHTML=format.Text; } else if (toolTip.Type===1) //信息地雷提示信息 { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var scrollPos=GetScrollPosition(); var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('KLineInfoDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-klineinfo-tooltip'; this.Tooltip.style.position = "absolute"; if(left+width>this.UIElement.getBoundingClientRect().width){ this.Tooltip.style.left = (left-width) + "px"; }else{ this.Tooltip.style.left = left + "px"; } this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text; this.Tooltip.style.display = "block"; } else if (toolTip.Type==2) //指标信息 { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('KLineTradeDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-klinetrade-tooltip'; this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = left + "px"; this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text;; this.Tooltip.style.display = "block"; } else if (toolTip.Type==3) //分时图异动信息 { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('MinuteInfoDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-minuteinfo-tooltip'; //分时图异动 this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = left + "px"; this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text;; this.Tooltip.style.display = "block"; } else if (toolTip.Type==4) //ChartMultiSVGIconV2 图标信息 { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('IconDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-iconinfo-tooltip'; //图标信息 this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = left + "px"; this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text;; this.Tooltip.style.display = "block"; } else if (toolTip.Type==5) { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('ChartOXDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.Period=this.Period; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-chartox-tooltip'; //OX指标数据 this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = left + "px"; this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text;; this.Tooltip.style.display = "block"; } else if (toolTip.Type==6) //散点图 { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('ScatterPlotDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.Period=this.Period; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-charscatterplot-tooltip'; //OX指标数据 this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = left + "px"; this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text;; this.Tooltip.style.display = "block"; } else if (toolTip.Type==7) //ChartDrawSVG { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } var left = x; var top = y; var format=g_DivTooltipDataForamt.Create('ChartDrawSVGDataStringFormat'); format.Value=toolTip; format.Symbol=this.Symbol; format.Period=this.Period; format.LanguageID=this.LanguageID; if (!format.Operator()) return; var width=format.Width; this.Tooltip.className='jchart-chartdrawsvg-tooltip'; //ChartDrawSVG指标数据 this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = left + "px"; this.Tooltip.style.top = (top +xMove)+ "px"; this.Tooltip.style.width = width+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=format.Text; this.Tooltip.style.display = "block"; } else if (toolTip.Type==8) //ChartDrawSVG 新版本 { if (this.FloatTooltip) { this.DrawFloatTooltip({X:x, Y:y, YMove:20/pixelTatio}, toolTip); bHideFloatToolip=false; return; } } if (bHideFloatToolip) this.HideFloatTooltip(); } this.UpdateDOMTooltip=function(toolTipType, data) { if (!this.TooltipCache.IsShow) return ; if (this.TooltipCache.Type!=toolTipType) return; if (!this.TooltipCache.Data) return; if (this.TooltipCache.Type===0) { if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) return; var lastItem=data.Data[data.Data.length-1]; if (lastItem.Date!=this.TooltipCache.Data.Date) return; if (IFrameSplitOperator.IsNumber(lastItem.Time) && lastItem.Time!=this.TooltipCache.Data.Time) return; var klinePaint=this.ChartPaint[0]; var format=g_DivTooltipDataForamt.Create('HistoryDataStringFormat'); format.Value={ Data:lastItem, ChartPaint:klinePaint, Type:this.TooltipCache.Type }; format.Symbol=this.Symbol; format.LanguageID=this.LanguageID; format.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (!format.Operator()) return; if (format.Text==this.TooltipCache.InnerHTML) return; this.Tooltip.innerHTML=format.Text; this.TooltipCache.InnerHTML=format.Text; } } this.HideTooltip=function() { this.TooltipCache.IsShow=false; this.TooltipCache.Type=null; this.TooltipCache.InnerHTML=null; this.TooltipCache.Data=null; if (this.Tooltip.style.display!="none") this.Tooltip.style.display = "none"; this.HideFloatTooltip(); } this.UpdateSelectRect=function(start,end) { if (!this.ChartPaint[0].Data) return; var paint=this.GetRectSelectPaint(); if (!paint) return; var data=this.ChartPaint[0].Data; var count=data.Data.length; if (end>=count) end=count-1; var startItem=data.Data[start]; var endItem=data.Data[end]; JSConsole.Chart.Log('[JSChartContainer::UpdateSelectRect]',startItem,endItem); paint.SetPoint(startItem, { Index:0, DataIndex:start }); paint.SetPoint(endItem, { Index:1, DataIndex:end }); this.Draw(); } this.HideSelectRect=function() { this.ClearDragSelectRect(); } this.ResetFrameXYSplit=function() { if (typeof(this.Frame.ResetXYSplit)=='function') this.Frame.ResetXYSplit(); } this.ResetFrameXSplit=function() { if (typeof(this.Frame.ResetXSplit)=='function') this.Frame.ResetXSplit(); } this.ResetFrameYCustomSplit=function(windowIndex) { if (typeof(this.Frame.ResetYCustomSplit)=='function') this.Frame.ResetYCustomSplit(windowIndex); } 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;jrange.Min) frameItem.Range.Min=range.Min; } else { frameItem={ OverlayFrame:[] }; frameItem.Frame=paint.ChartFrame; frameItem.Range=range; frameMaxMinData.push(frameItem); } } //当前计算 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 in this.ChartPaint) { var item =this.ChartPaint[i]; if (!item.Data) continue; item.Data.DataOffset=data.DataOffset; } for(var i in this.OverlayChartPaint) { var item =this.OverlayChartPaint[i]; if (!item.Data) continue; item.Data.DataOffset=data.DataOffset; } //叠加指标当前显示的数据偏移 for (var i in this.Frame.SubFrame) { var subFrame=this.Frame.SubFrame[i]; for(var j in subFrame.OverlayIndex) { var overlayItem=subFrame.OverlayIndex[j]; for(var k in overlayItem.ChartPaint) { var item=overlayItem.ChartPaint[k]; if (!item.Data) continue; item.Data.DataOffset=data.DataOffset; } } } } this.GetMoveOneStepWidth=function() { if (IFrameSplitOperator.IsPlusNumber(this.StepPixel)) return this.StepPixel; var pixelRatio=GetDevicePixelRatio(); var mainFrame=this.Frame.SubFrame[0].Frame; var dataWidth=mainFrame.DataWidth; var distanceWidth=mainFrame.DistanceWidth; var oneStepWidth=this.StepPixel; var oneStepWidth=(dataWidth+distanceWidth)/pixelRatio; if (oneStepWidth<1) oneStepWidth=1; return oneStepWidth; } this.DataMove=function(step,isLeft) { var oneStepWidth=this.GetMoveOneStepWidth(); var moveStep=step; step=parseInt(step/oneStepWidth); //除以4个像素 if (step<=0) return false; var data=null; if (!this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; 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 (this.Frame.SubFrame && this.Frame.SubFrame.length>0 && this.Frame.SubFrame[0].Frame) { var fristFrame=this.Frame.SubFrame[0].Frame; if (fristFrame.DataWidth<=1 || fristFrame.DistanceWidth<=1) //K线在缩放很小的时候 移动加速 { if (IFrameSplitOperator.IsPlusNumber(this.StepPixel)) step=parseInt(moveStep)*this.StepPixel; } } if (isLeft) //--> { 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; } } this.XCoordinateZoom=function(step, isMoveLeft) { var oneStepWidth=this.GetMoveOneStepWidth(); var moveStep=step; step=parseInt(step/oneStepWidth); //除以4个像素 if (step<=0) return false; return this.Frame.XCoordinateZoom(isMoveLeft); } //获取鼠标在当前子窗口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.beginPath(); 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.GetSelectRectData=function(selectData) { if (Math.abs(selectData.XStart-selectData.XEnd)<5) return false; var startClientPos=this.PtInClient(selectData.XStart, selectData.YStart); var endClientPos=this.PtInClient(selectData.XEnd, selectData.YEnd); var data=null; if (this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; if (!data) return false; var start=this.GetDataIndexByPoint(selectData.XStart); var end=this.GetDataIndexByPoint(selectData.XEnd); if (Math.abs(start-end)<2) return false; selectData.Data=data; if (start>end) { selectData.Start=end; selectData.End=start; } else { selectData.Start=start; selectData.End=end; } return true; } //获取当前的点对应的 画图工具的图形 //data.X data.Y 鼠标位置 返回 data.ChartDrawPicture 数据在画图工具 data.PointIndex 在画图工具对应点索引 this.GetChartDrawPictureByPoint=function(data) { for(var i=0;i=0) { data.ChartDrawPicture=item; data.PointIndex=pointIndex; if (item.GetCursorType) data.Cursor=item.GetCursorType(pointIndex); //鼠标形状 return true; } } return false; } // 保存图片 this.SaveToImage = function (format,colorGB) { if (this.UIElement.width<=0 || this.UIElement.height<=0) return null; if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return null; // 数据加载中不能保存 JSConsole.Chart.Log('[JSChartContainer::SaveToImage]', this.UIElement); var clrBG='rgb(255,255,255)'; if (colorGB) clrBG=colorGB; this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); this.Canvas.fillStyle=clrBG; this.Canvas.fillRect(0,0,this.UIElement.width,this.UIElement.height); //画一个背景色, 不然是一个黑的背景 var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度 this.Frame.Draw(); //框架 for (var i in this.ChartPaint) //框架内图形 { var item=this.ChartPaint[i]; if (item.IsDrawFirst) item.Draw(); } for(var i in this.ChartPaint) { var item=this.ChartPaint[i]; if (!item.IsDrawFirst) item.Draw(); } for(var i in this.ChartPaintEx) { var item=this.ChartPaintEx[i]; item.Draw(); } for(var i in this.OverlayChartPaint) //叠加股票 { var item=this.OverlayChartPaint[i]; item.Draw(); } for(var i in this.ExtendChartPaint) //固定扩展图形 { var item=this.ExtendChartPaint[i]; if (!item.IsDynamic && item.IsAnimation==false) item.Draw(); } if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal(); this.Frame.DrawLock(); for(var i in this.ExtendChartPaint) //动态扩展图形 { var item=this.ExtendChartPaint[i]; if (item.IsDynamic && item.DrawAfterTitle===false) item.Draw(); } if (this.LastPoint.X!=null || this.LastPoint.Y!=null) { if (this.ChartCorssCursor) //十字光标不画 { this.ChartCorssCursor.LastPoint=this.LastPoint; this.ChartCorssCursor.CursorIndex=this.CursorIndex; } } for(var i in this.TitlePaint) { var item=this.TitlePaint[i]; if (!item.IsDynamic) continue; item.CursorIndex=this.CursorIndex; item.Draw(); } for(var i in this.ExtendChartPaint) //动态扩展图形 { var item=this.ExtendChartPaint[i]; if (item.IsDynamic && item.DrawAfterTitle===true && item.IsAnimation==false) item.Draw(); } if (this.EnableAnimation) { for(var i in this.ExtendChartPaint) //动画 { var item=this.ExtendChartPaint[i]; if (item.IsAnimation===true) item.Draw(); } } for(var i in this.ChartDrawPicture) { var item=this.ChartDrawPicture[i]; item.Draw(); } if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10) { this.CurrentChartDrawPicture.Draw(); } var dataURL=this.UIElement.toDataURL(format ? format:'image/png', 1.0); JSConsole.Chart.Log('[JSChartContainer::SaveToImage] data= ', dataURL); return dataURL; } this.SaveToImageUrl=function(obj,callback) //obj:{Format: 图片格式, ColorGB: 背景色}, callback:function(bSuccess,obj) { if (!obj) obj={Format:'image/png', ColorGB:'rgb(255,255,255)'}; var imageData=this.SaveToImage(obj.Format, obj.ColorGB); var postData={"Base64":imageData, "BucketName":"downloadcache", "Path":"hqchart/hq_snapshot"}; var url=g_JSChartResource.Domain+'/API/FileUploadForBase64'; JSNetwork.HttpRequest({ url: url, method: "POST", dataType: "json", data: postData, success: function (data) { JSConsole.Chart.Log('[JSChartContainer::SaveToImageUrl] recv data', data); var result={Path:data.relativeurl, Domain:'http://127.0.0.1:8087'}; result.Url=`${result.Domain}/${result.Path}`; if (callback) callback(true,result,''); }, error: function (request) { JSConsole.Chart.Log('[JSChartContainer::SaveToImageUrl] error ', request); if (callback) callback(false,null,'upload failed'); } }); } this.ExportDataToCSV=function(data) { var strCSV=""; var strRow=""; var rowCount=0; //标题 for(var i=0;i=this.Frame.SubFrame.length) continue; var subFrame=this.Frame.SubFrame[i]; var border=subFrame.Frame.ChartBorder; if (IFrameSplitOperator.IsNumber(item.TitleHeight)) border.TitleHeight=item.TitleHeight*pixelTatio; } for(var i in option.Frame) { var item=option.Frame[i]; if (i>=this.Frame.SubFrame.length) continue; var subFrame=this.Frame.SubFrame[i]; var border=subFrame.Frame.ChartBorder; if (item.TopSpace>=0) border.TopSpace=item.TopSpace*pixelTatio; if (item.BottomSpace>=0) border.BottomSpace=item.BottomSpace*pixelTatio; } } this.ReloadFrame=function(resource) { for(var i=0; i=0) this.ChartDrawOption.Zoom=option.Zoom; if (option.Magnet) { var item=option.Magnet; if (!this.ChartDrawOption.Magnet) this.ChartDrawOption.Magnet={ Type:0, Distance:20*GetDevicePixelRatio(), Enable:false }; if (IFrameSplitOperator.IsBool(item.Enable)) this.ChartDrawOption.Magnet.Enable=item.Enable; if (IFrameSplitOperator.IsNumber(item.Type)) this.ChartDrawOption.Magnet.Type=item.Type; if (IFrameSplitOperator.IsNumber(item.Distance)) this.ChartDrawOption.Magnet.Distance=item.Distance; } } //是否显示十字光标的十字线 this.EnableShowCorssCursorLine=function(bShow) { if (!this.ChartCorssCursor) return; this.ChartCorssCursor.IsShowCorss=bShow; } //获取扩展画法 this.GetExtendChartByClassName=function(name) { for(var i=0; i=this.ExtendChartPaint.length) return; if (this.ExtendChartPaint[data.Index]!=data.Chart) return; if (typeof(data.Chart.Clear)=='function') data.Chart.Clear(); this.ExtendChartPaint.splice(data.Index,1); } //删除扩展画法 this.DeleteExtendChartByID=function(id) { for(var i=0;i=0) subFrame.Height = frameItem.Height; } } this.SetSubFrameOption=function(subFrame, option) { if (!option) return; var frame=subFrame.Frame; if (option.Window) { var item=option.Window; if (IFrameSplitOperator.IsBool(item.Modify)) frame.ModifyIndex=item.Modify; if (IFrameSplitOperator.IsBool(item.Change)) frame.ChangeIndex=item.Change; if (IFrameSplitOperator.IsBool(item.Close)) frame.CloseIndex=item.Close; if (IFrameSplitOperator.IsBool(item.Overlay)) frame.OverlayIndex=item.Overlay; if (IFrameSplitOperator.IsBool(item.Export)) frame.ExportData=item.Export; if (IFrameSplitOperator.IsBool(item.MaxMin)) frame.MaxMinWindow=item.MaxMin; if (IFrameSplitOperator.IsBool(item.TitleWindow)) frame.TitleWindow=item.TitleWindow; if (IFrameSplitOperator.IsBool(item.IsDrawTitleBG)) frame.IsDrawTitleBG=item.IsDrawTitleBG; if (IFrameSplitOperator.IsBool(item.IsShowNameArrow)) frame.IsShowNameArrow=item.IsShowNameArrow; if (item.OverlayIndexType) { if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.Position)) frame.OverlayIndexType.Position=item.OverlayIndexType.Position; if (IFrameSplitOperator.IsNumber(item.OverlayIndexType.LineSpace)) frame.OverlayIndexType.LineSpace=item.OverlayIndexType.LineSpace; } if (IFrameSplitOperator.IsNonEmptyArray(item.CustomToolbar)) //自定义工具按钮 { frame.CustomToolbar=item.CustomToolbar.slice(); } } 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.IsNumber(option.TitleArrowType)) subFrame.Frame.TitleArrowType=option.TitleArrowType; 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.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.IsShowIndexTitle=option.IsShowIndexTitle; if (IFrameSplitOperator.IsBool(option.IsShowLeftText)) { subFrame.Frame.IsShowYText[0]=option.IsShowLeftText; subFrame.Frame.YSplitOperator.IsShowLeftText=option.IsShowLeftText; //显示左边刻度 } if (IFrameSplitOperator.IsBool(option.IsShowRightText)) { subFrame.Frame.IsShowYText[1]=option.IsShowRightText; subFrame.Frame.YSplitOperator.IsShowRightText=option.IsShowRightText; //显示右边刻度 } } this.AddNewSubFrame=function(option) { var index=this.Frame.SubFrame.length; var subFrame=this.CreateSubFrameItem(index); var pixelRatio=GetDevicePixelRatio(); subFrame.Frame.ChartBorder.TitleHeight*=pixelRatio; 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; this.SetSubFrameOption(subFrame,option); //最后一个显示X轴坐标 for(var i=0;i=kData.Data.length) dataIndex=kData.Data.length-1; var item = kData.Data[dataIndex]; JSConsole.Chart.Log("[KLineChartContainer::MoveRectSelectPoint] point, item", obj.PointIndex, item); if (!paint.SetPoint(item,{ Index: obj.PointIndex, DataIndex:dataIndex })) return false; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAG_SELECT_RECT); if (event) { var selectData=paint.GetSelectRectData(); var data={ X:obj.X, Y:obj.Y, SelectData:selectData, RectSelectPaint:paint }; event.Callback(event,data,this); } if (this.IsShowSelectRectDialog()) //区间统计 { var selectData=paint.GetSelectRectData(); var data= { Chart:this, X:obj.X, Y:obj.Y, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; var e={ data:data } this.DrawSelectRectDialog(e); } return true; } this.MoveSubRectSelect=function(obj) { var paint=this.GetRectSelectPaint(); if (!paint) return false; if (!paint.MoveSubRect(obj.Step, obj.IsLeft)) return false; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAG_SUB_SELECT_RECT); if (event) { var subRectData={Start:paint.SubClient.FirstPoint, End: paint.SubClient.SecondPoint } var data={ X:obj.X, Y:obj.Y, SubRectSelectData: subRectData, RectSelectPaint:paint }; event.Callback(event,data,this); } return true; } this.ClearRectSelect=function(bEnforce) { var paint=this.GetRectSelectPaint(); if (!paint) return false; if (bEnforce) paint.PreventClose=false; return paint.ClearPoint(); } //删除指定窗口的所有叠加指标 this.DeleteWindowsOverlayIndex=function(windowIndex) { if (!IFrameSplitOperator.IsNumber(windowIndex)) return; if (windowIndex<0 || windowIndex>=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) { if (windowsIndex>=this.Frame.SubFrame.length) return null; var item=this.WindowIndex[windowsIndex]; if (item && item.Guid==guid) return { Type:0, Data:item, WindowIndex:windowsIndex }; var item=this.Frame.SubFrame[windowsIndex]; for(var i=0; i=this.Frame.SubFrame.length ) return false; if ( !IFrameSplitOperator.IsNumber(dest.WindowIndex) || dest.WindowIndex<0 || dest.WindowIndex>=this.Frame.SubFrame.length ) return false; var find=this.FindScriptIndex(src.IndexID,src.WindowIndex); if (!find) return false; var findItem=null,findOverlayItem=null; if (find.Type==0) findItem=find.Data; else if (find.Type==1) findOverlayItem=find.Data; if (!findOverlayItem && !findItem) return false; //固定窗口 var fixedWindowCount=0; var isMinuteChart=(this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") ? true:false; if (isMinuteChart) fixedWindowCount=2; //走势图固定2个窗口 if (dest.WindowIndex>=fixedWindowCount && this.WindowIndex[dest.WindowIndex]==null) //主指标是空的,移动到主指标上 { if (findItem) this.WindowIndex[dest.WindowIndex] = this.CreateMainScript(findItem); else if (findOverlayItem) this.WindowIndex[dest.WindowIndex] = this.CreateMainScript(findOverlayItem.Script); if (option.Operator==0) //移动模式, 删除原来的 { if (findOverlayItem) this.DeleteOverlayIndex(findOverlayItem.Identify, src.WindowIndex); else if (findItem) this.DeleteMainIndex(findItem.Guid,src.WindowIndex); } var bindData=this.GetMainData(); this.BindIndexData(dest.WindowIndex,bindData); //执行脚本 this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } else { var subFrame=this.Frame.SubFrame[dest.WindowIndex]; var overlayFrame=new OverlayIndexItem(); var frame=this.CreateOverlayFrame(); frame.Canvas=this.Canvas; frame.MainFrame=subFrame.Frame; frame.ChartBorder=subFrame.Frame.ChartBorder; if (findOverlayItem) frame.IsShow=findOverlayItem.Frame.IsShow; //if (obj.IsShareY===true) frame.IsShareY=true; 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); }; overlayFrame.Frame=frame; var scriptIndex; if (findItem) { scriptIndex=this.CreateOverlayScript(findItem); scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:dest.WindowIndex, Frame:overlayFrame }; //叠加指标信息 } else if (findOverlayItem) { scriptIndex=this.CreateOverlayScript(findOverlayItem.Script); scriptIndex.OverlayIndex={ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:dest.WindowIndex, Frame:overlayFrame }; //叠加指标信息 } overlayFrame.Script=scriptIndex; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_OVERLAY_FRAME); if (event && event.Callback) { var sendData={ OverlayFrame:overlayFrame, WindowIndex:dest.WindowIndex, SubFrame:subFrame }; event.Callback(event, sendData, this); } subFrame.OverlayIndex.push(overlayFrame); var updateWindowIndex=dest.WindowIndex; if (option.Operator==0) //移动模式, 删除原来的 { if (findOverlayItem) this.DeleteOverlayIndex(findOverlayItem.Identify, src.WindowIndex); else if (findItem) { this.DeleteMainIndex(findItem.Guid,src.WindowIndex); var find=this.FindScriptIndex(overlayFrame.Identify); if (find) updateWindowIndex=find.WindowIndex; } } var bindData=this.GetMainData(); this.BindOverlayIndexData(overlayFrame,updateWindowIndex,bindData); this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } } //移动指标到新的指标窗口 src={ WindowIndex:指标窗口索引,IndexID:指标ID } , option={ Operator: 0=移动, 1=复制 } this.MoveIndexToNewWindow=function(src, option) { if (!src || !option) return false; if (!IFrameSplitOperator.IsNumber(src.WindowIndex) || src.WindowIndex<0 || src.WindowIndex>=this.Frame.SubFrame.length) return false; var find=this.FindScriptIndex(src.IndexID,src.WindowIndex); if (!find) return false; var findItem=null,findOverlayItem=null; if (find.Type==0) findItem=find.Data; else if (find.Type==1) findOverlayItem=find.Data; if (!findOverlayItem && !findItem) return false; if (src.WindowIndex==this.Frame.SubFrame.length-1 && this.Frame.SubFrame[src.WindowIndex].OverlayIndex<=0) return false; //指标在最后一个窗口不需要移动 this.RemoveMinSizeWindows(); //清空隐藏的指标 var index=this.Frame.SubFrame.length; var subFrame=this.CreateSubFrameItem(index); var pixelRatio=GetDevicePixelRatio(); subFrame.Frame.ChartBorder.TitleHeight*=pixelRatio; 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.SelectedChart=this.SelectedChart; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.TitlePaint[index+1]=titlePaint; this.SetSubFrameOption(subFrame, option); //最后一个显示X轴坐标 for(var i=0;i{ this.OnClickRightMenu(data); } var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_RIGHT_MENU); if (event && event.Callback) { var sendData={ MenuData:menuData, FrameID:frameID }; event.Callback(event, sendData, this); } this.PopupMenuByRClick(menuData, x, y); } //指标窗口扩展图形 this.CreateChartPaintExtend=function(chart, windowIndex) { if (windowIndex<0) return false; var subFrame=this.Frame.SubFrame[windowIndex]; if (!subFrame || !subFrame.Frame) return false; var frame=subFrame.Frame; chart.Canvas=this.Canvas; chart.ChartBorder=frame.ChartBorder; chart.ChartFrame=frame; this.ChartPaintEx.push(chart); return true; } //删除指标窗口扩展图形 option={ ChartID:图形ID, WindowIndex:窗口 } this.DeleteChartPaintExtend=function(option, bCallDestroy) { if (!option) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.ChartPaintEx)) return; if (IFrameSplitOperator.IsNumber(option.WindowIndex)) { var windowIndex=option.WindowIndex; if (!this.Frame.SubFrame[windowIndex]) return; var subFrame=this.Frame.SubFrame[windowIndex].Frame; if (!subFrame) return; var paint=[]; //踢出当前窗口的指标画法 var deleteCount=0; for(var i=0;i0) this.ChartPaintEx=paint; } } this.ClearCurrnetDrawPicture=function() { this.CurrentChartDrawPicture=null; } this.CreateDragSelectRect=function(option) { var chart=g_ExtendChartPaintFactory.Create("RectDragPaint",option); if (!chart) return null; if (option && option.Enable===true) chart.Enable=true; chart.ChartBorder=this.Frame.ChartBorder; chart.ChartFrame=this.Frame; chart.HQChart=this; chart.SetOption(option); this.ChartDragSelectRect=chart; } this.ClearDragSelectRect=function() { if (!this.ChartDragSelectRect) return; this.ChartDragSelectRect.ClearPoint(); } this.ShowDragSelectRect=function(ptStart, ptEnd) { if (!this.ChartDragSelectRect) return; this.ChartDragSelectRect.SetFirstPoint(ptStart.X, ptStart.Y); this.ChartDragSelectRect.SetSecondPoint(ptEnd.X, ptEnd.Y); this.ChartDragSelectRect.Draw(); } //切换窗口指标 option={ Window:{}, OverlayIndex:[], Frame:{ }} this.ChangeIndexWindow=function(windowIndex, option) { JSConsole.Chart.Log('[KLineChartContainer::ChangeIndexWindow] windowIndex, option', windowIndex, option); if (windowIndex<0 || windowIndex>=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{ return element.ID==item.ID;} )) { aryID.push(i); } } if (!IFrameSplitOperator.IsNonEmptyArray(aryID)) return false; if (this.IsKLineContainer()) //K线 { var bindData=new ChartData(); bindData.Data=this.SourceData.Data; bindData.Period=this.Period; bindData.Right=this.Right; if (this.IsApiPeriod) { } else { if (bindData.Right>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; } } } else if (this.IsMinuteContainer()) //分时图 { var bindData=this.SourceData; } else { return; } for(var i=0;i0) return true; } return false; } function OnKeyDown(e) //键盘事件 { if(this.JSChartContainer && this.JSChartContainer.OnKeyDown) this.JSChartContainer.OnKeyDown(e); } function OnWheel(e) //上下滚动事件 { if(this.JSChartContainer && this.JSChartContainer.OnWheel) this.JSChartContainer.OnWheel(e); } function ToFixed(number, precision) { var b = 1; if (isNaN(number)) return number; if (number < 0) b = -1; var multiplier = Math.pow(10, precision); var value=Math.round(Math.abs(number) * multiplier) / multiplier * b; if (/^(\d+(?:\.\d+)?)(e)([\-]?\d+)$/.test(value)) var s=value.toFixed2(precision); else var s = value.toString(); var rs = s.indexOf('.'); if (rs < 0 && precision>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 "guid" + (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); } function GetScrollPosition() { var scrollPos={}; var scrollTop=0; var scrollLeft=0; if (document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)) { scrollTop=document.documentElement.scrollTop; scrollLeft=document.documentElement.scrollLeft; } else if(document.body) { scrollTop=document.body.scrollTop; scrollLeft=document.body.scrollLeft; } scrollPos.Top=scrollTop; scrollPos.Left=scrollLeft; return scrollPos; } //修正线段有毛刺 function ToFixedPoint(value) { return parseInt(value)+0.5; } //修正粗线段毛刺 function ToFixedPoint2(width, value) { var fixValue=(width % 2)===0 ? Math.floor(value):Math.floor(value) + 0.5; //毛边修正 return fixValue; } function ToFixedRect(value) { // With a bitwise or. //rounded = (0.5 + somenum) | 0; // A double bitwise not. //rounded = ~~ (0.5 + somenum); // Finally, a left bitwise shift. //value*=GetDevicePixelRatio(); var rounded; return rounded = (0.5 + value) << 0; } function PtInRect(x,y, rect) { if (x>=rect.Left && x<=rect.Right && y>=rect.Top && y<=rect.Bottom) return true; return false; } //深拷贝 function CloneData(data) { if (!data) return null; var strData=JSON.stringify(data); var item= JSON.parse(strData); return item; } function IsRecvOverlap(rect1, rect2) { return Math.max(rect1.Left,rect2.Left) < Math.min(rect1.Right,rect2.Right) && Math.max(rect1.Top,rect2.Top) < Math.min(rect1.Bottom,rect2.Bottom); } function CopyMarginConfig(dest,src) { if (!src || !dest) return; if (IFrameSplitOperator.IsNumber(src.Left)) dest.Left=src.Left; if (IFrameSplitOperator.IsNumber(src.Top)) dest.Top=src.Top; if (IFrameSplitOperator.IsNumber(src.Right)) dest.Right=src.Right; if (IFrameSplitOperator.IsNumber(src.Bottom)) dest.Bottom=src.Bottom; } //兼容老版本 function CopyMerginConfig(dest,src) { CopyMarginConfig(dest,src); } //数值比较 function NumberCompare() { } //< NumberCompare.LT=function(left, right) { if (IFrameSplitOperator.IsNumberV2(left, right)) { //== if (Math.abs(left - right)< 0.0000001) return false; } return left NumberCompare.GT=function(left, right) { if (IFrameSplitOperator.IsNumberV2(left, right)) { //== if (Math.abs(left - right)< 0.0000001) return false; } return left>right; } function Point() { this.X; this.Y; } function SelectRectData() { this.Data; //主数据 this.JSChartContainer; //行情控件 this.Start; //数据起始位子 this.End; //数据结束位置 this.XStart;//X坐标起始位置 this.YStart; this.XEnd; //X位置结束为止 this.YEnd; } //坐标信息 function CoordinateInfo() { this.Value; //坐标数据 this.Message=[]; //坐标输出文字信息 0=左 1=右 2=内左 3=内右 this.TextColor=g_JSChartResource.FrameSplitTextColor //文字颜色 this.TextBGColor; //文字背景色 this.TextColor2; //右侧文字颜色,空使用TextColor this.Font=g_JSChartResource.FrameSplitTextFont; //字体 this.LineColor=g_JSChartResource.FrameSplitPen; //线段颜色 this.LineDash=null; //当线段类型==2时 可以设置虚线样式 this.LineType=1; //线段类型 -1=不画线段 0=虚线 1,2=虚线, 3=短线 8,9=集合竞价坐标 this.LineWidth; //线段宽度 this.ExtendLine; //延长线长度[ ] { Width:长度 } [0]=左 [1]=右 实例: [null, { Width: 50}]; this.ExtendData; //扩展属性 //百分比 { PriceColor:, PercentageColor:, SplitColor:, Font: } //自定义刻度 { Custom:{ Position: 1=强制内部 }} //输出位置的Y轴偏移 //this.YOffset; this.AreaData; //区域: { Start:, End:, BGColor:, Position:[0=左, 1=右] } //不在当前屏范围 (可定义刻度使用) //this.OutRange={ BGColor:"", TextColor:, BorderColor: TopYOffset:, BottomYOffset: } //Y轴文字偏移 //this.YOffset=[{ Offset:5}, { Offset:10}] //目前只对框子外的刻度文字生效 } //边框信息 function ChartBorder() { this.UIElement; //四周间距 this.Left=50; this.Right=80; this.Top=50; this.Bottom=50; this.TitleHeight=24; //标题高度 this.TopSpace=0; this.BottomSpace=0; this.LeftExtendWidth=0; //左边扩展图形宽度 this.RightExtendWidth=0; this.MultiDayMinute={ Count:1, Left:0, Right:0 } // { Count:天数, Left:, Right: } this.IsShowTitleOnly=false; // 是否只显示标题 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 }; if (this.MultiDayMinute && this.MultiDayMinute.Count>1 && ( this.MultiDayMinute.Left>0 || this.MultiDayMinute.Right>0 )) { var frameWidth=this.UIElement.width-this.Left-this.Right; //坐标框子宽度 var dayWidth=frameWidth/this.MultiDayMinute.Count; // 每天的框子的宽度 var dayBorder=[]; for(var i=0;i0) item.Left+=1; //第2天的盘前 移到一个像素,跟上一天分开 dayBorder.push(item); } data.DayBorder=dayBorder; } 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 }; if (this.MultiDayMinute && this.MultiDayMinute.Count>1 && ( this.MultiDayMinute.Left>0 || this.MultiDayMinute.Right>0 )) { var frameWidth=this.UIElement.height-this.Top-this.Bottom; //坐标框子宽度 var dayWidth=frameWidth/this.MultiDayMinute.Count; //每天的框子的宽度 var dayBorder=[]; for(var i=0;i10) { canvas.beginPath(); if (isHScreen===true) { canvas.rect(border.Left,border.Top,border.Right-border.Left,border.TopEx-border.Top); } else { canvas.rect(border.Left,border.Top,border.LeftEx-border.Left,border.Bottom-border.Top); } if (canvas.isPointInPath(x,y)) return 2; } if (this.RightExtendWidth>10) { canvas.beginPath(); if (isHScreen===true) { canvas.rect(border.Left,border.BottomEx,border.Right-border.Left,border.Bottom-border.BottomEx); } else { canvas.rect(border.RightEx,border.Top,border.Right-border.RightEx,border.Bottom-border.Top); } if (canvas.isPointInPath(x,y)) return 3; } return -1; } this.GetChartWidth=function() { return this.UIElement.width; } this.GetChartHeight=function() { return this.UIElement.height; } this.GetLeft=function() { return this.Left+this.LeftExtendWidth; } this.GetRight=function() { return this.UIElement.width-this.Right-this.RightExtendWidth; } 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.LeftExtendWidth-this.RightExtendWidth; } 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 ChartFrameFactory() { //[key:name, { Create:function(option) { return new class(); }} ] this.DataMap=new Map( [ ["KLineFrame", { Create:function(option) { return new KLineFrame(); } }], //K线图 ["KLineHScreenFrame", { Create:function(option) { return new KLineHScreenFrame(); } }], ]); this.Create=function(name, option) { if (!this.DataMap.has(name)) { JSConsole.Warn(`[ChartFrameFactory::Create] can't find class=${name}.`); return null; } var item=this.DataMap.get(name); return item.Create(option); } this.Add=function(name, option) { var oldData=null; if (this.DataMap.has(name)) oldData=this.DataMap.get(name); this.DataMap.set(name, { Create:option.Create } ); return oldData; } } var g_ChartFrameFactory=new ChartFrameFactory(); function IChartFramePainting() { this.HorizontalInfo=new Array(); //Y轴 this.VerticalInfo=new Array(); //X轴 this.ClassName='IChartFramePainting'; this.Canvas; //画布 this.Identify; //窗口标识 this.Guid=Guid(); //内部窗口唯一标识 this.ChartBorder; this.PenBorder=g_JSChartResource.FrameBorderPen; //边框颜色 this.TitleBGColor=g_JSChartResource.FrameTitleBGColor; //标题背景色 this.IsShow=true; //是否显示 this.SizeChange=true; //大小是否改变 this.XYSplit=true; //XY轴坐标信息改变 this.XSplit=true; //X轴变化 this.YCustomSplit=true; //自定义Y轴分割线 this.HorizontalMax; //Y轴最大值 this.HorizontalMin; //Y轴最小值 this.HorizontalReserved=null; //Y轴预留高度 { Top:上, Bottom:下 } this.XPointCount=10; //X轴数据个数 this.ClientBGColor; //客户区背景色 //Y轴原始的最大值 最小值 this.YMaxMin={ Max:null, Min:null }; this.YSplitOperator; //Y轴分割 this.XSplitOperator; //X轴分割 this.Data; //主数据 this.IsLocked=false; //是否上锁 this.LockPaint = null; this.YSpecificMaxMin=null; //指定Y轴最大最小值 this.IsShowBorder = true; //是否显示边框 this.IsShowTitleArrow=g_JSChartResource.IndexTitle.EnableIndexArrow; //是否显示指标信息上涨下跌箭头 this.TitleArrowType=g_JSChartResource.IndexTitle.ArrowType; //指标信息上涨下跌箭头类型 0=独立颜色 1=跟指标名字颜色一致 this.IsShowIndexName=true; //是否显示指标名字 this.IsShowOverlayIndexName=true; //是否显示叠加指标名字 //this.OverlayIndexType= { Position:0, LineSpace:5 }; this.OverlayIndexType= { Position:1, LineSpace:3 }; this.IndexParamSpace=2; //指标参数数值显示间距 this.IndexTitleSpace=0; //指标标题和参数值之间的间距 this.IsShowIndexTitle=true; //显示整个指标标题信息 this.IsDrawTitleBottomLine=false; this.BorderLine=null; //1=上 2=下 4=左 8=右 this.Buttons=[]; //按钮事件 this.LeftButtonWidth=0; //左侧按钮的宽度 this.IsMinSize=false; //窗口是否最小化 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; this.LogoBGColor=g_JSChartResource.FrameLogo.BGColor; this.GlobalOption; //this.IsDrawLeftBorder; this.IsDrawRightBorder=false; //是否绘制右侧刻度空白的边框 this.IsDrawLeftBorder=false; //是否绘制右侧刻度空白的边框 this.HorizontalLabel; //Y轴刻度标签页 (支持点击的才会有)[ { ID:, Args:[], }] this.PtInButtons=function(x,y) //坐标是否在按钮上 { for(var i=0;i0) //上 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(right,top); } if ((this.BorderLine&2)>0) //下 { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } if ((this.BorderLine&4)>0) //左 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(left,bottom); } if ((this.BorderLine&8)>0) //右 { this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); } this.Canvas.stroke(); } /* if (this.IsDrawRightBorder) { var xRight=ToFixedPoint(border.ChartWidth); var xLeft=right; this.Canvas.beginPath(); this.Canvas.moveTo(xLeft,top); this.Canvas.lineTo(xRight,top); this.Canvas.lineTo(xRight,bottom); this.Canvas.lineTo(xLeft,bottom); this.Canvas.stroke(); } */ } //画标题背景色 this.DrawTitleBG=function() { if (this.ChartBorder.TitleHeight<=0) return; var border=this.GetBorder(); var left=ToFixedPoint(border.Left); var top=ToFixedPoint(border.Top); var right=ToFixedPoint(border.Right); var bottom=ToFixedPoint(this.ChartBorder.GetTopTitle()); var width=right-left; var height=bottom-top; this.Canvas.fillStyle=this.TitleBGColor; this.Canvas.fillRect(left,top,width,height); if (this.IsDrawTitleBottomLine) { this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(left,ToFixedPoint(border.TopTitle)); this.Canvas.lineTo(right,ToFixedPoint(border.TopTitle)); this.Canvas.stroke(); } } this.DrawLock=function() { if (this.IsLocked) { if (this.LockPaint == null) this.LockPaint = new ChartLock(); this.LockPaint.Canvas=this.Canvas; this.LockPaint.ChartBorder=this.ChartBorder; this.LockPaint.ChartFrame=this; this.LockPaint.Draw(true); } } this.DrawLogo=function() { var border=this.GetBorder(); var text=g_JSChartResource.FrameLogo.Text; if (!IFrameSplitOperator.IsString(text)) return; this.Canvas.font=this.LogoTextFont; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; var height=this.Canvas.measureText("擎").width; var width=this.Canvas.measureText(text).width; if (this.IsHScreen) { var x=border.Left+5; var y=border.Top+5; this.Canvas.save(); this.Canvas.translate(x,y); this.Canvas.rotate(90 * Math.PI / 180); var rtBG={ Left:0, Bottom:0, Width:width+4, Height:height+4 }; rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; if (this.LogoBGColor) { this.Canvas.fillStyle=this.LogoBGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); } this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.fillText(text,1,0); this.Canvas.restore(); } else { var rtBG={ Left:border.Left+5, Bottom:border.Bottom-5, Width:width+4, Height:height+4 }; rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; if (this.LogoBGColor) { this.Canvas.fillStyle=this.LogoBGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); } var x=rtBG.Left+1; var y=rtBG.Bottom-1; this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.fillText(text,x,y); } } this.CalculateLock=function() { if (this.IsLocked) { if (this.LockPaint == null) this.LockPaint = new ChartLock(); this.LockPaint.Canvas=this.Canvas; this.LockPaint.ChartBorder=this.ChartBorder; this.LockPaint.ChartFrame=this; this.LockPaint.Draw(false); } } //设施上锁 this.SetLock=function(lockData) { if (!lockData) //空数据不上锁 { this.IsLocked=false; return; } this.IsLocked=true; if (!this.LockPaint) this.LockPaint=new ChartLock(); //创建锁 if (lockData.Callback) this.LockPaint.Callback=lockData.Callback; //回调 if (lockData.IndexName) this.LockPaint.IndexName=lockData.IndexName; //指标名字 if (lockData.ID) this.LockPaint.LockID=lockData.ID; //锁ID if (lockData.BG) this.LockPaint.BGColor=lockData.BG; //背景色 if (lockData.Text) this.LockPaint.Title= lockData.Text; if (lockData.TextColor) this.LockPaint.TextColor=lockData.TextColor; if (lockData.Font) this.LockPaint.Font=lockData.Font; if (lockData.Count) this.LockPaint.LockCount=lockData.Count; if (lockData.MinWidth>0) this.LockPaint.MinWidth=lockData.MinWidth; } this.GetLockRect=function() { if (!this.IsLocked) return null; if (!this.LockPaint) return null; return this.LockPaint.LockRect; } this.ReloadResource=function(resource) { if (!resource) { this.PenBorder=g_JSChartResource.FrameBorderPen; //边框颜色 this.TitleBGColor=g_JSChartResource.FrameTitleBGColor; //标题背景色 } for(var i in this.HorizontalInfo) { var item=this.HorizontalInfo[i]; if (item.Font) item.Font=g_JSChartResource.FrameSplitTextFont; //字体 if (item.TextColor) item.TextColor=g_JSChartResource.FrameSplitTextColor //文字颜色 if (item.LineColor) item.LineColor=g_JSChartResource.FrameSplitPen; //线段颜色 } for(var i in this.VerticalInfo) { var item=this.VerticalInfo[i]; if (item.Font) item.Font=g_JSChartResource.FrameSplitTextFont; //字体 if (item.TextColor) item.TextColor=g_JSChartResource.FrameSplitTextColor //文字颜色 if (item.LineColor) item.LineColor=g_JSChartResource.FrameSplitPen; //线段颜色 } } this.GetFontHeight=function(font) { return GetFontHeight(this.Canvas, font, "擎"); } //左右刻度文字宽度 this.GetScaleTextWidth=function() { } //bIncludeOverlay =false不包含叠加框架 true=主框架+叠加框架 默认true this.IsMinuteFrame=function(bIncludeOverlay) { var aryName=["MinuteFrame", "MinuteHScreenFrame", "OverlayMinuteFrame", "OverlayMinuteHScreenFrame"]; if (bIncludeOverlay===false) aryName=["MinuteFrame", "MinuteHScreenFrame"]; var isMinute=aryName.includes(this.ClassName); return isMinute; } //bIncludeOverlay =false不包含叠加框架 true=主框架+叠加框架 默认true this.IsKLineFrame=function(bIncludeOverlay) { var aryName=["KLineFrame", "KLineHScreenFrame", "KLineHScreenFrame", "OverlayKLineHScreenFrame"]; if (bIncludeOverlay===false) aryName=["KLineFrame", "KLineHScreenFrame"]; var isKline=aryName.includes(this.ClassName); return isKline; } } //空框架只画边框 function NoneFrame() { this.newMethod=IChartFramePainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="NoneFrame"; this.Snapshot=function() { } this.SetSizeChage=function(sizeChange) { this.SizeChange=sizeChange; //画布的位置 this.Position={ X:this.ChartBorder.UIElement.offsetLeft, Y:this.ChartBorder.UIElement.offsetTop, W:this.ChartBorder.UIElement.clientWidth, H:this.ChartBorder.UIElement.clientHeight }; } } function AverageWidthFrame() { this.newMethod=IChartFramePainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="AverageWidthFrame"; this.DataWidth=50*GetDevicePixelRatio(); this.DistanceWidth=10*GetDevicePixelRatio(); this.MinXDistance = 30*GetDevicePixelRatio(); //X轴刻度最小间距 this.MinYDistance=12*GetDevicePixelRatio(); //Y轴刻度最小间距 this.CoordinateType=0; //坐标类型 0=普通坐标 1=反转坐标 this.IsShowYText=[true,true]; //是否显示Y轴坐标坐标 [0=左侧] [1=右侧] this.XBottomOffset=g_JSChartResource.Frame.XBottomOffset; //X轴文字显示向下偏移 this.YTextTopOffset=g_JSChartResource.Frame.YTopOffset; //Y轴顶部文字向下偏移 this.YTextPosition=[0,0], //是坐标否强制画在内部 [0=左侧] [1=右侧] 1=OUT" , 2=INSIDE this.YTextPadding=[g_JSChartResource.Frame.YTextPadding[0], g_JSChartResource.Frame.YTextPadding[1]], //Y轴文字和边框间距 [0=左侧] [1=右侧] this.IsShowXLine=true; //是否显示X轴刻度线 this.IsShowYLine=true; this.YInsideOffset=0; this.YTextBaseline=0; //0=居中 1=上部 (目前就支持内部刻度) this.MultiTextFormat=0; //多行刻度信息显示模式 0=显示第1行 1=价格/百分比 2=显示2行 this.RightTextMaxWidth=0; this.ShortYLineLength=5; this.ShortXLineLength=5; this.BeforeDrawXYCallback; //坐标绘制前回调,绘制深度图 this.GetEventCallback; //事件回调 //工具栏的按钮样式 this.ToolbarButtonStyle=g_JSChartResource.ToolbarButtonStyle; this.CloseWindowButton=CloneData(g_JSChartResource.Buttons.CloseWindow); this.OverlayIndexButton=CloneData(g_JSChartResource.Buttons.OverlayIndex); this.ChangeIndexButton=CloneData(g_JSChartResource.Buttons.ChangeIndex); this.ModifyIndexParamButton=CloneData(g_JSChartResource.Buttons.ModifyIndexParam); this.MaxMinWindowButton=CloneData(g_JSChartResource.Buttons.MaxMinWindow); this.TitleWindowButton=CloneData(g_JSChartResource.Buttons.TitleWindow); this.ExportDataButton=CloneData(g_JSChartResource.Buttons.ExportData); this.ButtonTooltip=CloneData(g_JSChartResource.Buttons.Tooltip); //Y轴刻度长线 this.YLineExtend; //[0]=左 [1]=右 { Width:5, Color:颜色, } this.YTextExtend; //[0]=左 [1]=右 { Align:0=默认 1=左对齐 2=右对齐 } this.YRightTextInfo; //X轴延长线 this.XTextExtend; //[0]=底部 { Align:0=默认(居中), 1=左对齐 } this.XLineExtend; //[0]=底部 { Mode:1, Color: } Mode=1 分割线 Mode=2短线 this.FrameData={ SubFrameItem:null }; //窗口框架信息 //画图工具刻度 this.DrawPicture={ BGColor:g_JSChartResource.DrawPicture.XYCoordinate.BGColor, TextBGColor:g_JSChartResource.DrawPicture.XYCoordinate.TextBGColor, TextColor:g_JSChartResource.DrawPicture.XYCoordinate.TextColor, Font:g_JSChartResource.DrawPicture.XYCoordinate.Font }; this.IChartFramePainting_ReloadResource=this.ReloadResource; this.ReloadResource=function(resource) { this.IChartFramePainting_ReloadResource(resource); if (!resource) { this.ToolbarButtonStyle=g_JSChartResource.ToolbarButtonStyle; this.CloseWindowButton=CloneData(g_JSChartResource.Buttons.CloseWindow); this.OverlayIndexButton=CloneData(g_JSChartResource.Buttons.OverlayIndex); this.ChangeIndexButton=CloneData(g_JSChartResource.Buttons.ChangeIndex); this.ModifyIndexParamButton=CloneData(g_JSChartResource.Buttons.ModifyIndexParam); this.MaxMinWindowButton=CloneData(g_JSChartResource.Buttons.MaxMinWindow); this.TitleWindowButton=CloneData(g_JSChartResource.Buttons.TitleWindow); this.ButtonTooltip=CloneData(g_JSChartResource.Buttons.Tooltip); } } this.DrawFrame=function() { if (this.XPointCount>0) { let dInterval=this.ChartBorder.GetWidth()/(6*this.XPointCount); //分6份, 数据4 间距2 this.DistanceWidth=2*dInterval; this.DataWidth=4*dInterval; } this.DrawHorizontal(); this.DrawVertical(); } this.DrawTitleButton=function(aryButton, moveonPoint, mouseStatus) { var border=this.GetBorder(); if (this.IsHScreen) { var y=border.Bottom-3; var x=border.RightTitle+this.ChartBorder.TitleHeight/2; this.Canvas.save(); this.Canvas.translate(x, y); this.Canvas.rotate(90 * Math.PI / 180); //底部开始画 var yButton=0, xButton=0, bottom=0; for(var i=0;i=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { color=item.Style.MoveOnColor; if (mouseStatus) mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:item, Frame:this, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } this.Canvas.fillStyle=color; this.Canvas.font=font; this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(item.Style.Text, xBotton, yButton); this.Buttons.push({ ID:item.ID, Rect:rtButton }); right=xBotton; } } } this.DrawToolbarTooltip=function(mouseOnToolbar) { if (!mouseOnToolbar) return; var border=this.GetBorder(); var text=null; if (mouseOnToolbar.Item.TooltipText) { text=mouseOnToolbar.Item.TooltipText; } else { var key='Toolbar-'+mouseOnToolbar.Item.ID; text=g_JSChartLocalization.GetText(key,0); } if (!text) return; var pixelRatio=GetDevicePixelRatio(); var canvas=this.Canvas; if (this.GetExtraCanvas) { var finder=this.GetExtraCanvas(JSChart.TooltipCursorCanvasKey); if (finder) canvas=finder.Canvas; } var xCenter=mouseOnToolbar.Rect.Left+mouseOnToolbar.Rect.Width/2; canvas.font=this.ButtonTooltip.Font; canvas.textAlign="left"; canvas.textBaseline="bottom"; var mergin= this.ButtonTooltip.Mergin; var textWidth=canvas.measureText(text).width+mergin.Left+mergin.Right; var textHeight=this.GetFontHeight(); var bgHeight=textHeight+mergin.Top+mergin.Bottom; if (mouseOnToolbar.ID=="TitleButton") { var x=mouseOnToolbar.Point.X; var y=mouseOnToolbar.Point.Y+20; } else if (JSCHART_BUTTON_ID.CLOSE_BEFOREOPEN_ID==mouseOnToolbar.Item.ID) { var x=mouseOnToolbar.Rect.Right+5; var y=mouseOnToolbar.Rect.Top; } else if (JSCHART_BUTTON_ID.DRAW_PICTURE_DELETE==mouseOnToolbar.Item.ID || JSCHART_BUTTON_ID.DRAW_PICTURE_SETTING==mouseOnToolbar.Item.ID || (mouseOnToolbar.Item.ID>=JSCHART_BUTTON_ID.DRAW_PICTURE_BUTTON_1 && mouseOnToolbar.Item.ID<=JSCHART_BUTTON_ID.DRAW_PICTURE_BUTTON_18 )) { var x=mouseOnToolbar.Point.X; var y=mouseOnToolbar.Point.Y+20; if ((x+textWidth)>=border.ChartWidth) x=border.ChartWidth-textWidth-2; } else { var x=xCenter-textWidth/2; var y=border.Top-bgHeight; if (y<0) y=border.TopEx+1; if (x+textWidth>border.ChartWidth) x=border.ChartWidth-textWidth-2; } if (IFrameSplitOperator.IsNumber(this.ButtonTooltip.BorderRadius)) //圆角 { var roundRadius=this.ButtonTooltip.BorderRadius; canvas.beginPath(); canvas.roundRect(ToFixedPoint(x), ToFixedPoint(y), ToFixedRect(textWidth), ToFixedRect(bgHeight), [roundRadius]); canvas.closePath(); canvas.fillStyle=this.ButtonTooltip.ColorBG; canvas.fill(); canvas.strokeStyle=this.ButtonTooltip.ColorBorder; canvas.stroke(); canvas.fillStyle=this.ButtonTooltip.Color; canvas.fillText(text, x+mergin.Left, y+bgHeight-mergin.Bottom); } else { canvas.fillStyle=this.ButtonTooltip.ColorBG; canvas.fillRect(x,y,textWidth,bgHeight); //画一个背景色, 不然是一个黑的背景 canvas.fillStyle=this.ButtonTooltip.Color; canvas.fillText(text, x+mergin.Left,y+bgHeight-mergin.Bottom); } } //isLimit 是否限制在当前坐标下 this.GetYFromData=function(value, isLimit) { if (this.Logarithmic && this.GetYLogarithmicFromData) { return this.GetYLogarithmicFromData(value, isLimit); } if (isLimit===false) { if (this.CoordinateType==1) { var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return this.ChartBorder.GetTopEx()+height; } else { var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return this.ChartBorder.GetBottomEx()-height; } } else { if (this.CoordinateType==1) { if(value<=this.HorizontalMin) return this.ChartBorder.GetTopEx(); if(value>=this.HorizontalMax) return this.ChartBorder.GetBottomEx(); var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return this.ChartBorder.GetTopEx()+height; } else { if(value<=this.HorizontalMin) return this.ChartBorder.GetBottomEx(); if(value>=this.HorizontalMax) return this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return this.ChartBorder.GetBottomEx()-height; } } } //画Y轴 this.DrawHorizontal=function() { this.RightTextMaxWidth=0; if (!IFrameSplitOperator.IsNonEmptyArray(this.HorizontalInfo)) return; if (this.ChartBorder.IsShowTitleOnly) return; var border=this.ChartBorder.GetBorder(); var left=border.Left; var right=border.Right var bottom = border.Bottom var top = this.ChartBorder.GetTop(); var borderRight=this.ChartBorder.Right; var borderLeft=this.ChartBorder.Left; var isDrawLeft=borderLeft>10 && this.IsShowYText[0]===true && this.YTextPosition[0]!=2; var isDrawRight=borderRight>10 && this.IsShowYText[1]===true && this.YTextPosition[1]!=2; var rightExtendLine=null; //右侧延长线 var leftExtendLine=null; //左侧延长线 if (IFrameSplitOperator.IsNonEmptyArray(this.YLineExtend)) { rightExtendLine=this.YLineExtend[1]; leftExtendLine=this.YLineExtend[0]; } var rightExtendText=null; //右侧文字设置 var leftExtendText=null; //左侧文字设置 if (IFrameSplitOperator.IsNonEmptyArray(this.YTextExtend)) { leftExtendText=this.YTextExtend[0]; rightExtendText=this.YTextExtend[1]; } var yPrev=null; //上一个坐标y的值 var pixelRatio=GetDevicePixelRatio(); var itemHeight=(border.BottomEx-border.TopEx)/this.HorizontalInfo.length; var aryMultiText=[]; var rtPreRight, rtRight, rtLeft, rtPreLeft; var textBaseline=0; //0=上 1=中 2=下 for(var i=this.HorizontalInfo.length-1; i>=0; --i) //从上往下画分割线 { var item=this.HorizontalInfo[i]; if (!IFrameSplitOperator.IsNumber(item.Value)) continue; if (NumberCompare.GT(item.Value,this.HorizontalMax) || NumberCompare.LT(item.Value,this.HorizontalMin)) continue; var y=this.GetYFromData(item.Value); if (y!=null && yPrev!=null && Math.abs(y-yPrev)0) { if (g_JSChartResource.FrameYLineDash) { this.Canvas.save(); this.Canvas.setLineDash(g_JSChartResource.FrameYLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(left,yFixed); this.Canvas.lineTo(right,yFixed); this.Canvas.stroke(); this.Canvas.setLineDash([]); this.Canvas.restore(); } else { this.Canvas.beginPath(); this.Canvas.moveTo(left,yFixed); this.Canvas.lineTo(right,yFixed); this.Canvas.stroke(); } } if (bChangeLineWidth) { this.Canvas.lineWidth=pixelRatio; } } var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; textBaseline=2; } else if (y <= top + 2) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; textBaseline=0; } else { this.Canvas.textBaseline = "middle"; textBaseline=1; } //左边 坐标信息 间距小于10 不画坐标 this.Canvas.strokeStyle=item.TextColor; this.Canvas.fillStyle=item.TextColor; if (item.Message[0]!=null && isDrawLeft) { var yOffset=0; if (IFrameSplitOperator.IsNonEmptyArray(item.YOffset)) //文字Y轴偏移 { var offsetItem=item.YOffset[0]; if (offsetItem && IFrameSplitOperator.IsNumber(offsetItem.Offset)) yOffset=offsetItem.Offset; } if (Array.isArray(item.Message[0])) { if (this.MultiTextFormat==3) { var obj={ Data:item.Message[0], X:left, Y:yText, TextBaseLine:textBaseline, IsLeft:true, Item:item, TextPadding:this.YTextPadding[0] }; this.DrawMultiLineText(obj); } } else { if (item.Font!=null) this.Canvas.font=item.Font; var xText=left; if (leftExtendLine && leftExtendLine.Width>1) { var lineLength=leftExtendLine.Width; if (leftExtendLine.Color) this.Canvas.strokeStyle=leftExtendLine.Color; else this.Canvas.strokeStyle=item.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(xText,yFixed); this.Canvas.lineTo(xText-lineLength,yFixed); this.Canvas.stroke(); xText-=lineLength; } rtLeft=this.GetTextTopBottom(textBaseline,yText); if (!rtPreLeft || (rtLeft && !this.IsTextTopBottomOverlap(rtLeft, rtPreLeft))) { if (leftExtendText && leftExtendText.Align===1) { this.Canvas.textAlign="left"; this.Canvas.fillText(item.Message[0],this.YTextPadding[0],yText+yOffset); } else { this.Canvas.textAlign="right"; this.Canvas.fillText(item.Message[0],xText-this.YTextPadding[0],yText+yOffset); rtPreLeft=rtLeft; } } } } //右边 坐标信息 间距小于10 不画坐标 if (item.Message[1]!=null && isDrawRight) { var yOffset=0; if (IFrameSplitOperator.IsNonEmptyArray(item.YOffset)) //文字Y轴偏移 { var offsetItem=item.YOffset[1]; if (offsetItem && IFrameSplitOperator.IsNumber(offsetItem.Offset)) yOffset=offsetItem.Offset; } if (item.Font!=null) this.Canvas.font=item.Font; var xText=right; if (item.LineType==3) { var lineLength=this.ShortYLineLength*GetDevicePixelRatio(); this.Canvas.beginPath(); this.Canvas.moveTo(xText,yFixed); this.Canvas.lineTo(xText+lineLength,yFixed); this.Canvas.stroke(); xText+=lineLength; } //右侧延长线 if (rightExtendLine && rightExtendLine.Width>1) { var lineLength=rightExtendLine.Width; if (rightExtendLine.Color) this.Canvas.strokeStyle=rightExtendLine.Color; else this.Canvas.strokeStyle=item.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(xText,yFixed); this.Canvas.lineTo(xText+lineLength,yFixed); this.Canvas.stroke(); xText+=lineLength+2; } this.Canvas.textAlign="left"; if (Array.isArray(item.Message[1])) { if (this.MultiTextFormat==1) //显示1行 格式:价格/百分比 { if (item.ExtendData) { if (item.ExtendData.Font) this.Canvas.font=item.ExtendData.Font; } var textData= { Text: [ {Text:item.Message[1][0], Width:this.Canvas.measureText(item.Message[1][0]).width }, {Text:item.Message[1][1], Width:this.Canvas.measureText(item.Message[1][1]).width } ], X:xText+2, Y:yText, TextBaseline:this.Canvas.textBaseline, Item:item } aryMultiText.push(textData); } else if (this.MultiTextFormat==2) //显示2行 { this.Canvas.fillText(item.Message[1][0],xText+this.YTextPadding[1],yText); var lineHeight=this.Canvas.measureText('M').width; if (itemHeight>lineHeight*2) this.Canvas.fillText(item.Message[1][1],xText+this.YTextPadding[1],yText+lineHeight); } else if (this.MultiTextFormat==3) { var obj={ Data:item.Message[1], X:xText, Y:yText, TextBaseLine:textBaseline, IsLeft:false, Item:item, TextPadding:this.YTextPadding[1] }; this.DrawMultiLineText(obj); } else //显示第1行 { var text=item.Message[1][0]; if (item.TextColor2) this.Canvas.fillStyle=item.TextColor2; if (rightExtendText && rightExtendText.Align===2 && this.YRightTextInfo) //右对齐 { this.Canvas.textAlign="right"; var xRight=this.YRightTextInfo.MainTextWidth+right-this.YTextPadding[1]; this.Canvas.fillText(text,xRight,yText); } else { this.Canvas.fillText(text,xText+this.YTextPadding[1],yText); } } } else { //计算显示的区域 rtRight=this.GetTextTopBottom(textBaseline,yText); if (!rtPreRight || (rtRight && !this.IsTextTopBottomOverlap(rtRight,rtPreRight))) { if (item.TextColor2) this.Canvas.fillStyle=item.TextColor2; if (rightExtendText && rightExtendText.Align===2 && this.YRightTextInfo) //右对齐 { this.Canvas.textAlign="right"; var xRight=this.YRightTextInfo.MainTextWidth+right-this.YTextPadding[1]; this.Canvas.fillText(item.Message[1],xRight,yText+yOffset); } else { this.Canvas.fillText(item.Message[1],xText+this.YTextPadding[1],yText+yOffset); } rtPreRight=rtRight; } } } yPrev=y; } if (IFrameSplitOperator.IsNonEmptyArray(aryMultiText) && this.MultiTextFormat==1) this.DrawHorizontalMuText(aryMultiText); if (isDrawRight && this.IsDrawRightBorder && this.YRightTextInfo) { var xRight=this.YRightTextInfo.MainTextWidth+right; xLine=ToFixedPoint(xRight); this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(xLine,top); this.Canvas.lineTo(xLine,bottom); this.Canvas.stroke(); if (IFrameSplitOperator.IsNonEmptyArray(this.YRightTextInfo.AryOverlayWidth)) { this.Canvas.beginPath(); for(var i=0;i=rt.Top && rt2.Top<=rt.Bottom) return true; if (rt2.Bottom>=rt.Top && rt2.Bottom<=rt.Bottom) return true; return false; } this.GetTextTopBottom=function(textBaseline, yText) { var rtRight=null; var textHeight=this.Canvas.measureText('擎').width; if (textBaseline==0) { rtRight={ Top: yText, Bottom:yText+textHeight } } else if (textBaseline==1) { rtRight={ Top: yText-textHeight/2 }; rtRight.Bottom=rtRight.Top+textHeight; } else if (textBaseline==2) { rtRight={ Bottom:yText }; rtRight.Top=rtRight.Bottom-textHeight; } return rtRight; } this.DrawHorizontalMuText=function(aryText) { var maxWidth=[null,null]; for(var i=0;i= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev!=null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 if (item.Message[2]) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if (y <= top + 2) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { this.Canvas.textBaseline = "middle"; } var textObj={ X:left, Y:yText, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[0]}} ; if (!this.IsOverlayMaxMin || !this.IsOverlayMaxMin(textObj)) { this.Canvas.fillText(item.Message[2], left + 1*pixelTatio, yText); if (yInsideText==null || yInsideText>yText) { this.YInsideOffset=this.Canvas.measureText(item.Message[2]).width+4*GetDevicePixelRatio(); yInsideText=yText; } } } if (item.Message[3]) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if (y <= top + 2) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { this.Canvas.textBaseline = "middle"; } var textWidth = this.Canvas.measureText(item.Message[3]).width; var textObj={ X:right-textWidth, Y:yText, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[1]}} ; if (!this.IsOverlayMaxMin || !this.IsOverlayMaxMin(textObj)) this.Canvas.fillText(item.Message[3], right - 1*pixelTatio, yText); } yPrev = y; } } //Y刻度画在左边内部 this.DrawInsideHorizontal = function () { if (this.IsHScreen===true) return; //横屏不画 if (this.IsMinSize) return; if (this.ChartBorder.IsShowTitleOnly) return; if (this.IsShowYText[0]===false && this.IsShowYText[1]===false) return; this.DrawInsideClientHorizontal(); var border=this.ChartBorder.GetBorder(); var left = border.Left var right = border.Right; var bottom = border.Bottom; var top = border.TopTitle; var borderRight = this.ChartBorder.Right; var borderLeft = this.ChartBorder.Left; var titleHeight = this.ChartBorder.TitleHeight; var isDrawLeft= (borderLeft<10 || this.YTextPosition[0]==2) && this.IsShowYText[0]===true; var isDrawRight= (borderRight<10 || this.YTextPosition[1]==2) && this.IsShowYText[1]===true; if ( isDrawLeft || isDrawRight ) { var pixelTatio = GetDevicePixelRatio(); var yPrev = null; //上一个坐标y的值 var yInsideText=null; for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev!=null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 //坐标信息 左边 间距小于10 画在内部 if (item.Message[0] != null && isDrawLeft) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; var textHeight=this.Canvas.measureText("擎").width; var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if ((y-textHeight/2)<=top) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { if (this.YTextBaseline==1) this.Canvas.textBaseline = "bottom"; else this.Canvas.textBaseline = "middle"; } var textObj={ X:left, Y:yText, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[0]}} ; if (!this.IsOverlayMaxMin || !this.IsOverlayMaxMin(textObj)) { this.Canvas.fillText(item.Message[0], left + 1*pixelTatio, yText); if (yInsideText==null || yInsideText>yText) { this.YInsideOffset=this.Canvas.measureText(item.Message[0]).width+4*GetDevicePixelRatio(); yInsideText=yText; } } } if (item.Message[1] != null && isDrawRight) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; var textHeight=this.Canvas.measureText("擎").width; var yText=y; if (y >= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } else if (y-textHeight/2 <= top) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; } else { if (this.YTextBaseline==1) this.Canvas.textBaseline = "bottom"; else this.Canvas.textBaseline = "middle"; } if (Array.isArray(item.Message[1])) var text=item.Message[1][0]; else var text=item.Message[1]; var textWidth = this.Canvas.measureText(text).width; var textObj={ X:right-textWidth, Y:yText, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[1]}} ; if (!this.IsOverlayMaxMin || !this.IsOverlayMaxMin(textObj)) this.Canvas.fillText(text, right - 1*pixelTatio, yText); } yPrev = y; } } } this.GetXFromIndex=function(index) { var count=this.XPointCount; if (count==1) { if (index==0) return this.ChartBorder.GetLeft(); else return this.ChartBorder.GetRight(); } else if (count<=0) { return this.ChartBorder.GetLeft(); } else if (index>=count) { return this.ChartBorder.GetRight(); } else { var offset=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*index/count; return offset; } } //画X轴 this.DrawVertical=function() { var border=this.GetBorder(); var top=border.TopTitle; var bottom=border.Bottom; var right=border.RightEx; var pixelRatio = GetDevicePixelRatio(); //获取设备的分辨率 //JSConsole.Chart.Log('[AverageWidthFrame.DrawVertical] bottom',bottom); //if (this.ChartBorder.Bottom<=5*GetDevicePixelRatio()) return; //高度不够 不显示 var mapX=null; if (this.GetVerticalXCache) mapX=this.GetVerticalXCache(); var bottomTextExtend=null; if (this.XTextExtend) { bottomTextExtend=this.XTextExtend[0]; } var bottomLineExtend=null; if (this.XLineExtend) { bottomLineExtend=this.XLineExtend[0]; } var xPrev=null; //上一个坐标x的值 var textRightPrev=null; //上一次刻度输出右边x坐标 for(var i=0; iright) break; if (xPrev!=null && Math.abs(x-xPrev)0) //实线 { if (g_JSChartResource.FrameXLineDash) { this.Canvas.strokeStyle=this.VerticalInfo[i].LineColor; this.Canvas.setLineDash(g_JSChartResource.FrameXLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,top); this.Canvas.lineTo(xFixed,bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.strokeStyle=this.VerticalInfo[i].LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,top); this.Canvas.lineTo(xFixed,bottom); this.Canvas.stroke(); } } } if (item.BG && this.DrawDayVertical) { this.DrawDayVertical(item, x, border); } if (this.VerticalInfo[i].Message[0]!=null && this.ChartBorder.Bottom>5*pixelRatio) { if (this.VerticalInfo[i].Font) this.Canvas.font=this.VerticalInfo[i].Font; var textLeft=0; this.Canvas.strokeStyle=item.TextColor; var testWidth=this.Canvas.measureText(this.VerticalInfo[i].Message[0]).width; var textHeight=this.Canvas.measureText("擎").width; if (bottomTextExtend && bottomTextExtend.Align==1) { this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; textLeft=x; } else { if (x= this.ChartBorder.GetChartWidth()) { this.Canvas.textAlign = "right"; this.Canvas.textBaseline="top"; textLeft=x-testWidth; } else { this.Canvas.textAlign="center"; this.Canvas.textBaseline="top"; textLeft=x-(testWidth/2); } } if (textRightPrev==null || textLeft>textRightPrev) { var yText=bottom; if (item.LineType==3) { var lineLength=this.ShortXLineLength*pixelRatio; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,yText); this.Canvas.lineTo(xFixed,yText+lineLength); this.Canvas.stroke(); yText+=lineLength+2*pixelRatio; } if (bottomLineExtend) { if (bottomLineExtend.Mode===1) { if (item.Value>1) { if (bottomLineExtend.Color) this.Canvas.strokeStyle=bottomLineExtend.Color; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,bottom); this.Canvas.lineTo(xFixed,border.ChartHeight); this.Canvas.stroke(); x+=1; } } else if (bottomLineExtend.Mode===2) { if (bottomLineExtend.Width>=1) { var lineLength=bottomLineExtend.Width; if (bottomLineExtend.Color) this.Canvas.strokeStyle=bottomLineExtend.Color; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,yText); this.Canvas.lineTo(xFixed,yText+lineLength); this.Canvas.stroke(); yText+=lineLength+2; } } } //item.TextBGColor="rgb(0,255,0)"; if (item.TextBGColor) //文字背景色 { var rtText={ Left:textLeft, Top:yText+this.XBottomOffset, Width:testWidth, Height:textHeight }; this.Canvas.fillStyle=item.TextBGColor; this.Canvas.fillRect(rtText.Left-1, rtText.Top, rtText.Width+2, rtText.Height); } this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(this.VerticalInfo[i].Message[0],x,yText+this.XBottomOffset); textRightPrev=textLeft+testWidth; } } xPrev=x; } } //Y坐标转y轴数值 this.GetYData=function(y,isLimit) { if (this.Logarithmic && this.GetYLogarithmicFromData) { return this.GetYLogarithmicData(y); } if (this.CoordinateType==1) //反转坐标 { if (isLimit==false) { return (y-this.ChartBorder.GetTopEx())/this.ChartBorder.GetHeightEx()*(this.HorizontalMax-this.HorizontalMin)+this.HorizontalMin; } else { if (ythis.ChartBorder.GetBottomEx()) return this.HorizontalMax; return (y-this.ChartBorder.GetTopEx())/this.ChartBorder.GetHeightEx()*(this.HorizontalMax-this.HorizontalMin)+this.HorizontalMin; } } else { if (isLimit==false) { return (this.ChartBorder.GetBottomEx()-y)/this.ChartBorder.GetHeightEx()*(this.HorizontalMax-this.HorizontalMin)+this.HorizontalMin; } else { if (ythis.ChartBorder.GetBottomEx()) return this.HorizontalMin; return (this.ChartBorder.GetBottomEx()-y)/this.ChartBorder.GetHeightEx()*(this.HorizontalMax-this.HorizontalMin)+this.HorizontalMin; } } } //X坐标转x轴数值 this.GetXData=function(x) { if (x<=this.ChartBorder.GetLeft()) return 0; if (x>=this.ChartBorder.GetRight()) return this.XPointCount; return (x-this.ChartBorder.GetLeft())*(this.XPointCount*1.0/this.ChartBorder.GetWidth()); } //选中的画图工具X,Y轴坐标信息 this.DrawPictureXCoordinate=function(drawPicture, range, option) { if (this.IsHScreen) return; if (!range) return; if (!IFrameSplitOperator.IsNonEmptyArray(range.Points)) return; var border=this.GetBorder(); var left=border.Left; var right=border.Right; this.Canvas.font=this.DrawPicture.Font; var fontHeight=this.GetFontHeight(); this.Canvas.textAlign="left"; this.Canvas.textBaseline = "bottom"; if (range.X) { var xRange=range.X; var xLeft=xRange.Min.X; var xRight=xRange.Max.X; if (xLeftright) xRight=right; this.Canvas.fillStyle=this.DrawPicture.BGColor; this.Canvas.fillRect(xLeft, border.Bottom, xRight-xLeft, fontHeight); } for(var i=0;iright) continue; var index=this.GetXData(item.X, false); var index=Math.round(index); var kItem=this.GetKItem(index); if (kItem) { var text=IFrameSplitOperator.FormatDateString(kItem.Date,null); if (ChartData.IsMinutePeriod(option.Period)) text+=" " + IFrameSplitOperator.FormatTimeString(kItem.Time, "HH:MM"); else if (ChartData.IsMilliSecondPeriod(option.Period)) text+=" " + IFrameSplitOperator.FormatTimeString(kItem.Time, "HH:MM:SS.fff"); var textWidth=this.Canvas.measureText(text).width+2; var textLeft=item.X-textWidth/2; if (textLeftbottom) yBottom=bottom; this.Canvas.fillStyle=this.DrawPicture.BGColor; this.Canvas.fillRect(right, yTop, textWidth+5, yBottom-yTop); } for(var i=0;ibottom) continue; this.Canvas.fillStyle=this.DrawPicture.TextBGColor; this.Canvas.fillRect(right, item.Y-fontHeight/2, textWidth, fontHeight); this.Canvas.fillStyle=this.DrawPicture.TextColor; var yText=item.Y+fontHeight/2; this.Canvas.fillText(item.Text,right+this.YTextPadding[1],yText); } } this.DrawPicturePointYCoordinate=function(drawPicture, option) { if (this.IsHScreen) return; if (!drawPicture.GetYCoordinatePoint) return; var aryPoint=drawPicture.GetYCoordinatePoint(); if (!IFrameSplitOperator.IsNonEmptyArray(aryPoint)) return; var border=this.GetBorder(); var top=border.TopEx; var bottom=border.BottomEx; var right=border.Right; this.Canvas.font=this.DrawPicture.Font; var fontHeight=this.GetFontHeight(); this.Canvas.textAlign="left"; this.Canvas.textBaseline = "bottom"; var defaultfloatPrecision=2; if (option && option.Symbol) defaultfloatPrecision=GetfloatPrecision(option.Symbol); for(var i=0; ibottom) continue; var text=item.YValue.toFixed(defaultfloatPrecision); var textWidth=this.Canvas.measureText(text).width+2; textWidth+=this.YTextPadding[1]; this.Canvas.fillStyle=this.DrawPicture.TextBGColor; this.Canvas.fillRect(right, item.Y-fontHeight/2, textWidth, fontHeight); this.Canvas.fillStyle=this.DrawPicture.TextColor; var yText=item.Y+fontHeight/2; this.Canvas.fillText(text,right+this.YTextPadding[1],yText); } } //字体外部设置好 this.GetCustomItemTextInfo=function(item, bLeft,pixelTatio) { var text=bLeft?item.Message[0]:item.Message[1]; var aryText=[]; var width=0; if (Array.isArray(text)) { for(var i=0;iwidth) width=value; var outItem={ Text:text[i].Text, Width:value+2*pixelTatio }; if (item.TextColor) outItem.TextColor=item.TextColor; if (item.BGColor) outItem.BGColor=item.BGColor; if (IFrameSplitOperator.IsBool(item.EnableBGColor)) outItem.EnableBGColor=item.EnableBGColor; //是否启用背景色 aryText.push(outItem); } } if (width>0) width+=2*pixelTatio; } else { width=this.Canvas.measureText(text).width+2*pixelTatio; aryText.push( {Text:text, Width:width} ); } return { MaxWidth:width, Text:aryText }; } this.DrawOutRangeCustomItem=function(item, mapTextRect) { if (this.IsHScreen===true) return; if (!this.IsShow && !this.IsYDrawMainFrame) return; if (!item.Message[1] && !item.Message[0]) return; if (!item.OutRange) return; var position=0; //1=top 2=bottom if (item.Value>this.HorizontalMax) position=1; else if (item.Value=10) { if (item.Font != null) this.Canvas.font = item.Font; var textInfo=this.GetCustomItemTextInfo(item,true,pixelTatio); var textWidth=textInfo.MaxWidth; var itemLeft=left-textWidth; var fontHeight=this.GetFontHeight(); var textHeight=fontHeight>defaultTextHeight? fontHeight:defaultTextHeight; this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "middle"; var yText=null; if (position==1) { yText=border.TopEx; if (IFrameSplitOperator.IsNumber(outRange.TopYOffset)) yText+=outRange.TopYOffset; } else if (position==2) { yText=border.BottomEx+textHeight; if (IFrameSplitOperator.IsNumber(outRange.BottomYOffset)) yText+=outRange.BottomYOffset; } for(var i=0;i=10) { if (item.Font != null) this.Canvas.font = item.Font; var textInfo=this.GetCustomItemTextInfo(item,false,pixelTatio); var textWidth=textInfo.MaxWidth; var itemRight=right+textWidth; var fontHeight=this.GetFontHeight(); var textHeight=fontHeight>defaultTextHeight? fontHeight:defaultTextHeight; this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; var yText=null; if (position==1) { yText=border.TopEx; if (IFrameSplitOperator.IsNumber(outRange.TopYOffset)) yText+=outRange.TopYOffset; } else if (position==2) { yText=border.BottomEx+textHeight; if (IFrameSplitOperator.IsNumber(outRange.BottomYOffset)) yText+=outRange.BottomYOffset; } for(var i=0;ithis.HorizontalMax || item.ValuedefaultTextHeight? fontHeight:defaultTextHeight; var bgColor=item.LineColor; var rgb=this.RGBToStruct(item.LineColor); if (rgb) bgColor=`rgba(${rgb.R}, ${rgb.G}, ${rgb.B}, ${g_JSChartResource.FrameLatestPrice.BGAlpha})`; //内部刻度 背景增加透明度 if (item.BGColor) bgColor=item.BGColor; var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var bgColor=item.LineColor; var rgb=this.RGBToStruct(item.LineColor); if (rgb) bgColor=`rgba(${rgb.R}, ${rgb.G}, ${rgb.B}, ${g_JSChartResource.FrameLatestPrice.BGAlpha})`; //内部刻度 背景增加透明度 var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var preTextRect=null; if (mapTextRect && mapTextRect.has(3)) preTextRect=mapTextRect.get(3); var yText=y; var rtText={ }; for(var i=0;i=this.HorizontalMax) return; if (max<=this.HorizontalMin) return; if (max>this.HorizontalMax) max=this.HorizontalMax; if (min10) //左 { var rtBG={ Left:0, Right:left-1, Top:yTop, Bottom:yBottom }; rtBG.Height=rtBG.Bottom-rtBG.Top; rtBG.Width=rtBG.Right-rtBG.Left; if (IFrameSplitOperator.IsNonEmptyArray(item.AreaData.Width)) //指定宽度 { var bgWidth=item.AreaData.Width[0]; if (IFrameSplitOperator.IsNumber(bgWidth)) { if (rtBG.Width>bgWidth) { rtBG.Width=bgWidth; rtBG.Left=rtBG.Right-rtBG.Width; } } } this.Canvas.fillStyle=item.AreaData.BGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); this.DrawCustomAreaText(rtBG, item, 0); } if (item.AreaData.Position.includes(1) && borderRight>10) //右 { var rtBG={ Left:right+1, Top:yTop, Bottom:yBottom }; rtBG.Height=rtBG.Bottom-rtBG.Top; if (this.YRightTextInfo && IFrameSplitOperator.IsNumber(this.YRightTextInfo.MainTextWidth)) //右侧自动调整 可以获取宽度 { rtBG.Width=this.YRightTextInfo.MainTextWidth-1; rtBG.Right=rtBG.Left+rtBG.Width; } else { rtBG.Right=border.ChartWidth; rtBG.Width=rtBG.Right-rtBG.Left; } if (IFrameSplitOperator.IsNonEmptyArray(item.AreaData.Width)) //指定宽度 { var bgWidth=item.AreaData.Width[1]; if (IFrameSplitOperator.IsNumber(bgWidth)) { if (rtBG.Width>bgWidth) { rtBG.Width=bgWidth; rtBG.Right=rtBG.Left+rtBG.Width; } } } this.Canvas.fillStyle=item.AreaData.BGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); this.DrawCustomAreaText(rtBG, item, 1); } } this.DrawCustomAreaText=function(rtBG, item, position) //position 0=左 1=右 { if (item.Font != null) this.Canvas.font = item.Font; var fontHeight=this.GetFontHeight(); if (rtBG.Height10*pixelTatio && this.IsShowYText[0]===true && this.YTextPosition[0]!=2; var isDrawRight=borderBottom>10*pixelTatio && this.IsShowYText[1]===true && this.YTextPosition[1]!=2; } else { var borderRight=this.ChartBorder.Right; var borderLeft=this.ChartBorder.Left; var isDrawLeft=borderLeft>10 && this.IsShowYText[0]===true && this.YTextPosition[0]!=2; var isDrawRight=borderRight>10 && this.IsShowYText[1]===true && this.YTextPosition[1]!=2; } if (!isDrawRight && !isDrawLeft) return null; var width={ Left:null, Right:null }; var rightExtendWidth=0; var isYPercentage=false; //是否是百分比坐标 if (this.YSplitOperator && this.YSplitOperator.CoordinateType==1) isYPercentage=true; var leftExtendLineWidth=0; var rightExtendLineWidth=0; if (IFrameSplitOperator.IsNonEmptyArray(this.YLineExtend)) { if (this.YLineExtend[0] && this.YLineExtend[0].Width>1) leftExtendLineWidth=this.YLineExtend[0].Width; if (this.YLineExtend[1] && this.YLineExtend[1].Width>1) rightExtendLineWidth=this.YLineExtend[1].Width; } for(var i=0;itextWidth) textWidth=perTextWidth; } } } else { textWidth=this.Canvas.measureText(item.Message[1]).width; } if (width.Right==null || width.Right`; const changeButton=``; const closeButton=``; var spanIcon=modifyButton+changeButton; if (this.CloseIndex) { spanIcon+=closeButton; } //var scrollPos=GetScrollPosition(); //left = left+scrollPos.Left; //top = top+scrollPos.Top; divToolbar.style.left = left + "px"; divToolbar.style.top = top + "px"; divToolbar.style.width=toolbarWidth+"px"; //宽度先不调整吧 divToolbar.style.height=(toolbarHeight/pixelTatio)+'px'; //只调整高度 divToolbar.innerHTML=spanIcon; var chart=this.ChartBorder.UIElement.JSChartContainer; var identify=this.Identify; if (!this.ModifyIndex) //隐藏'改参数' $("#"+divToolbar.id+" .index_param").hide(); else if (typeof(this.ModifyIndexEvent)=='function') //绑定点击事件 $("#"+divToolbar.id+" .index_param").click( { Chart:this.ChartBorder.UIElement.JSChartContainer, Identify:this.Identify },this.ModifyIndexEvent); if (!this.ChangeIndex) //隐藏'换指标' { $("#"+divToolbar.id+" .index_change").hide(); } else if (typeof(this.ChangeIndexEvent)=='function') { $("#"+divToolbar.id+" .index_change").click( { Chart:this.ChartBorder.UIElement.JSChartContainer, Identify:this.Identify, IsOverlay:false },this.ChangeIndexEvent); } $("#"+divToolbar.id+" .index_close").click( { Chart:this.ChartBorder.UIElement.JSChartContainer, Identify:this.Identify }, function(event) { var hqChart=event.data.Chart; var id=event.data.Identify; hqChart.RemoveIndexWindow(id); }); divToolbar.style.display = "block"; } //手绘,不用DOM,使用DOM太麻烦了 this.DrawToolbarV2=function(moveonPoint, mouseStatus) { if (g_JSChartResource.IsDOMFrameToolbar===true) return; if (this.Identify==0 && this.IsShowCloseButton) this.DrawCloseBeforeButton(moveonPoint, mouseStatus); //盘前集合竞价关闭按钮 if (this.ChartBorder.TitleHeight<5) return; var aryButton=[]; if (this.Identify!=0 && this.Identify!=1) //价格图和成交量图只有自定义按钮 { if (this.CloseIndex) aryButton.push( { ID:JSCHART_BUTTON_ID.CLOSE_INDEX_WINDOW, Style:this.CloseWindowButton }); if (this.MaxMinWindow) aryButton.push({ ID:JSCHART_BUTTON_ID.MAX_MIN_WINDOW, Style:this.MaxMinWindowButton }) if (this.TitleWindow) aryButton.push({ ID:JSCHART_BUTTON_ID.TITLE_WINDOW, Style:this.TitleWindowButton }); if (this.ExportData) aryButton.push( {ID:JSCHART_BUTTON_ID.EXPORT_DATA, Style:this.ExportDataButton}); if (this.OverlayIndex) aryButton.push( { ID:JSCHART_BUTTON_ID.OVERLAY_INDEX, Style:this.OverlayIndexButton }); if (this.ChangeIndex) aryButton.push( { ID:JSCHART_BUTTON_ID.CHANGE_INDEX, Style:this.ChangeIndexButton }); if (this.ModifyIndex) aryButton.push( { ID:JSCHART_BUTTON_ID.MODIFY_INDEX_PARAM, Style:this.ModifyIndexParamButton }); } if (IFrameSplitOperator.IsNonEmptyArray(this.CustomToolbar)) { for(var i=0;i=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { color=this.BeforeCloseIcon.MoveOnColor; if (mouseStatus) mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:item, Frame:this, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } var font=`${this.BeforeCloseIcon.Size}px ${this.BeforeCloseIcon.Family}`; this.Canvas.font=font; this.Canvas.fillStyle=color; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline='top'; this.Canvas.fillText(this.BeforeCloseIcon.Text,border.Left,border.TopEx); this.Buttons.push(item); } this.DrawMultiDayBeforeDataBG=function(border) { var dayBorder=border.DayBorder; var top=ToFixedPoint(border.Top); var bottom=ToFixedPoint(border.Bottom); var height=bottom-top; this.Canvas.strokeStyle=this.MultiDayBorderPen; for(var i=0; i3) //盘前 { this.Canvas.fillStyle=this.BeforeBGColor; this.Canvas.fillRect(left,top,width,height); ++drawCount; } var left=ToFixedPoint(item.RightEx); var right=ToFixedPoint(item.Right); var width=right-left; if (width>3) //盘后 { this.Canvas.fillStyle=this.AfterBGColor; this.Canvas.fillRect(left,top,width,height); ++drawCount; } if (drawCount==2 && i!=dayBorder.length-1) { this.Canvas.beginPath(); this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); this.Canvas.stroke(); } } } this.DrawCallAuctionVertical=function(verticalInfo, callAuctionData, border, isBeforeClose) { if (!callAuctionData) return; var top=border.TopTitle; var bottom=border.Bottom; var left=border.Left; var right=border.LeftEx; var pixelRatio = GetDevicePixelRatio(); //获取设备的分辨率 var xPrev=null; //上一个坐标x的值 var textRightPrev=null; //上一次刻度输出右边x坐标 for(var i in verticalInfo) { var item=verticalInfo[i]; var x=this.GetLeftExtendXFromIndex(item.Value,callAuctionData); if (x>right) break; if (xPrev!=null && Math.abs(x-xPrev)0) //实线 { if (g_JSChartResource.FrameXLineDash) { this.Canvas.strokeStyle=item.LineColor; this.Canvas.setLineDash(g_JSChartResource.FrameXLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,top); this.Canvas.lineTo(xFixed,bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.strokeStyle=item.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,top); this.Canvas.lineTo(xFixed,bottom); this.Canvas.stroke(); } } } if (item.Message[0]!=null && this.ChartBorder.Bottom>5*pixelRatio) { if (item.Font!=null) this.Canvas.font=item.Font; var textLeft=0; this.Canvas.fillStyle=item.TextColor; this.Canvas.strokeStyle=item.TextColor; var testWidth=this.Canvas.measureText(item.Message[0]).width; if (x= border.ChartWidth) { this.Canvas.textAlign = "right"; this.Canvas.textBaseline="top"; textLeft=x-testWidth; } else { this.Canvas.textAlign="center"; this.Canvas.textBaseline="top"; textLeft=x-(testWidth/2); } if (textRightPrev==null || textLeft>textRightPrev) { var yText=bottom; if (item.LineType==3) { var lineLength=this.ShortXLineLength*pixelRatio; this.Canvas.beginPath(); this.Canvas.moveTo(xFixed,yText); this.Canvas.lineTo(xFixed,yText+lineLength); this.Canvas.stroke(); yText+=lineLength+2*pixelRatio; } this.Canvas.fillText(item.Message[0],x,yText+this.XBottomOffset); textRightPrev=textLeft+testWidth; } } xPrev=x; } } //画集合竞价背景 this.DrawBeforeDataBG=function() { var border=this.ChartBorder.GetBorder(); if (border.DayBorder) { this.DrawMultiDayBeforeDataBG(border); return; } if (this.ChartBorder.LeftExtendWidth<10 && this.ChartBorder.RightExtendWidth<10) return; //if (this.Identify>=2) return; var top=ToFixedPoint(border.Top); var bottom=ToFixedPoint(border.Bottom); this.Canvas.fillStyle=this.BeforeBGColor; if (this.ChartBorder.LeftExtendWidth>10) //盘前 { var left=ToFixedPoint(border.Left); var right=ToFixedPoint(this.ChartBorder.GetLeft()); var width=right-left; var height=bottom-top; this.Canvas.fillRect(left,top,width,height); this.DrawCallAuctionVertical(this.BeforeOpenVerticalInfo, this.YSplitOperator.BeforeOpenData, border, true); } if (this.ChartBorder.RightExtendWidth>10) //盘后 { this.Canvas.fillStyle=this.AfterBGColor; var left=ToFixedPoint(this.ChartBorder.GetRight()); var right=ToFixedPoint(border.Right); var width=right-left; var height=bottom-top; this.Canvas.fillRect(left,top,width,height); } } this.DrawCustomBG=function() { if (!this.HQChart) return; if (this.IsHScreen) return; var symbol=this.HQChart.Symbol; if (!symbol) return; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_MINUTE_BG) if (!event || !event.Callback) return; var aryDay=null; if (this.DayCount>1) { if (!IFrameSplitOperator.IsNonEmptyArray(this.HQChart.DayData)) return; aryDay=[]; for(var i=this.HQChart.DayData.length-1;i>=0;--i) { aryDay.push({ Date:this.HQChart.DayData[i].Date, BGColor:null } ); } } else if (this.DayCount==1) { if (!IFrameSplitOperator.IsPlusNumber(this.HQChart.DataStatus.LatestDate)) return; aryDay=[{ Date:this.HQChart.DataStatus.LatestDate, BGColor:null }]; } if (!IFrameSplitOperator.IsNonEmptyArray(aryDay)) return; var sendData={ XPointCount:this.XPointCount, DayCount:this.DayCount, MinuteCount:this.MinuteCount , AryDay:aryDay, PreventDefault:false }; event.Callback(event, sendData, this); if (sendData.PreventDefault) return; var border=this.ChartBorder.GetBorder(); for(var i=0;iright) xRight=right; this.Canvas.fillStyle=this.DrawPicture.BGColor; this.Canvas.fillRect(xLeft, border.Bottom, xRight-xLeft, fontHeight); } for(var i=0;iright) continue; var index=parseInt(this.GetXData(item.X)); var kItem=this.GetKItem(index,option); if (kItem) { //var text=IFrameSplitOperator.FormatDateString(kItem.Date,null); var text=IFrameSplitOperator.FormatTimeString(kItem.Time, "HH:MM"); var textWidth=this.Canvas.measureText(text).width+2; var textLeft=item.X-textWidth/2; if (textLeftmaxWidth) break; var newItem={ Text:item.Text, Width:textWidth, Color:item.Color, Space:item.Space }; itemWidth+=textWidth; item.Width=textWidth; if (item.Space>=1) itemWidth+=item.Space; aryOut.push(newItem); } var xText=xStart+(maxWidth-itemWidth)/2; for(var j=0;j=1) xText+=item.Space; } yText+=lineHeight; } } } //分割x,y轴坐标信息 this.SplitXYCoordinate=function() { if (this.XYSplit==false) { //计算自定义刻度 if (this.YCustomSplit) { if (this.YSplitOperator && this.YSplitOperator.CustomCoordinate) this.YSplitOperator.CustomCoordinate(); } return; } if (this.XSplitOperator!=null) this.XSplitOperator.Operator(); if (this.YSplitOperator!=null) this.YSplitOperator.Operator(); } this.GetMultiDayXFromIndex=function(index, border) { var dayBorder=border.DayBorder; var minuteIndex=index%this.MinuteCount; var dayIndex=parseInt(index/this.MinuteCount); if (dayIndex>=dayBorder.length) dayIndex=dayBorder.length-1; var client=dayBorder[dayIndex]; var count=this.MinuteCount-1; if (minuteIndex>=count) { return client.RightEx; } else { var width=(client.RightEx-client.LeftEx); var offset=client.LeftEx+width*minuteIndex/count; return offset; } } this.GetXFromIndex=function(index) { var count=this.XPointCount-1; var border=this.ChartBorder.GetBorder(); if (border.DayBorder) return this.GetMultiDayXFromIndex(index, border); if (count==1) { if (index==0) return border.LeftEx; else return border.RightEx; } else if (count<=0) { return border.LeftEx; } else if (index>=count) { return border.RightEx; } else { var width=(border.RightEx-border.LeftEx); var offset=border.LeftEx+width*index/count; return offset; } } this.GetMultiDayXData=function(x,border) { var dayBorder=border.DayBorder; for(var i=0;i=client.Left && x<=client.Right) { var count=this.MinuteCount-1; var dayMinuteCount=this.MinuteCount*i; if (x<=client.LeftEx) return 0+dayMinuteCount; if (x>=client.RightEx) return count+dayMinuteCount; var width=client.RightEx-client.LeftEx; return (x-client.LeftEx)*(count*1.0/width)+dayMinuteCount; } } } //X坐标转x轴数值 this.GetXData=function(x) { var count=this.XPointCount-1; if (count<0) count=0; var border=this.ChartBorder.GetBorder(); if (border.DayBorder) return this.GetMultiDayXData(x, border); if (x<=border.LeftEx) return 0; if (x>=border.RightEx) return count; var width=border.RightEx-border.LeftEx; return (x-border.LeftEx)*(count*1.0/width); } this.DrawCustomHorizontal=function() //Y轴刻度定制显示 { if (this.IsMinSize) return; for(var i in this.CustomHorizontalInfo) { var item=this.CustomHorizontalInfo[i]; switch(item.Type) { case 0: case 1: case 10://自定义的 this.DrawCustomItem(item); //自定义刻度 break; } } } this.GetLeftExtendXFromIndex=function(index, obj) { var count=obj.TotalCount-1; var border=this.ChartBorder.GetBorder(); if (border.DayBorder) return this.GetLeftExtendMultiDayXFromIndex(index, obj, border); var left=border.Left; var width=this.ChartBorder.LeftExtendWidth; var offset=left+width*index/count; return offset; } this.GetLeftExtendMultiDayXFromIndex=function(index, obj, border) { var dayBorder=border.DayBorder; var client=dayBorder[obj.Index]; var count=obj.TotalCount-1; var left=client.Left; var right=client.LeftEx; var width=right-left; var offset=left+width*index/count; return offset; } this.GetLeftExtendMultiDayXData=function(x, obj, border) { var dayBorder=border.DayBorder; for(var i=0; i=client.Left && x<=client.LeftEx) { if (!obj[i]) return null; var count=obj[i].TotalCount-1; var left=client.Left; var right=client.LeftEx; var width=right-left; var index=(x-left)*(count*1.0/width); return { DayIndex:parseInt(i), DataIndex:index }; } } } this.GetLeftExtendXData=function(x, obj) { var border=this.ChartBorder.GetBorder(); if (border.DayBorder) return this.GetLeftExtendMultiDayXData(x, obj, border); var count=obj.TotalCount-1; if (count<0) count=0; var left=border.Left; var right=border.LeftEx; if (x<=left) return 0; if (x>=right) return count; var width=right-left; return (x-left)*(count*1.0/width); } this.MoveXIndexLeft=function(step, obj) { JSConsole.Chart.Log("[MinuteFrame::MoveXIndexLeft] obj ", obj); if (obj.DataType==2) //多日数据 { var dayIndex=obj.IndexData.DayIndex; var dataIndex=obj.IndexData.DataIndex-step; var itemIndex=-1; if (obj.IndexData.Type==20) itemIndex=0; else if (obj.IndexData.Type==10) itemIndex=1; else if (obj.IndexData.Type==30) itemIndex=2; else return false; for(var i=dayIndex, j=itemIndex; i>=0; --i) { var dayItem=obj.Data[i]; for(; j>=0; --j) { var dataItem=dayItem[j]; if (!dataItem.DayItem || !dataItem.DayItem.Data) continue; if (dataIndex==null) dataIndex=dataItem.DayItem.Data.length-1; for(; dataIndex>=0;--dataIndex) { var item=dataItem.DayItem.Data[dataIndex]; if (!item) continue; if (dataItem.Type==10) { var cursorIndex=this.MinuteCount*i+dataIndex; obj.Point.X=this.GetXFromIndex(cursorIndex); obj.Point.Y=this.GetYFromData(item.Close); obj.IndexData.CursorIndex=cursorIndex; obj.IndexData.DayIndex=i; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } else if (dataItem.Type==20) { if (!IFrameSplitOperator.IsNumber(item.Price)) continue; obj.Point.X=this.GetLeftExtendXFromIndex(dataIndex,dataItem.DayItem); obj.Point.Y=this.GetLeftExtendYFromData(item.Price); obj.IndexData.CursorIndex=-1; obj.IndexData.DayIndex=i; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } else if (dataItem.Type==30) { if (!IFrameSplitOperator.IsNumber(item.Price)) continue; obj.Point.X=this.GetRightExtendXFromIndex(dataIndex,dataItem.DayItem); obj.Point.Y=this.GetRightExtendYFromData(item.Price); obj.IndexData.CursorIndex=-1; obj.IndexData.DayIndex=i; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } } dataIndex=null; } j=2; } return false; } else if (obj.DataType==1) //单日 { var dayIndex=obj.IndexData.DayIndex; var dataIndex=obj.IndexData.DataIndex-step; var itemIndex=-1; if (obj.IndexData.Type==2) itemIndex=0; else if (obj.IndexData.Type==1) itemIndex=1; else if (obj.IndexData.Type==3) itemIndex=2; else return false; for(var i=itemIndex; i>=0; --i) { var dataItem=obj.Data[i]; if (!dataItem || !dataItem.DayItem || !dataItem.DayItem.Data) continue; if (dataIndex==null) dataIndex=dataItem.DayItem.Data.length-1; for(; dataIndex>=0;--dataIndex) { if (dataItem.Type==1) { var offset=dataItem.DayItem.DataOffset; var item=dataItem.DayItem.Data[dataIndex+offset]; if (!item) continue; var cursorIndex=dataIndex; obj.Point.X=this.GetXFromIndex(cursorIndex); obj.Point.Y=this.GetYFromData(item.Close); obj.IndexData.CursorIndex=cursorIndex; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } else if (dataItem.Type==2) { var item=dataItem.DayItem.Data[dataIndex]; if (!item) continue; if (!IFrameSplitOperator.IsNumber(item.Price)) continue; obj.Point.X=this.GetLeftExtendXFromIndex(dataIndex,dataItem.DayItem); obj.Point.Y=this.GetLeftExtendYFromData(item.Price); obj.IndexData.CursorIndex=-1; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } else if (dataItem.Type==3) { var item=dataItem.DayItem.Data[dataIndex]; if (!item) continue; if (!IFrameSplitOperator.IsNumber(item.Price)) continue; obj.Point.X=this.GetRightExtendXFromIndex(dataIndex,dataItem.DayItem); obj.Point.Y=this.GetRightExtendYFromData(item.Price); obj.IndexData.CursorIndex=-1; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } } dataIndex=null; } } } this.MoveXIndexRight=function(step, obj) { JSConsole.Chart.Log("[MinuteFrame::MoveXIndexRight] obj ", obj); if (obj.DataType==2) //多日数据 { var dayIndex=obj.IndexData.DayIndex; var dataIndex=obj.IndexData.DataIndex+step; var itemIndex=-1; if (obj.IndexData.Type==20) itemIndex=0; else if (obj.IndexData.Type==10) itemIndex=1; else if (obj.IndexData.Type==30) itemIndex=2; else return false; for(var i=dayIndex, j=itemIndex; i=this.XPointCount) break; var offset=dataItem.DayItem.DataOffset; var item=dataItem.DayItem.Data[dataIndex+offset]; if (!item) continue; var cursorIndex=dataIndex; obj.Point.X=this.GetXFromIndex(cursorIndex); obj.Point.Y=this.GetYFromData(item.Close); obj.IndexData.CursorIndex=cursorIndex; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } else if (dataItem.Type==2) { var item=dataItem.DayItem.Data[dataIndex]; if (!item) continue; if (!IFrameSplitOperator.IsNumber(item.Price)) continue; obj.Point.X=this.GetLeftExtendXFromIndex(dataIndex,dataItem.DayItem); obj.Point.Y=this.GetLeftExtendYFromData(item.Price); obj.IndexData.CursorIndex=-1; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } else if (dataItem.Type==3) { var item=dataItem.DayItem.Data[dataIndex]; if (!item) continue; if (!IFrameSplitOperator.IsNumber(item.Price)) continue; obj.Point.X=this.GetRightExtendXFromIndex(dataIndex,dataItem.DayItem); obj.Point.Y=this.GetRightExtendYFromData(item.Price); obj.IndexData.CursorIndex=-1; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=dataIndex; obj.IndexData.Type=dataItem.Type; return true; } } dataIndex=null; } } } //获取有效数据 this.GetLeftExtendXValidData=function(x, obj) { var border=this.ChartBorder.GetBorder(); if (border.DayBorder) { var indexData=this.GetLeftExtendXData(x, obj.Data); if (!indexData) return false; var index=parseInt(indexData.DataIndex.toFixed(0)); var dayData=obj.Data[indexData.DayIndex]; if (index>=0 && index=dayData.Data.length) index=dayData.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=dayData.Data[i]; if (item && IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) return false; obj.IndexData.DataIndex=findIndex; obj.IndexData.Point.X=this.GetLeftExtendXFromIndex(findIndex, dayData); //调整X轴坐标 JSConsole.Chart.Log(`[MinuteFrame::GetLeftExtendXValidData] DayIndex:${obj.IndexData.DayIndex}, Type:${obj.IndexData.Type}, x:${x}=>${obj.IndexData.Point.X}, index:${index}=>${findIndex}`); return true; } else { var index=this.GetLeftExtendXData(x, obj.Data); index=parseInt(index.toFixed(0)); if (index>=0 && index=obj.Data.Data.length) index=obj.Data.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=obj.Data.Data[i]; if (IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) { for(var i=index+1; i${obj.IndexData.Point.X}, index:${index}=>${findIndex}`); return true; } } this.GetRightExtendXValidData=function(x, obj) { var border=this.ChartBorder.GetBorder(); if (border.DayBorder) { var indexData=this.GetRightExtendXData(x, obj.Data); if (!indexData) return false; var index=parseInt(indexData.DataIndex.toFixed(0)); var dayData=obj.Data[indexData.DayIndex]; if (index>=0 && index=dayData.Data.length) index=dayData.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=dayData.Data[i]; if (item && IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) return false; obj.IndexData.DataIndex=findIndex; obj.IndexData.Point.X=this.GetRightExtendXFromIndex(findIndex, dayData); //调整X轴坐标 JSConsole.Chart.Log(`[MinuteFrame::GetRightExtendXValidData] DayIndex:${obj.IndexData.DayIndex}, Type:${obj.IndexData.Type}, x:${x}=>${obj.IndexData.Point.X}, index:${index}=>${findIndex}`); return true; } else { if (!obj || !obj.Data) return false; var index=this.GetRightExtendXData(x, obj.Data); index=parseInt(index.toFixed(0)); if (index>=0 && index=obj.Data.Data.length) index=obj.Data.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=obj.Data.Data[i]; if (IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) { for(var i=index+1; i${obj.IndexData.Point.X}, index:${index}=>${findIndex}`); return true; } } this.GetLeftExtendYFromData=function(value,isLimit,obj) { if (!obj || !obj.Range) return this.GetYFromData(value,isLimit); var range=obj.Range; var border=this.ChartBorder.GetBorder(); var height=border.BottomEx-border.TopEx; var offset=height*(value-range.Min)/(range.Max-range.Min); return border.BottomEx-offset; } this.GetLeftExtendYData=function(y, isLimit, obj) { if (!obj || !obj.Range) return this.GetYData(y,isLimit); var range=obj.Range; var border=this.ChartBorder.GetBorder(); var height=border.BottomEx-border.TopEx; return (border.BottomEx-y)/height*(range.Max-range.Min)+range.Min; } this.GetRightExtendMultiDayXFromIndex=function(index, obj, border) { var dayBorder=border.DayBorder; var client=dayBorder[obj.Index]; var count=obj.TotalCount-1; var left=client.RightEx; var right=client.Right; var width=right-left; var offset=left+width*index/count; return offset; } this.GetRightExtendXFromIndex=function(index, obj) { var count=obj.TotalCount-1; var border=this.ChartBorder.GetBorder(); if (border.DayBorder) return this.GetRightExtendMultiDayXFromIndex(index, obj, border); var left=border.RightEx; var width=this.ChartBorder.RightExtendWidth; var offset=left+width*index/count; return offset; } this.GetRightExtendYFromData=function(value,isLimit,obj) { return this.GetLeftExtendYFromData(value,isLimit,obj) } this.GetRightExtendYData=function(y, isLimit, obj) { if (!obj || !obj.Range) return this.GetYData(y,isLimit); return this.GetLeftExtendYData(y, isLimit, obj); } this.GetRightExtendMultiDayXData=function(x, obj, border) { var dayBorder=border.DayBorder; for(var i=0; i=client.RightEx && x<=client.Right) { if (!obj[i]) return null; var count=obj[i].TotalCount-1; var left=client.RightEx; var right=client.Right; var width=right-left; var index=(x-left)*(count*1.0/width); return { DayIndex:parseInt(i), DataIndex:index }; } } return null; } this.GetRightExtendXData=function(x, obj) { var border=this.ChartBorder.GetBorder(); if (border.DayBorder) return this.GetRightExtendMultiDayXData(x, obj, border); var count=obj.TotalCount-1; if (count<0) count=0; var left=border.RightEx; var right=border.Right; if (x<=left) return 0; if (x>=right) return count; var width=right-left; return (x-left)*(count*1.0/width); } } //走势图 横屏框架 function MinuteHScreenFrame() { this.newMethod=MinuteFrame; //派生 this.newMethod(); delete this.newMethod; this.ClassName="MinuteHScreenFrame"; this.IsHScreen=true; //是否是横屏 //画标题背景色 this.DrawTitleBG=function() { if (this.ChartBorder.TitleHeight<=0) return; var border=this.ChartBorder.GetHScreenBorder(); var left=ToFixedPoint(border.RightEx); var top=ToFixedPoint(border.Top); var bottom=ToFixedPoint(border.Bottom); var width=this.ChartBorder.TitleHeight; var height=bottom-top; this.Canvas.fillStyle=this.TitleBGColor; this.Canvas.fillRect(left,top,width,height); } this.DrawToolbar=function() { return; } //画集合竞价背景 this.DrawBeforeDataBG=function() { var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) { this.DrawMultiDayBeforeDataBG(border); return; } if (this.ChartBorder.LeftExtendWidth<10 && this.ChartBorder.RightExtendWidth<10) return; var left=ToFixedPoint(border.Left); var right=ToFixedPoint(border.Right); this.Canvas.fillStyle=this.BeforeBGColor; if (this.ChartBorder.LeftExtendWidth>10) { var top=ToFixedPoint(border.Top); var bottom=ToFixedPoint(border.TopEx); var width=right-left; var height=bottom-top; this.Canvas.fillRect(left,top,width,height); } if (this.ChartBorder.RightExtendWidth>10) { var top=border.BottomEx; var bottom=border.Bottom; var width=right-left; var height=bottom-top; this.Canvas.fillRect(left,top,width,height); } } this.DrawMultiDayBeforeDataBG=function(border) { var dayBorder=border.DayBorder; var left=ToFixedPoint(border.Left); var right=ToFixedPoint(border.Right); var width=right-left; this.Canvas.strokeStyle=this.MultiDayBorderPen; for(var i=0; i3) //盘前 { this.Canvas.fillStyle=this.BeforeBGColor; this.Canvas.fillRect(left,top,width,height); ++drawCount; } var top=ToFixedPoint(item.BottomEx); var bottom=ToFixedPoint(item.Bottom); var height=bottom-top; if (height>3) //盘后 { this.Canvas.fillStyle=this.AfterBGColor; this.Canvas.fillRect(left,top,width,height); ++drawCount; } if (drawCount==2 && i!=dayBorder.length-1) { this.Canvas.beginPath(); this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); this.Canvas.stroke(); } } } //Y坐标转y轴数值 this.GetYData=function(x) { var border=this.ChartBorder.GetHScreenBorder(); if (xborder.RightEx) return this.HorizontalMax; var width=border.RightEx-border.LeftEx; return (x-border.LeftEx)/width*(this.HorizontalMax-this.HorizontalMin)+this.HorizontalMin; } this.GetMultiDayXData=function(y,border) { var dayBorder=border.DayBorder; for(var i=0;i=client.Top && y<=client.Bottom) { var count=this.MinuteCount-1; var dayMinuteCount=this.MinuteCount*i; if (y<=client.TopEx) return 0+dayMinuteCount; if (y>=client.BottomEx) return count+dayMinuteCount; var width=client.BottomEx-client.TopEx; return (y-client.TopEx)*(count*1.0/width)+dayMinuteCount; } } } //X坐标转x轴数值 this.GetXData=function(y) { var count=this.XPointCount-1; if (count<0) count=0; var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) return this.GetMultiDayXData(y, border); if (y<=border.TopEx) return 0; if (y>=border.BottomEx) return count; var height=(border.BottomEx-border.TopEx); return (y-border.TopEx)*(count*1.0/height); } this.GetMultiDayXFromIndex=function(index, border) { var dayBorder=border.DayBorder; var minuteIndex=index%this.MinuteCount; var dayIndex=parseInt(index/this.MinuteCount); if (dayIndex>=dayBorder.length) dayIndex=dayBorder.length-1; var client=dayBorder[dayIndex]; var count=this.MinuteCount-1; if (minuteIndex>=count) { return client.BottomEx; } else { var width=(client.BottomEx-client.TopEx); var offset=client.TopEx+width*minuteIndex/count; return offset; } } this.GetXFromIndex=function(index) { var count=this.XPointCount-1; var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) return this.GetMultiDayXFromIndex(index, border); if (count==1) { if (index==0) return border.TopEx; else return border.BottomEx; } else if (count<=0) { return border.TopEx; } else if (index>=count) { return border.BottomEx; } else { var height=border.BottomEx-border.TopEx; var offset=border.TopEx+height*index/count; return offset; } } this.GetYFromData=function(value) { var border=this.ChartBorder.GetHScreenBorder(); if(value<=this.HorizontalMin) return border.LeftEx; if(value>=this.HorizontalMax) return border.RightEx; var width=(border.RightEx-border.LeftEx)*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return border.LeftEx+width; } this.DrawVolTitle=function(symbol) { if (!MARKET_SUFFIX_NAME.IsShowMinuteVolTitle(symbol)) return; if (this.Identify==1) //显示"成交量" { var pixelRatio=GetDevicePixelRatio(); var left=this.ChartBorder.GetRight()-2*pixelRatio; var top=this.ChartBorder.GetTopEx()+2*pixelRatio; var xText=left,yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); var x=this.YInsideOffset,y=0; this.Canvas.textAlign='left'; this.Canvas.textBaseline='top'; if (g_JSChartResource.Minute.VolBarColor || g_JSChartResource.Minute.VolTitleColor) { if (g_JSChartResource.Minute.VolBarColor) this.Canvas.fillStyle=g_JSChartResource.Minute.VolBarColor else this.Canvas.fillStyle=g_JSChartResource.Minute.VolTitleColor; var languageID=this.YSplitOperator.LanguageID; var text=g_JSChartLocalization.GetText('MVol-Vol',languageID); this.Canvas.fillText(text,x,y); x+=this.Canvas.measureText(text).width; x+=6*GetDevicePixelRatio(); } if (this.IsShowPositionTitle) { text=g_JSChartLocalization.GetText('MVol-Position',languageID); this.Canvas.fillStyle=g_JSChartResource.Minute.PositionColor; this.Canvas.fillText(text,x,y); } this.Canvas.restore(); } } //画Y轴 this.DrawHorizontal=function() { var border=this.ChartBorder.GetHScreenBorder(); var top=border.Top; var bottom=border.Bottom; var left=border.Left; var right=border.Right; var borderTop=this.ChartBorder.Top; var borderBottom=this.ChartBorder.Bottom; var yPrev=null; //上一个坐标y的值 for(var i=this.HorizontalInfo.length-1; i>=0; --i) //从左往右画分割线 { var item=this.HorizontalInfo[i]; var y=this.GetYFromData(item.Value); if (y!=null && Math.abs(y-yPrev)= right - 2) { this.Canvas.textBaseline = 'top'; y = right; } else if (y <= left + 2) { this.Canvas.textBaseline = 'bottom'; y=left; if (y != null && Math.abs(y - yPrev) < 2*this.MinYDistance) continue; //两个坐标在近了 就不画了 } else { this.Canvas.textBaseline = "middle"; } //坐标信息 左边 间距小于10 不画坐标 if (item.Message[0]!=null && borderTop>10) { if (item.Font!=null) this.Canvas.font=item.Font; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="right"; var xText=y,yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], -2, 0); this.Canvas.restore(); } //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1]!=null && borderBottom>10) { if (item.Font!=null) this.Canvas.font=item.Font; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="left"; var xText=y,yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[1], 2, 0); this.Canvas.restore(); } yPrev=y; } } this.DrawInsideClientHorizontal=function() { var border=this.GetBorder(); var left=border.Left; var right=border.Right; var bottom=border.BottomEx; var top=border.TopEx; var pixelTatio = GetDevicePixelRatio(); var yPrev = null; //上一个坐标y的值 var yInsideText=null; for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; if (!item || !item.Message[2] || !item.Message[3]) continue; var y = this.GetYFromData(item.Value); if (y != null && yPrev!=null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 if (y >= right - 2) { this.Canvas.textBaseline = 'top'; y = right; } else if (y <= left + 2) { this.Canvas.textBaseline = 'bottom'; y=left; if (y != null && Math.abs(y - yPrev) < 2*this.MinYDistance) continue; //两个坐标在近了 就不画了 } else { this.Canvas.textBaseline = "middle"; } if (item.Message[2]) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; var xText=y,yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[2], 2, 0); this.Canvas.restore(); } if (item.Message[3]) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; var xText=y,yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[3], -2, 0); this.Canvas.restore(); } yPrev = y; } } //画X轴 this.DrawVertical=function() { var border=this.ChartBorder.GetHScreenBorder(); var left=border.Left; var right=border.Right; var bottom=border.Bottom; var xPrev=null; //上一个坐标x的值 for(var i in this.VerticalInfo) { var x=this.GetXFromIndex(this.VerticalInfo[i].Value); if (x>bottom) break; if (xPrev!=null && Math.abs(x-xPrev)= this.ChartBorder.GetChartHeight()) { this.Canvas.textAlign = "right"; this.Canvas.textBaseline = "top"; } else { this.Canvas.textAlign="center"; this.Canvas.textBaseline="top"; } var xText=left,yText=x; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(this.VerticalInfo[i].Message[0], 0, 0); this.Canvas.restore(); } xPrev=x; } } //Y刻度画在左边内部 this.DrawInsideHorizontal = function () { if (this.IsMinSize) return; if (this.IsShowYText[0]===false && this.IsShowYText[1]===false) return; this.DrawInsideClientHorizontal(); var border=this.ChartBorder.GetHScreenBorder(); var left = border.Left; var right = border.RightEx; var top=border.Top; var bottom=border.Bottom; var borderTop=this.ChartBorder.Top; var borderBottom=this.ChartBorder.Bottom; var titleHeight = this.ChartBorder.TitleHeight; var pixelTatio = GetDevicePixelRatio(); if ( (borderTop<10*pixelTatio && this.IsShowYText[0]===true) || (borderBottom<10*pixelTatio && this.IsShowYText[1]===true) ) { var pixelTatio = GetDevicePixelRatio(); var yPrev = null; //上一个坐标y的值 var yInsideText=null; for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev!=null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 //坐标信息 左边 间距小于10 画在内部 if (item.Message[0] != null && borderTop < 10*pixelTatio && this.IsShowYText[0]===true) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textObj={ X:left, Y:y, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[0]}} ; var xText=y,yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], 2*pixelTatio, 0); this.Canvas.restore(); if (yInsideText==null || yInsideText= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textWidth = this.Canvas.measureText(item.Message[1]).width; var textObj={ X:right-textWidth, Y:y, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[1]}} ; var xText=y,yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[1], -2*pixelTatio, 0); this.Canvas.restore(); } yPrev = y; } } } this.GetLeftExtendXFromIndex=function(index, obj) { var count=obj.TotalCount-1; var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) return this.GetLeftExtendMultiDayXFromIndex(index, obj, border); var left=border.Top; var width=this.ChartBorder.LeftExtendWidth; var offset=left+width*index/count; return offset; } this.GetLeftExtendMultiDayXFromIndex=function(index, obj, border) { var dayBorder=border.DayBorder; var client=dayBorder[obj.Index]; var count=obj.TotalCount-1; var left=client.Top; var right=client.TopEx; var width=right-left; var offset=left+width*index/count; return offset; } this.GetLeftExtendMultiDayXData=function(y, obj, border) { var dayBorder=border.DayBorder; for(var i=0; i=client.Top && y<=client.TopEx) { if (!obj[i]) return null; var count=obj[i].TotalCount-1; var left=client.Top; var right=client.TopEx; var width=right-left; var index=(y-left)*(count*1.0/width); return { DayIndex:parseInt(i), DataIndex:index }; } } return null; } this.GetLeftExtendXData=function(y, obj) { var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) return this.GetLeftExtendMultiDayXData(y, obj, border); var count=obj.TotalCount-1; if (count<0) count=0; var left=border.Top; var right=border.TopEx; if (y<=left) return 0; if (y>=right) return count; var width=right-left; return (y-left)*(count*1.0/width); } this.GetLeftExtendYFromData=function(value,isLimit,obj) { if (!obj || !obj.Range) return this.GetYFromData(value,isLimit); var range=obj.Range; var border=this.ChartBorder.GetHScreenBorder(); var width=border.RightEx-border.LeftEx; var offset=width*(value-range.Min)/(range.Max-range.Min); return border.LeftEx+offset; } this.GetLeftExtendYData=function(x, isLimit, obj) { if (!obj || !obj.Range) return this.GetYData(y,isLimit); var range=obj.Range; var border=this.ChartBorder.GetHScreenBorder(); var width=border.RightEx-border.LeftEx; return (x-border.LeftEx)/width*(range.Max-range.Min)+range.Min; } this.GetRightExtendMultiDayXFromIndex=function(index, obj, border) { var dayBorder=border.DayBorder; var client=dayBorder[obj.Index]; var count=obj.TotalCount-1; var left=client.BottomEx; var right=client.Bottom; var width=right-left; var offset=left+width*index/count; return offset; } this.GetRightExtendXFromIndex=function(index, obj) { var count=obj.TotalCount-1; var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) return this.GetRightExtendMultiDayXFromIndex(index, obj, border); var left=border.BottomEx; var width=this.ChartBorder.RightExtendWidth; var offset=left+width*index/count; return offset; } this.GetRightExtendMultiDayXData=function(y, obj, border) { var dayBorder=border.DayBorder; for(var i=0; i=client.BottomEx && y<=client.Bottom) { if (!obj[i]) return null; var count=obj[i].TotalCount-1; var left=client.BottomEx; var right=client.Bottom; var width=right-left; var index=(y-left)*(count*1.0/width); return { DayIndex:parseInt(i), DataIndex:index }; } } return null; } this.GetRightExtendXData=function(y, obj) { var border=this.ChartBorder.GetHScreenBorder(); if (border.DayBorder) return this.GetRightExtendMultiDayXData(y, obj, border); var count=obj.TotalCount-1; if (count<0) count=0; var left=border.BottomEx; var right=border.Bottom; if (y<=left) return 0; if (y>=right) return count; var width=right-left; return (y-left)*(count*1.0/width); } this.GetRightExtendYFromData=function(value,isLimit,obj) { if (!obj || !obj.Range) return this.GetYFromData(value,isLimit); return this.GetLeftExtendYFromData(value,isLimit,obj); } this.DrawNightDayBG=function() { if (this.DayCount!=1) return; if (!this.HQChart) return; if (!this.HQChart.EnableNightDayBG) return; var symbol=this.HQChart.Symbol; if (!symbol) return; var xIndex=-1; //获取夜盘和日期的分界线X索引位置 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_MINUTE_NIGHT_DAY_X_INDEX) if (!event || !event.Callback) return; var sendData={ Symbol:symbol, XIndex:xIndex, MinuteTimeStringData:g_MinuteTimeStringData }; event.Callback(event,sendData,this); xIndex=sendData.XIndex; if (xIndex<0) return; var border=this.ChartBorder.GetHScreenBorder(); var y=this.GetXFromIndex(xIndex); var rtNight={ Left: border.Left, Top:border.Top, Right:border.RightEx, Bottom:y }; rtNight.Width=rtNight.Right-rtNight.Left; rtNight.Height=rtNight.Bottom-rtNight.Top; this.Canvas.fillStyle = this.NightDayConfig.NightBGColor; this.Canvas.fillRect(rtNight.Left, rtNight.Top, rtNight.Width, rtNight.Height); if (this.Identify!=0) return; //显示 日盘夜盘文字 this.Canvas.font=this.NightDayConfig.Font; this.Canvas.textBaseline = "bottom"; this.Canvas.textAlign = 'left'; var aryTitle=[{ Title:"夜盘", Position:1, Config:this.NightDayConfig.Night }, { Title:"日盘", Position:0,Config:this.NightDayConfig.Day }]; var textHeight= this.Canvas.measureText("擎").width; for(var i=0;i`; const changeButton=``; const overlayButton=``; const closeButton=``; var spanIcon=modifyButton+changeButton+overlayButton; if (this.Identify!==0 && this.CloseIndex) //第1个窗口不能关闭 { spanIcon+=closeButton; } if (IFrameSplitOperator.IsNonEmptyArray(this.CustomToolbar)) { for(var i=0;i=0) { var offset=this.ChartBorder.GetLeft()+g_JSChartResource.FrameLeftMargin+this.DistanceWidth/2+this.DataWidth/2; for(var i=1;i<=index;++i) { offset+=this.DistanceWidth+this.DataWidth; } } else { var offset=(this.ChartBorder.GetLeft()+g_JSChartResource.FrameLeftMargin)-(this.DistanceWidth/2+this.DataWidth+this.DistanceWidth); var absIndex=Math.abs(index); for(var i=1;i this.xPointCount - 1) index = this.xPointCount - 1; var offset=this.ChartBorder.GetLeft()+g_JSChartResource.FrameLeftMargin+this.DistanceWidth/2+this.DataWidth/2; for(var i=1;i<=index;++i) { offset+=this.DistanceWidth+this.DataWidth; } } return offset; } //X坐标转x轴数值 isLimit=是否限制在当前屏坐标下 this.GetXData=function(x,isLimit) { var distanceWidth=this.DistanceWidth; var dataWidth=this.DataWidth; var left=this.ChartBorder.GetLeft()+g_JSChartResource.FrameLeftMargin; var maxDataCount=10000*50; if (isLimit==false) { if (x-maxDataCount) { if (xPoint<=x) break; xPoint-=(dataWidth+distanceWidth); --index; } return index; } else { var index=0; var xPoint=left+distanceWidth/2+dataWidth+distanceWidth; while(index=x) break; xPoint+=(dataWidth+distanceWidth); ++index; } return index; } } else { if (x<=this.ChartBorder.GetLeft()) return 0; if (x>=this.ChartBorder.GetRight()) return this.XPointCount-1; var right=this.ChartBorder.GetRight()-g_JSChartResource.FrameRightMargin; var index=0; var xPoint=left+distanceWidth/2+dataWidth+distanceWidth; while(xPoint=x) break; xPoint+=(dataWidth+distanceWidth); ++index; } //var test=(x-this.ChartBorder.GetLeft())*(this.XPointCount*1.0/this.ChartBorder.GetWidth()); return index; } } //计算数据宽度 this.CalculateDataWidth=function() { if (this.XPointCount<2) return; //JSConsole.Chart.Log(`[KLineFrame::CalculateDataWidth] ZoomIndex=${this.ZoomIndex}, XPointCount=${this.XPointCount}, DataWidth=${this.DataWidth}, DistanceWidth=${this.DistanceWidth}`); var width=this.GetFrameWidth()-g_JSChartResource.FrameMargin; if (this.ZoomIndex>=0 && this.LastCalculateStatus.Width==width && this.LastCalculateStatus.XPointCount==this.XPointCount) //宽度没变 尝试使用原来的柱子宽度 { var caclWidth=(this.DistanceWidth/2+g_JSChartResource.FrameLeftMargin)+(this.DataWidth + this.DistanceWidth)*(this.XPointCount-1); var caclWidth2=(this.DataWidth + this.DistanceWidth) * this.XPointCount; if (this.DataWidth<2) { if (caclWidth2<= width) //当前的柱子宽度够用 就不调整了 return; } else { if (caclWidth<= width) //当前的柱子宽度够用 就不调整了 return; } } this.LastCalculateStatus.Width=width; this.LastCalculateStatus.XPointCount=this.XPointCount; for(var i=0;i width) { this.DistanceWidth -= 0.01; break; } this.DistanceWidth += 0.01; } } //当前坐标信息 是否覆盖最大 最小值输出 this.IsOverlayMaxMin=function(obj) { if (!this.ChartKLine) return false; if (!this.ChartKLine.Max || !this.ChartKLine.Min) return false; var textWidth=this.Canvas.measureText(obj.Text.Value).width+4; //刻度文字宽度 if (obj.Text.TextAlign==='right') obj.X-=textWidth; var max=this.ChartKLine.Max, min=this.ChartKLine.Min; var isOverlayMax=false, isOverlayMin=false; const textHeight=20; //字体高度 if (max.X>=obj.X && max.X<=obj.X+textWidth) //最大值X 坐标不在 刻度文字范围内 { var y1=max.Y+textHeight, y2=max.Y-textHeight; if ( (y1>=obj.Y-textHeight && y1<=obj.Y+textHeight) || (y2>=obj.Y-textHeight && y2<=obj.Y+textHeight)) isOverlayMax=true; } if (isOverlayMax==true) return true; if (min.X>=obj.X && min.X<=obj.X+textWidth) { var y1=min.Y+textHeight, y2=min.Y-textHeight; if ( (y1>=obj.Y-textHeight && y1<=obj.Y+textHeight) || (y2>=obj.Y-textHeight && y2<=obj.Y+textHeight)) isOverlayMin=true; } return isOverlayMax || isOverlayMin; } //分割x,y轴坐标信息 this.SplitXYCoordinate=function() { if (this.XYSplit==false) { if (this.XSplit) { if (this.XSplitOperator) this.XSplitOperator.Operator(); } if (this.YCustomSplit) { //计算自定义刻度 if (this.YSplitOperator && this.YSplitOperator.CustomCoordinate) this.YSplitOperator.CustomCoordinate(); } return; } if (this.YSplitOperator!=null) this.YSplitOperator.Operator(); if (this.XSplitOperator!=null) this.XSplitOperator.Operator(); if (this.Logarithmic) this.SplitLogarithmicXYCoordinate(); } this.SplitLogarithmicXYCoordinate=function() { var up=this.Logarithmic.Up; var down=this.Logarithmic.Down; var logHeight=0; //对数额外高度 var count=0; var maxCount=Math.max(up.length, down.length); var aryLogHeight=[]; for(var i=0;i=0;--i) //上部 { var item=down[i]; item.Height=perHeight+(heightRate*item.LogHeight); item.Top=itemTop; item.Bottom=item.Top+item.Height; itemTop=item.Bottom; } var itemBottom=bottom; for(var i=up.length-1;i>=0;--i) //下部 { var item=up[i]; item.Height=perHeight+(heightRate*item.LogHeight) item.Bottom=itemBottom; item.Top=itemBottom-item.Height; itemBottom=item.Top; } } else { var itemTop=top; for(var i=up.length-1;i>=0;--i) { var item=up[i]; item.Height=perHeight+(heightRate*item.LogHeight); item.Top=itemTop; item.Bottom=item.Top+item.Height; itemTop=item.Bottom; } var itemBottom=bottom; for(var i=down.length-1;i>=0;--i) { var item=down[i]; item.Height=perHeight+(heightRate*item.LogHeight) item.Bottom=itemBottom; item.Top=itemBottom-item.Height; itemBottom=item.Top; } } JSConsole.Chart.Log("[KLineFrame::SplitLogarithmicXYCoordinate]", this.Logarithmic); } this.GetYLogarithmicFromData=function(value, isLimit) { if (this.CoordinateType==1) { if(value<=this.HorizontalMin) return this.ChartBorder.GetTopEx(); if(value>=this.HorizontalMax) return this.ChartBorder.GetBottomEx(); if (value>this.Logarithmic.OpenPrice) { var up=this.Logarithmic.Up; for(var i in up) { var item=up[i]; if (value>=item.Start && value<=item.End) { var itemHeight=item.Bottom-item.Top; var height=itemHeight*(value-item.Start)/(item.End-item.Start); return item.Top+height; } } } else { var down=this.Logarithmic.Down; for(var i in down) { var item=down[i]; if (value>=item.Start && value<=item.End) { var itemHeight=item.Bottom-item.Top; var height=itemHeight*(value-item.Start)/(item.End-item.Start); return item.Top+height; } } } } else { if(value<=this.HorizontalMin) return this.ChartBorder.GetBottomEx(); if(value>=this.HorizontalMax) return this.ChartBorder.GetTopEx(); if (value>this.Logarithmic.OpenPrice) { var up=this.Logarithmic.Up; for(var i in up) { var item=up[i]; if (value>=item.Start && value<=item.End) { var itemHeight=item.Bottom-item.Top; var height=itemHeight*(value-item.Start)/(item.End-item.Start); return item.Bottom-height; } } } else { var down=this.Logarithmic.Down; for(var i in down) { var item=down[i]; if (value>=item.Start && value<=item.End) { var itemHeight=item.Bottom-item.Top; var height=itemHeight*(value-item.Start)/(item.End-item.Start); return item.Bottom-height; } } } } } this.GetYLogarithmicData=function(y) { if (this.CoordinateType==1) //反转坐标 { if (ythis.ChartBorder.GetBottomEx()) return this.HorizontalMax; var up=this.Logarithmic.Up; for(var i in up) { var item=up[i]; if (y>=item.Top && y<=item.Bottom) { return (y-item.Top)/item.Height*(item.End-item.Start)+item.Start; } } var down=this.Logarithmic.Down; for(var i in down) { var item=down[i]; if (y>=item.Top && y<=item.Bottom) { return (y-item.Top)/item.Height*(item.End-item.Start)+item.Start; } } } else { if (ythis.ChartBorder.GetBottomEx()) return this.HorizontalMin; var up=this.Logarithmic.Up; for(var i in up) { var item=up[i]; if (y>=item.Top && y<=item.Bottom) { return (item.Bottom-y)/item.Height*(item.End-item.Start)+item.Start; } } var down=this.Logarithmic.Down; for(var i in down) { var item=down[i]; if (y>=item.Top && y<=item.Bottom) { return (item.Bottom-y)/item.Height*(item.End-item.Start)+item.Start; } } } } this.CalculateCount=function(zoomIndex) { var dataWidth=ZOOM_SEED[zoomIndex][0]; var distanceWidth=ZOOM_SEED[zoomIndex][1]; var width=this.GetFrameWidth()-g_JSChartResource.FrameMargin-distanceWidth/2; return parseInt(width/(dataWidth + distanceWidth)); } this.ZoomUp=function(cursorIndex) { if (this.ZoomIndex<=0) return false; if (this.Data.DataOffset<0) return false; var dataCount=this.Data.Data.length; var maxDataCount=dataCount+this.RightSpaceCount; var rightSpaceCount=0; var lastDataIndex = this.Data.DataOffset + this.XPointCount - 1; //最右边的数据索引 var lastCursorIndex=this.Data.DataOffset + cursorIndex.Index; if (lastDataIndex>=dataCount) { rightSpaceCount=lastDataIndex-(this.Data.Data.length-1); //计算右边预留空间 lastDataIndex=this.Data.Data.length-1; if (rightSpaceCount>this.RightSpaceCount) rightSpaceCount=this.RightSpaceCount; } var xPointCount=this.CalculateCount(this.ZoomIndex-1); JSConsole.Chart.Log(`[KLineFrame::ZoomUp] old status. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${this.Data.Data.length} rightSpaceCount=${rightSpaceCount}`); var isShowAll=false; --this.ZoomIndex; if (cursorIndex.IsLockRight==true) //固定右边 { var rightDataIndex=this.Data.DataOffset + this.XPointCount; //最右边的数据索引 if (xPointCount>rightDataIndex) { xPointCount=rightDataIndex; this.XPointCount=xPointCount; this.Data.DataOffset=0; } else { var dataOffset=lastDataIndex - (xPointCount-rightSpaceCount)+1; this.XPointCount=xPointCount; this.Data.DataOffset=dataOffset; if (this.Data.DataOffset<0) this.Data.DataOffset=0; } } else if (xPointCount>=maxDataCount) { //xPointCount=maxDataCount; //this.XPointCount=xPointCount; this.Data.DataOffset=0; this.XPointCount=xPointCount; isShowAll=true; JSConsole.Chart.Log(`[KLineFrame::ZoomUp] Show all data. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount}`); } else { var dataOffset=lastDataIndex - (xPointCount-rightSpaceCount)+1; if (cursorIndex.ZoomType==1) //以十字光标为中心左右放大 { var moveOffset=(this.XPointCount-xPointCount)+1; var leftOffset=parseInt(cursorIndex.Index/this.XPointCount*moveOffset); var rightOffset=moveOffset-leftOffset; var offset=this.Data.DataOffset+leftOffset; if (offset=showCount) { index=i; this.XPointCount=showCount; this.ZoomIndex=index; this.DataWidth=dataWidth; this.DistanceWidth=distanceWidth; if (dataWidth<=1 && distanceWidth==0) this.DataWidth=width/this.XPointCount; this.LastCalculateStatus.XPointCount=this.XPointCount; this.LastCalculateStatus.Width=width; return; } } //太多了 就平均分了 this.XPointCount=showCount; this.ZoomIndex=ZOOM_SEED.length-1; this.DataWidth=width/this.XPointCount; this.DistanceWidth=0; this.LastCalculateStatus.XPointCount=this.XPointCount; this.LastCalculateStatus.Width=width; } this.XCoordinateZoom=function(isMoveLeft) { var oldXPointCount=this.XPointCount; if (isMoveLeft) //放大 右边固定 { if (this.ZoomIndex<=0) return false; if (this.Data.DataOffset<0) return false; var zoomIndex=this.ZoomIndex-1; var xPointCount=this.CalculateCount(zoomIndex); var dataCount=this.Data.Data.length; var moveOffset=oldXPointCount-xPointCount; if (moveOffset<=0) return false; this.Data.DataOffset+=moveOffset; if (this.Data.DataOffset>dataCount) this.Data.DataOffset=0; } else //缩小 { if (this.ZoomIndex+1>=ZOOM_SEED.length) return false; if (this.Data.DataOffset<0) return false; var zoomIndex=this.ZoomIndex+1; var xPointCount=this.CalculateCount(zoomIndex); var moveOffset=xPointCount-oldXPointCount; this.Data.DataOffset-=moveOffset; if (this.Data.DataOffset<0) this.Data.DataOffset=0; } //JSConsole.Chart.Log(`[KLineFrame::XCoordinateZoom] old (XPointCount=${oldXPointCount} ZoomIndex=${this.ZoomIndex}) DataCount= ${this.Data.Data.length} `); this.XPointCount=xPointCount; this.ZoomIndex=zoomIndex; this.DataWidth = ZOOM_SEED[this.ZoomIndex][0]; this.DistanceWidth = ZOOM_SEED[this.ZoomIndex][1]; var width=this.GetFrameWidth()-g_JSChartResource.FrameMargin; this.TrimKLineDataWidth(width); this.LastCalculateStatus.XPointCount=this.XPointCount; return true; //var lastCursorIndex=this.Data.DataOffset + cursorIndex.Index; } this.ZoomDown=function(cursorIndex, option) //缩小 { if (this.ZoomIndex+1>=ZOOM_SEED.length) return false; if (this.Data.DataOffset<0) return false; if (this.Data.DataOffset<=0 && cursorIndex.IsLockRight==true) return false; var dataCount=this.Data.Data.length; var maxDataCount=dataCount+this.RightSpaceCount; //if (this.XPointCount>=maxDataCount) return false; var rightSpaceCount=0; var lastDataIndex = this.Data.DataOffset + this.XPointCount - 1; //最右边的数据索引 if (lastDataIndex>=this.Data.Data.length) { rightSpaceCount=lastDataIndex-(this.Data.Data.length-1); //计算右边预留空间 lastDataIndex=this.Data.Data.length-1; if (rightSpaceCount>this.RightSpaceCount) rightSpaceCount=this.RightSpaceCount; } var xPointCount=this.CalculateCount(this.ZoomIndex+1); var lastCursorIndex=this.Data.DataOffset + cursorIndex.Index; JSConsole.Chart.Log(`[KLineFrame::ZoomDown] old status. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${this.Data.Data.length} lastCursorIndex=${lastCursorIndex} rightSpaceCount=${rightSpaceCount}`); var isShowAll=false; ++this.ZoomIndex; if (cursorIndex.IsLockRight==true) //固定右边 { var rightDataIndex=this.Data.DataOffset + this.XPointCount; //最右边的数据索引 if (xPointCount>rightDataIndex) { xPointCount=rightDataIndex; this.XPointCount=xPointCount; this.Data.DataOffset=0; } else { var dataOffset=lastDataIndex - (xPointCount-rightSpaceCount)+1; this.XPointCount=xPointCount; this.Data.DataOffset=dataOffset; if (this.Data.DataOffset<0) this.Data.DataOffset=0; } } else if (xPointCount>=maxDataCount) //所有数据无法显示完一屏 { //xPointCount=maxDataCount; this.XPointCount=xPointCount; this.Data.DataOffset=0; //isShowAll=true; //数据铺满全屏, 不需要调整宽度 JSConsole.Chart.Log(`[KLineFrame::ZoomDown] Show all data. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount}`); if (xPointCount-this.RightSpaceCount>dataCount) { if (option && option.ZoomDownloadDataCallback) { option.ZoomDownloadDataCallback({ PageSize:xPointCount, DataCount:dataCount, RightSpaceCount:this.RightSpaceCount, Count:xPointCount-dataCount }); } } } else { var dataOffset=lastDataIndex - (xPointCount-rightSpaceCount)+1; if (cursorIndex.ZoomType==1) //当前十字光标位置左右同时缩小 { var moveOffset=(xPointCount-this.XPointCount)+1; var leftOffset=parseInt(cursorIndex.Index/this.XPointCount*moveOffset); var rightOffset=moveOffset-leftOffset; var dataOffset=this.Data.DataOffset-leftOffset; if (dataOffset+(xPointCount-this.RightSpaceCount)>=dataCount) dataOffset=this.Data.DataOffset-moveOffset; } this.XPointCount=xPointCount; this.Data.DataOffset=dataOffset; if (this.Data.DataOffset<0) this.Data.DataOffset=0; JSConsole.Chart.Log(`[KLineFrame::ZoomDown] calculate. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount} DataOffset=${this.Data.DataOffset}`); } this.DataWidth = ZOOM_SEED[this.ZoomIndex][0]; this.DistanceWidth = ZOOM_SEED[this.ZoomIndex][1]; if (!isShowAll) { var width=this.GetFrameWidth()-g_JSChartResource.FrameMargin; this.TrimKLineDataWidth(width); } this.LastCalculateStatus.XPointCount=this.XPointCount; cursorIndex.Index=lastCursorIndex-this.Data.DataOffset; return true; } this.GetFrameWidth=function() { if (this.IsHScreen) { var border=this.ChartBorder.GetHScreenBorder(); return border.BottomEx-border.TopEx; //return this.ChartBorder.GetHeight(); } else { var border=this.ChartBorder.GetBorder(); return border.RightEx-border.LeftEx; //return this.ChartBorder.GetWidth(); } } this.DrawCustomHorizontal=function() //Y轴刻度定制显示 { if (this.IsMinSize) return; if (this.ChartBorder.IsShowTitleOnly) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.CustomHorizontalInfo)) return; var aryHorizontal=this.CustomHorizontalInfo.slice(); aryHorizontal.sort((left, right)=>{ return right.Value-left.Value; }); var mapTextRect=new Map(); //key=position(1=左外 2=左内, 3=右外 4=右内), value:{ Rect:, Item: } for(var i=0; i0) xText+=rightLine.Width+1; else xText+=1; } else { this.Canvas.textBaseline="top"; if (leftLine && leftLine.Width>0) xText-=leftLine.Width; else xText-=2; } var yText=top+(bottom-top)/2; this.Canvas.fillStyle=this.TitleColor; this.Canvas.font=this.TitleFont; this.Canvas.textAlign="center"; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(this.Title, 0, 0); this.Canvas.restore(); } this.GetScaleTextWidth=function() { if (!this.IsShow) return null; var border=this.ChartBorder.GetBorder(); var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 if (this.IsHScreen) { var borderBottom=this.ChartBorder.Bottom; var isDrawRight=borderBottom>10*pixelTatio && this.IsShowYText[1]===true && this.YTextPosition[1]!=2; } else { var borderRight=this.ChartBorder.Right; var isDrawRight=borderRight>10 && this.IsShowYText[1]===true && this.YTextPosition[1]!=2; } if (!isDrawRight) return null; var width={ Left:null, Right:0 }; for(var i=0;i0) width.Right+=line.Width; } return { TextWidth:width }; } //同步主图坐标 this.SyncMainHorizontalInfo=function() { if (!this.MainFrame) return false; if (this.MainFrame.YMaxMin) { this.YMaxMin.Max=this.MainFrame.YMaxMin.Max; this.YMaxMin.Min=this.MainFrame.YMaxMin.Min; } this.HorizontalMax=this.MainFrame.HorizontalMax; this.HorizontalMin=this.MainFrame.HorizontalMin; this.HorizontalInfo=[]; for(var i=0;i=0; --i) //从上往下画分割线 { var item=this.HorizontalInfo[i]; var y=this.GetYFromData(item.Value); if (y!=null && Math.abs(y-yPrev)= bottom - 2) this.Canvas.textBaseline = 'bottom'; else if (y <= top + 2) this.Canvas.textBaseline = 'top'; else this.Canvas.textBaseline = "middle"; if (leftLine && leftLine.Width>0) //左边 { this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(xLine-leftLine.Width,ToFixedPoint(y)); this.Canvas.lineTo(xLine,ToFixedPoint(y)); this.Canvas.stroke(); } if (rightLine && rightLine.Width>0) { this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(xLine+rightLine.Width,ToFixedPoint(y)); this.Canvas.lineTo(xLine,ToFixedPoint(y)); this.Canvas.stroke(); } //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1]!=null && borderRight>10) { if (item.Font!=null) this.Canvas.font=item.Font; var text=item.Message[1]; if (Array.isArray(item.Message[1])) text=item.Message[1][0]; if (rightExtendText && rightExtendText.Align) { var textWidth=rightWidth; this.Canvas.textAlign="right"; var xRight=border.Right+this.RightOffset+textWidth-this.YTextPadding[1]; this.Canvas.fillText(text,xRight,y); } else { var xText=right+2; if (rightLine && rightLine.Width>0) xText+=rightLine.Width; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="left"; this.Canvas.fillText(text,xText,y); } } yPrev=y; } } //画X轴 this.DrawVertical=function() { var border=this.ChartBorder.GetBorder(); var top=border.TopEx; var bottom=border.BottomEx; var right=this.GetXHorizontal(); this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(right),ToFixedPoint(top)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(bottom)); this.Canvas.stroke(); } this.DrawToolbar=function(moveonPoint, isMinSize, mouseStatus) { this.Buttons=[]; if (isMinSize==true) return; if (this.ChartBorder.IsShowTitleOnly) return; if (this.ChartBorder.TitleHeight<5) return; if (!this.IsShowToolbar) return; var aryButton=[]; aryButton.push( { ID:JSCHART_BUTTON_ID.MODIFY_OVERLAY_INDEX_PARAM, Style:this.ModifyIndexParamButton }); aryButton.push( { ID:JSCHART_BUTTON_ID.CLOSE_OVERLAY_INDEX, Style:this.CloseWindowButton }); if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_OVERLAY_TOOLBAR); if (event && event.Callback) { var sendData={ PreventDefault:false, DefaultButton:aryButton, AryButton:null, Guid:this.Guid }; event.Callback(event, sendData, this); if (sendData.PreventDefault) { this.DrawToolbarButton(sendData.AryButton,moveonPoint, mouseStatus); return; } } } this.DrawToolbarButton(aryButton, moveonPoint, mouseStatus); } this.DrawToolbarButton=function(aryButton, moveonPoint, mouseStatus) { if (!IFrameSplitOperator.IsNonEmptyArray(aryButton)) return; var border=this.ChartBorder.GetBorder(); var yButton=border.Top+this.ChartBorder.TitleHeight/2; var rightWidth=this.GetHorizontalWidth(); var xBotton=border.Right+this.RightOffset+rightWidth-this.CloseButton.MerginLeft; for(var i=aryButton.length-1;i>=0;--i) { var item=aryButton[i]; var size=item.Style.Size; var font=`${size}px ${item.Style.Family}`; var rtButton={ Left:xBotton-size-item.Style.MerginLeft, Top:yButton-size/2, Right:xBotton, Bottom:yButton+size/2, Width:size+item.Style.MerginLeft, Height:size }; var color=this.CloseButton.Color; if (moveonPoint && (moveonPoint.X>=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { color=item.Style.MoveOnColor; if (mouseStatus) mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:item, Frame:this, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } this.Canvas.fillStyle=color; this.Canvas.font=font; this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(item.Style.Text, xBotton, yButton); this.Buttons.push({ ID:item.ID, Rect:rtButton }); xBotton=rtButton.Left; } } this.DrawCustomItem=function(item, mapTextRect) //显示自定义Y刻度 { if (!this.IsShow && !this.IsYDrawMainFrame) return; if (!item.Message[1] && !item.Message[0]) return; if (item.Value>this.HorizontalMax || item.ValuedefaultTextHeight? fontHeight:defaultTextHeight; var bgColor=item.LineColor; var rgb=this.RGBToStruct(item.LineColor); if (rgb) bgColor=`rgba(${rgb.R}, ${rgb.G}, ${rgb.B}, ${g_JSChartResource.FrameLatestPrice.BGAlpha})`; //内部刻度 背景增加透明度 var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var bgColor=item.LineColor; var rgb=this.RGBToStruct(item.LineColor); if (rgb) bgColor=`rgba(${rgb.R}, ${rgb.G}, ${rgb.B}, ${g_JSChartResource.FrameLatestPrice.BGAlpha})`; //内部刻度 背景增加透明度 var yText=y; for(var i=0;idefaultTextHeight? fontHeight:defaultTextHeight; var preTextRect=null; if (mapTextRect && mapTextRect.has(3)) preTextRect=mapTextRect.get(3); var yText=y; var rtText={ }; for(var i=0;i=this.HorizontalMax) return border.RightEx; var width=(border.RightEx-border.LeftEx)*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return border.LeftEx+width; } } //画Y轴 this.DrawHorizontal=function() { var border=this.ChartBorder.GetHScreenBorder(); var top=border.Top; var bottom=border.Bottom; var borderTop=this.ChartBorder.Top; var borderBottom=this.ChartBorder.Bottom; var left=border.Left; var right=border.Right; var yPrev=null; //上一个坐标y的值 var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 var isDrawLeft=borderTop>10*pixelTatio && this.IsShowYText[0]===true && this.YTextPosition[0]!=2; var isDrawRight=borderBottom>10*pixelTatio && this.IsShowYText[1]===true && this.YTextPosition[1]!=2; for(var i=this.HorizontalInfo.length-1; i>=0; --i) //从左往右画分割线 { var item=this.HorizontalInfo[i]; var y=this.GetYFromData(item.Value); if (y!=null && Math.abs(y-yPrev)0) { this.Canvas.strokeStyle=item.LineColor; if (g_JSChartResource.FrameYLineDash) { this.Canvas.setLineDash(g_JSChartResource.FrameYLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(y),top); this.Canvas.lineTo(ToFixedPoint(y),bottom); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else { this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(y),top); this.Canvas.lineTo(ToFixedPoint(y),bottom); this.Canvas.stroke(); } } } //坐标信息 左边 间距小于10 不画坐标 if (item.Message[0]!=null && isDrawLeft) { if (item.Font!=null) this.Canvas.font=item.Font; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; var xText=y,yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], -2, 0); this.Canvas.restore(); } //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1]!=null && isDrawRight) { if (item.Font!=null) this.Canvas.font=item.Font; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; var text; if (Array.isArray(item.Message[1])) //横屏只支持单行 { text=item.Message[1][0]; } else { text=item.Message[1]; } var xText=y,yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text, 2, 0); this.Canvas.restore(); } yPrev=y; } } //Y刻度画在左边内部 this.DrawInsideHorizontal = function () { if (this.IsMinSize) return; if (this.IsShowYText[0]===false && this.IsShowYText[1]===false) return; var left = this.ChartBorder.GetLeft(); var right = this.ChartBorder.GetRightEx(); var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); var borderTop=this.ChartBorder.Top; var borderBottom=this.ChartBorder.Bottom; var titleHeight = this.ChartBorder.TitleHeight; var pixelTatio = GetDevicePixelRatio(); var isDrawLeft= (borderTop<10*pixelTatio || this.YTextPosition[0]==2) && this.IsShowYText[0]===true; var isDrawRight= (borderBottom<10*pixelTatio || this.YTextPosition[1]==2) && this.IsShowYText[1]===true; if ( isDrawLeft || isDrawRight ) { var pixelTatio = GetDevicePixelRatio(); var yPrev = null; //上一个坐标y的值 for (var i = this.HorizontalInfo.length - 1; i >= 0; --i) //从上往下画分割线 { var item = this.HorizontalInfo[i]; var y = this.GetYFromData(item.Value); if (y != null && yPrev!=null && Math.abs(y - yPrev) < this.MinYDistance) continue; //两个坐标在近了 就不画了 //坐标信息 左边 间距小于10 画在内部 if (item.Message[0] != null && isDrawLeft) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "left"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; var textObj={ X:left, Y:y, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:item.Message[0]}} ; var xText=y,yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(item.Message[0], -2, 0); this.Canvas.restore(); } if (item.Message[1] != null && isDrawRight) { if (item.Font != null) this.Canvas.font = item.Font; this.Canvas.fillStyle = item.TextColor; this.Canvas.textAlign = "right"; if (y >= right - 2) this.Canvas.textBaseline = 'top'; else if (y <= left + 2) this.Canvas.textBaseline = 'bottom'; else this.Canvas.textBaseline = "middle"; if (Array.isArray(item.Message[1])) var text=item.Message[1][0]; else var text=item.Message[1]; var textWidth = this.Canvas.measureText(text).width; var textObj={ X:right-textWidth, Y:y, Text:{ BaseLine:this.Canvas.textBaseline, TextAlign: this.Canvas.textAlign, Font:this.Canvas.font, Value:text}} ; var xText=y,yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text, -2, 0); this.Canvas.restore(); } yPrev = y; } } } this.GetXFromIndex=function(index,isLimit) { if (isLimit===false) { var border=this.ChartBorder.GetHScreenBorder(); if (index>=0) { var offset=border.TopEx+ g_JSChartResource.FrameLeftMargin + this.DistanceWidth/2+this.DataWidth/2; for(var i=1;i<=index;++i) { offset+=this.DistanceWidth+this.DataWidth; } } else { var offset=border.TopEx-(this.DistanceWidth/2+this.DataWidth+this.DistanceWidth); var absIndex=Math.abs(index); for(var i=1;i this.xPointCount - 1) index = this.xPointCount - 1; var border=this.ChartBorder.GetHScreenBorder(); var offset=border.TopEx+ g_JSChartResource.FrameLeftMargin + this.DistanceWidth/2+this.DataWidth/2; for(var i=1;i<=index;++i) { offset+=this.DistanceWidth+this.DataWidth; } } return offset; } //画X轴 this.DrawVertical=function() { var mapX=null; if (this.GetVerticalXCache) mapX=this.GetVerticalXCache(); var border=this.ChartBorder.GetHScreenBorder(); var left=border.Left; var right=border.RightTitle; var bottom=border.Bottom; var pixelRatio = GetDevicePixelRatio(); //获取设备的分辨率 var xPrev=null; //上一个坐标x的值 for(var i=0; i=bottom) break; if (xPrev!=null && Math.abs(x-xPrev)<80) continue; if (item.LineType==2) { this.Canvas.strokeStyle=this.VerticalInfo[i].LineColor; this.Canvas.setLineDash([5*pixelRatio,5*pixelRatio]); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(left,ToFixedPoint(x)); this.Canvas.lineTo(right,ToFixedPoint(x)); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else if (item.LineType>0) { this.Canvas.strokeStyle=this.VerticalInfo[i].LineColor; if (g_JSChartResource.FrameXLineDash) { this.Canvas.setLineDash(g_JSChartResource.FrameXLineDash); //虚线 this.Canvas.beginPath(); this.Canvas.moveTo(left,ToFixedPoint(x)); this.Canvas.lineTo(right,ToFixedPoint(x)); this.Canvas.stroke(); this.Canvas.setLineDash([]); } else //实线 { this.Canvas.beginPath(); this.Canvas.moveTo(left,ToFixedPoint(x)); this.Canvas.lineTo(right,ToFixedPoint(x)); this.Canvas.stroke(); } } if (this.VerticalInfo[i].Message[0]!=null) { if (this.VerticalInfo[i].Font!=null) this.Canvas.font=this.VerticalInfo[i].Font; this.Canvas.fillStyle=this.VerticalInfo[i].TextColor; var testWidth=this.Canvas.measureText(this.VerticalInfo[i].Message[0]).width; if (xborder.RightEx) return this.HorizontalMax; var width=border.RightEx-border.LeftEx; return (x-border.LeftEx)/width*(this.HorizontalMax-this.HorizontalMin)+this.HorizontalMin; } } //X坐标转x轴数值 this.GetXData=function(y,isLimit) { var border=this.ChartBorder.GetHScreenBorder(); var left=border.TopEx+g_JSChartResource.FrameLeftMargin; var right=border.BottomEx; var distanceWidth=this.DistanceWidth; var dataWidth=this.DataWidth; var maxDataCount=10000*10; if (isLimit==false) { if (y-maxDataCount) { if (xPoint<=y) break; xPoint-=(dataWidth+distanceWidth); --index; } return index; } else { var index=0; var xPoint=left+distanceWidth/2+dataWidth+distanceWidth; while(index=y) break; xPoint+=(dataWidth+distanceWidth); ++index; } return index; } } else { if (y<=border.TopEx) return 0; if (y>=border.BottomEx) return this.XPointCount-1; var index=0; var xPoint=left+distanceWidth/2+ dataWidth+distanceWidth; while(xPointy) break; xPoint+=(dataWidth+distanceWidth); ++index; } return index; } //return (y-this.ChartBorder.GetTop())*(this.XPointCount*1.0/this.ChartBorder.GetHeight()); } this.DrawBottons=function() { } //计算数据宽度 /* this.CalculateDataWidth=function() { if (this.XPointCount<2) return; var width=this.ChartBorder.GetHeight()-g_JSChartResource.FrameMargin; for(var i=0;i=dataCount) return false; var rightSpaceCount=0; var lastDataIndex = this.Data.DataOffset + this.XPointCount - 1; //最右边的数据索引 var lastCursorIndex=this.Data.DataOffset + cursorIndex.Index; if (lastDataIndex>=dataCount) { rightSpaceCount=lastDataIndex-(dataCount-1); //计算右边预留空间 lastDataIndex=dataCount-1; if (rightSpaceCount>this.RightSpaceCount) rightSpaceCount=this.RightSpaceCount; } var xPointCount=this.CalculateCount(this.ZoomIndex-1); JSConsole.Chart.Log(`[KLineHScreenFrame::ZoomUp] old status. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${this.Data.Data.length} rightSpaceCount=${rightSpaceCount}`); --this.ZoomIndex; if (xPointCount>=maxDataCount) { xPointCount=maxDataCount; this.XPointCount=xPointCount; this.Data.DataOffset=0; JSConsole.Chart.Log(`[KLineHScreenFrame::ZoomUp] Show all data. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount}`); } else { this.XPointCount=xPointCount; this.Data.DataOffset = lastDataIndex - (this.XPointCount-rightSpaceCount)+1; JSConsole.Chart.Log(`[KLineHScreenFrame::ZoomUp] calculate. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount} DataOffset=${this.Data.DataOffset}`); } this.DataWidth = ZOOM_SEED[this.ZoomIndex][0]; this.DistanceWidth = ZOOM_SEED[this.ZoomIndex][1]; var width=this.ChartBorder.GetHeight()-g_JSChartResource.FrameMargin; this.TrimKLineDataWidth(width); this.LastCalculateStatus.XPointCount=this.XPointCount; cursorIndex.Index=lastCursorIndex-this.Data.DataOffset; return true; } this.ZoomDown=function(cursorIndex) { if (this.ZoomIndex+1>=ZOOM_SEED.length) return false; if (this.Data.DataOffset<0) return false; var dataCount=this.Data.Data.length; var maxDataCount=dataCount+this.RightSpaceCount; if (this.XPointCount>=dataCount) return false; var rightSpaceCount=0; var lastDataIndex = this.Data.DataOffset + this.XPointCount - 1; //最右边的数据索引 if (lastDataIndex>=this.Data.Data.length) { rightSpaceCount=lastDataIndex-(this.Data.Data.length-1); //计算右边预留空间 lastDataIndex=this.Data.Data.length-1; if (rightSpaceCount>this.RightSpaceCount) rightSpaceCount=this.RightSpaceCount; } var xPointCount=this.CalculateCount(this.ZoomIndex+1); var lastCursorIndex=this.Data.DataOffset + cursorIndex.Index; JSConsole.Chart.Log(`[KLineHScreenFrame::ZoomDown] old status. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${this.Data.Data.length} lastCursorIndex=${lastCursorIndex} rightSpaceCount=${rightSpaceCount}`); ++this.ZoomIndex; if (xPointCount>=maxDataCount) { xPointCount=maxDataCount; this.XPointCount=xPointCount; this.Data.DataOffset=0; JSConsole.Chart.Log(`[KLineHScreenFrame::ZoomDown] Show all data. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount}`); } else { this.XPointCount=xPointCount; this.Data.DataOffset = lastDataIndex - (this.XPointCount-rightSpaceCount)+1; JSConsole.Chart.Log(`[KLineHScreenFrame::ZoomDown] calculate. XPointCount=${xPointCount} ZoomIndex=${this.ZoomIndex} DataCount= ${dataCount} DataOffset=${this.Data.DataOffset}`); } this.DataWidth = ZOOM_SEED[this.ZoomIndex][0]; this.DistanceWidth = ZOOM_SEED[this.ZoomIndex][1]; var width=this.ChartBorder.GetHeight()-g_JSChartResource.FrameMargin; this.TrimKLineDataWidth(width); this.LastCalculateStatus.XPointCount=this.XPointCount; cursorIndex.Index=lastCursorIndex-this.Data.DataOffset; return true; } */ } function OverlayKLineHScreenFrame() { this.newMethod=KLineHScreenFrame; //派生 this.newMethod(); delete this.newMethod; this.ClassName='OverlayKLineHScreenFrame'; this.MainFrame=null; //主框架 this.IsShareY=false; //使用和主框架公用Y轴 this.IsCalculateYMaxMin=true; //是否计算Y最大最小值 this.RightOffset=50; this.PenBorder=g_JSChartResource.OverlayFrame.BolderPen; //'rgb(0,0,0)' this.IsShow=true; //坐标是否显示 this.Title=null; this.TitleColor=g_JSChartResource.OverlayFrame.TitleColor; this.TitleFont=g_JSChartResource.OverlayFrame.TitleFont; this.Draw=function() { this.SplitXYCoordinate(); if (this.IsShow) { this.DrawVertical(); this.DrawHorizontal(); this.DrawTitle(); } this.SizeChange=false; this.XYSplit=false; this.XSplit=false; this.YCustomSplit=false; //自定义Y轴分割线 } this.DrawTitle=function() //画标题 { /* if (!this.Title) return; var top = this.ChartBorder.GetTopTitle(); var bottom = this.ChartBorder.GetBottom(); var right=this.ChartBorder.GetRight(); right+=this.RightOffset; this.Canvas.fillStyle=this.TitleColor; this.Canvas.font=this.TitleFont; this.Canvas.textAlign="center"; this.Canvas.textBaseline="top"; var xText=right-2,yText=top+(bottom-top)/2; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(this.Title, 0, 0); this.Canvas.restore(); */ } //分割x,y轴坐标信息 this.SplitXYCoordinate=function() { if (this.XYSplit==false) return; if (this.IsShareY) //和主图指标共享Y轴坐标 { this.HorizontalMax=this.MainFrame.HorizontalMax; this.HorizontalMin=this.MainFrame.HorizontalMin; this.HorizontalInfo=[]; for(var i in this.MainFrame.HorizontalInfo) { var item=this.MainFrame.HorizontalInfo[i]; this.HorizontalInfo.push(item); } } else { if (this.YSplitOperator!=null) this.YSplitOperator.Operator(); } // if (this.XSplitOperator!=null) this.XSplitOperator.Operator(); 子坐标和主坐标X轴一致 所以不用计算 } //画Y轴 this.DrawHorizontal=function() { /* var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var bottom = this.ChartBorder.GetBottom(); var top = this.ChartBorder.GetTopTitle(); var borderRight=this.ChartBorder.Right; right+=this.RightOffset; var yPrev=null; //上一个坐标y的值 for(var i=this.HorizontalInfo.length-1; i>=0; --i) //从上往下画分割线 { var item=this.HorizontalInfo[i]; var y=this.GetYFromData(item.Value); if (y!=null && Math.abs(y-yPrev)= bottom - 2) this.Canvas.textBaseline = 'bottom'; else if (y <= top + 2) this.Canvas.textBaseline = 'top'; else this.Canvas.textBaseline = "middle"; this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(right-2,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); this.Canvas.stroke(); //坐标信息 右边 间距小于10 不画坐标 if (item.Message[1]!=null && borderRight>10) { if (item.Font!=null) this.Canvas.font=item.Font; this.Canvas.fillStyle=item.TextColor; this.Canvas.textAlign="left"; this.Canvas.fillText(item.Message[1],right+2,y); } yPrev=y; } */ } //画X轴 this.DrawVertical=function() { /* var top=this.ChartBorder.GetTopEx(); //var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var bottom=this.ChartBorder.GetBottomEx(); right+=this.RightOffset; this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(right),ToFixedPoint(top)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(bottom)); this.Canvas.stroke(); */ } this.GetScaleTextWidth=function() { return { TextWidth:0 }; } } function SubFrameItem() { this.Frame; this.Height; this.OverlayIndex=[]; //叠加指标 //this.Interval=60; //子坐标间间距 } 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.SubFrame=new Array(); //SubFrameItem 数组 this.SizeChange=true; //大小是否改变 this.ChartBorder; this.Canvas; //画布 this.ScreenImageData; //截图 this.Data; //主数据 this.Position; //画布的位置 this.SizeChange=true; this.MinSubFrameHeight=g_JSChartResource.DragSubFrameBorder.MinFrameHeight; this.DragBorderHeight=g_JSChartResource.DragSubFrameBorder.TopBorderHeight; //拖拽边框高度 this.AutoLeftBorder=null; //{ Blank:10 留白宽度, MinWidth:最小宽度 } this.AutoRightBorder=null; //{ Blank:10 留白宽度, MinWidth:最小宽度 } this.OverlayBlankWidth=30; this.AuotRightWidth; //右边主坐标刻度宽度 (自动模式) //固定模式右侧宽度 this.FixedRightWidth={ Main:60, Overlay:80 }; this.ZoomWindowsInfo=null; //附图指标缩放,备份信息 this.ZoomStartWindowIndex=1; //允许缩放窗口起始位置 this.GetExtendChartByClassName; this.GetEventCallback; this.OnMoveFromeBorder=function(index, yMove) { if (this.SubFrame.length<=0) return false; var topFrame=this.SubFrame[index]; var bottomFrame=null; for(var i=index+1;i0) { bottomFrame=item; break; } } if (!topFrame || !bottomFrame) return false; var bottomBackup=topFrame.Frame.ChartBorder.Bottom; var topBackup=bottomFrame.Frame.ChartBorder.Top; topFrame.Frame.ChartBorder.Bottom-=yMove; bottomFrame.Frame.ChartBorder.Top+=yMove; var height=topFrame.Frame.ChartBorder.GetHeightEx(); var height2=bottomFrame.Frame.ChartBorder.GetHeightEx(); //缩小的时候 小于最小高度 不处理 if ((height0)) { topFrame.Frame.ChartBorder.Bottom=bottomBackup; bottomFrame.Frame.ChartBorder.Top=topBackup; return false; } return true; } this.ReDrawToolbar=function() { for(var i in this.SubFrame) { this.SubFrame[i].Frame.ReDrawToolbar=true; } } this.SetFrameBorderSizeChange=function() { var firstFrame=this.SubFrame[0]; if (!firstFrame || !firstFrame.Frame) return; var splitOper=firstFrame.Frame.YSplitOperator; if (!splitOper) return; if (splitOper.CoordinateType==2) //对数坐标 需要重新计算Y轴分割 { firstFrame.Frame.XYSplit=true; } } this.CancelZoomUpDownFrameY=function(obj) { var index=obj.Index; if (this.SubFrame.length<=0) return false; if (!this.SubFrame[index]) return false; var subFrame=this.SubFrame[index]; var frame=subFrame.Frame; if (obj.IsOverlay) { var overlayItem=subFrame.OverlayIndex[obj.OverlayIndex]; if (!overlayItem) return false; if (!overlayItem.Frame.IsShareY) frame=overlayItem.Frame; } var splitOper=frame.YSplitOperator; if (splitOper.FixedYMaxMin) { splitOper.FixedYMaxMin=null; splitOper.EnableZoomUpDown=false; frame.XYSplit=true; for(var i in subFrame.OverlayIndex) { var item=subFrame.OverlayIndex[i]; if (item.Frame.IsShareY) item.Frame.XYSplit=true; } JSConsole.Chart.Log(`[HQTradeFrame::CancelZoomUpDownFrameY]`); return true; } return false; } this.OnZoomUpDownFrameY=function(obj, yMove) { var index=obj.Index; if (this.SubFrame.length<=0) return false; if (!this.SubFrame[index]) return false; var subFrame=this.SubFrame[index]; var frame=subFrame.Frame; if (obj.IsOverlay) { var overlayItem=subFrame.OverlayIndex[obj.OverlayIndex]; if (!overlayItem) return false; if (!overlayItem.Frame.IsShareY) frame=overlayItem.Frame; } var top=frame.ChartBorder.GetTopEx(); var bottom=frame.ChartBorder.GetBottomEx(); var maxValue=frame.HorizontalMax; var minValue=frame.HorizontalMin; var moveStep=(maxValue-minValue)*Math.abs(yMove)/(bottom-top); var splitOper=frame.YSplitOperator; var newFixedYMaxMin={ Max:maxValue, Min:minValue }; if (obj.Position==1) { var step=yMove>0 ? -moveStep:moveStep; newFixedYMaxMin.Max+=step; } else if (obj.Position==2) { var step=yMove>0 ? -moveStep:moveStep; newFixedYMaxMin.Min+=step; } else if (obj.Position==0) { var step=yMove>0 ? moveStep:-moveStep; newFixedYMaxMin.Max+=step; newFixedYMaxMin.Min-=step; } else { return false; } if (newFixedYMaxMin.Max>newFixedYMaxMin.Min) { splitOper.FixedYMaxMin=newFixedYMaxMin; splitOper.EnableZoomUpDown=true; frame.XYSplit=true; for(var i=0;i0 ? -moveStep:moveStep; var newFixedYMaxMin={ Max:maxValue, Min:minValue }; newFixedYMaxMin.Max-=step; newFixedYMaxMin.Min-=step; splitOper.FixedYMaxMin=newFixedYMaxMin; splitOper.EnableZoomUpDown=true; frame.XYSplit=true; for(var i in subFrame.OverlayIndex) { var item=subFrame.OverlayIndex[i]; if (item.Frame.IsShareY) item.Frame.XYSplit=true; } JSConsole.Chart.Log(`[HQTradeFrame::OnUpDonwFrameY] Max=${newFixedYMaxMin.Max}, Min=${newFixedYMaxMin.Min}, yMove=${yMove}, moveStep=${moveStep}`); return true; } this.ClearUpDonwFrameYData=function(option) //清空上下拖拽的数据 { if (this.SubFrame.length<=0) return; if (option) { var index=option.Index; if (index<0 || index>=this.SubFrame.length) return; var item=this.SubFrame[index]; if (!item || !item.Frame || !item.Frame.YSplitOperator) return; var splitOper=item.Frame.YSplitOperator; if (splitOper.EnableZoomUpDown==true) splitOper.FixedYMaxMin=null; } else { for(var i=0;i0) totalTitleHeight+=frame.ChartBorder.TitleHeight; else totalHeight+=item.Height; } height-=totalTitleHeight; for(var i=0; i0) { var frameHeight=item.Frame.ChartBorder.Top+frame.ChartBorder.TitleHeight; item.Frame.ChartBorder.Bottom=this.ChartBorder.GetChartHeight()-frameHeight; top=frameHeight; } else { var frameHeight=height*(item.Height/totalHeight)+top; item.Frame.ChartBorder.Bottom=this.ChartBorder.GetChartHeight()-frameHeight; top=frameHeight; } } if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SIZE_FRAME); if (event && event.Callback) { var sendData={ SubFrame:this.SubFrame }; event.Callback(event, sendData, this); } } } this.SetExtendWidth=function(obj) { if (!obj) return; var leftWidth=null, rightWidth=null; if (IFrameSplitOperator.IsNumber(obj.Left)) { leftWidth=obj.Left; this.ChartBorder.LeftExtendWidth=leftWidth; } if (IFrameSplitOperator.IsNumber(obj.Right)) { rightWidth=obj.Right; this.ChartBorder.RightExtendWidth=rightWidth; } for(var i in this.SubFrame) { var item=this.SubFrame[i]; if (leftWidth!=null) item.Frame.ChartBorder.LeftExtendWidth=leftWidth; if (rightWidth!=null) item.Frame.ChartBorder.RightExtendWidth=rightWidth; } } this.CalculateChartBorder2=function() //计算每个子框架的边框信息(思维导图用) { if (this.SubFrame.length<=0) return; var top=this.ChartBorder.Top; var bottom=this.ChartBorder.Bottom; var height=this.ChartBorder.GetHeight(); var totalHeight=0; for(var i in this.SubFrame) { var item=this.SubFrame[i]; totalHeight+=item.Height; } var tempHeight=0; for(var i in this.SubFrame) { var item=this.SubFrame[i]; item.Frame.ChartBorder.Top=top; item.Frame.ChartBorder.Left=this.ChartBorder.Left; item.Frame.ChartBorder.Right=this.ChartBorder.Right; item.Frame.ChartBorder.X=this.ChartBorder.X; item.Frame.ChartBorder.Y=this.ChartBorder.Y; item.Frame.ChartBorder.Width=this.ChartBorder.Width; item.Frame.ChartBorder.Height=this.ChartBorder.Height; var frameHeight=height*(item.Height/totalHeight); tempHeight+=frameHeight; bottom=this.ChartBorder.Bottom+(height-tempHeight); item.Frame.ChartBorder.Bottom=bottom; top+=frameHeight; } } this.GetScaleTextWidth=function() { var width={ Left:null, Right:null, OverlayRight:0 }; var aryOverlayWidth=[];// 叠加坐标 for(var i=0; i0) max+=this.OverlayBlankWidth for(var j=0; jvalue) 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; } this.AuotRightWidth=value; rightTextInfo.MainTextWidth=value; //主图坐标宽度 if (IFrameSplitOperator.IsNonEmptyArray(textWidth.AryOverlayWidth)) rightTextInfo.AryOverlayWidth=textWidth.AryOverlayWidth; if (IFrameSplitOperator.IsPlusNumber(textWidth.OverlayRight)) { this.AuotRightWidth=value; value+=textWidth.OverlayRight; } if (this.GetExtendChartRightWidth) { var extendWidth=this.GetExtendChartRightWidth(); if (this.GetExtendChartByClassName) { var finder=this.GetExtendChartByClassName("StockChip"); if (finder && finder.Chart) { finder.Chart.Left=value; } } value+=extendWidth; } if (this.IsHScreen) { if (this.ChartBorder.Bottom!=value) bSizeChange=true; this.ChartBorder.Bottom=value; } else { if (this.ChartBorder.Right!=value) bSizeChange=true; this.ChartBorder.Right=value; } for(var i=0; irightOffset) rightOffset=item.Frame.RightTextMaxWidth; for(var j =0, index=0; j=left && x<=right && y>bottom && y=0) { var item=this.SubFrame[windowIndex]; if (item.Frame) item.Frame.YCustomSplit=true; } else { for(var i=0;i0) //第1个窗口主坐标已经算好了 { item.Frame.XPointCount= mainFrame.XPointCount; item.Frame.ZoomIndex= mainFrame.ZoomIndex; item.Frame.DataWidth= mainFrame.DataWidth; item.Frame.DistanceWidth= mainFrame.DistanceWidth; item.Frame.LastCalculateStatus.Width=mainFrame.LastCalculateStatus.Width; item.Frame.LastCalculateStatus.XPointCount=mainFrame.LastCalculateStatus.XPointCount; } for(var j in item.OverlayIndex) { var overlayItem=this.SubFrame[i].OverlayIndex[j]; overlayItem.Frame.XPointCount= mainFrame.XPointCount; overlayItem.Frame.ZoomIndex= mainFrame.ZoomIndex; overlayItem.Frame.DataWidth= mainFrame.DataWidth; overlayItem.Frame.DistanceWidth= mainFrame.DistanceWidth; overlayItem.Frame.LastCalculateStatus.Width=mainFrame.LastCalculateStatus.Width; overlayItem.Frame.LastCalculateStatus.XPointCount=mainFrame.LastCalculateStatus.XPointCount; } } } //鼠标是否在边框上 this.PtInFrameBorder=function(x,y) { var height=this.DragBorderHeight; for(var i=0;imaxTopHegith) { var barTop=top+maxTopHegith; var barBottom=bottom-maxTopHegith; } else { var internal=barHegith/3; var barTop=top+internal; var barBottom=bottom-internal; } var position=0; if (ybarBottom) position=2; if (rightWidth>=10) { if (IFrameSplitOperator.IsNonEmptyArray(item.OverlayIndex)) { var overlayItem=item.OverlayIndex[0]; var rightOffset=overlayItem.Frame.RightOffset; item.Frame.Canvas.beginPath(); item.Frame.Canvas.rect(right,top,rightOffset,(bottom-top)); if (item.Frame.Canvas.isPointInPath(x,y)) { return { Index:i, Right:true, Left:false, Position:position, IsOverlay:false }; //Position 1=上面 2 下面 0=中间(TODO) } var overlayRight=right+rightOffset; for(var j=0;j=10) { item.Frame.Canvas.beginPath(); item.Frame.Canvas.rect(0,top,leftWidth,(bottom-top)); if (item.Frame.Canvas.isPointInPath(x,y)) { return { Index:i, Right:false, Left:true, Position:position,IsOverlay:false }; } } } return null; } this.SetDayCount=function(dayCount) { this.ChartBorder.MultiDayMinute.Count=dayCount; for(var i=0;i0) totalTitleHeight+=frame.ChartBorder.TitleHeight; else totalHeight+=item.Height; } width-=totalTitleHeight; for(var i=0; i0) { var frameWidth=frame.ChartBorder.TitleHeight; item.Frame.ChartBorder.Right=right; item.Frame.ChartBorder.Left=left-frameWidth; right+=frameWidth; left-=frameWidth; } else { var frameWidth=width*(item.Height/totalHeight); item.Frame.ChartBorder.Right=right; item.Frame.ChartBorder.Left=left-frameWidth; right+=frameWidth; left-=frameWidth; } } } this.GetYData=function(x,outObject) { var frame; for(var i=0; i0) { var minPrice=this.BidPrice[0]; if (price0) { var maxPrice=this.AskPrice[this.AskPrice.length-1]; if (price>maxPrice) { isAskPrice=true; find=maxPrice; } } } if (find==null) return null; var x=this.GetXFromIndex(find); return { X:x, Price:find, IsAsk:isAskPrice }; } this.GetPrice=function(aryPrice, price) { if (!aryPrice || !Array.isArray(aryPrice) || aryPrice.length<=0) return null; if (pricearyPrice[aryPrice.length-1]) return null; var lastPrice=null; for(var i in aryPrice) { var item=aryPrice[i]; if (price==item) { return item; } if (pricexRange.MaxDiffer) differ=xRange.MaxDiffer; xRange.Differ=differ; xRange.Min=xRange.Center-xRange.Differ; xRange.Max=xRange.Center+xRange.Differ; return true; } } //历史K线数据 function HistoryData() { this.Date; this.YClose; this.Open; this.Close; this.High; this.Low; this.Vol; this.Amount; this.Time; //mmhh 或者 mmhhss this.FlowCapital=null; //流通股本 this.Position=null; //持仓量 this.IsVirtual=false; //是否为虚拟数据 this.IsNonTrade=false; //非交易日 //期货 this.YFClose=null; //前结算价 this.FClose=null; //结算价 //指数才有的数据 this.Stop; //停牌家数 this.Up; //上涨 this.Down; //下跌 this.Unchanged; //平盘 this.ExtendData; //扩展数据 this.BFactor; //前复权 this.AFactor; //后复权 this.RightSeed; //本地计算的复权系数 /* { PriceOffset: 每个单元的价格间距, High: [ { Price:, Value:, Text: Color ,Font:{ Weight:}}, ..... ], Low:[ { Price:, Value:, Text: Color , Font:{ Weight:}}, ..... ] , Order: //订单信息 [ { Price:, Ask:{ Color:, Value: , Text:, BG:, Font:{ Weight:} } Bid:{ Color:, Value:, Text:, BG:, Font:{ Weight:} }, //横线柱子 Width K线宽度比值, Height:高度 Type:0=长度由Width决定, 1=当收盘价小于Price后,线就不需要在继续延伸 2=当收盘价大于Price后,线就不需要在继续延伸了 HBar:{ Color:, Width, Height: 1, Type:0,1,2 }, Vol:{ Value:, BG:, Text:, Color: } }, ........ ] } */ this.OrderFlow; //订单流 this.ColorData; //自定义颜色 {Type:0=空心 1=实心, Line:{ Color:'上下线颜色'}, Border:{Color:柱子边框颜色}, BarColor:柱子颜色}; /* { PriceOffset:每个单元的价格间距, Order: [ { Price:价格, Color:颜色, Value: } ] } */ this.HeatMap; } //数据复制 HistoryData.Copy=function(data) { var newData=new HistoryData(); newData.Date=data.Date; if (IFrameSplitOperator.IsNumber(data.Time)) newData.Time=data.Time; newData.YClose=data.YClose; newData.Open=data.Open; newData.Close=data.Close; newData.High=data.High; newData.Low=data.Low; newData.Vol=data.Vol; newData.Amount=data.Amount; if (IFrameSplitOperator.IsNumber(data.FlowCapital)) newData.FlowCapital=data.FlowCapital; if (IFrameSplitOperator.IsNumber(data.Position)) newData.Position=data.Position; if (IFrameSplitOperator.IsNumber(data.YFClose)) newData.YFClose=data.YFClose; if (IFrameSplitOperator.IsNumber(data.FClose)) newData.FClose=data.FClose; //指数涨停家数 if (IFrameSplitOperator.IsNumber(data.Stop)) newData.Stop=data.Stop; if (IFrameSplitOperator.IsNumber(data.Up)) newData.Up=data.Up; if (IFrameSplitOperator.IsNumber(data.Down)) newData.Down=data.Down; if (IFrameSplitOperator.IsNumber(data.Unchanged)) newData.Unchanged=data.Unchanged; //复权因子 if (IFrameSplitOperator.IsNumber(data.BFactor)) newData.BFactor=data.BFactor; if (IFrameSplitOperator.IsNumber(data.AFactor)) newData.AFactor=data.AFactor; if (IFrameSplitOperator.IsBool(data.IsVirtual)) newData.IsVirtual=data.IsVirtual; if (IFrameSplitOperator.IsBool(data.IsNonTrade)) newData.IsNonTrade=data.IsNonTrade; if (data.OrderFlow) newData.OrderFlow=data.OrderFlow; if (data.ColorData) newData.ColorData=data.ColorData; if (data.ExtendData) newData.ExtendData=data.ExtendData; if (data.HeatMap) newData.HeatMap=data.HeatMap; return newData; } //把数据 src 复制到 dest中 HistoryData.CopyTo=function(dest,src) { dest.Date=src.Date; if (IFrameSplitOperator.IsNumber(src.Time)) dest.Time=src.Time; dest.YClose=src.YClose; dest.Open=src.Open; dest.Close=src.Close; dest.High=src.High; dest.Low=src.Low; dest.Vol=src.Vol; dest.Amount=src.Amount; if (IFrameSplitOperator.IsNumber(src.FlowCapital)) dest.FlowCapital=src.FlowCapital; if (IFrameSplitOperator.IsNumber(src.Position)) dest.Position=src.Position; if (IFrameSplitOperator.IsNumber(src.YFClose)) dest.YFClose=src.YFClose; if (IFrameSplitOperator.IsNumber(src.FClose)) dest.FClose=src.FClose; if (IFrameSplitOperator.IsNumber(src.Stop)) dest.Stop=src.Stop; if (IFrameSplitOperator.IsNumber(src.Up)) dest.Up=src.Up; if (IFrameSplitOperator.IsNumber(src.Down)) dest.Down=src.Down; if (IFrameSplitOperator.IsNumber(src.Unchanged)) dest.Unchanged=src.Unchanged; if (IFrameSplitOperator.IsNumber(src.BFactor)) dest.BFactor=src.BFactor; if (IFrameSplitOperator.IsNumber(src.AFactor)) dest.AFactor=src.AFactor; if (IFrameSplitOperator.IsBool(src.IsVirtual)) dest.IsVirtual=src.IsVirtual; if (IFrameSplitOperator.IsBool(src.IsNonTrade)) dest.IsNonTrade=src.IsNonTrade; if (src.OrderFlow) dest.OrderFlow=src.OrderFlow; if (src.ColorData) dest.ColorData=src.ColorData; if (src.HeatMap) dest.HeatMap=src.HeatMap; if (src.ExtendData) dest.ExtendData=src.ExtendData; } //数据复权拷贝 HistoryData.CopyRight=function(data,seed) { var newData=new HistoryData(); newData.Date=data.Date; if (IFrameSplitOperator.IsNumber(data.Time)) newData.Time=data.Time; newData.YClose=data.YClose*seed; newData.Open=data.Open*seed; newData.Close=data.Close*seed; newData.High=data.High*seed; newData.Low=data.Low*seed; newData.Vol=data.Vol; newData.Amount=data.Amount; newData.FlowCapital=data.FlowCapital; newData.Position=data.Position; newData.YFClose=data.YFClose; newData.FClose=data.FClose; if (data.ColorData) newData.ColorData=data.ColorData; //K线颜色 if (data.ExtendData) newData.ExtendData=data.ExtendData; //扩张数据 return newData; } function MinuteData() { this.Close; this.Open; this.High; this.Low; this.Vol; //量 this.Amount; //金额 this.DateTime; this.Increase; //涨幅 this.Risefall; //涨跌 this.AvPrice; //均价 this.Lead=null; //领先指标 this.Time; //时间 this.Date; //日期 this.Position=null; //持仓量 this.YClearing; //昨结算价 this.YClose; //昨收价 this.ExtendData; //扩展数据 } //盘前集合竞价 function BeforeOpenData() { this.Time; this.Date; this.Price; //匹配的价格 this.AvPrice; //均价 this.Vol=[]; //[0]=匹配量 [1]=未匹配量 this.ColorID; //0=平盘 1=红 2=绿 3 ...自定义颜色 this.YClose; //昨收价 } //收盘集合竞价 function AfterCloseData() { this.Time; this.Date; this.Price; //匹配的价格 this.AvPrice; //均价 this.Vol=[]; //[0]=匹配量 [1]=未匹配量 this.ColorID; //0=平盘 1=红 2=绿 3 ...自定义颜色 this.YClose; //昨收价 } //单指标数据 function SingleData() { this.Date; //日期 this.Time; //时间 this.Value; //数据 (可以是一个数组) } var KLINE_INFO_TYPE= { INVESTOR:1, //互动易 ANNOUNCEMENT:2, //公告 PFORECAST:3, //业绩预告 ANNOUNCEMENT_QUARTER_1:4, //一季度报 ANNOUNCEMENT_QUARTER_2:5, //半年报 ANNOUNCEMENT_QUARTER_3:6, //2季度报 ANNOUNCEMENT_QUARTER_4:7, //年报 RESEARCH:8, //调研 BLOCKTRADING:9, //大宗交易 TRADEDETAIL:10, //龙虎榜 //公告预留类型 ANNOUNCEMENT_EX_START:100, ANNOUNCEMENT_EX_END:200, } function KLineInfoData() { this.ID; this.Date; this.Time; //时间 this.Title; this.InfoType; this.ExtendData; //扩展数据 } //外部数据计算方法接口 function DataPlus () { this.PeriodCallback=new Map(); //key=周期id value={ Period, Callback(period,data,self): } this.GetPeriodCallback=function(period) { if (!this.PeriodCallback.has(period)) return null; return this.PeriodCallback.get(period); } this.AddPeriodCallback=function(obj) { if (!IFrameSplitOperator.IsNumber(obj.Period) || !obj.Callback) return; var item={ Period:obj.Period, Callback:obj.Callback }; this.PeriodCallback.set(obj.Period, item); } this.RemovePeriodCallback=function(obj) { if (!this.PeriodCallback.has(obj.ID)) return; this.PeriodCallback.delete(obj.ID); } }; var g_DataPlus=new DataPlus(); function ChartData() { this.Data=new Array(); this.DataOffset=0; //数据偏移 this.Period=0; //周期 0 日线 1 周线 2 月线 3年线 this.Right=0; //复权 0 不复权 1 前复权 2 后复权 this.Symbol; //股票代码 this.Data2=new Array(); //第1组数据 走势图:历史分钟数据 this.GetCloseMA=function(dayCount) { var result=new Array(); for (var i = 0, len = this.Data.length; i < len; i++) { if (i < dayCount) { result[i]=null; continue; } var sum = 0; for (var j = 0; j < dayCount; j++) { sum += this.Data[i - j].Close; } result[i]=sum / dayCount; } return result; } this.GetVolMA=function(dayCount) { var result=new Array(); for (var i = 0, len = this.Data.length; i < len; i++) { if (i < dayCount) { result[i]=null; continue; } var sum = 0; for (var j = 0; j < dayCount; j++) { sum += this.Data[i - j].Vol; } result[i]=sum / dayCount; } return result; } this.GetAmountMA=function(dayCount) { var result=new Array(); for (var i = 0, len = this.Data.length; i < len; i++) { if (i < dayCount) { result[i]=null; continue; } var sum = 0; for (var j = 0; j < dayCount; j++) { sum += this.Data[i - j].Amount; } result[i]=sum / dayCount; } return result; } //获取收盘价 this.GetClose=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].Close; } return result; } this.GetYClose=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].YClose; } return result; } this.GetHigh=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].High; } return result; } this.GetLow=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].Low; } return result; } this.GetOpen=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].Open; } return result; } this.GetVol=function(unit) { var value=1; if (IFrameSplitOperator.IsNumber(unit)) value=unit; var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].Vol/value; } return result; } this.GetAmount=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].Amount; } return result; } this.GetPosition=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].Position; } return result; } this.GetSettlementPrice=function() //结算价 { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].FClose; } return result; } this.GetIsEqual=function() { var result=[]; for(var i in this.Data) { var item=this.Data[i]; result[i]=(item.Close==item.Open? 1:0); } return result; } this.GetIsUp=function() { var result=[]; for(var i in this.Data) { var item=this.Data[i]; result[i]=(item.Close>item.Open? 1:0); } return result; } this.GetIsDown=function() { var result=[]; for(var i in this.Data) { var item=this.Data[i]; result[i]=(item.CloseCUSTOM_MINUTE_PERIOD_START && period<=CUSTOM_MINUTE_PERIOD_END) { periodDataCount=period-CUSTOM_MINUTE_PERIOD_START; return this.GetMinuteCustomPeriodData(periodDataCount); } else return this.Data; var bFirstPeriodData = false; var newData = null; var preTime=null; //上一次的计算时间 for (var i = 0; i < this.Data.length; ) { bFirstPeriodData = true; for (var j = 0; j < periodDataCount && i < this.Data.length; ++i) { if (bFirstPeriodData) { newData = new HistoryData(); result.push(newData); bFirstPeriodData = false; } var minData = this.Data[i]; if (minData == null) { ++j; continue; } if (minData.Time==925 && (preTime==null || preTime!=924)) //9:25, 9:30 不连续就不算个数 { } else if (minData.Time == 930 && (preTime==null || preTime!=929) ) { } else if (minData.Time == 1300 && (preTime==null || preTime!=1259) ) //1点的数据 如果不是连续的 就不算个数 { } else ++j; newData.Date = minData.Date; newData.Time = minData.Time; preTime=newData.Time; if (minData.Open==null || minData.Close==null) continue; if (newData.Open==null || newData.Close==null) { newData.Open=minData.Open; newData.High=minData.High; newData.Low=minData.Low; newData.YClose=minData.YClose; newData.Close=minData.Close; newData.Vol=minData.Vol; newData.Amount=minData.Amount; newData.FlowCapital=minData.FlowCapital; newData.Position=minData.Position; newData.YFClose=minData.YFClose; newData.FClose=minData.FClose; } else { if (newData.HighminData.Low) newData.Low=minData.Low; newData.Close=minData.Close; newData.Vol+=minData.Vol; if (minData.Amount!=null) newData.Amount+=minData.Amount; newData.Position=minData.Position; newData.FlowCapital=minData.FlowCapital; newData.FClose=minData.FClose; } if (i+1 < this.Data.length) //判断下一个数据是否是不同日期的 { var nextItem=this.Data[i+1]; if (nextItem && nextItem.Date!=minData.Date) //不同日期的, 周期结束 { ++i; break; } } } } return result; } //自定义分钟 this.GetMinuteCustomPeriodData=function(count) { var result = new Array(); var periodDataCount = count; var bFirstPeriodData = false; var newData = null; for (var i = 0; i < this.Data.length; ) { bFirstPeriodData = true; for (var j = 0; j < periodDataCount && i < this.Data.length; ++i, ++j) { if (bFirstPeriodData) { newData = new HistoryData(); result.push(newData); bFirstPeriodData = false; } var minData = this.Data[i]; if (minData == null) continue; newData.Date = minData.Date; newData.Time = minData.Time; if (minData.Open==null || minData.Close==null) continue; if (newData.Open==null || newData.Close==null) { newData.Open=minData.Open; newData.High=minData.High; newData.Low=minData.Low; newData.YClose=minData.YClose; newData.Close=minData.Close; newData.Vol=minData.Vol; newData.Amount=minData.Amount; newData.FlowCapital=minData.FlowCapital; newData.Position=minData.Position; newData.YFClose=minData.YFClose; newData.FClose=minData.FClose; } else { if (newData.HighminData.Low) newData.Low=minData.Low; newData.Close=minData.Close; newData.Vol+=minData.Vol; if (minData.Amount!=null) newData.Amount+=minData.Amount; //null数据不相加 newData.Position=minData.Position; newData.FlowCapital=minData.FlowCapital; newData.FClose=minData.FClose; } } } return result; } //计算周,月,年 this.GetDayPeriodData=function(period) { if (period>CUSTOM_DAY_PERIOD_START && period<=CUSTOM_DAY_PERIOD_END) return this.GetDayCustomPeriodData(period-CUSTOM_DAY_PERIOD_START); var isBit=MARKET_SUFFIX_NAME.IsBIT(this.Symbol); var result=new Array(); var index=0; var startDate=0; var weekCount=2; var newData=null; for(var i in this.Data) { var isNewData=false; var dayData=this.Data[i]; switch(period) { case 1: //周线 if (isBit) var fridayDate=ChartData.GetSunday(dayData.Date); //数字货币全年的 else var fridayDate=ChartData.GetFirday(dayData.Date); if (fridayDate!=startDate) { isNewData=true; startDate=fridayDate; } break; case 21: //双周 if (isBit) var fridayDate=ChartData.GetSunday(dayData.Date); //数字货币全年的 else var fridayDate=ChartData.GetFirday(dayData.Date); if (fridayDate!=startDate) { ++weekCount; if (weekCount>=2) { isNewData=true; weekCount=0; } startDate=fridayDate; } break; case 2: //月线 if (parseInt(dayData.Date/100)!=parseInt(startDate/100)) { isNewData=true; startDate=dayData.Date; } break; case 3: //年线 if (parseInt(dayData.Date/10000)!=parseInt(startDate/10000)) { isNewData=true; startDate=dayData.Date; } break; case 22://半年: var halfYear=ChartData.GetHalfYear(dayData.Date); if (halfYear!=startDate) { isNewData=true; startDate=halfYear; } break; case 9: //季线 var now=ChartData.GetQuarter(dayData.Date); now=parseInt(dayData.Date/10000)*10+now; var last=ChartData.GetQuarter(startDate); last=parseInt(startDate/10000)*10+last; if (now!=last) { isNewData=true; startDate=dayData.Date; } break; } if (isNewData) { newData=new HistoryData(); newData.Date=dayData.Date; result.push(newData); if (dayData.Open==null || dayData.Close==null) continue; newData.Open=dayData.Open; newData.High=dayData.High; newData.Low=dayData.Low; newData.YClose=dayData.YClose; newData.Close=dayData.Close; newData.Vol=dayData.Vol; newData.Amount=dayData.Amount; newData.FlowCapital=dayData.FlowCapital; newData.Position=dayData.Position; newData.YFClose=dayData.YFClose; newData.FClose=dayData.FClose; } else { if (newData==null) continue; if (dayData.Open==null || dayData.Close==null) continue; if (newData.Open==null || newData.Close==null) { newData.Open=dayData.Open; newData.High=dayData.High; newData.Low=dayData.Low; newData.YClose=dayData.YClose; newData.Close=dayData.Close; newData.Vol=dayData.Vol; newData.Amount=dayData.Amount; newData.FlowCapital=dayData.FlowCapital; newData.Position=dayData.Position; newData.YFClose=dayData.YFClose; newData.FClose=dayData.FClose; } else { if (newData.HighdayData.Low) newData.Low=dayData.Low; newData.Close=dayData.Close; newData.Vol+=dayData.Vol; if (dayData.Amount!=null) newData.Amount+=dayData.Amount; newData.Position=dayData.Position; newData.FlowCapital=dayData.FlowCapital; newData.Date=dayData.Date; newData.FClose=dayData.FClose; } } } return result; } this.GetDayCustomPeriodData=function(count) { var result = []; var periodDataCount = count; var bFirstPeriodData = false; var newData = null; for (var i = 0; i < this.Data.length; ) { bFirstPeriodData = true; for (var j = 0; j < periodDataCount && i < this.Data.length; ++i, ++j) { if (bFirstPeriodData) { newData = new HistoryData(); result.push(newData); bFirstPeriodData = false; } var dayData = this.Data[i]; if (dayData == null) continue; newData.Date = dayData.Date; if (dayData.Open==null || dayData.Close==null) continue; if (newData.Open==null || newData.Close==null) { newData.Open=dayData.Open; newData.High=dayData.High; newData.Low=dayData.Low; newData.YClose=dayData.YClose; newData.Close=dayData.Close; newData.Vol=dayData.Vol; newData.Amount=dayData.Amount; newData.FlowCapital=dayData.FlowCapital; newData.Position=dayData.Position; newData.YFClose=dayData.YFClose; newData.FClose=dayData.FClose; } else { if (newData.HighdayData.Low) newData.Low=dayData.Low; newData.Close=dayData.Close; newData.Vol+=dayData.Vol; if (dayData.Amount!=null) newData.Amount+=dayData.Amount; newData.Position=dayData.Position; newData.FlowCapital=dayData.FlowCapital; newData.FClose=dayData.FClose; } } } return result; } //周期数据 1=周 2=月 3=年 this.GetPeriodData=function(period) { //外部自定义周期计算函数 var itemCallback=g_DataPlus.GetPeriodCallback(period); if (itemCallback) return itemCallback.Callback(period,this.Data,this); if (MARKET_SUFFIX_NAME.IsBIT(this.Symbol)) { if (period==5 || period==6 || period==7 || period==8 || (period>CUSTOM_MINUTE_PERIOD_START && period<=CUSTOM_MINUTE_PERIOD_END)) //分钟K线 { var periodDataCount = 5; if (period == 5) periodDataCount = 5; else if (period == 6) periodDataCount = 15; else if (period == 7) periodDataCount = 30; else if (period == 8) periodDataCount = 60; else if (period==11) periodDataCount = 120; else if (period==12) periodDataCount = 240; else if (period>CUSTOM_MINUTE_PERIOD_START && period<=CUSTOM_MINUTE_PERIOD_END) periodDataCount=period-CUSTOM_MINUTE_PERIOD_START; return this.GetMinuteCustomPeriodData(periodDataCount); } } //if (period==1 || period==2 || period==3 || period==9 || period==21 || period==22 || (period>CUSTOM_DAY_PERIOD_START && period<=CUSTOM_DAY_PERIOD_END)) if (ChartData.IsDayPeriod(period,false)) return this.GetDayPeriodData(period); //if (period==5 || period==6 || period==7 || period==8 || period==11 || period==12 || (period>CUSTOM_MINUTE_PERIOD_START && period<=CUSTOM_MINUTE_PERIOD_END)) return this.GetMinutePeriodData(period); if (ChartData.IsMinutePeriod(period,false)) return this.GetMinutePeriodData(period); } //复权 0 不复权 1 前复权 2 后复权 this.GetRightData=function(right, option) { var result=[]; if (this.Data.length<=0) return result; if (option && option.AlgorithmType==1) //使用复权因子计算 { for(var i=0;i=0; --index) { if (yClose!=this.Data[index].Close) break; var newItem=HistoryData.Copy(this.Data[index]); newItem.RightSeed=seed; result[index]=newItem; yClose=this.Data[index].YClose; } for(; index>=0; --index) { var value=this.Data[index].Close; if(yClose!=value && value!=0) seed *= yClose/value; var newItem=HistoryData.CopyRight(this.Data[index],seed); newItem.RightSeed=seed; result[index]=newItem yClose=this.Data[index].YClose; } } else if (right==2) { var index=0; var seed=1; var close=this.Data[index].Close; result[index]=HistoryData.Copy(this.Data[index]); result[index].RightSeed=seed; for(++index;index=overlayData.length) { result[i]=new HistoryData(); result[i].Date=date; ++i; continue;; } var overlayDate=overlayData[j].Date; if (overlayDate==date) { result[i]=new HistoryData(); result[i].Date=overlayData[j].Date; result[i].YClose=overlayData[j].YClose; result[i].Open=overlayData[j].Open; result[i].High=overlayData[j].High; result[i].Low=overlayData[j].Low; result[i].Close=overlayData[j].Close; result[i].Vol=overlayData[j].Vol; result[i].Amount=overlayData[j].Amount; //涨跌家数数据 result[i].Stop=overlayData[j].Stop; result[i].Up=overlayData[j].Up; result[i].Down=overlayData[j].Down; result[i].Unchanged=overlayData[j].Unchanged; ++j; ++i; } else if (overlayDate=overlayData.length) { result[i]=new HistoryData(); result[i].Date=date; result[i].Time=time; ++i; continue;; } var overlayDate=overlayData[j].Date; var overlayTime=overlayData[j].Time; if (overlayDate==date && overlayTime==time) { result[i]=new HistoryData(); result[i].Date=overlayData[j].Date; result[i].Time=overlayData[j].Time; result[i].YClose=overlayData[j].YClose; result[i].Open=overlayData[j].Open; result[i].High=overlayData[j].High; result[i].Low=overlayData[j].Low; result[i].Close=overlayData[j].Close; result[i].Vol=overlayData[j].Vol; result[i].Amount=overlayData[j].Amount; //涨跌家数数据 result[i].Stop=overlayData[j].Stop; result[i].Up=overlayData[j].Up; result[i].Down=overlayData[j].Down; result[i].Unchanged=overlayData[j].Unchanged; ++j; ++i; } else if (overlayDate=overlayData.length) { result[i]=null; ++i; continue;; } var overlayDate=overlayData[j].Date; if (overlayDate==date) { var item=new SingleData(); item.Date=overlayData[j].Date; item.Value=overlayData[j].Value; result[i]=item; ++j; ++i; } else if (overlayDate=overlayData.length) { result[i]=new SingleData(); result[i].Date=date; result[i].Value=emptyValue; ++i; continue;; } var overlayDate=overlayData[j].Date; if (overlayDate==date) { var item=new SingleData(); item.Date=overlayData[j].Date; item.Value=overlayData[j].Value; result[i]=item; ++j; ++i; } else if (overlayDate=data.length) break; var dateItem=data[j]; if (dateItem.Date==date) { dateItem.Index=i; ++j; } else if (dateItem.Date=data.length) break; var dateTimeItem=data[j]; if (dateTimeItem.Date==date && dateTimeItem.Time==time) { dateTimeItem.Index=i; ++j; } else if (dateTimeItem.Date=overlayData.length) { result[i]=null; ++i; continue;; } var overlayDate=overlayData[j].Date; var overlayTime=overlayData[j].Time; const overlayItem=overlayData[j]; if (overlayDate==date && overlayTime==time) { var item=new SingleData(); item.Date=overlayItem.Date; item.Time=overlayItem.Time; item.Value=overlayItem.Value; result[i]=item; ++j; ++i; } else if (overlayDate=overlayData.length) { result[i]=null; ++i; continue;; } var overlayDate=overlayData[j].Date; var overlayTime=overlayData[j].Time; const overlayItem=overlayData[j]; if (overlayDate==date && overlayTime==time) { var item=new SingleData(); item.Date=overlayItem.Date; item.Time=overlayItem.Time; item.Value=overlayItem.Value; result[i]=item; ++j; ++i; } else if (overlayDate=overlayData.length) { result[i]=null; ++i; continue;; } var overlayDate=overlayData[j].Date; var overlayTime=overlayData[j].Time; const overlayItem=overlayData[j]; if (overlayDate==date && overlayTime==time) { var item=new SingleData(); item.Date=overlayItem.Date; item.Time=overlayItem.Time; item.Value=overlayItem.Value; result[i]=item; latestItem=overlayItem; ++j; ++i; } else if (overlayDate=0) { var item=result[index]; if (item) { if (overlayDatefirstItem.Date || (date==firstItem.Date && time>=firstItem.Time)) { break; } } for(var j=0;idate) { var item=new SingleData(); item.Date=date; item.Value=nullValue; result[i]=item; ++i; continue; } } if (j+1date || (tradeData[j].Date==date && tradeData[j].Time>time)) { var item=new SingleData(); item.Date=date; item.Time=time; item.Value=nullValue; result[i]=item; ++i; continue; } } if (j+1=overlayData.length) { result[i]=null; ++i; continue;; } var overlayDate=overlayData[j].Date; if (overlayDate==date) { var item=new SingleData(); item.Date=overlayData[j].Date; item.Value=overlayData[j].Value; item.Text=overlayData[j].Text; result[i]=item; ++j; ++i; } else if (preDate!=null && preDateoverlayDate) { var item=new SingleData(); item.Date=date; item.OverlayDate=overlayData[j].Date; item.Value=overlayData[j].Value; item.Text=overlayData[j].Text; result[i]=item; ++j; ++i; } else if (overlayDate=2) { isNewData=true; weekCount=0; } startDate=fridayDate; } break; case 2: //月线 if (parseInt(dayData.Date/100)!=parseInt(startDate/100)) { isNewData=true; startDate=dayData.Date; } break; case 3: //年线 if (parseInt(dayData.Date/10000)!=parseInt(startDate/10000)) { isNewData=true; startDate=dayData.Date; } break; case 9: //季线 var now=ChartData.GetQuarter(dayData.Date); now=parseInt(dayData.Date/10000)*10+now; var last=ChartData.GetQuarter(startDate); last=parseInt(startDate/10000)*10+last; if (now!=last) { isNewData=true; startDate=dayData.Date; } break; } if (isNewData) { newData=new SingleData(); newData.Date=dayData.Date; newData.Value=dayData.Value; result.push(newData); } else { if (newData==null) continue; if (dayData.Value==null || isNaN(dayData.Value)) continue; if (newData.Value==null || isNaN(newData.Value)) newData.Value=dayData.Value; } } return result; } /* 分钟数据方法 this.GetClose() 每分钟价格 this.GetVol() 每分钟成交量 */ //分钟均线 this.GetMinuteAvPrice=function() { var result=new Array(); for(var i in this.Data) { result[i]=this.Data[i].AvPrice; } return result; } this.MergeMinuteData=function(data) //合并数据 { if (!this.Data || this.Data.length<=0) { this.Data=data; return true; } var sourceFirstItem=this.Data[0]; var firstItemID=0; var firstItem=null; for(var i=0;isourceFirstItem.Date) { firstItemID=i; firstItem=item; break; } if (item.Date==sourceFirstItem.Date && item.Time>=sourceFirstItem.Time) { firstItemID=i; firstItem=item; break; } } if (firstItem==null) return false; var index=null; var bFind=false; //第1个数据是否完全匹配 for(var i=this.Data.length-1; i>=0;--i) { var date=this.Data[i].Date; var time=this.Data[i].Time; if (firstItem.Date>date || (firstItem.Date==date && firstItem.Time>=time) ) { index=i; if (firstItem.Date==date && firstItem.Time==time) bFind=true; break; } } if (index==null) return false; var j=index; //原始数据插入位置 var i=firstItemID; //合并数据起始位置 if (bFind==true) //第1个数据匹配,覆盖 { var item=data[i]; if (j-1>0) { var preItem=this.Data[j-1]; if (!item.YClose) item.YClose=preItem.Close; //前收盘如果没有就是上一记录的收盘 //流通股使用上一个数据的 if (!IFrameSplitOperator.IsNumber(item.FlowCapital) && IFrameSplitOperator.IsNumber(preItem.FlowCapital)) item.FlowCapital=preItem.FlowCapital; } var newItem=HistoryData.Copy(item); this.Data[j]=newItem; ++j; ++i; } else //从下一个数据开始插入 { ++j; } for(;i=this.Data.length-1) { if (j-1>0) { var preItem=this.Data[j-1]; if (!item.YClose) item.YClose=preItem.Close; //前收盘如果没有就是上一记录的收盘 //流通股使用上一个数据的 if (!IFrameSplitOperator.IsNumber(item.FlowCapital) && IFrameSplitOperator.IsNumber(preItem.FlowCapital)) item.FlowCapital=preItem.FlowCapital; } //if (j-1>0 && !item.YClose) item.YClose=this.Data[j-1].YClose; //前收盘如果没有就是上一记录的收盘 //if (j-1>0 && !IFrameSplitOperator.IsNumber(item.FlowCapital) && IFrameSplitOperator.IsNumber(this.Data[j-1].FlowCapital)) item.FlowCapital=this.Data[j-1].FlowCapital; var newItem=HistoryData.Copy(item); this.Data[j]=newItem; ++j; ++i; } else { var oldItem=this.Data[j]; if (oldItem.Date==item.Date && oldItem.Time==item.Time) //更新数据 { HistoryData.CopyTo(oldItem,item); ++j; ++i; } else { ++j; } } } //JSConsole.Chart.Log('[ChartData::MergeMinuteData] ', this.Data, data); return true; } //跨周期转化 this.ConverPeriod=function(data, curPeriod, changePeriod) //把数据用data, 日期时间不变, curPeriod=当前周期 changePeriod=需要转换周期 { var result=[]; var tempItem=null; var isMinute=ChartData.IsMinutePeriod(curPeriod,true); var isMinute2=ChartData.IsMinutePeriod(changePeriod,true); var isMimToMin=isMinute && isMinute2; var isMinToDay=isMinute && !isMinute2; var isDayToDay=!isMinute && !isMinute2; for(var i=0,j=0; iitem.Date) || (periodItem.Date==item.Date && periodItem.Time>=item.Time) ) { tempItem=periodItem; break; } } else if (isMinToDay || isDayToDay) //分钟 => 日线, 日线 => 日线 { if (periodItem.Date>=item.Date) { tempItem=periodItem; break; } } } var newItem=null; if (tempItem) { newItem=HistoryData.Copy(tempItem); newItem.PDate=tempItem.Date; newItem.PTime=tempItem.Time; } else newItem=new HistoryData(); newItem.Date=item.Date; if (isMimToMin || isMinToDay) newItem.Time=item.Time; result.push(newItem); } JSConsole.Chart.Log('[ChartData::ConverPeriod] result', result); return result; } this.GetRef=function(n) { let result=[]; for(var i=0 ;i 日线(原始) 日线(拟合 => 分钟(原始) { if (item.Date>=firstItem.Date) { indexStart = i; break; } } else if (isMinutePeriod[0] && isMinutePeriod[1]) //分钟(拟合 => 分钟(原始) { if (item.Date>firstItem.Date) { indexStart = i; break; } if (item.Date == firstItem.Date && item.Time >= firstItem.Time ) { indexStart = i; break; } } } for(var i=0, j=indexStart; i=indexCount) { var fitItem={ Date:item.Date, Time:item.Time, Index:-1 }; aryFixDataID[i]=fitItem; ++i; continue; } var destItem=ChartData.GetKLineDataTime(kLineData[j]); if ( (isDayPeriod[0] && isDayPeriod[1]) || (isMinutePeriod[0] && isDayPeriod[1]) ) //日线(拟合) => 日线(原始) 日线(拟合 => 分钟(原始) { if (destItem.Date == item.Date) { var fitItem={ Date:item.Date, Time:item.Time, Index:j, Data2:destItem.Date, Time2:destItem.Time }; aryFixDataID[i]=fitItem; ++i; } else { if (j+1item.Date ) { var fitItem={ Date:item.Date, Time:item.Time, Index:j+1, Data2:nextDestItem.Date, Time2:nextDestItem.Time }; aryFixDataID[i]=fitItem; ++i; } else if (nextDestItem.Date <= item.Date ) { ++j; } else { var fitItem={ Date:item.Date, Time:item.Time, Index:-1 }; aryFixDataID[i]=fitItem; ++i; } } else { ++j; } } } else if (isMinutePeriod[0] && isMinutePeriod[1]) //分钟(拟合 => 分钟(原始) { if (destItem.Date == item.Date && destItem.Time == item.Time) { var fitItem={ Date:item.Date, Time:item.Time, Index:j, Data2:destItem.Date, Time2:destItem.Time }; aryFixDataID[i]=fitItem; ++i; } else { if (j+1item.Date) || (destItem.Date == item.Date && destItem.Time < item.Time && nextDestItem.Date == item.Date && nextDestItem.Time > item.Time) || (destItem.Date == item.Date && destItem.Time < item.Time && nextDestItem.Date > item.Date) || (destItem.Date < item.Date && nextDestItem.Date == item.Date && nextDestItem.Time > item.Time) ) { var fitItem={ Date:item.Date, Time:item.Time, Index:j+1, Data2:nextDestItem.Date, Time2:nextDestItem.Time }; aryFixDataID[i]=fitItem; ++i; } else if (nextDestItem.Date < item.Date || (nextDestItem.Date == item.Date && nextDestItem.Time <= item.Time) ) { ++j; } else { var fitItem={ Date:item.Date, Time:item.Time, Index:-1 }; aryFixDataID[i]=fitItem; ++i; } } else { ++j; } } } } //拟合数据 var result=[]; for(var i in outVar) { var item=outVar[i]; if (Array.isArray(item.Data)) { var data=[]; result[i]={ Data:data, Name:item.Name } ; for(var j=0;j=0 && dataItem.Index=0) continue; if (IFrameSplitOperator.IsNumber(findItem.Time)) { if (findItem.Date==item.Date && findItem.Time==item.Time) { findItem.Index=parseInt(i); ++findCount; break; } } else { if (findItem.Date==item.Date) { findItem.Index=parseInt(i); ++findCount; break; } } if (findCount>=aryDateTime.length) break; } } } //深拷贝数据 this.CloneData=function(className) { var result=[]; if (className=="HistoryData") { for(var i in this.Data) { var item=this.Data[i]; var newItem=HistoryData.Copy(item); result.push(newItem); } } return result; } this.GetAPIDataIndex=function(date,time) { var result=[]; if (date && time) { var count=this.Data.length; //原始K线数据 var indexCount=date.length; //拟合数据 var firstItem=ChartData.GetKLineDataTime(this.Data[0]); var indexStart=indexCount; //拟合数据的起始位置 var indexStart=indexCount; //拟合数据的起始位置 for(var i=0;ifirstItem.Date || (itemDate == firstItem.Date && itemTime >= firstItem.Time)) { indexStart = i; break; } } for(var i=0, j=indexStart; i=indexCount) { var fitItem={ KDate:item.Date, KTime:item.Time, KIndex:i, Index:-1 }; result[i]=fitItem; ++i; continue; } var itemDate=date[j]; var itemTime=time[j]; if (itemDate == item.Date && itemTime == item.Time) { var fitItem={ KDate:item.Date, KTime:item.Time, KIndex:i, Index:j, Data:itemDate, Time:itemTime }; result[i]=fitItem; ++i; } else { if (j+1item.Date) || (itemDate == item.Date && itemTime < item.Time && nextItemDate == item.Date && nextItemTime > item.Time) || (itemDate == item.Date && itemTime < item.Time && nextItemDate > item.Date) || (itemDate < item.Date && nextItemDate == item.Date && nextItemTime > item.Time) ) { var fitItem={ KDate:item.Date, KTime:item.Time, KIndex:i, Index:j, Data:itemDate, Time:itemTime }; result[i]=fitItem; ++i; } else if (nextItemDate < item.Date || (nextItemDate == item.Date && nextItemTime <= item.Time) ) { ++j; } else { var fitItem={ KDate:item.Date, KTime:item.Time, KIndex:i, Index:-1 }; result[i]=fitItem; ++i; } } else { ++j; } } } } else if (date) { var count=this.Data.length; //原始K线数据 var indexCount=date.length; //拟合数据 var firstItem=ChartData.GetKLineDataTime(this.Data[0]); var indexStart=indexCount; //拟合数据的起始位置 for(var i=0;i=firstItem.Date) { indexStart = i; break; } } for(var i=0, j=indexStart; i=indexCount) { var fitItem={ KDate:item.Date, KIndex:i, Index:-1 }; result[i]=fitItem; ++i; continue; } var destDate=date[j]; if (destDate == item.Date) { var fitItem={ KDate:item.Date, KIndex:i, Index:j, Data:destDate }; result[i]=fitItem; ++i; } else { if (j+1item.Date ) { var fitItem={ KDate:item.Date, KIndex:i, Index:j, Data:destDate }; result[i]=fitItem; ++i; } else if (nextDestDate <= item.Date ) { ++j; } else { var fitItem={ KDate:item.Date, KIndex:i, Index:-1 }; result[i]=fitItem; ++i; } } else { ++j; } } } } return result; } //K线数据拟合 this.FixKData=function(aryKData, period) { if (ChartData.IsDayPeriod(period,true)) { return this.FixKData_Day(aryKData); } else if (ChartData.IsMinutePeriod(period,true)) { return this.FixKData_Minute(aryKData); } return null; } this.FixKData_Day=function(aryKData) { var result=[]; var nOverlayDataCount=aryKData.length; for(var i=0,j=0; ikItem.Date) { ++i; continue; } } if (j+1kDateTime) { ++i; continue; } } if (j+10) { var prevTimestamp=(24*60*60*1000)*(7-day); timestamp+=prevTimestamp; } date.setTime(timestamp); var sundayDate= date.getFullYear()*10000+(date.getMonth()+1)*100+date.getDate(); var week=date.getDay(); return sundayDate; } ChartData.GetQuarter=function(value) { var month=parseInt(value%10000/100); if (month==1 || month==2 || month==3) return 1; else if (month==4 || month==5 || month==6) return 2; else if (month==7 || month==8 || month==9) return 3; else if (month==10 || month==11 || month==12) return 4; else return 0; } ChartData.GetHalfYear=function(value) { var year=parseInt(value/10000); var day=value%10000; if (day<=630) return year*10000+630; return year*10000+1231; } //是否是日线周期 0=日线 1=周线 2=月线 3=年线 9=季线 21=双周 22=半年 [40001-50000) 自定义日线 (isIncludeBase 是否包含基础日线周期) var CUSTOM_DAY_PERIOD_START=40000, CUSTOM_DAY_PERIOD_END=49999; ChartData.IsDayPeriod=function(period, isIncludeBase) { if (period==1 || period==2 || period==3 || period==9 || period==21 || period==22) return true; if (period>CUSTOM_DAY_PERIOD_START && period<=CUSTOM_DAY_PERIOD_END) return true; if (period==0 && isIncludeBase==true) return true; return false; } //是否是分钟周期 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 11=120分钟 12=240分钟 [20001-30000) 自定义分钟 (isIncludeBase 是否包含基础1分钟周期) var CUSTOM_MINUTE_PERIOD_START=20000, CUSTOM_MINUTE_PERIOD_END=29999; ChartData.IsMinutePeriod=function(period,isIncludeBase) { if (period==5 || period==6 || period==7 || period==8 ||period==11 || period==12) return true; if (period>CUSTOM_MINUTE_PERIOD_START && period<=CUSTOM_MINUTE_PERIOD_END) return true; if (period==4 && isIncludeBase==true) return true; return false; } //是否是秒周期 [30001-32000) var CUSTOM_SECOND_PERIOD_START=30000, CUSTOM_SECOND_PERIOD_END=32000; ChartData.IsSecondPeriod=function(period) { if (period>CUSTOM_SECOND_PERIOD_START && period<=CUSTOM_SECOND_PERIOD_END) return true; return false; } var CUSTOM_MILLISECOND_PERIOD_START=50000, CUSTOM_MILLISECOND_PERIOD_END=60000; ChartData.IsMilliSecondPeriod=function(period) { if (period>CUSTOM_MILLISECOND_PERIOD_START && period<=CUSTOM_MILLISECOND_PERIOD_END) return true; return false; } //是否是分笔图 10=分笔 ChartData.IsTickPeriod=function(period) { return period==10; } //获取周期名字 ChartData.GetPeriodName=function(period) { var mapName=new Map( [ [0, '日线'],[1, '周线'],[2, '月线'],[3, '年线'],[9, '季线'], [21,'双周'],[22,"半年"], [4, '1分'], [5, '5分'], [6, '15分'],[7, '30分'],[8, '60分'],[11, '2小时'],[12, '4小时'], [10, '分笔'] ]); if (mapName.has(period)) return mapName.get(period); return ''; } function TooltipData() //提示信息 { this.ChartPaint; this.Data; this.Type=0; } function Rect(x,y,width,height) { this.X=x, this.Y=y; this.Width=width; this.Height=height; } //图形外部挂接 function ChartPaintFactory() { //[key:name, { Create:function(option) { return new class(); }} ] this.DataMap=new Map( [ ["ChartKLine", { Create:function(option) { return new ChartKLine(); } }], //K线图 ["ChartMinuteVolumBar",{ Create:function(option) { return new ChartMinuteVolumBar(); } }], //分时成交量柱子 ["ChartMinutePriceLine",{ Create:function(option) { return new ChartMinutePriceLine();} }] ]); this.Create=function(name, option) { if (!this.DataMap.has(name)) { JSConsole.Warn(`[ChartPaintFactory::Create] can't find class=${name}.`); return null; } var item=this.DataMap.get(name); return item.Create(option); } this.Add=function(name, option) { this.DataMap.set(name, { Create:option.Create } ); } } var g_ChartPaintFactory=new ChartPaintFactory(); //图新画法接口类 function IChartPainting() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='IChartPainting'; //类名 this.Data=new ChartData(); //数据区 this.Script; //图形对应的指标脚本 (只有指标图形才有) this.NotSupportMessage=null; this.MessageFont=g_JSChartResource.Index.NotSupport.Font; this.MessageColor=g_JSChartResource.Index.NotSupport.TextColor; this.IsDrawFirst=false; this.IsShow=true; this.IsVisible=true; //是否显示 (预留给外部单独设置线段显隐) this.GetEventCallback; this.SelectedLineWidth=g_JSChartResource.SelectedChart.LineWidth; this.SelectedLineColor=g_JSChartResource.SelectedChart.LineColor; this.SelectedRadius=g_JSChartResource.SelectedChart.Radius; this.SelectedPointMinSpace=g_JSChartResource.SelectedChart.MinSpace; //点和点间最小间距 this.SelectedBGColor=g_JSChartResource.SelectedChart.BGColor; this.DrawSelectedStatus; //function() { } //选中状态 this.PtInChart; //function(x,y) { } this.IsFullRangeMaxMin=false; //this.GetMaxMin() true=计算全部的最大最小值 false=计算可视范围的最大最小值 this.IsExcludeYValue=false; //不参与Y轴计算 this.Draw=function() { } //数据导出 数据格式 [{ Title:数据名称, Data:[] }] //this.ExportData=function(aryKData) { } this.GetBorder=function() { if (this.ChartFrame.IsHScreen) return this.ChartBorder.GetHScreenBorder(); return this.ChartBorder.GetBorder(); } this.ClipClient=function(isHScreen) //裁剪客户端 { if (isHScreen==true) { var left=this.ChartBorder.GetLeftEx(); var right=this.ChartBorder.GetRightEx(); var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); } else { var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); } this.Canvas.beginPath(); this.Canvas.rect(left,top,(right-left),(bottom-top)); //this.Canvas.stroke(); //调试用 this.Canvas.clip(); } this.GetYFromData=function(value,isLimit) { return this.ChartFrame.GetYFromData(value,isLimit); } this.IsMinuteFrame=function() { var isMinute=(this.ChartFrame.ClassName=="MinuteFrame" || this.ChartFrame.ClassName=="MinuteHScreenFrame" || this.ChartFrame.ClassName=="OverlayMinuteFrame" || this.ChartFrame.ClassName=="OverlayMinuteHScreenFrame" ); return isMinute } this.DrawNotSupportmessage=function() { this.Canvas.font=this.MessageFont; this.Canvas.fillStyle=this.MessageColor; var left=this.ChartBorder.GetLeft(); var width=this.ChartBorder.GetWidth(); var top=this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx(); var x=left+width/2; var y=top+height/2; this.Canvas.textAlign="center"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(this.NotSupportMessage,x,y); } this.GetTooltipData=function(x,y,tooltip) { return false; } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; if (this.ChartFrame.GlobalOption && this.ChartFrame.GlobalOption.IsValueFullRange) { start=0; xPointCount=this.Data.Data.length; } var range={}; range.Min=null; range.Max=null; if(!this.Data || !this.Data.Data) return range; for(var i=start,j=0;ivalue) range.Min=value; } return range; } this.GetDynamicFont=function(dataWidth, distanceWidth, maxSize, minSize, zoom, fontname) //根据宽度自动获取对应字体 { var pixelTatio = GetDevicePixelRatio(); maxSize*=pixelTatio; minSize*=pixelTatio; if (maxSize==minSize) //固定大小 { var font=`${maxSize.toFixed(0)}px ${fontname}` ; return font; } var fontSize=(dataWidth+distanceWidth); if (zoom) { if (zoom.Type==0) { if (zoom.Value>0) fontSize=(dataWidth*zoom.Value); } else if (zoom.Type==1) { if (zoom.Value>0) fontSize=(dataWidth+distanceWidth)*zoom.Value; } else if (zoom.Type==2) { if (IFrameSplitOperator.IsNumber(zoom.Value)) fontSize=(dataWidth+distanceWidth) + (2*zoom.Value)*pixelTatio; } } if (fontSizemaxSize) fontSize=maxSize; var font=`${fontSize.toFixed(0)}px ${fontname}` ; /* if (dataWidth < 5) font =4*pixelTatio + 'px Arial'; //字体根据数据宽度动态调整 else if (dataWidth < 7) font = 6*pixelTatio +'px Arial'; else if (dataWidth < 9) font = 8*pixelTatio +'px Arial'; else if (dataWidth < 11) font =10*pixelTatio +'px Arial'; else if (dataWidth < 13) font =12*pixelTatio +'px Arial'; else if (dataWidth < 15) font =14*pixelTatio + 'px Arial'; else font =16*pixelTatio + 'px Arial'; */ return font; } this.GetLockRect=function() { return this.ChartFrame.GetLockRect(); } this.SetFillStyle=function(color, x0, y0, x1, y1) { if (Array.isArray(color)) { let gradient = this.Canvas.createLinearGradient(x0, y0, x1, y1); var offset=1/(color.length-1); for(var i=0; i0) iconSize=(dataWidth*zoom.Value); } else if (zoom.Type==1) { if (zoom.Value>0) iconSize=(dataWidth+distanceWidth)*zoom.Value; } else if (zoom.Type==2) { if (IFrameSplitOperator.IsNumber(zoom.Value)) iconSize=(dataWidth+distanceWidth) + (2*zoom.Value)*pixelTatio; } } if (iconSizemaxSize) iconSize=maxSize; return iconSize; } this.GetFontHeight=function(font) { return GetFontHeight(this.Canvas, font, "擎"); } //选中图形画点 this.DrawLinePoint=function(option) { var bHScreen=(this.ChartFrame.IsHScreen===true); if (bHScreen) return; if (!this.IsShow) return; var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } var pixelRatio=GetDevicePixelRatio(); this.Canvas.save(); this.ClipClient(bHScreen); this.Canvas.lineWidth=this.SelectedLineWidth*pixelRatio; this.Canvas.strokeStyle=this.SelectedLineColor; if (this.SelectedBGColor) this.Canvas.fillStyle=this.SelectedBGColor; var radius=this.SelectedRadius; var pointSpace=Math.ceil(this.SelectedPointMinSpace/(dataWidth+distanceWidth)); if (pointSpace<=0) pointSpace=1; if (isMinute) { var barWidth=(border.Right-border.Left)/xPointCount; pointSpace=Math.ceil(this.SelectedPointMinSpace/barWidth); } var valueType=0; var firstOpen=null, firstOverlayOpen=null; if (option) { if (option.KLineClose) valueType=1; //K线收盘价 else if (option.MinuteVolBar) { valueType=2; //分时图柱子 } else if (option.MinuteOverlayPrice) //叠加分时图价格 { if (option.OverlayType==1) valueType=1; else valueType=3; } else if (option.OverlayKLine) { valueType=4; //叠加K线 firstOpen=this.GetFirstOpen(); } else if (option.StackedBar) valueType=5; //叠加柱子 } for(var i=this.Data.DataOffset,j=0,k=0;i0) maxValue+=barValue; else if (barValue<0) minValue+=barValue; } value=(maxValue+minValue)/2; } else { value=this.Data.Data[i]; } if (value==null) continue; if (kchartright) break; var x=left+(right-left)/2; } var y=this.GetYFromData(value,false); if (x>chartright) break; this.Canvas.beginPath(); this.Canvas.arc(x,y,radius,0,360,false); this.Canvas.closePath(); if (this.SelectedBGColor) this.Canvas.fill(); this.Canvas.stroke(); } this.Canvas.restore(); } //点是否在线段上 this.PtInLine=function(x, y, option) { if (!this.IsShow || this.ChartFrame.IsMinSize) return; var bHScreen=(this.ChartFrame.IsHScreen===true); if (bHScreen) return; var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } if (xchartright) return null; if (y>border.BottomEx || ychartright) break; var xLine=left+(right-left)/2; } var yLine=this.GetYFromData(value,false); if (xLinechartright) break; } if (!IFrameSplitOperator.IsNumber(ptStart.X) || !IFrameSplitOperator.IsNumber(ptStart.Y)) return null; if (!IFrameSplitOperator.IsNumber(ptEnd.X) || !IFrameSplitOperator.IsNumber(ptEnd.Y)) return null; if (x==ptStart.X && y==ptStart.Y) return { Identify:this.Identify, Chart:this }; if (x==ptEnd.X && y==ptEnd.Y) return { Identify:this.Identify, Chart:this }; var lineWidth=5; this.Canvas.beginPath(); if (ptStart.X==ptEnd.X) //竖线 { this.Canvas.moveTo(ptStart.X-lineWidth,ptStart.Y); this.Canvas.lineTo(ptStart.X+lineWidth,ptStart.Y); this.Canvas.lineTo(ptEnd.X+lineWidth,ptEnd.Y); this.Canvas.lineTo(ptEnd.X-lineWidth,ptEnd.Y); } else { this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth); this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth); } this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) return { Identify:this.Identify, Chart:this }; return null; } //option={ BarWidth:柱子宽度(空为K线宽度) } this.PtInBar=function(x, y, option) { if (!this.IsShow || this.ChartFrame.IsMinSize) return null; var bHScreen=(this.ChartFrame.IsHScreen===true); if (bHScreen) return null; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; var lockRect=this.GetLockRect(); if (lockRect) chartright=lockRect.Left; if (xchartright) return null; if (y>border.BottomEx || y0) barWidth=option.BarWidth; if (option.MinuteVolBar==true) { isMinuteVolBar=true; barWidth=4; } else if (option.StackedBar==true) { isStackedBar=true; } } for(var i=this.Data.DataOffset,j=0;ichartright) break; } if (isMinuteVolBar) { if (!IFrameSplitOperator.IsNumber(value.Vol)) continue; var yBar=this.ChartFrame.GetYFromData(value.Vol); var barTop=yBar, barBottom=yBottom; } else if (isStackedBar) { var maxValue=0, minValue=0; if (!IFrameSplitOperator.IsNonEmptyArray(value)) continue; for(var k=0;k0) maxValue+=barValue; else if (barValue<0) minValue+=barValue; } var barTop=this.ChartFrame.GetYFromData(maxValue); var barBottom=this.ChartFrame.GetYFromData(minValue); } else { var yBar=this.ChartFrame.GetYFromData(value); var barTop=yBar, barBottom=yBottom; } if (barTop>barBottom) { barTop=yBottom; barBottom=yBar; } var barLeft=left, barRight=right; if (barWidth>0) { barLeft=left+(right-left)/2-barWidth/2; barRight=barLeft+barWidth; } if (x>=barLeft && x<=barRight && y>=barTop && y<=barBottom) return { Identify:this.Identify, Chart:this }; if (right>x) break; } return null; } this.PtInKBar=function(x,y,option) { if (!this.IsShow || this.ChartFrame.IsMinSize) return null; var isHScreen=(this.ChartFrame.IsHScreen===true); if (isHScreen) return null; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; } if (xchartright) return null; if (y>border.BottomEx || ychartright) break; if (x>=left && x<=right) { if (kBarType==1) { var yLow=this.GetYFromData(data.Low/firstOverlayOpen*firstOpen,false); var yHigh=this.GetYFromData(data.High/firstOverlayOpen*firstOpen,false); } else { var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); } if (y<=yLow && y>=yHigh) return { Identify:this.Identify, Chart:this }; } if (right>x) break; } } this.IsShowIndexTitleOnly=function() { if (this.ChartFrame && this.ChartFrame.ChartBorder && this.ChartFrame.ChartBorder.IsShowTitleOnly) return true; return false; } //是否隐藏指标 this.IsHideScriptIndex=function() { if (this.Script && this.Script.IsShow==false) return true; return false; } //导出单数组数据 this.ExportArrayData=function(aryKData, option) { var data=this.Data.ExportArrayData(aryKData, option); return [ { Name:this.Name, Data:data }]; } this.ExportBoolData=function(aryKData, option) { var data=this.Data.ExportBoolData(aryKData, option); return [ { Name:this.Name, Data:data }]; } //获取单数组的数据某一个数据 indexData={ Index:数据索引 } this.GetArrayItemData=function(indexData) { if (!indexData) return null; if (!IFrameSplitOperator.IsNumber(indexData.Index)) return null; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null; var index=indexData.Index; if (index<0 || index>=this.Data.Data.length) return null; var item=this.Data.Data[index]; return [ { Value:item, Color:this.Color, Name: this.Name } ]; } } //缩放因子 /* var ZOOM_SEED= [ [49,10], [46,9], [43,8], [41,7.5], [39,7], [37,6], [31,5.5], [27,5], [23,4.5], [21,4], [18,3.5], [16,3], [13,2.5], [11,2], [8,1.5], [6,1], [3,0.6], [2.2,0.5], //太多了卡, //[1.1,0.3], //[0.9,0.2], [0.7,0.15], //[0.6,0.12], [0.5,0.1], [0.4,0.08], //[0.3,0.06], [0.2,0.04], [0.1,0.02] ]; */ var ZOOM_SEED= //0=柱子宽度 1=间距 [ [48,10], [44,10], [40,9], [36,9], [32,8], [28,8], [24,7], [20,7], [18,6], [16,6], [15,5], [13,5], [9,4], [7,4], [5,4], [3,3], [3,1], [2,1], [1,1], [1,0], //[0.5,0],[0.4,0],[0.3,0],[0.2,0],[0.1,0] ]; //K线画法 支持横屏 function ChartKLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartKLine'; //类名 this.Symbol; //股票代码 this.DrawType=0; // 0=实心K线柱子 1=收盘价线 2=美国线 3=空心K线柱子 4=收盘价面积图 5=订单流 6=空心K线柱子2(全部空心) 7=订单流样式2 8=订单流样式3 // 9=自定义颜色K线 // 10=renko // 11=Heikin Ashi // 12=line break // 13=high low // 14=外部自定义图 // 15=HLC Area // 16=kagi // 17=订单流样式4 // 18=订单流样式5 this.CloseLineColor=g_JSChartResource.CloseLineColor; this.CloseLineAreaColor=g_JSChartResource.CloseLineAreaColor; this.CloseLineWidth=g_JSChartResource.CloseLineWidth; this.UpColor=g_JSChartResource.UpBarColor; this.DownColor=g_JSChartResource.DownBarColor; this.UnchagneColor=g_JSChartResource.UnchagneBarColor; //平盘 this.ColorData; //五彩K线颜色 >0:g_JSChartResource.UpBarColor 其他:g_JSChartResource.DownBarColor this.TradeData; //交易系统 包含买卖数据{Buy:, Sell:, Name:指标名称 } this.TradeIcon=g_JSChartResource.KLine.TradeIcon; this.TooltipRect=[]; //2位数组 0 数据序号 1 区域 this.InfoTooltipRect=[]; //2维数组 0 数据, 1 区域 this.TradeIconTooltipRect=[]; //2维数组 0 数据, 1 区域 this.IsShowMaxMinPrice=true; //是否显示最大最小值 this.IsShowKTooltip=true; //是否显示K线tooltip this.TextFont=g_JSChartResource.KLine.MaxMin.Font; this.TextColor=g_JSChartResource.KLine.MaxMin.Color; this.InfoData; //信息地雷 key=日期 value=信息数据 this.InfoPosition=0; // 0=K线上 1 底部 this.PtMax; //最大值的位置 this.PtMin; //最小值的位置 this.TickSymbol='╳'; //分笔显示的图标 this.TickFontName='arial'; this.Period; //周期 this.ShowRange={ }; //K线显示范围 { Start:, End:, DataCount:, ShowCount: } this.CustomKLine; //自定义K线, key=date*1000000+time, key={ Color:, DrawType: } this.DrawKRange={ Start:null, End:null }; //当前屏K线的索引{ Start: , End:} this.IsThinAKBar=true; //美国线 柱子是否是线段 (false=柱子) this.OneLimitBarType=0; //一字板颜色类型 4个价格全部都在同一个价位上 0=使用平盘颜色 1=跟昨收比较 this.HighLowBarColor=g_JSChartResource.HighLowBarColor; this.HighLowTextConfig= { FontName:g_JSChartResource.HighLowText.FontName, MaxSize:g_JSChartResource.HighLowText.MaxSize, MinSize:g_JSChartResource.HighLowText.MinSize, Color:g_JSChartResource.HighLowText.Color, //未用 MaxText:g_JSChartResource.HighLowText.MaxText }; this.HLCAreaConfig= { HighLineColor:g_JSChartResource.HLCArea.HighLineColor, LowLineColor:g_JSChartResource.HLCArea.LowLineColor, CloseLineColor:g_JSChartResource.HLCArea.CloseLineColor, LineWidth:g_JSChartResource.HLCArea.LineWidth, UpAreaColor:g_JSChartResource.HLCArea.UpAreaColor, DownAreaColor:g_JSChartResource.HLCArea.DownAreaColor, } //虚线柱子 this.VirtualBarConfig={ Color:g_JSChartResource.VirtualKLine.Color, LineDash:g_JSChartResource.VirtualKLine.LineDash }; //DrawType==14 自定义图形 this.FFKChart; /* this.CustomKLine=new Map([ [20210415*1000000, { Color:'rgb(255,0,255)', DrawType:3, BGColor:"rgba(135,206,250,0.5)" }], [20210412*1000000, { DrawType:3 }], [20210108*1000000, { DrawType:3,BGColor:"rgba(135,206,250,0.5)" }], [20210122*1000000, {Color:'rgb(122,135,155)'}] ]); */ //订单流配置 this.OrderFlow= { UpColor:{BG:g_JSChartResource.OrderFlow.UpColor.BG, Border:g_JSChartResource.OrderFlow.UpColor.Border }, DownColor:{ BG:g_JSChartResource.OrderFlow.DownColor.BG, Border:g_JSChartResource.OrderFlow.DownColor.Border }, UnchagneColor: { BG:g_JSChartResource.OrderFlow.UnchagneColor.BG, Border:g_JSChartResource.OrderFlow.UnchagneColor.Border }, Text:{ Color: g_JSChartResource.OrderFlow.Text.Color , Family:g_JSChartResource.OrderFlow.Text.Family, FontMaxSize:g_JSChartResource.OrderFlow.Text.FontMaxSize, MaxValue:g_JSChartResource.OrderFlow.Text.MaxValue }, Line:{ UpDownColor: g_JSChartResource.OrderFlow.Line.UpDownColor, MiddleColor:g_JSChartResource.OrderFlow.Line.MiddleColor }, POCGBColor:g_JSChartResource.OrderFlow.POCGBColor, ShowType:0, //显示类型 0, 1 AskBarColor:g_JSChartResource.OrderFlow.AskBarColor, BidBarColor:g_JSChartResource.OrderFlow.BidBarColor, AlwaysShowOrderText:g_JSChartResource.OrderFlow.AlwaysShowOrderText, IsShowAskText:true, IsShowAskBar:false, //是否显示横向柱子 IsShowBidText:true, IsShowBidBar:false, //是否显示横向柱子 IsShowPOCBG:true, } this.OrderFlow_Style2= { BarWidth:g_JSChartResource.OrderFlow_Style2.BarWidth, //柱子颜色 UpColor:g_JSChartResource.OrderFlow_Style2.UpColor, DownColor:g_JSChartResource.OrderFlow_Style2.DownColor, UnchagneColor:g_JSChartResource.OrderFlow_Style2.UnchagneColor, } this.OrderFlow_Style3= { BarWidth:g_JSChartResource.OrderFlow_Style3.BarWidth, //柱子颜色 UpColor:g_JSChartResource.OrderFlow_Style3.UpColor, DownColor:g_JSChartResource.OrderFlow_Style3.DownColor, UnchagneColor:g_JSChartResource.OrderFlow_Style3.UnchagneColor, } this.OrderFlow_Style4= { //柱子颜色 UpColor:g_JSChartResource.OrderFlow_Style4.UpColor, DownColor:g_JSChartResource.OrderFlow_Style4.DownColor, UnchagneColor:g_JSChartResource.OrderFlow_Style4.UnchagneColor, KBarType:1, //0=不显示K线柱子 1=左侧显示K线 VolBarSpace:g_JSChartResource.OrderFlow_Style4.VolBarSpace, //间距 KBarWidth:g_JSChartResource.OrderFlow_Style4.KBarWidth, LeftMargin:g_JSChartResource.OrderFlow_Style4.LeftMargin, RightMargin:g_JSChartResource.OrderFlow_Style4.RightMargin, } this.OrderFlow_Style5= { AskBarColor:g_JSChartResource.OrderFlow_Style5.AskBarColor, //左 BidBarColor:g_JSChartResource.OrderFlow_Style5.BidBarColor, //右 LeftMargin:g_JSChartResource.OrderFlow_Style5.LeftMargin, RightMargin:g_JSChartResource.OrderFlow_Style5.RightMargin, } this.IsShowOrderText=false; this.AryOrderFlowBorder=[]; //订单流边框 临时变量 this.ChartHeatMap; //=new ChartHeatMap(); //未回补的价格缺口 this.PriceGap={ Enable:false, Count:1 }; this.PriceGapStyple= { Line:{ Color:g_JSChartResource.PriceGapStyple.Line.Color }, Text:{ Color:g_JSChartResource.PriceGapStyple.Text.Color, Font: g_JSChartResource.PriceGapStyple.Text.Font } }; this.AryPriceGapCache=[]; //缺口数据 { } this.ReloadResource=function(resource) { this.TextFont=g_JSChartResource.KLine.MaxMin.Font; this.TextColor=g_JSChartResource.KLine.MaxMin.Color; this.CloseLineColor=g_JSChartResource.CloseLineColor; this.CloseLineAreaColor=g_JSChartResource.CloseLineAreaColor; this.CloseLineWidth=g_JSChartResource.CloseLineWidth; this.UpColor=g_JSChartResource.UpBarColor; this.DownColor=g_JSChartResource.DownBarColor; this.UnchagneColor=g_JSChartResource.UnchagneBarColor; //平盘 this.HighLowBarColor=g_JSChartResource.HighLowBarColor; this.OrderFlow.UpColor={BG:g_JSChartResource.OrderFlow.UpColor.BG, Border:g_JSChartResource.OrderFlow.UpColor.Border }; this.OrderFlow.DownColor={ BG:g_JSChartResource.OrderFlow.DownColor.BG, Border:g_JSChartResource.OrderFlow.DownColor.Border }; this.OrderFlow.UnchagneColor= { BG:g_JSChartResource.OrderFlow.UnchagneColor.BG, Border:g_JSChartResource.OrderFlow.UnchagneColor.Border }; this.OrderFlow.Text={ Color: g_JSChartResource.OrderFlow.Text.Color , Family:g_JSChartResource.OrderFlow.Text.Family, FontMaxSize:g_JSChartResource.OrderFlow.Text.FontMaxSize, MaxValue:g_JSChartResource.OrderFlow.Text.MaxValue }; this.OrderFlow.Line={ UpDownColor: g_JSChartResource.OrderFlow.Line.UpDownColor, MiddleColor:g_JSChartResource.OrderFlow.Line.MiddleColor }; } this.ClearCustomKLine=function() { this.CustomKLine=null; } this.GetCustomKLine=function(kItem) { if (!this.CustomKLine) return null; if (!kItem) return null; var key=kItem.Date*1000000; if (IFrameSplitOperator.IsNumber(kItem.Time)) key+=kItem.Time; if (!this.CustomKLine.has(key)) return null; var value=this.CustomKLine.get(key); return value; } this.DrawHeatMap=function() { if (!this.ChartHeatMap) return; this.ChartHeatMap.Canvas=this.Canvas; this.ChartHeatMap.ChartBorder=this.ChartBorder; this.ChartHeatMap.ChartFrame=this.ChartFrame; this.ChartHeatMap.Data=this.Data; this.ChartHeatMap.Draw(); } this.ClearHeatMap=function() { this.ChartHeatMap=null; } this.CreateHeatMap=function() { this.ChartHeatMap=new ChartHeatMap(); } this.DrawAKLine=function() //美国线 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var upColor=this.UpColor; var downColor=this.DownColor; var unchagneColor=this.UnchagneColor; var ptMax={X:null,Y:null,Value:null,Align:'left'}; var ptMin={X:null,Y:null,Value:null,Align:'left'}; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) { eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR); } var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); var yOpen=this.GetYFromData(data.Open,false); var yClose=this.GetYFromData(data.Close,false); this.DrawKRange.End=i; var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; if (ptMax.Value==null || ptMax.Valuedata.Low) //求最小值 { ptMin.X=x; ptMin.Y=yLow; ptMin.Value=data.Low; ptMin.Align=jdata.Close) { this.Canvas.strokeStyle=this.DownColor; //阳线 } else { if (eventUnchangeKLine && eventUnchangeKLine.Callback) { var sendData={ KItem:data, DataIndex:i, DefaultColor:unchagneColor, BarColor:null }; eventUnchangeKLine.Callback(eventUnchangeKLine, sendData, this); if (sendData.BarColor) unchagneColor=sendData.BarColor; } this.Canvas.strokeStyle=unchagneColor; //平线 } if (this.ColorData) ///五彩K线颜色设置 { if (i0?this.UpColor:this.DownColor); else upColor=downColor=unchagneColor=this.DownColor; } if (this.IsThinAKBar==false && dataWidth>=9) { var coordinateInfo={YLow:yLow, YHigh:yHigh, YOpen:yOpen, YClose:yClose, X:x, Left:left, Right:right }; var colorInfo={ UpColor:upColor, DownColor:downColor, UnchangeColor:unchagneColor }; this.DrawAKBar(data, dataWidth, isHScreen, coordinateInfo, colorInfo); } else { this.Canvas.beginPath(); //最高-最低 if (isHScreen) { if (data.High==data.Low && dataWidth<4) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow-1,ToFixedPoint(x)); } else { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } } else { if (data.High==data.Low && dataWidth<4) { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow+1); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } } this.Canvas.stroke(); if (dataWidth>=4) { this.Canvas.beginPath(); //开盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen),left); this.Canvas.lineTo(ToFixedPoint(yOpen),x); } else { this.Canvas.moveTo(left,ToFixedPoint(yOpen)); this.Canvas.lineTo(x,ToFixedPoint(yOpen)); } this.Canvas.stroke(); this.Canvas.beginPath(); //收盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yClose),right); this.Canvas.lineTo(ToFixedPoint(yClose),x); } else { this.Canvas.moveTo(right,ToFixedPoint(yClose)); this.Canvas.lineTo(x,ToFixedPoint(yClose)); } this.Canvas.stroke(); } } if(this.Data.DataType==0) { var infoItem={Xleft:left,XRight:right, YMax:yHigh, XCenter:x, YMin:yLow, DayData:data, Index:j}; this.DrawInfo(infoItem); } if (this.PriceGap.Enable && preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } this.PtMax=ptMax; this.PtMin=ptMin; } this.DrawAKBar=function(data, dataWidth, isHScreen, coordinateInfo, colorInfo) { var barWidth=dataWidth/3; var left=ToFixedRect(coordinateInfo.Left); var aryX=[left, ToFixedRect(left+barWidth), ToFixedRect(left+barWidth*2), ToFixedRect(left+barWidth*3)]; var yHigh=coordinateInfo.YHigh, yLow=coordinateInfo.YLow, yOpen=coordinateInfo.YOpen, yClose=coordinateInfo.YClose; if (data.Opendata.Close) { this.Canvas.strokeStyle=colorInfo.DownColor; //阳线 this.Canvas.fillStyle=colorInfo.DownColor; } else { this.Canvas.strokeStyle=colorInfo.UnchangeColor; //平线 this.Canvas.fillStyle=colorInfo.UnchangeColor; } //最高-最低 if (isHScreen) { if (data.High==data.Low) { var yTop=yHigh-barWidth/2; this.Canvas.fillRect(yTop,aryX[1],barWidth,aryX[2]-aryX[1]); } else { this.Canvas.fillRect(yHigh,aryX[1],(yLow-yHigh),aryX[2]-aryX[1]); } } else { if (data.High==data.Low) { var yTop=yHigh-barWidth/2; this.Canvas.fillRect(aryX[1],yTop,aryX[2]-aryX[1],barWidth); } else { this.Canvas.fillRect(aryX[1],yHigh,aryX[2]-aryX[1],(yLow-yHigh)); } } //开盘 var yTop=yOpen-barWidth/2; if (isHScreen) { this.Canvas.fillRect(yTop,aryX[0],(barWidth),aryX[1]-aryX[0]); } else { this.Canvas.fillRect(aryX[0],yTop,aryX[1]-aryX[0],(barWidth)); } //收盘 var yTop=yClose-barWidth/2; if (isHScreen) { this.Canvas.fillRect(yTop,aryX[2],(barWidth),aryX[3]-aryX[2]); } else { this.Canvas.fillRect(aryX[2],yTop,aryX[3]-aryX[2],(barWidth)); } } this.DrawCloseArea=function() //收盘价面积图 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var borderLeft=border.TopEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var borderLeft=border.LeftEx; } var bFirstPoint=true; var firstPoint=null; this.Canvas.beginPath(); this.Canvas.strokeStyle=this.CloseLineColor; if (IFrameSplitOperator.IsNumber(this.CloseLineWidth)) this.Canvas.lineWidth=this.CloseLineWidth; var ptLast=null; if (this.Data.DataOffset>0) //把最左边的一个点连上 { var data=this.Data.Data[this.Data.DataOffset-1]; if (data && IFrameSplitOperator.IsNumber(data.Close)) { var x=borderLeft; var yClose=this.GetYFromData(data.Close,false); if (isHScreen) { this.Canvas.moveTo(yClose,x); firstPoint={ X:yClose, Y:x }; } else { this.Canvas.moveTo(x,yClose); firstPoint={ X:x, Y:yClose }; } bFirstPoint=false; } } this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yClose=this.GetYFromData(data.Close,false); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) { this.Canvas.moveTo(yClose,x); firstPoint={ X:yClose, Y:x }; } else { this.Canvas.moveTo(x,yClose); firstPoint={ X:x, Y:yClose }; } bFirstPoint=false; } else { if (isHScreen) this.Canvas.lineTo(yClose,x); else this.Canvas.lineTo(x,yClose); } if (i==this.Data.Data.length-1) { ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright }; } if (this.PriceGap.Enable ) { var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; if (preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } } this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点 if (bFirstPoint) return; this.Canvas.stroke(); if (isHScreen) { this.Canvas.lineTo(border.Left,x); this.Canvas.lineTo(border.Left,firstPoint.Y); } else { this.Canvas.lineTo(x,border.Bottom); this.Canvas.lineTo(firstPoint.X,border.Bottom); } this.Canvas.closePath(); if (Array.isArray(this.CloseLineAreaColor)) { if (isHScreen) { let gradient = this.Canvas.createLinearGradient(this.ChartBorder.GetRightEx(),this.ChartBorder.GetTop(), this.ChartBorder.GetLeft(),this.ChartBorder.GetTop()); gradient.addColorStop(0, this.CloseLineAreaColor[0]); gradient.addColorStop(1, this.CloseLineAreaColor[1]); this.Canvas.fillStyle=gradient; } else { let gradient = this.Canvas.createLinearGradient(firstPoint.X,this.ChartBorder.GetTopEx(), firstPoint.X,this.ChartBorder.GetBottom()); gradient.addColorStop(0, this.CloseLineAreaColor[0]); gradient.addColorStop(1, this.CloseLineAreaColor[1]); this.Canvas.fillStyle=gradient; } } else { this.Canvas.fillStyle=this.CloseLineAreaColor; } this.Canvas.fill(); } this.DrawCloseLine=function() //收盘价线 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var bFirstPoint=true; this.Canvas.beginPath(); this.Canvas.strokeStyle=this.CloseLineColor; if (IFrameSplitOperator.IsNumber(this.CloseLineWidth)) this.Canvas.lineWidth=this.CloseLineWidth; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yClose=this.GetYFromData(data.Close,false); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) this.Canvas.moveTo(yClose,x); else this.Canvas.moveTo(x,yClose); bFirstPoint=false; } else { if (isHScreen) this.Canvas.lineTo(yClose,x); else this.Canvas.lineTo(x,yClose); } if (this.PriceGap.Enable ) { var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; if (preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } } if (bFirstPoint==false) this.Canvas.stroke(); } this.DrawKBar=function() //蜡烛头 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; } var ptMax={X:null,Y:null,Value:null,Align:'left'}; var ptMin={X:null,Y:null,Value:null,Align:'left'}; var upColor=this.UpColor; var downColor=this.DownColor; var unchagneColor=this.UnchagneColor; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; var ptLast=null; this.DrawKRange.Start=this.Data.DataOffset; var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) { eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR); } var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }}; this.DrawKRange.End=i; if (ptMax.Value==null || ptMax.Valuedata.Low) //求最小值 { ptMin.X=x; ptMin.Y=yLow; ptMin.Value=data.Low; ptMin.Align=j0?this.UpColor:this.DownColor); else upColor=downColor=unchagneColor=this.DownColor; } var kLineOption=this.GetCustomKLine(data); if (data.IsNonTrade) //非交易日 绘制虚线柱子 { this.DrawVirtualBar(data, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } else if (kLineOption) { var barColor=kLineOption.Color; if (!barColor) { if (data.Opendata.Close) barColor=downColor; else barColor=unchagneColor; } var drawType=this.DrawType; if (IFrameSplitOperator.IsNumber(kLineOption.DrawType)) drawType=kLineOption.DrawType; this.DrawKBar_Custom(data, dataWidth, barColor, drawType, kLineOption, x, y, left, right, yLow, yHigh, yOpen, yClose, border, isHScreen); } else if (this.DrawType==9 && data.ColorData) { this.DrawColorKBar(data, data.ColorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } else if (data.Opendata.Close) //阴线 { this.DrawKBar_Down(data, dataWidth, downColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } else // 平线 { var barColor=unchagneColor; if (eventUnchangeKLine && eventUnchangeKLine.Callback) { var sendData={ KItem:data, DataIndex:i, DefaultColor:barColor, BarColor:null }; eventUnchangeKLine.Callback(eventUnchangeKLine, sendData, this); if (sendData.BarColor) barColor=sendData.BarColor; } this.DrawKBar_Unchagne(data, dataWidth, barColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } if (this.IsShowKTooltip && !isHScreen) //添加tooltip区域 { var yTop=Math.min(yOpen,yClose); var yBottom=Math.max(yOpen,yClose); if (Math.abs(yOpen-yClose)<5) //高度太小了, 上下各+5px { yTop=Math.min(yHigh,yTop-5); yBottom=Math.max(yLow,yBottom+5); } if (data.IsNonTrade) { yTop=yHigh; yBottom=yLow; } var rect=new Rect(left,yTop,dataWidth,yBottom-yTop); //this.Canvas.fillStyle="rgb(0,0,100)"; //this.Canvas.fillRect(rect.X,rect.Y,rect.Width,rect.Height); this.TooltipRect.push([i,rect]); //[0]数据索引 [1]数据区域 } if(this.Data.DataType==0 || this.Data.DataType==1) { var infoItem={Xleft:left,XRight:right, XCenter:x, YMax:yHigh, YMin:yLow, DayData:data, Index:j}; this.DrawInfo(infoItem); } if (i==this.Data.Data.length-1) { ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright }; } if (this.PriceGap.Enable && preKItemInfo) { this.CheckPriceGap(kItemInfo); var value=this.IsPriceGap(kItemInfo,preKItemInfo); if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); } preKItemInfo=kItemInfo; } this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点 this.PtMax=ptMax; this.PtMin=ptMin; } this.DrawKBar_Up=function(data, dataWidth, upColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //阳线 { var isEmptyBar=(drawType==3 || drawType==6); if (dataWidth>=4) { if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } this.Canvas.strokeStyle=upColor; if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(drawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen))); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose)); } } this.Canvas.stroke(); y=yClose; } else { y=yClose; } this.Canvas.fillStyle=upColor; if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(drawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen))); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=upColor; this.Canvas.stroke(); } } this.DrawKBar_Down=function(data, dataWidth, downColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //阴线 { var isEmptyBar=(drawType==6); if (dataWidth>=4) { if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } this.Canvas.strokeStyle=downColor; if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen))); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yOpen)); } } this.Canvas.stroke(); y=yOpen; } else { y=yOpen } this.Canvas.fillStyle=downColor; if (isHScreen) { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yClose-y),ToFixedRect(dataWidth)); } else { if (Math.abs(yClose-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(Math.min(y,yClose)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yClose-y))); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yClose)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yClose-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen))); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=downColor; this.Canvas.stroke(); } } this.DrawKBar_Unchagne=function(data, dataWidth, unchagneColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //平线 { if (this.OneLimitBarType===1&& this.IsOneLimitBar(data)) //一字板 { unchagneColor=this.GetOneLimitBarColor(data); } if (dataWidth>=4) { if ((dataWidth%2)!=0) dataWidth-=1; this.Canvas.strokeStyle=unchagneColor; this.Canvas.beginPath(); if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yOpen,ToFixedPoint(x)); } else { var xFixed=ToFixedPoint(left+dataWidth/2); this.Canvas.moveTo(xFixed,y); this.Canvas.lineTo(xFixed,yOpen); } y=yOpen; } else { y=yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(left+dataWidth),ToFixedPoint(y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=ToFixedPoint(left+dataWidth/2); this.Canvas.moveTo(xFixed,ToFixedPoint(y)); this.Canvas.lineTo(xFixed,ToFixedPoint(yLow)); } } this.Canvas.stroke(); } else { this.Canvas.beginPath(); if (isHScreen) { if (data.High==data.Low) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow-1,ToFixedPoint(x)); } else { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } } else { if (data.High==data.Low) { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow+1); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } } this.Canvas.strokeStyle=unchagneColor; this.Canvas.stroke(); } } //是否是一字板 this.IsOneLimitBar=function(kItem) { if (kItem.Open==kItem.Close && kItem.High==kItem.Low && kItem.Open==kItem.High) return true; return false; } //一字板颜色 和昨收比较 this.GetOneLimitBarColor=function(kItem) { if (!kItem || !IFrameSplitOperator.IsNumber(kItem.YClose)) return this.UnchagneColor; if (kItem.Close>kItem.YClose) return this.UpColor; else if (kItem.Close=4) { this.Canvas.strokeStyle=barColor; if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(drawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(drawType==3?Math.min(yClose,yOpen):yClose)); } this.Canvas.stroke(); y=yClose; } else { y=yClose; } this.Canvas.fillStyle=barColor; if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (drawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (drawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(drawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(drawType==3?Math.max(yClose,yOpen):y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=barColor; this.Canvas.stroke(); } } //绘制自定义K线 this.DrawColorKBar=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (Math.abs(yClose-yOpen)<1) this.DrawColorKBar_Line(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); else if (colorData.Border || colorData.Type===0) this.DrawColorKBar_Border(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); else this.DrawColorKBar_NoBorder(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } //带边框柱子 this.DrawColorKBar_Border=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=4) { if ((dataWidth%2)!=0) dataWidth-=1; var topPrice=Math.max(data.Close,data.Open); var bottomPrice=Math.min(data.Close,data.Open); if (isHScreen) { var yBarTop=Math.max(yClose,yOpen); var yBarBottom=Math.min(yClose,yOpen); } else { var yBarTop=Math.min(yClose,yOpen); var yBarBottom=Math.max(yClose,yOpen); } var yBarHeight=Math.abs(yClose-yOpen); //上影线 if (data.High>topPrice && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yBarTop),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yBarTop)); } this.Canvas.stroke(); } //下影线 if (bottomPrice>data.Low && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yBarBottom),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yBarBottom)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } this.Canvas.stroke(); } //中心柱子 if (isHScreen) { var pathBar=new Path2D(); pathBar.rect(ToFixedPoint(yBarBottom),ToFixedPoint(left),ToFixedRect(yBarHeight),ToFixedRect(dataWidth)); } else { var pathBar=new Path2D(); pathBar.rect(ToFixedPoint(left),ToFixedPoint(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarHeight)); } if (colorData.Type==0) //空心柱子 { if (colorData.BarColor) //边框 { this.Canvas.strokeStyle=colorData.BarColor; this.Canvas.stroke(pathBar); } if (colorData.Border) { this.Canvas.strokeStyle=colorData.Border.Color; this.Canvas.stroke(pathBar); } } else if (colorData.Type==1) //实心 { if (colorData.BarColor) //内部填充 { this.Canvas.fillStyle=colorData.BarColor; this.Canvas.fill(pathBar); } if (colorData.Border) //边框 { this.Canvas.strokeStyle=colorData.Border.Color; this.Canvas.stroke(pathBar); } } } else { this.DrawColorKBar_MinBar(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } } //不带边框柱子 this.DrawColorKBar_NoBorder=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=4) { var topPrice=Math.max(data.Close,data.Open); var bottomPrice=Math.min(data.Close,data.Open); if (isHScreen) { var yBarTop=Math.max(yClose,yOpen); var yBarBottom=Math.min(yClose,yOpen); } else { var yBarTop=Math.min(yClose,yOpen); var yBarBottom=Math.max(yClose,yOpen); } var yBarHeight=Math.abs(yClose-yOpen); //上影线 if (data.High>topPrice && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yBarTop),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yBarTop)); } this.Canvas.stroke(); } //下影线 if (bottomPrice>data.Low && colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yBarBottom),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yBarBottom)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } this.Canvas.stroke(); } //中心柱子 if (isHScreen) { var pathBar=new Path2D(); pathBar.rect(ToFixedRect(yBarBottom),ToFixedRect(left),ToFixedRect(yBarHeight),ToFixedRect(dataWidth)); } else { var pathBar=new Path2D(); pathBar.rect(ToFixedRect(left),ToFixedRect(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarHeight)); } if (colorData.Type==1) //实心 { if (colorData.BarColor) //内部填充 { this.Canvas.fillStyle=colorData.BarColor; this.Canvas.fill(pathBar); } } } else { this.DrawColorKBar_MinBar(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } } this.DrawColorKBar_MinBar=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } /* var barColor; if (colorData.Type==0) //空心柱子 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } else if (colorData.Type==1) //实心 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } if (barColor) { this.Canvas.strokeStyle=barColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yOpen)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose)); } this.Canvas.stroke(); } */ } //十字线 this.DrawColorKBar_Line=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=4) { if (colorData.Line) { this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } var barColor; if (colorData.Type==0) //空心柱子 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } else if (colorData.Type==1) //实心 { if (colorData.Border) barColor=colorData.Border.Color; else if (colorData.BarColor) barColor=colorData.BarColor; } if (barColor) { this.Canvas.strokeStyle=barColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(yOpen)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(yOpen)); } this.Canvas.stroke(); } } else { if (colorData.Line) { var xFixed=left+dataWidth/2; this.Canvas.strokeStyle=colorData.Line.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } } this.DrawVirtualBar=function(data, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { var yTop=Math.min(yHigh,yLow), yBottom=Math.max(yHigh,yLow); this.Canvas.strokeStyle=this.VirtualBarConfig.Color; this.Canvas.setLineDash(this.VirtualBarConfig.LineDash); if (isHScreen) { if (dataWidth>=4) { this.Canvas.strokeRect(ToFixedPoint(yTop),ToFixedPoint(left),ToFixedRect(yBottom-yTop),ToFixedRect(dataWidth)); } else { this.Canvas.beginPath(); this.Canvas.moveTo(yTop,ToFixedPoint(x)); this.Canvas.lineTo(yBottom,ToFixedPoint(x)); this.Canvas.stroke(); } } else { if (dataWidth>=4) { //this.Canvas.beginPath(); this.Canvas.strokeRect(ToFixedPoint(left),ToFixedPoint(yTop),ToFixedRect(dataWidth),ToFixedRect(yBottom-yTop)); //this.Canvas.stroke(); } else { this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(x),yTop); this.Canvas.lineTo(ToFixedPoint(x),yBottom); this.Canvas.stroke(); } } this.Canvas.setLineDash([]); } this.DrawRenkoCandle=function() //砖型K线 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var ptMax={X:null,Y:null,Value:null,Align:'left'}; var ptMin={X:null,Y:null,Value:null,Align:'left'}; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); this.DrawKRange.End=i; if (ptMax.Value==null || ptMax.Valuedata.Low) //求最小值 { ptMin.X=x; ptMin.Y=yLow; ptMin.Value=data.Low; ptMin.Align=jdata.Close) { this.Canvas.strokeStyle=this.DownColor; //阴线 this.Canvas.fillStyle=this.DownColor; } if (dataWidth>=4) { if (isHScreen) { this.Canvas.fillRect(ToFixedRect(yLow),ToFixedRect(left),ToFixedRect(Math.abs(yLow-yHigh)),ToFixedRect(dataWidth)); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(yHigh),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yLow-yHigh))); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.PtMax=ptMax; this.PtMin=ptMin; } this.DrawLineBreak=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var halfDistanceWidth=distanceWidth/2; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin-halfDistanceWidth; var chartright=border.BottomEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin-halfDistanceWidth; var chartright=border.RightEx; } var ptMax={X:null,Y:null,Value:null,Align:'left'}; var ptMin={X:null,Y:null,Value:null,Align:'left'}; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); this.DrawKRange.End=i; if (ptMax.Value==null || ptMax.Valuedata.Low) //求最小值 { ptMin.X=x; ptMin.Y=yLow; ptMin.Value=data.Low; ptMin.Align=jdata.Close) { this.Canvas.strokeStyle=this.DownColor; //阴线 this.Canvas.fillStyle=this.DownColor; } if (dataWidth>=4) { if (isHScreen) { this.Canvas.fillRect(ToFixedRect(yLow),ToFixedRect(left),ToFixedRect(Math.abs(yLow-yHigh)),ToFixedRect(dataWidth+distanceWidth)); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(yHigh),ToFixedRect(dataWidth+distanceWidth),ToFixedRect(Math.abs(yLow-yHigh))); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.PtMax=ptMax; this.PtMin=ptMin; } this.DrawKagi=function() //卡吉图 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var left=border.TopEx+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var left=border.Left+g_JSChartResource.FrameLeftMargin; } var ptMax={X:null,Y:null,Value:null,Align:'left'}; var ptMin={X:null,Y:null,Value:null,Align:'left'}; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; var lineWidth=2*GetDevicePixelRatio(); this.Canvas.lineWidth=lineWidth; var preItem={ Item:null, X:left, Y:null }; var index=this.Data.DataOffset-1; if (index>=0 && indexchartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); this.DrawKRange.End=i; if (ptMax.Value==null || ptMax.Valuedata.Low) //求最小值 { ptMin.X=x; ptMin.Y=yLow; ptMin.Value=data.Low; ptMin.Align=jprePrice) { this.Canvas.lineTo(xFixed, yLow); this.Canvas.strokeStyle=this.DownColor; //阳线 this.Canvas.stroke(); } else { var yPrePrice=this.GetYFromData(prePrice,false); this.Canvas.lineTo(xFixed, yPrePrice); this.Canvas.strokeStyle=this.DownColor; //阳线 this.Canvas.stroke(); this.Canvas.beginPath(); this.Canvas.moveTo(xFixed, yPrePrice); this.Canvas.lineTo(xFixed, yLow); this.Canvas.strokeStyle=this.UpColor; this.Canvas.stroke(); } } } else { this.Canvas.beginPath(); if (data.Direction==1) { this.Canvas.moveTo(xFixed, yLow); this.Canvas.lineTo(xFixed, yHigh); } else if (data.Direction==2) { this.Canvas.moveTo(xFixed, yHigh); this.Canvas.lineTo(xFixed, yLow); } this.Canvas.stroke(); } /* if (data.YClosedata.Close) { this.Canvas.strokeStyle=this.DownColor; //阴线 this.Canvas.fillStyle=this.DownColor; } this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint2(lineWidth,x),yHigh); this.Canvas.lineTo(ToFixedPoint2(lineWidth,x),yLow); } this.Canvas.stroke(); */ preItem.Item=data; preItem.X=x; if (data.Direction==1) preItem.Y=yHigh; //上 else if (data.Direction==2) preItem.Y=yLow //下 } this.PtMax=ptMax; this.PtMin=ptMin; } this.DrawTrade=function() //交易系统 { if (!this.TradeData) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; chartright=this.ChartBorder.GetBottom(); } var sellData=this.TradeData.Sell; var buyData=this.TradeData.Buy; var arrowWidth=dataWidth; if (arrowWidth>10) arrowWidth=10; for(var i=this.Data.DataOffset,j=0;i0; if (buyData && i0; if (!sell && !buy) continue; var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); var yOpen=this.GetYFromData(data.Open,false); var yClose=this.GetYFromData(data.Close,false); var y=yHigh; if (buy) { this.Canvas.fillStyle=this.UpColor; this.Canvas.strokeStyle=this.UnchagneColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yLow-1,x); this.Canvas.lineTo(yLow-arrowWidth-1,x-arrowWidth/2); this.Canvas.lineTo(yLow-arrowWidth-1,x+arrowWidth/2); } else { this.Canvas.moveTo(x,yLow+1); this.Canvas.lineTo(x-arrowWidth/2,yLow+arrowWidth+1); this.Canvas.lineTo(x+arrowWidth/2,yLow+arrowWidth+1); } this.Canvas.closePath(); this.Canvas.fill(); this.Canvas.stroke(); } if (sell) { this.Canvas.fillStyle=this.DownColor; this.Canvas.strokeStyle=this.UnchagneColor; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh+1,x); this.Canvas.lineTo(yHigh+arrowWidth+1,x-arrowWidth/2); this.Canvas.lineTo(yHigh+arrowWidth+1,x+arrowWidth/2); } else { this.Canvas.moveTo(x,yHigh-1); this.Canvas.lineTo(x-arrowWidth/2,yHigh-arrowWidth-1); this.Canvas.lineTo(x+arrowWidth/2,yHigh-arrowWidth-1); } this.Canvas.closePath(); this.Canvas.fill(); this.Canvas.stroke(); } } } this.DrawTick=function() //分笔图 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; if (isHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); if (isHScreen) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var fontSize=parseInt(dataWidth); if (fontSize<=1) fontSize=2; else if (fontSize>=18) fontSize=18; var bFirstPoint=true; var pixelRatio=GetDevicePixelRatio(); var textSize=fontSize*pixelRatio; this.Canvas.beginPath(); this.Canvas.font=fontSize*pixelRatio+'px '+this.TickFontName; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yClose=this.ChartFrame.GetYFromData(data.Close,false); this.DrawKRange.End=i; if (data.Flag===0) this.Canvas.fillStyle=this.UpColor; else if (data.Flag==1) this.Canvas.fillStyle=this.DownColor; else this.Canvas.fillStyle=this.UnchagneColor; this.Canvas.textAlign='center' this.Canvas.textBaseline='middle'; if (isHScreen) this.Canvas.fillText(this.TickSymbol,yClose,x); else this.Canvas.fillText(this.TickSymbol,x,yClose); if (this.IsShowKTooltip && !isHScreen) //添加tooltip区域 { var rect=new Rect(x-textSize/2,yClose-textSize/2,textSize,textSize); //this.Canvas.fillStyle="rgb(0,0,100)"; //this.Canvas.fillRect(rect.X,rect.Y,rect.Width,rect.Height); this.TooltipRect.push([i,rect]); //[0]数据索引 [1]数据区域 } } } this.DrawHLCArea=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var borderLeft=border.TopEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var borderLeft=border.LeftEx; } var lowPath=new Path2D(); var highPath=new Path2D(); var closePath=new Path2D(); var upArea=new Path2D(); var downArea=new Path2D(); var aryHighPoint=[]; var aryLowPoint=[]; var aryClosePoint=[]; var bFirstPoint=true; if (this.Data.DataOffset>0) //把最左边的一个点连上 { var data=this.Data.Data[this.Data.DataOffset-1]; if (data && IFrameSplitOperator.IsNumber(data.Close) && IFrameSplitOperator.IsNumber(data.High) && IFrameSplitOperator.IsNumber(data.Low)) { var x=borderLeft; var yClose=this.GetYFromData(data.Close,false); var yHigh=this.GetYFromData(data.High,false); var yLow=this.GetYFromData(data.Low,false); if (isHScreen) { closePath.moveTo(yClose,x); highPath.moveTo(yHigh,x); lowPath.moveTo(yLow,x); upArea.moveTo(yHigh,x); downArea.moveTo(yLow,x); aryClosePoint.push({ X:yClose, Y:x }); aryHighPoint.push({ X:yHigh, Y:x }); aryLowPoint.push({ X:yLow, Y:x }); } else { closePath.moveTo(x,yClose); highPath.moveTo(x,yHigh); lowPath.moveTo(x,yLow); upArea.moveTo(x,yHigh); downArea.moveTo(x,yLow); aryClosePoint.push({ X:x, Y:yClose }); aryHighPoint.push({ X:x, Y:yHigh }); aryLowPoint.push({ X:x, Y:yLow }); } bFirstPoint=false; } } this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yClose=this.GetYFromData(data.Close,false); var yHigh=this.GetYFromData(data.High,false); var yLow=this.GetYFromData(data.Low,false); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) { closePath.moveTo(yClose,x); highPath.moveTo(yHigh,x); lowPath.moveTo(yLow,x); upArea.moveTo(yHigh,x); downArea.moveTo(yLow,x); } else { closePath.moveTo(x,yClose); highPath.moveTo(x,yHigh); lowPath.moveTo(x,yLow); upArea.moveTo(x,yHigh); downArea.moveTo(x,yLow); } bFirstPoint=false; } else { if (isHScreen) { closePath.lineTo(yClose,x); highPath.lineTo(yHigh,x); lowPath.lineTo(yLow,x); upArea.lineTo(yHigh,x); downArea.lineTo(yLow,x); } else { closePath.lineTo(x,yClose); highPath.lineTo(x,yHigh); lowPath.lineTo(x,yLow); upArea.lineTo(x,yHigh); downArea.lineTo(x,yLow); } } if (isHScreen) { aryClosePoint.push({ X:yClose, Y:x }); aryHighPoint.push({ X:yHigh, Y:x }); aryLowPoint.push({ X:yLow, Y:x }); } else { aryClosePoint.push({ X:x, Y:yClose }); aryHighPoint.push({ X:x, Y:yHigh }); aryLowPoint.push({ X:x, Y:yLow }); } } if (bFirstPoint) return; for(var i=aryClosePoint.length-1; i>=0;--i) { var item=aryClosePoint[i]; upArea.lineTo(item.X, item.Y); downArea.lineTo(item.X, item.Y); } upArea.closePath(); downArea.closePath(); this.Canvas.fillStyle=this.HLCAreaConfig.UpAreaColor; this.Canvas.fill(upArea); this.Canvas.fillStyle=this.HLCAreaConfig.DownAreaColor; this.Canvas.fill(downArea); if (IFrameSplitOperator.IsNumber(this.HLCAreaConfig.LineWidth)) this.Canvas.lineWidth=this.HLCAreaConfig.LineWidth; this.Canvas.strokeStyle=this.HLCAreaConfig.CloseLineColor; this.Canvas.stroke(closePath); this.Canvas.strokeStyle=this.HLCAreaConfig.HighLineColor; this.Canvas.stroke(highPath); this.Canvas.strokeStyle=this.HLCAreaConfig.LowLineColor; this.Canvas.stroke(lowPath); } this.ClipTickClient=function(isHScreen) { var border=this.GetBorder(); if (isHScreen==true) { var left=this.ChartBorder.GetLeftEx(); var right=this.ChartBorder.GetRightEx(); var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); } else { var left=border.Left; var right=border.Right; var top=border.TopTitle; var bottom=border.Bottom; } this.Canvas.beginPath(); this.Canvas.rect(left,top,(right-left),(bottom-top)); this.Canvas.clip(); } this.ClipWindow=function(isHScreen) { if (isHScreen==true) { var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRightEx(); var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); } else { var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottom(); } this.Canvas.beginPath(); this.Canvas.rect(left,top,(right-left),(bottom-top)); //this.Canvas.stroke(); //调试用 this.Canvas.clip(); } this.ClipClient=function(isHScreen) //裁剪客户端 { if (isHScreen==true) { var left=this.ChartBorder.GetLeftEx(); var right=this.ChartBorder.GetRightEx(); var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); } else { var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); if (this.ChartBorder.BottomSpace>0) bottom+=1; if (this.DrawType==13) //需要显示文字,裁剪要大点 { top=this.ChartBorder.GetTopTitle(); bottom=this.ChartBorder.GetBottom(); } } this.Canvas.beginPath(); this.Canvas.rect(left,top,(right-left),(bottom-top)); //this.Canvas.stroke(); //调试用 this.Canvas.clip(); } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; this.IsShowOrderText=false; this.TooltipRect=[]; this.InfoTooltipRect=[]; this.TradeIconTooltipRect=[]; this.PtMax={X:null,Y:null,Value:null,Align:'left'}; //清空最大 this.PtMin={X:null,Y:null,Value:null,Align:'left'}; //清空最小 this.DrawKRange={ Start:null, End:null }; this.AryPriceGapCache=[]; this.ChartFrame.ChartKLine={Max:null, Min:null }; //保存K线上 显示最大最小值坐标 this.DrawHeatMap(); if (!this.IsShow) return; if (this.ChartFrame.IsMinSize && this.Name=="Self Kline") return; if (ChartData.IsTickPeriod(this.Period)) //分笔图 { this.Canvas.save(); if (this.DrawType==1) { this.ClipClient(this.ChartFrame.IsHScreen); this.DrawCloseLine(); } else if (this.DrawType==4) { this.ClipClient(this.ChartFrame.IsHScreen); this.DrawCloseArea(); } else { this.ClipTickClient(this.ChartFrame.IsHScreen); this.DrawTick(); } this.Canvas.restore(); return; } this.Canvas.save(); this.ClipClient(this.ChartFrame.IsHScreen); if (this.DrawType==1) { this.DrawCloseLine(); this.Canvas.restore(); if (this.PriceGap.Enable) this.DrawPriceGap(); return; } else if (this.DrawType==2) { this.DrawAKLine(); } else if (this.DrawType==4) { this.DrawCloseArea(); } else if (this.DrawType==5) { this.DrawOrderFlow(); } else if (this.DrawType==7) { this.DrawOrderFlow_Style2(); } else if (this.DrawType==8) { this.DrawOrderFlow_Style3(); } else if (this.DrawType==9) { this.DrawKBar(); } else if (this.DrawType==10) { this.DrawRenkoCandle(); } else if (this.DrawType==12) { this.DrawLineBreak(); } else if (this.DrawType==13) { this.DrawHighLow(); } else if (this.DrawType==14) { if (this.FFKChart && this.FFKChart.Draw) { this.FFKChart.Draw(this); } } else if (this.DrawType==15) { this.DrawHLCArea(); } else if (this.DrawType==16) { this.DrawKagi(); } else if (this.DrawType==17) { this.DrawOrderFlow_Style4(); } else if (this.DrawType==18) { this.DrawOrderFlow_Style5(); } else { this.DrawKBar(); } if (this.TradeIcon) this.DrawTradeIcon() else this.DrawTrade(); this.Canvas.restore(); if (this.PriceGap.Enable) this.DrawPriceGap(); if (this.IsShowMaxMinPrice) //标注最大值最小值 { if (this.ChartFrame.IsHScreen===true) this.HScreenDrawMaxMinPrice(this.PtMax,this.PtMin); else this.DrawMaxMinPrice(this.PtMax,this.PtMin); } if (this.DrawType==14) //自定义图形 标注最大最小值 { if (this.FFKChart && this.FFKChart.DrawMaxMinPrice) { this.FFKChart.DrawMaxMinPrice(); } } } this.OnFormatHighLowTitle=function(ptMax, ptMin) { if (!ptMax || !ptMin) return null; if (!IFrameSplitOperator.IsNumber(ptMax.Value) || !IFrameSplitOperator.IsNumber(ptMin.Value)) return null; var defaultfloatPrecision=GetfloatPrecision(this.Symbol); //小数位数 var title= { High:ptMax.Value.toFixed(defaultfloatPrecision), Low:ptMin.Value.toFixed(defaultfloatPrecision) }; if (!this.GetEventCallback) return title; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_KLINE_HIGH_LOW_TITLE); if (!event || !event.Callback) return title; var data={ Max:ptMax, Min:ptMin, Symbol:this.Symbol, Title:{ High:title.High, Low:title.Low }, Decimal:defaultfloatPrecision, PreventDefault:false }; event.Callback(event, data, this); if (data.PreventDefault) return data.Title; //使用外部回调的数值 return title; } this.DrawMaxMinPrice=function(ptMax,ptMin) { if (ptMax.X==null || ptMax.Y==null || ptMax.Value==null) return; if (ptMin.X==null || ptMin.Y==null || ptMin.Value==null) return; var title=this.OnFormatHighLowTitle(ptMax,ptMin); if (!title) return; var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow; var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow; var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset; var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset; var defaultfloatPrecision=GetfloatPrecision(this.Symbol); this.Canvas.font=this.TextFont; var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); var ptTop=ptMax; var text=title.High; var textColor=this.TextColor; if (this.ChartFrame.CoordinateType==1) //反转坐标 { if (ptMax.YptMin.Y) ptTop=ptMin; this.Canvas.textBaseline='bottom'; if (title.HighColor) textColor=title.HighColor; } this.Canvas.fillStyle=textColor; this.Canvas.textAlign=ptTop.Align; var left=ptTop.Align=='left'?ptTop.X:ptTop.X; if (IFrameSplitOperator.IsNumber(highYOffset)) ptTop.Y+=highYOffset; //var text=ptTop.Value.toFixed(defaultfloatPrecision); if (ptTop.Align=='left') text=leftArrow+text; else text=text+rightArrow; if (ptTop.Y>(top-2)) { this.Canvas.fillText(text,left,ptTop.Y); this.ChartFrame.ChartKLine.Max={X:left, Y:ptTop.Y, Text: { BaseLine:'bottom'}}; } var ptBottom=ptMin; var text=title.Low; var textColor=this.TextColor; if (this.ChartFrame.CoordinateType==1) { if (ptMin.Y>ptMax.Y) ptBottom=ptMax; this.Canvas.textBaseline='bottom'; var text=title.High; if (title.HighColor) textColor=title.HighColor; } else { if (ptMax.Y>ptMin.Y) ptTop=ptMin; this.Canvas.textBaseline='top'; if (title.LowColor) textColor=title.LowColor; } this.Canvas.fillStyle=textColor; this.Canvas.textAlign=ptBottom.Align; var left=ptBottom.Align=='left'?ptBottom.X:ptBottom.X; if (IFrameSplitOperator.IsNumber(lowYOffset)) ptBottom.Y+=lowYOffset; //var text=ptMin.Value.toFixed(defaultfloatPrecision); if (ptBottom.Align=='left') text=leftArrow+text; else text=text+rightArrow; if (ptBottom.Y<(bottom+1)) { this.Canvas.fillText(text,left,ptBottom.Y); this.ChartFrame.ChartKLine.Min={X:left, Y:ptBottom.Y, Text:{ BaseLine:'top'}}; } } this.HScreenDrawMaxMinPrice=function(ptMax,ptMin) //横屏模式下显示最大最小值 { if (ptMax.X==null || ptMax.Y==null || ptMax.Value==null) return; if (ptMin.X==null || ptMin.Y==null || ptMin.Value==null) return; var title=this.OnFormatHighLowTitle(ptMax,ptMin); if (!title) return; var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow; var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow; var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset; var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset; //var defaultfloatPrecision=GetfloatPrecision(this.Symbol); var xText=ptMax.Y; var yText=ptMax.X; if (IFrameSplitOperator.IsNumber(highYOffset)) xText+=highYOffset; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); var text=title.High; this.Canvas.font=this.TextFont; if (title.HighColor) this.Canvas.fillStyle=title.HighColor; else this.Canvas.fillStyle=this.TextColor; this.Canvas.textAlign=ptMax.Align; this.Canvas.textBaseline='bottom'; //var text=ptMax.Value.toFixed(defaultfloatPrecision); if (ptMax.Align=='left') text=leftArrow+text; else text=text+rightArrow; this.Canvas.fillText(text,0,0); this.Canvas.restore(); var xText=ptMin.Y; var yText=ptMin.X; if (IFrameSplitOperator.IsNumber(lowYOffset)) xText+=lowYOffset; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); var text=title.Low; this.Canvas.font=this.TextFont; if (title.LowColor) this.Canvas.fillStyle=title.LowColor; else this.Canvas.fillStyle=this.TextColor; this.Canvas.textAlign=ptMin.Align; this.Canvas.textBaseline='top'; //var text=ptMin.Value.toFixed(defaultfloatPrecision); if (ptMin.Align=='left') text=leftArrow+text; else text=text+rightArrow; this.Canvas.fillText(text,0,0); this.Canvas.restore(); } //画某一天的信息地雷 this.DrawInfo=function(item) { if (!this.InfoData || this.InfoData.size<=0) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var bottom=this.ChartBorder.GetBottom(); var top=this.ChartBorder.GetTop(); var key=`${item.DayData.Date}`; if (this.Data.DataType==1) key=`${item.DayData.Date}-${item.DayData.Time}`; if (!this.InfoData.has(key)) return; var infoData=this.InfoData.get(key); if (!infoData || infoData.Data.length<=0) return; this.Canvas.restore(); this.Canvas.save(); this.ClipWindow(isHScreen); var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 var iconSize=dataWidth+distanceWidth; var minIconSize=18*pixelTatio; var bShowNum=true; if (iconSize<=15) bShowNum=false; if (iconSize=2 && numText && bShowNum) //太小了 就不显示了 { var iconID=value.Data.length; if (iconID>=numText.length) iconID=0; this.Canvas.fillStyle=g_JSChartResource.KLine.NumIcon.Color; var text=numText[iconID]; this.Canvas.fillText(text,value.TextRect.X,value.TextRect.Y,iconSize); } if (!isHScreen) this.InfoTooltipRect.push(value); //横屏没有tooltip } this.Canvas.restore(); this.Canvas.save(); this.ClipClient(isHScreen); } //画交易图标 this.DrawTradeIcon=function() { if (!this.TradeData) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; chartright=this.ChartBorder.GetBottom(); } var sellData=this.TradeData.Sell; var buyData=this.TradeData.Buy; var iconSize=dataWidth+distanceWidth; var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 var iconSizeMax=24*pixelTatio,iconSizeMin=12*pixelTatio; if (iconSizeiconSizeMax) iconSize=iconSizeMax; this.Canvas.font=iconSize+'px '+this.TradeIcon.Family; for(var i=this.Data.DataOffset,j=0;i0; if (buyData && i0; if (!sell && !buy) continue; var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); var yOpen=this.GetYFromData(data.Open,false); var yClose=this.GetYFromData(data.Close,false); var y=yHigh; if (buy) { this.Canvas.fillStyle=this.TradeIcon.Buy.Color; if (isHScreen) { this.Canvas.textAlign='right'; this.Canvas.textBaseline='middle'; this.Canvas.fillText(this.TradeIcon.Buy.HScreenText,yLow,x); } else { this.Canvas.textAlign='center'; this.Canvas.textBaseline='top'; this.Canvas.fillText(this.TradeIcon.Buy.Text,x,yLow); var iconRect=new Rect(x-iconSize/2,yLow,iconSize,iconSize); var iconData={ Data:{ Type:1, KData:data, Name:this.TradeData.Name, Param:this.TradeData.Param }, Rect:iconRect, TextRect:{X:x, Y:yLow} }; this.TradeIconTooltipRect.push(iconData); } } if (sell) { this.Canvas.fillStyle=this.TradeIcon.Sell.Color; if (isHScreen) { this.Canvas.textAlign='left'; this.Canvas.textBaseline='middle'; this.Canvas.fillText(this.TradeIcon.Sell.HScreenText,yHigh,x); } else { this.Canvas.textAlign='center'; this.Canvas.textBaseline='bottom'; this.Canvas.fillText(this.TradeIcon.Sell.Text,x,yHigh); var iconRect=new Rect(x-iconSize/2,yHigh-iconSize,iconSize,iconSize); var iconData={ Data:{ Type:2, KData:data, Name:this.TradeData.Name,Param:this.TradeData.Param }, Rect:iconRect, TextRect:{X:x, Y:yHigh} }; this.TradeIconTooltipRect.push(iconData); } } } } this.GetTooltipData=function(x,y,tooltip) { if (!this.IsShow) return false; for(var i in this.TradeIconTooltipRect) { var item=this.TradeIconTooltipRect[i]; if (!item.Rect) continue; var rect=item.Rect; this.Canvas.beginPath(); this.Canvas.rect(rect.X,rect.Y,rect.Width,rect.Height); if (this.Canvas.isPointInPath(x,y)) { JSConsole.Chart.Log('[ChartKLine::GetTooltipData] trade icon ', item); tooltip.Data=item; tooltip.ChartPaint=this; tooltip.Type=2; //指标 return true; } } for(var i in this.InfoTooltipRect) { var item=this.InfoTooltipRect[i]; if (!item.Rect) continue; var rect=item.Rect; this.Canvas.beginPath(); this.Canvas.rect(rect.X,rect.Y,rect.Width,rect.Height); if (this.Canvas.isPointInPath(x,y)) { //JSConsole.Chart.Log('[ChartKLine::GetTooltipData] info ', item); tooltip.Data=item; tooltip.ChartPaint=this; tooltip.Type=1; //信息地雷 return true; } } for(var i in this.TooltipRect) { var rect=this.TooltipRect[i][1]; this.Canvas.beginPath(); this.Canvas.rect(rect.X,rect.Y,rect.Width,rect.Height); if (this.Canvas.isPointInPath(x,y)) { var index=this.TooltipRect[i][0]; tooltip.Data=this.Data.Data[index]; tooltip.ChartPaint=this; tooltip.Type=0; //K线信息 return true; } } return false; } //计算当天显示数据的最大最小值 this.GetMaxMin=function() { if (this.DrawType==14) { if (this.FFKChart && this.FFKChart.GetMaxMin) { return this.FFKChart.GetMaxMin(this); } } var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; if (this.ChartFrame.GlobalOption && this.ChartFrame.GlobalOption.IsValueFullRange) { start=0; xPointCount=this.Data.Data.length; } var range={ Max:null, Min:null }; if (this.DrawType==1 || this.DrawType==4 ) // 1=收盘价线 4=收盘价面积图 { for(var i=start,j=0;idata.Close) range.Min=data.Close; } } else { for(var i=start,j=0;iitem.Price) low=item.Price; } } high+=data.OrderFlow.PriceOffset; low-=data.OrderFlow.PriceOffset; if (range.Max==null) range.Max=high; if (range.Min==null) range.Min=low; if (range.Maxlow) range.Min=low; } else { if (range.Max==null) range.Max=data.High; if (range.Min==null) range.Min=data.Low; if (range.Maxdata.Low) range.Min=data.Low; } } } return range; } //获取所有的价格 this.GetAllPrice=function() { var xPointCount=this.ChartFrame.XPointCount; var setPrice=new Set(); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; this.DrawKRange.End=i; var yKline={ Low:yLow, High:yHigh, Open:yOpen, Close:yClose }; var xKLine={ Left:left, Center:x, Right:right, DataWidth:dataWidth }; this.DrawOrderFlowBar(data.OrderFlow, data, xKLine, yKline, isHScreen); if (this.IsShowKTooltip && !isHScreen) //添加tooltip区域 { var yTop=Math.min(yOpen,yClose); var yBottom=Math.max(yOpen,yClose); if (Math.abs(yOpen-yClose)<5) //高度太小了, 上下各+5px { yTop=Math.min(yHigh,yTop-5); yBottom=Math.max(yLow,yBottom+5); } var rect=new Rect(left,yTop,dataWidth,yBottom-yTop); //this.Canvas.fillStyle="rgb(0,0,100)"; //this.Canvas.fillRect(rect.X,rect.Y,rect.Width,rect.Height); this.TooltipRect.push([i,rect]); //[0]数据索引 [1]数据区域 } if(this.Data.DataType==0) { var infoItem={Xleft:left,XRight:right, XCenter:x, YMax:yHigh, YMin:yLow, DayData:data, Index:j}; this.DrawInfo(infoItem); } if (i==this.Data.Data.length-1) { ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright }; } } } this.DrawOrderFlowBar=function(orderFlow, kItem, xKLine, yKline, isHScreen) { var top=Math.min(yKline.Open, yKline.Close) var bottom=Math.max(yKline.Open, yKline.Close); var barHeight=Math.abs(yKline.Open-yKline.Close); var cellHeight=0; if (orderFlow && IFrameSplitOperator.IsNumber(orderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(orderFlow.PriceOffset); var textFont=this.GetDynamicOrderFlowFont(cellHeight, xKLine.DataWidth/2); this.IsShowOrderText=(cellHeight>5 && xKLine.DataWidth>10); if (this.OrderFlow.AlwaysShowOrderText) this.IsShowOrderText=true; var kColor; if (kItem.OpenkItem.Close) kColor=this.OrderFlow.DownColor; else kColor=this.OrderFlow.UnchagneColor; var isSmallKLine=(xKLine.DataWidth<4); if (isSmallKLine) { this.Canvas.strokeStyle=kColor.Border; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xKLine.Center),top-cellHeight/2); this.Canvas.lineTo(ToFixedPoint(xKLine.Center),bottom+cellHeight/2); this.Canvas.stroke(); } else { this.Canvas.fillStyle=kColor.BG; this.Canvas.fillRect(ToFixedRect(xKLine.Left),ToFixedRect(top-cellHeight/2),ToFixedRect(xKLine.DataWidth),ToFixedRect(barHeight+cellHeight)); } this.Canvas.textBaseline='middle'; this.Canvas.textAlign='center'; this.Canvas.font=textFont; var textWidth=xKLine.DataWidth/2; var textXOffset=textWidth/2; if (orderFlow && IFrameSplitOperator.IsNonEmptyArray(orderFlow.Order)) { var totalAsk=0, totalBid=0, maxTotalIndex=null; if (this.OrderFlow.IsShowAskBar || this.OrderFlow.IsShowBidBar || this.OrderFlow.IsShowPOCBG) { var maxTotal=0, value=0; for(var i=0;i0) { var barWidh=rect.Width*(item.Ask.Value/totalAsk); if (barWidh<1) barWidh=1; this.Canvas.fillStyle=this.OrderFlow.AskBarColor; this.Canvas.fillRect(ToFixedRect(rect.Right),ToFixedRect(rect.Top),ToFixedRect(-barWidh),ToFixedRect(rect.Height)); } var text=null; if (IFrameSplitOperator.IsString(item.Ask.Text)) text=item.Ask.Text; else if (IFrameSplitOperator.IsNumber(item.Ask.Value)) text=item.Ask.Value.toString(); if (text && this.IsShowOrderText && this.OrderFlow.IsShowAskText) { if (item.Ask.Color) this.Canvas.fillStyle=item.Ask.Color; else this.Canvas.fillStyle=this.OrderFlow.Text.Color; if (item.Ask.Font) { var itemFont=this.GetDynamicOrderFlowFont(cellHeight, xKLine.DataWidth/2, item.Ask.Font); this.Canvas.font=itemFont; this.Canvas.fillText(text,xKLine.Left+textXOffset,yPrice); this.Canvas.font=textFont; } else { this.Canvas.fillText(text,xKLine.Left+textXOffset,yPrice); } } var rect={ Left:xKLine.Center, Right:xKLine.Right, Bottom:yPrice+cellHeight/2, Top:yPrice-cellHeight/2 }; rect.Width=rect.Right-rect.Left; rect.Height=rect.Bottom-rect.Top; if (item.Bid.BG) { this.Canvas.fillStyle=item.Bid.BG; this.Canvas.fillRect(ToFixedRect(rect.Left),ToFixedRect(rect.Top),ToFixedRect(rect.Width),ToFixedRect(rect.Height)); } if (this.OrderFlow.IsShowPOCBG && maxTotalIndex==i) { this.Canvas.fillStyle=this.OrderFlow.POCGBColor; this.Canvas.fillRect(ToFixedRect(rect.Left),ToFixedRect(rect.Top),ToFixedRect(rect.Width),ToFixedRect(rect.Height)); } if (this.OrderFlow.IsShowBidBar && IFrameSplitOperator.IsNumber(item.Bid.Value) && totalBid>0) { var barWidh=rect.Width*(item.Bid.Value/totalBid); if (barWidh<1) barWidh=1; this.Canvas.fillStyle=this.OrderFlow.BidBarColor; this.Canvas.fillRect(ToFixedRect(rect.Left),ToFixedRect(rect.Top),ToFixedRect(barWidh),ToFixedRect(rect.Height)); } var text=null; if (IFrameSplitOperator.IsString(item.Bid.Text)) text=item.Bid.Text; else if (IFrameSplitOperator.IsNumber(item.Bid.Value)) text=item.Bid.Value.toString(); if (text && this.IsShowOrderText && this.OrderFlow.IsShowBidText) { if (item.Bid.Color) this.Canvas.fillStyle=item.Bid.Color; else this.Canvas.fillStyle=this.OrderFlow.Text.Color; if (item.Bid.Font) { var itemFont=this.GetDynamicOrderFlowFont(cellHeight, xKLine.DataWidth/2, item.Bid.Font); this.Canvas.font=itemFont; this.Canvas.fillText(text,xKLine.Center+textXOffset,yPrice); this.Canvas.font=textFont; } else { this.Canvas.fillText(text,xKLine.Center+textXOffset,yPrice); } } } } if (yKline.Highbottom) { this.Canvas.strokeStyle=this.OrderFlow.Line.UpDownColor; if (yKline.Highbottom) { this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xKLine.Center),yKline.Low+cellHeight/2); this.Canvas.lineTo(ToFixedPoint(xKLine.Center),bottom+cellHeight/2); this.Canvas.stroke(); } } if (!isSmallKLine && Math.abs(yKline.Open-yKline.Close)>1) //K线中间竖线 { this.Canvas.strokeStyle=this.OrderFlow.Line.MiddleColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xKLine.Center),top-cellHeight/2); this.Canvas.lineTo(ToFixedPoint(xKLine.Center),bottom+cellHeight/2); this.Canvas.stroke(); } //K线边框 if (!isSmallKLine) { this.Canvas.beginPath(); this.Canvas.strokeStyle=kColor.Border; this.Canvas.rect(ToFixedPoint(xKLine.Left),ToFixedPoint(top-cellHeight/2),ToFixedRect(xKLine.DataWidth),ToFixedRect(barHeight+cellHeight)); this.Canvas.stroke(); } //var fontHeight=this.Canvas.measureText("擎").width+2; var textFont=this.GetDynamicOrderFlowFont(cellHeight, xKLine.DataWidth); //上下文字 if (orderFlow && IFrameSplitOperator.IsNonEmptyArray(orderFlow.High) && this.IsShowOrderText) { for(var i=0;ithis.OrderFlow.Text.FontMaxSize) fontSize=this.OrderFlow.Text.FontMaxSize; else if (fontSize<=0) fontSize=1; var font=this.FormatFontString(fontSize, this.OrderFlow.Text.Family, fontOption); for(var i=fontSize; i>0; i-=2) { var font=this.FormatFontString(i, this.OrderFlow.Text.Family, fontOption); this.Canvas.font=font; var textWidth=this.Canvas.measureText(this.OrderFlow.Text.MaxValue).width+2; if (textWidthhorizontalMax || orderItem.PriceendOffset) continue; this.DrawOrderFlowHBarItem(i, kItem.OrderFlow, orderItem, dataWidth, distanceWidth); } } } this.DrawOrderFlowHBarItem=function(index, orderFlow, orderItem, dataWidth, distanceWidth) { var offset=this.ShowRange.Start; var endOffset=this.ShowRange.Start+this.ShowRange.ShowCount; var yPrice=this.GetYFromData(orderItem.Price, false); var value=parseInt(index+orderItem.HBar.Width); var start=index-offset; var end=value-offset; if (start<0) start=0; if (end<0) end=0; if (start<=end) { var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; var dataOffset=offset; var cellHeight=this.GetPriceYOffset(orderFlow.PriceOffset); var xStart=this.ChartFrame.GetXFromIndex(start)-dataWidth/2; if (orderItem.HBar.Type==1) { for(var i=0, j=index+1; iorderItem.Price) { end=(j-1)-dataOffset; break; } } } if (end<0) return; var xEnd=this.ChartFrame.GetXFromIndex(end)+dataWidth/2; var yTop=yPrice-cellHeight/2; var yHeight=cellHeight+0.5 if (IFrameSplitOperator.IsNumber(orderItem.HBar.Height)) yHeight=orderItem.HBar.Height*cellHeight+0.1; var fValue=orderItem.HBar.Width-parseInt(orderItem.HBar.Width); if (fValue>0.000001) xEnd+=(dataWidth+distanceWidth)*fValue; this.Canvas.fillStyle=orderItem.HBar.Color; this.Canvas.fillRect(ToFixedRect(xStart),ToFixedRect(yTop),ToFixedRect(xEnd-xStart),ToFixedRect(yHeight)); //高度适当加上,否则行间有空隙 } } this.PtInChart=function(x,y) { if (this.DrawType==1 || this.DrawType==4) { return this.PtInLine(x,y, {KLineClose:true}); } return this.PtInKBar(x,y); } this.DrawSelectedStatus=function() { this.DrawLinePoint({KLineClose:true}); } ////////////////////////////////////////////////////////////// //订单流样式2 this.DrawOrderFlow_Style2=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; this.AryOrderFlowBorder=[]; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; } var upColor=this.OrderFlow_Style2.UpColor; var downColor=this.OrderFlow_Style2.DownColor; var unchagneColor=this.OrderFlow_Style2.UnchagneColor; var barWidth=ToFixedRect(this.OrderFlow_Style2.BarWidth); var textWidth=dataWidth-barWidth; if (textWidth/7chartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; this.DrawKRange.End=i; var barTop=Math.min(yOpen,yClose); var barBottom=Math.max(yOpen,yClose); var barLeft=ToFixedRect(left); var barRight=barLeft+barWidth if (data.Opendata.Close) this.Canvas.fillStyle=downColor; else this.Canvas.fillStyle=unchagneColor; var cellHeight=0; if (data.OrderFlow && IFrameSplitOperator.IsNumber(data.OrderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(data.OrderFlow.PriceOffset); this.Canvas.fillRect(barLeft,ToFixedRect(barTop-cellHeight/2),barWidth,ToFixedRect(barBottom-barTop+cellHeight)); var yKline={ Low:yLow, High:yHigh, Open:yOpen, Close:yClose }; var xKLine={ Left:barRight, Center:x, Right:right, DataWidth:(right-barRight) }; xKLine.Center=xKLine.Left+xKLine.DataWidth/2; this.DrawOrderFlowBar_Style2(data.OrderFlow, data, xKLine, yKline, isHScreen); } //最后绘制边框 if (dataWidth-barWidth>5) { for(var i=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; this.DrawKRange.End=i; var barTop=Math.min(yOpen,yClose); var barBottom=Math.max(yOpen,yClose); var barLeft=ToFixedRect(left); var barRight=barLeft+barWidth if (data.Opendata.Close) this.Canvas.fillStyle=downColor; else this.Canvas.fillStyle=unchagneColor; var cellHeight=0; if (data.OrderFlow && IFrameSplitOperator.IsNumber(data.OrderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(data.OrderFlow.PriceOffset); this.Canvas.fillRect(barLeft,ToFixedRect(barTop-cellHeight/2),barWidth,ToFixedRect(barBottom-barTop+cellHeight)); var yKline={ Low:yLow, High:yHigh, Open:yOpen, Close:yClose }; var xKLine={ Left:barRight, Right:right, DataWidth:(right-barRight) }; this.DrawOrderFlowBar_Style3(data.OrderFlow, data, xKLine, yKline, isHScreen); } //最后绘制边框 if (dataWidth-barWidth>5) { for(var i=0;i5 && xKLine.DataWidth>10); if (this.OrderFlow.AlwaysShowOrderText) this.IsShowOrderText=true; /* 背景暂时不用 var kColor; if (kItem.OpenkItem.Close) kColor=this.OrderFlow.DownColor; else kColor=this.OrderFlow.UnchagneColor; var isSmallKLine=(xKLine.DataWidth<4); if (isSmallKLine) { this.Canvas.strokeStyle=kColor.Border; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xKLine.Center),top-cellHeight/2); this.Canvas.lineTo(ToFixedPoint(xKLine.Center),bottom+cellHeight/2); this.Canvas.stroke(); } else { this.Canvas.fillStyle=kColor.BG; this.Canvas.fillRect(ToFixedRect(xKLine.Left),ToFixedRect(top-cellHeight/2),ToFixedRect(xKLine.DataWidth),ToFixedRect(barHeight+cellHeight)); } */ this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.font=textFont; var textWidth=xKLine.DataWidth/2; var textXOffset=2; if (orderFlow && IFrameSplitOperator.IsNonEmptyArray(orderFlow.Order)) { for(var i=0;i5 && xKLine.DataWidth>10); if (this.OrderFlow.AlwaysShowOrderText) this.IsShowOrderText=true; /* 背景暂时不用 var kColor; if (kItem.OpenkItem.Close) kColor=this.OrderFlow.DownColor; else kColor=this.OrderFlow.UnchagneColor; var isSmallKLine=(xKLine.DataWidth<4); if (isSmallKLine) { this.Canvas.strokeStyle=kColor.Border; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xKLine.Center),top-cellHeight/2); this.Canvas.lineTo(ToFixedPoint(xKLine.Center),bottom+cellHeight/2); this.Canvas.stroke(); } else { this.Canvas.fillStyle=kColor.BG; this.Canvas.fillRect(ToFixedRect(xKLine.Left),ToFixedRect(top-cellHeight/2),ToFixedRect(xKLine.DataWidth),ToFixedRect(barHeight+cellHeight)); } */ this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.font=textFont; var textXOffset=2; if (orderFlow && IFrameSplitOperator.IsNonEmptyArray(orderFlow.Order)) { for(var i=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; this.DrawKRange.End=i; var barLeft=left+this.OrderFlow_Style4.LeftMargin; var barRight=right+distanceWidth-this.OrderFlow_Style4.RightMargin; if (this.OrderFlow_Style4.KBarType==1) { var kbarTop=Math.min(yOpen,yClose); var kbarBottom=Math.max(yOpen,yClose); var kbarLeft=ToFixedRect(left)+this.OrderFlow_Style4.LeftMargin; var kbarRight=barLeft+kBarWidth; if (data.Opendata.Close) this.Canvas.fillStyle=downColor; else this.Canvas.fillStyle=unchagneColor; var cellHeight=0; if (data.OrderFlow && IFrameSplitOperator.IsNumber(data.OrderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(data.OrderFlow.PriceOffset); this.Canvas.fillRect(kbarLeft,ToFixedRect(kbarTop-cellHeight/2),kBarWidth,ToFixedRect(kbarBottom-kbarTop+cellHeight)); barLeft=kbarRight+1; } var yKline={ Low:yLow, High:yHigh, Open:yOpen, Close:yClose }; var xKLine={ Left:barLeft, Center:x, Right:barRight, DataWidth:(barRight-barLeft) }; xKLine.Center=xKLine.Left+xKLine.DataWidth/2; this.DrawOrderFlowBar_Style4(data.OrderFlow, data, xKLine, yKline, isHScreen); } } this.DrawOrderFlowBar_Style4=function(orderFlow, kItem, xKLine, yKline, isHScreen) { var top=Math.min(yKline.Open, yKline.Close) var bottom=Math.max(yKline.Open, yKline.Close); var barHeight=Math.abs(yKline.Open-yKline.Close); var cellHeight=0; if (orderFlow && IFrameSplitOperator.IsNumber(orderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(orderFlow.PriceOffset); var textFont=this.GetDynamicOrderFlowFont(cellHeight, xKLine.DataWidth/2); this.IsShowOrderText=(cellHeight>5 && xKLine.DataWidth>10); if (this.OrderFlow.AlwaysShowOrderText) this.IsShowOrderText=true; this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.font=textFont; var volBarSpace=this.OrderFlow_Style4.VolBarSpace; if (cellHeight<=4) volBarSpace=0; //太细了 间距就不要了 if (orderFlow && IFrameSplitOperator.IsNonEmptyArray(orderFlow.Order)) { if (!orderFlow.Summary) orderFlow.Summary={ }; if (!orderFlow.Summary.VolMaxMin) //计算最大最小值 { var volMaxMin={ Max:null, Min:null }; for(var i=0;iitem.Vol.Value) volMaxMin.Min=item.Vol.Value; } orderFlow.Summary.VolMaxMin=volMaxMin; } var preItem=null; //上一个矩形框 var max=orderFlow.Summary.VolMaxMin.Max, min=orderFlow.Summary.VolMaxMin.Min; for(var i=0;ipreItem.Price) { rtBar.Bottom=preItem.Rect.Top-volBarSpace; } rtBar.Width=rtBar.Right-rtBar.Left; rtBar.Height=rtBar.Bottom-rtBar.Top; rtDraw={ Left:ToFixedRect(rtBar.Left), Top:ToFixedRect(rtBar.Top), Width:ToFixedRect(rtBar.Width), Height:ToFixedRect(rtBar.Height) }; rtDraw.Bottom=rtDraw.Top+rtDraw.Height; rtDraw.Right=rtDraw.Left+rtDraw.Width; if (rtDraw.Width<1) rtDraw.Width=1; if (itemVol.BG) //背景色 { this.Canvas.fillStyle=itemVol.BG; this.Canvas.fillRect(rtDraw.Left, rtDraw.Top, rtDraw.Width, rtDraw.Height); } xVolLeft=rtDraw.Right; } rtDraw.Left=xKLine.Left; rtDraw.Width=rtDraw.Right-rtDraw.Left; if (item.Vol.Text && this.IsShowOrderText) //文字 { this.Canvas.fillStyle=item.Vol.Color; if (item.Vol.Font) { var itemFont=this.GetDynamicOrderFlowFont(cellHeight, barWidth/2, item.Vol.Font); this.Canvas.font=itemFont; this.Canvas.fillText(text,xKLine.Center+textXOffset,yPrice); this.Canvas.font=textFont; } else { this.Canvas.fillText(item.Vol.Text,rtDraw.Left+2,yPrice); } } preItem={ Price: item.Price, Rect:rtDraw }; } else if (IFrameSplitOperator.IsNumber(item.Vol.Value)) { var barWidth=xKLine.Right-xKLine.Left; var volWidth=barWidth*(item.Vol.Value-min)/(max-min); var rect={ Left:xKLine.Left, Right:xKLine.Right, Bottom:yPrice+cellHeight/2, Top:yPrice-cellHeight/2 }; rect.Right=rect.Left+volWidth; if (preItem && item.Price>preItem.Price) { rect.Bottom=preItem.Rect.Top-volBarSpace; } rect.Width=rect.Right-rect.Left; rect.Height=rect.Bottom-rect.Top; var rtDraw={ Left:ToFixedRect(rect.Left), Top:ToFixedRect(rect.Top), Width:ToFixedRect(rect.Width), Height:ToFixedRect(rect.Height) }; rtDraw.Bottom=rtDraw.Top+rtDraw.Height; rtDraw.Right=rtDraw.Left+rtDraw.Width; if (rtDraw.Width<1) rtDraw.Width=1; if (item.Vol.BG) //背景色 { this.Canvas.fillStyle=item.Vol.BG; this.Canvas.fillRect(rtDraw.Left, rtDraw.Top, rtDraw.Width, rtDraw.Height); } if (item.Vol.BorderColor) //边框 { this.Canvas.strokeStyle = item.Vol.BorderColor; this.Canvas.strokeRect(ToFixedPoint(rtDraw.Left), ToFixedPoint(rtDraw.Top), rtDraw.Width, rtDraw.Height); } if (item.Vol.Text && this.IsShowOrderText) //文字 { this.Canvas.fillStyle=item.Vol.Color; if (item.Vol.Font) { var itemFont=this.GetDynamicOrderFlowFont(cellHeight, barWidth/2, item.Vol.Font); this.Canvas.font=itemFont; this.Canvas.fillText(text,xKLine.Center+textXOffset,yPrice); this.Canvas.font=textFont; } else { this.Canvas.fillText(item.Vol.Text,rtDraw.Left+2,yPrice); } } preItem={ Price: item.Price, Rect:rtDraw }; } else { continue; } } } } //////////////////////////////////////////////////////////////////////////////// //订单流样式5 this.DrawOrderFlow_Style5=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; this.AryOrderFlowBorder=[]; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; } var upColor=this.OrderFlow_Style2.UpColor; var downColor=this.OrderFlow_Style2.DownColor; var unchagneColor=this.OrderFlow_Style2.UnchagneColor; var barWidth=ToFixedRect(this.OrderFlow_Style2.BarWidth); var textWidth=dataWidth-barWidth; if (textWidth/7chartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; this.DrawKRange.End=i; var barTop=Math.min(yOpen,yClose); var barBottom=Math.max(yOpen,yClose); var barLeft=ToFixedRect(left); var barRight=barLeft+barWidth if (data.Opendata.Close) this.Canvas.fillStyle=downColor; else this.Canvas.fillStyle=unchagneColor; var cellHeight=0; if (data.OrderFlow && IFrameSplitOperator.IsNumber(data.OrderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(data.OrderFlow.PriceOffset); this.Canvas.fillRect(barLeft,ToFixedRect(barTop-cellHeight/2),barWidth,ToFixedRect(barBottom-barTop+cellHeight)); var yKline={ Low:yLow, High:yHigh, Open:yOpen, Close:yClose }; var xKLine={ Left:barRight, Center:x, Right:right, DataWidth:(right-barRight) }; xKLine.Center=xKLine.Left+xKLine.DataWidth/2; this.DrawOrderFlowBar_Style5(data.OrderFlow, data, xKLine, yKline, isHScreen); } } this.DrawOrderFlowBar_Style5=function(orderFlow, kItem, xKLine, yKline, isHScreen) { var top=Math.min(yKline.Open, yKline.Close) var bottom=Math.max(yKline.Open, yKline.Close); var barHeight=Math.abs(yKline.Open-yKline.Close); var cellHeight=0; if (orderFlow && IFrameSplitOperator.IsNumber(orderFlow.PriceOffset)) cellHeight=this.GetPriceYOffset(orderFlow.PriceOffset); var textFont=this.GetDynamicOrderFlowFont(cellHeight, xKLine.DataWidth/2); this.IsShowOrderText=(cellHeight>5 && xKLine.DataWidth>10); if (this.OrderFlow.AlwaysShowOrderText) this.IsShowOrderText=true; this.Canvas.textBaseline='middle'; this.Canvas.font=textFont; var textWidth=xKLine.DataWidth/2; if (orderFlow && IFrameSplitOperator.IsNonEmptyArray(orderFlow.Order)) { var maxValue=orderFlow.MaxValue; for(var i=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low,false); var yHigh=this.GetYFromData(data.High,false); this.DrawKRange.End=i; var yBarTop=yLow; var barHeight=yHigh-yLow; if (Math.abs(barHeight)<1) barHeight=1; //高度小于1,统一使用高度1 if (dataWidth>=4) { if (isHScreen) { this.Canvas.fillRect(ToFixedRect(yBarTop),ToFixedRect(left),ToFixedRect(barHeight),ToFixedRect(dataWidth)); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(yBarTop),ToFixedRect(dataWidth),ToFixedRect(barHeight)); if (bShowText) this.DrawHighLowText(yHigh, yLow, x, data, defaultfloatPrecision); //TODO:文字输出 } } else //竖线 { var x=left+(right-left)/2; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yLow),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yHigh),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yLow)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yHigh)); } this.Canvas.stroke(); } if (this.IsShowKTooltip && !isHScreen) //添加tooltip区域 { var yTop=Math.min(yLow,yHigh); var yBottom=Math.max(yLow,yHigh); if (Math.abs(yTop-yBottom)<5) //高度太小了, 上下各+5px { yTop=Math.min(yHigh,yTop-5); yBottom=Math.max(yLow,yBottom+5); } var rect=new Rect(left,yTop,dataWidth,yBottom-yTop); //this.Canvas.fillStyle="rgb(0,0,100)"; //this.Canvas.fillRect(rect.X,rect.Y,rect.Width,rect.Height); this.TooltipRect.push([i,rect]); //[0]数据索引 [1]数据区域 } } } this.DrawHighLowText=function(yHigh, yLow, x, kItem, floatPrecision) { this.Canvas.textAlign="center"; var text=kItem.High.toFixed(floatPrecision); this.Canvas.textBaseline="bottom"; this.Canvas.fillText(text,x,yHigh-2); var text=kItem.Low.toFixed(floatPrecision); this.Canvas.textBaseline="top"; this.Canvas.fillText(text,x,yLow+3); } this.GetHighLowTextFont=function(dataWidth, distanceWidth) { var barWidth=dataWidth+distanceWidth; var text=this.HighLowTextConfig.MaxText; var min=Math.min(this.HighLowTextConfig.MaxSize,this.HighLowTextConfig.MinSize); var max=Math.max(this.HighLowTextConfig.MaxSize,this.HighLowTextConfig.MinSize); for(var i=max; i>=min; --i) { var font=`${i*GetDevicePixelRatio()}px ${this.HighLowTextConfig.FontName}`; this.Canvas.font=font; var textWidth=this.Canvas.measureText(text).width; if (textWidth<=barWidth) return font; } return null; } ////////////////////////////////////////////////////////////// //标识缺口 // ///////////////////////////////////////////////////////////// this.DrawPriceGap=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.AryPriceGapCache)) return; if (this.PriceGap.Count<=0) return; var index=this.AryPriceGapCache.length-this.PriceGap.Count; if (index<0) index=0; var isHScreen=(this.ChartFrame.IsHScreen===true); var border=null; if (isHScreen) border=this.ChartBorder.GetHScreenBorder(); else border=this.ChartBorder.GetBorder(); this.Canvas.font=this.PriceGapStyple.Text.Font; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; var textHeight=this.Canvas.measureText("擎").width; var decNum=GetfloatPrecision(this.Symbol); for(var i=index;irect.Right) { rtText.Right=rect.Right; rtText.Left=rtText.Right-rtText.Width; } this.Canvas.fillStyle=this.PriceGapStyple.Text.Color; this.Canvas.fillText(text,rtText.Left,rtText.Bottom); } //this.Canvas.fillStyle="rgb(250,250,250)" //this.Canvas.fillRect(rtText.Left, rtText.Top, rtText.Width, rtText.Height); } } } //是否有缺口 this.IsPriceGap=function(item, preItem) { if (!preItem || !item) return 0; if (preItem.Data.Low>item.Data.High) return 2; //下缺口 if (preItem.Data.High=start.Data.Low) { this.AryPriceGapCache.splice(i,1); --i; continue; } if (kItem.High>end.Data.High) item.Data[1]=kItemInfo; } } } } function ChartColorKline() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartColorKline'; //类名 this.Symbol; //股票代码 this.Color='rgb(0,255,44)'; this.IsEmptyBar=false; this.DrawType=0; //0=实心K线柱子 3=空心K线柱子 this.KLineColor; //Map key=K线索引 value=设置 this.DrawName; this.Draw=function() { if (!this.IsShow) return; if (this.DrawName=="DRAWCOLORKLINE") { this.DrawColorBar(); } else { if (!this.KLineColor) return; this.DrawBar(); } } this.DrawUpBarItem=function(data, xOffset, dataWidth, option) { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; var yLow=this.ChartFrame.GetYFromData(data.Low); var yHigh=this.ChartFrame.GetYFromData(data.High); var yOpen=this.ChartFrame.GetYFromData(data.Open); var yClose=this.ChartFrame.GetYFromData(data.Close); var y=yHigh; if (dataWidth>=4) { if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):yClose)); } this.Canvas.stroke(); y=yClose; } else { y=yClose; } if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (this.DrawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (this.DrawType==3) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.DrawDownBarItem=function(data, xOffset, dataWidth, option) { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; var yLow=this.ChartFrame.GetYFromData(data.Low); var yHigh=this.ChartFrame.GetYFromData(data.High); var yOpen=this.ChartFrame.GetYFromData(data.Open); var yClose=this.ChartFrame.GetYFromData(data.Close); var y=yHigh; if (dataWidth>=4) { if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yOpen)); } this.Canvas.stroke(); y=yOpen; } else { y=yOpen } if (isHScreen) { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yClose-y),ToFixedRect(dataWidth)); } else { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yClose)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yClose-y))); } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.DrawUnChangeBarItem=function(data, xOffset, dataWidth, option) { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=xOffset; var right=xOffset+dataWidth; var x=left+(right-left)/2; var yLow=this.ChartFrame.GetYFromData(data.Low); var yHigh=this.ChartFrame.GetYFromData(data.High); var yOpen=this.ChartFrame.GetYFromData(data.Open); var yClose=this.ChartFrame.GetYFromData(data.Close); var y=yHigh; if (dataWidth>=4) { this.Canvas.beginPath(); if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yOpen,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),y); this.Canvas.lineTo(ToFixedPoint(x),yOpen); } y=yOpen; } else { y=yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } this.Canvas.stroke(); } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); } } this.DrawBar=function() { var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; if (this.IsHScreen) { xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; chartright=this.ChartBorder.GetBottom(); } for(var i=this.Data.DataOffset,j=0;ichartright) break; if (itemOption.Color) { this.Canvas.strokeStyle=itemOption.Color; this.Canvas.fillStyle=itemOption.Color; } else { this.Canvas.strokeStyle=this.Color; this.Canvas.fillStyle=this.Color; } if (data.Opendata.Close) //阴线 { this.DrawDownBarItem(data,xOffset,dataWidth,itemOption); } else //平线 { this.DrawUnChangeBarItem(data,xOffset,dataWidth,itemOption); } } } this.DrawColorBar=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; } for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low, false); var yHigh=this.GetYFromData(data.High, false); var yOpen=this.GetYFromData(data.Open, false); var yClose=this.GetYFromData(data.Close, false); var y=yHigh; if (data.Open==data.Close) this.DrawKBar_Unchagne(data, dataWidth, this.Color, this.IsEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); else this.DrawKBar_Custom(data, dataWidth, this.Color, this.IsEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen); } } this.DrawKBar_Unchagne=function(data, dataWidth, unchagneColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (dataWidth>=4) { if ((dataWidth%2)!=0) dataWidth-=1; this.Canvas.strokeStyle=unchagneColor; this.Canvas.beginPath(); if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yOpen,ToFixedPoint(x)); } else { var xFixed=ToFixedPoint(left+dataWidth/2); this.Canvas.moveTo(xFixed,y); this.Canvas.lineTo(xFixed,yOpen); } y=yOpen; } else { y=yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(left+dataWidth),ToFixedPoint(y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { var xFixed=ToFixedPoint(left+dataWidth/2); this.Canvas.moveTo(xFixed,ToFixedPoint(y)); this.Canvas.lineTo(xFixed,ToFixedPoint(yLow)); } } this.Canvas.stroke(); } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=unchagneColor; this.Canvas.stroke(); } } this.DrawKBar_Custom=function(data, dataWidth, barColor, isEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) { if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } if (dataWidth>=4) { this.Canvas.strokeStyle=barColor; if (data.High>data.Close) //上影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(isEmptyBar?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen))); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose)); } } this.Canvas.stroke(); y=yClose; } else { y=yClose; } this.Canvas.fillStyle=barColor; if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) //空心柱 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); } } } if (data.Open>data.Low) //下影线 { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(isEmptyBar?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { if (isEmptyBar) { var xFixed=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen))); this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } this.Canvas.stroke(); } } else { this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.strokeStyle=barColor; this.Canvas.stroke(); } } this.GetMaxMin=function() { var range={Max:null,Min:null }; if (this.DrawName=="DRAWCOLORKLINE") { var xPointCount=this.ChartFrame.XPointCount; for(var i=this.Data.DataOffset,j=0;idata.Low) range.Min=data.Low; } } return range; } } function ChartHeatMap() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartHeatMap'; //类名 this.Draw=function() { if (!this.IsShow) return; if (this.ChartFrame.IsMinSize) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; for(var i=this.Data.DataOffset,j=0;ichartright) break; var xCenter=left+(right-left)/2; this.DrawHeatMap(left, right+distanceWidth, data.HeatMap); } } this.DrawHeatMap=function(left, right, heatMap) { if (!IFrameSplitOperator.IsNonEmptyArray(heatMap.Order)) return; var max=this.ChartFrame.HorizontalMax; var min=this.ChartFrame.HorizontalMin; var cellHeight=0; if (IFrameSplitOperator.IsNumber(heatMap.PriceOffset)) cellHeight=this.GetPriceYOffset(heatMap.PriceOffset); for(var i=0;imax || item.Pricechartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low/firstOverlayOpen*firstOpen,false); var yHigh=this.GetYFromData(data.High/firstOverlayOpen*firstOpen,false); var yOpen=this.GetYFromData(data.Open/firstOverlayOpen*firstOpen,false); var yClose=this.GetYFromData(data.Close/firstOverlayOpen*firstOpen,false); var y=yHigh; this.DrawKRange.End=i; if (data.Open=4) { if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):yClose)); } y=yClose; } else { y=yClose; } if (isHScreen) { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 } else { if (drawType==3) this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); //空心柱 else this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); } } else { if (Math.abs(yOpen-y)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (drawType==3) this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); //空心柱 else this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); } } if (data.Open>data.Low) { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } } else { if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } } } else if (data.Open>data.Close) //阴线 { if (dataWidth>=4) { if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yOpen)); } y=yOpen; } else { y=yOpen } if (isHScreen) { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yClose-y),ToFixedRect(dataWidth)); } else { if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 else this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),ToFixedRect(yClose-y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } } else { if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } } } else // 平线 { if (dataWidth>=4) { if (data.High>data.Close) //上影线 { if (isHScreen) { this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yOpen,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),y); this.Canvas.lineTo(ToFixedPoint(x),yOpen); } y=yOpen; } else { y=yOpen; } if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right)); } else { this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(y)); } if (data.Open>data.Low) //下影线 { if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); } } } else { if (isHScreen) { if (data.High==data.Low) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow-1,ToFixedPoint(x)); } else { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } } else { if (data.High==data.Low) { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow+1); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } } } } //添加tooltip区域 { var yTop=Math.min(yLow,yHigh,yOpen,yClose); var yBottom=Math.max(yLow,yHigh,yOpen,yClose); var rect=new Rect(left,yTop,dataWidth,yBottom-yTop); //this.Canvas.fillStyle="rgb(0,0,100)"; //this.Canvas.fillRect(rect.X,rect.Y,rect.Width,rect.Height); this.TooltipRect.push([i,rect]); //[0]数据索引 [1]数据区域 } } if (isFristDraw==false) this.Canvas.stroke(); } this.DrawAKLine=function(firstOpen) //美国线 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; if (isHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); if (isHScreen) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var firstOverlayOpen=null; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.ShowRange.FirstOpen=firstOpen; this.DrawKRange.Start=this.Data.DataOffset; this.Canvas.strokeStyle=this.Color; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yLow=this.GetYFromData(data.Low/firstOverlayOpen*firstOpen,false); var yHigh=this.GetYFromData(data.High/firstOverlayOpen*firstOpen,false); var yOpen=this.GetYFromData(data.Open/firstOverlayOpen*firstOpen,false); var yClose=this.GetYFromData(data.Close/firstOverlayOpen*firstOpen,false); this.DrawKRange.End=i; this.Canvas.beginPath(); //最高-最低 if (isHScreen) { this.Canvas.moveTo(yHigh,ToFixedPoint(x)); this.Canvas.lineTo(yLow,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yHigh); this.Canvas.lineTo(ToFixedPoint(x),yLow); } this.Canvas.stroke(); if (dataWidth>=4) { this.Canvas.beginPath(); //开盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yOpen),left); this.Canvas.lineTo(ToFixedPoint(yOpen),x); } else { this.Canvas.moveTo(left,ToFixedPoint(yOpen)); this.Canvas.lineTo(x,ToFixedPoint(yOpen)); } this.Canvas.stroke(); this.Canvas.beginPath(); //收盘 if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yClose),right); this.Canvas.lineTo(ToFixedPoint(yClose),x); } else { this.Canvas.moveTo(right,ToFixedPoint(yClose)); this.Canvas.lineTo(x,ToFixedPoint(yClose)); } this.Canvas.stroke(); } } } this.DrawCloseLine=function(firstOpen) //收盘价线 { var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; if (isHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); if (isHScreen) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var firstOverlayOpen=null; var bFirstPoint=true; this.Canvas.strokeStyle=this.Color; if (IFrameSplitOperator.IsNumber(this.CloseLineWidth)) this.Canvas.lineWidth=this.CloseLineWidth; this.ShowRange.Start=this.Data.DataOffset; this.ShowRange.End=this.ShowRange.Start; this.ShowRange.DataCount=0; this.ShowRange.ShowCount=xPointCount; this.ShowRange.FirstOpen=firstOpen; this.DrawKRange.Start=this.Data.DataOffset; this.Canvas.beginPath(); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var yClose=this.GetYFromData(data.Close/firstOverlayOpen*firstOpen,false); this.DrawKRange.End=i; if (bFirstPoint) { if (isHScreen) this.Canvas.moveTo(yClose,x); else this.Canvas.moveTo(x,yClose); bFirstPoint=false; } else { if (isHScreen) this.Canvas.lineTo(yClose,x); else this.Canvas.lineTo(x,yClose); } } if (bFirstPoint==false) this.Canvas.stroke(); } this.GetFirstOpen=function() { if (!this.MainData || !this.Data) return null; var xPointCount=this.ChartFrame.XPointCount; for(var i=this.Data.DataOffset,j=0;ilow) range.Min=low; } return range; } this.GetTooltipData=function(x,y,tooltip) { for(var i in this.TooltipRect) { var rect=this.TooltipRect[i][1]; this.Canvas.beginPath(); this.Canvas.rect(rect.X,rect.Y,rect.Width,rect.Height); if (this.Canvas.isPointInPath(x,y)) { var index=this.TooltipRect[i][0]; tooltip.Data=this.Data.Data[index]; tooltip.ChartPaint=this; return true; } } return false; } this.PtInChart=function(x,y) { var drawType=this.DrawType; if (IFrameSplitOperator.IsNumber(this.CustomDrawType)) drawType=this.CustomDrawType; if (drawType==1 || drawType==4) //线段,面积不支持选中 { return null; //return this.PtInLine(x,y, {KLineClose:true}); } return this.PtInKBar(x,y, {OverlayKLine:true}); } this.DrawSelectedStatus=function() { this.DrawLinePoint({OverlayKLine:true}); } } //K线表格 function ChartKLineTable() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartKlineTable'; //类名 this.Data; this.RowName; this.IsShowRowName=false; this.BGColor; //背景色 this.RowCount=5; //行数 this.RowHeight=10; //行高 this.TextFontConfig=CloneData(g_JSChartResource.ChartKLineTable.TextFont); this.ItemMergin=CloneData(g_JSChartResource.ChartKLineTable.ItemMergin); this.TextFont; this.TextColor='rgb(0,0,0)'; this.NameColor="rgb(0,0,0)"; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true); if (isHScreen) return; if (this.RowCount<=0) return; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var border=this.ChartFrame.GetBorder(); var height=border.Bottom-border.TopTitle; this.RowHeight=height/this.RowCount; var xOffset=border.LeftEx+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var top=border.TopTitle; var bottom=border.Bottom; if (this.BGColor) { this.Canvas.fillStyle=this.BGColor; var left=border.LeftEx; var width=border.RightEx-border.LeftEx; var height=bottom-top; this.Canvas.fillRect(left, top, width, height); } var itemHeight=this.RowHeight; var itemWidth=dataWidth+distanceWidth; if (itemHeight-this.ItemMergin.Top-this.ItemMergin.Bottom>0) itemHeight=itemHeight-this.ItemMergin.Left-this.ItemMergin.Right; if (itemWidth-this.ItemMergin.Left-this.ItemMergin.Right>0) itemWidth=itemWidth-this.ItemMergin.Left-this.ItemMergin.Right; var font=this.GetDynamicTextFont(itemHeight, itemWidth); this.TextFont=font; this.Canvas.font=this.TextFont; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; if (x>chartright) break; if (j==0 && this.IsShowRowName) { this.DrawRowName(top, bottom, left, right); } else { this.DrawRow(item, top, bottom, left, right); //绘制一列 } } } this.DrawRowName=function(top, bottom, left, right) { if (!IFrameSplitOperator.IsNonEmptyArray(this.RowName)) return; var x=left,y=top, width=right-left; for(var i=0;i10) { this.Canvas.fillStyle=item.Color?item.Color:this.TextColor; this.Canvas.textBaseline='middle'; if (item.TextAlign=='right') { this.Canvas.textAlign='right'; this.Canvas.fillText(item.Name,rtBG.Right-2,rtBG.Top+this.RowHeight/2, width-4); } else if (item.TextAlign=='center') { this.Canvas.textAlign='center'; this.Canvas.fillText(item.Name,rtBG.Left+rtBG.Width/2,rtBG.Top+this.RowHeight/2, width-4); } else { this.Canvas.textAlign='left'; this.Canvas.fillText(item.Name,rtBG.Left+2,rtBG.Top+this.RowHeight/2, width-4); } } y+=this.RowHeight; } } this.DrawRow=function(data, top, bottom, left, right) { var x=left,y=top, width=right-left; for(var i=0;i10) { this.Canvas.fillStyle=item.Color; this.Canvas.textBaseline='middle'; if (item.TextAlign=='right') { this.Canvas.textAlign='right'; this.Canvas.fillText(item.Text,rtBG.Right-2,rtBG.Top+this.RowHeight/2, width-4); } else if (item.TextAlign=='center') { this.Canvas.textAlign='center'; this.Canvas.fillText(item.Text,rtBG.Left+rtBG.Width/2,rtBG.Top+this.RowHeight/2, width-4); } else { this.Canvas.textAlign='left'; this.Canvas.fillText(item.Text,rtBG.Left+2,rtBG.Top+this.RowHeight/2, width-4); } } y+=this.RowHeight; } } this.GetDynamicTextFont=function(cellHeight, width, fontOption) { var fontSize=parseInt(cellHeight)-2; if (cellHeight<5) fontSize=parseInt(cellHeight); //高度太小了就不要上下间距了 if (fontSize>this.TextFontConfig.FontMaxSize) fontSize=this.TextFontConfig.FontMaxSize; else if (fontSize<=0) fontSize=1; var font=this.FormatFontString(fontSize, this.TextFontConfig.Family, fontOption); return font; } this.FormatFontString=function(fontSize, family, option) { var font; if (!option) { font=`${fontSize}px ${family}`; } else { if (option.Weight) font=`${option.Weight} ${fontSize}px ${family}`; } return font; } this.GetMaxMin=function() { return {Min:0, Max:this.RowCount}; } } //分钟成交量 支持横屏 function ChartMinuteVolumBar() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartMinuteVolumBar'; //类名 this.UpColor = g_JSChartResource.UpBarColor; //上涨 this.DownColor = g_JSChartResource.DownBarColor; //下跌 this.UnchangeColor=g_JSChartResource.UnchagneBarColor; //平盘 this.BarColorType=1; //柱子颜色显示类型 0=红绿 1=红绿白 this.CustomColor=g_JSChartResource.Minute.VolBarColor; //自定义颜色 this.YClose; //前收盘 this.Symbol; this.BeforeOpenData; //盘前数据 this.AfterCloseData; //盘后数据 this.BeforeVolColor=g_JSChartResource.Minute.Before.VolColor; this.ShareAfterVol=0; this.MultiDayBeforeOpenData; //多日分时图 盘前数据 数组 1天一个 this.MultiDayAfterCloseData; //多日分时图 盘后数据 数组 1天一个 this.PtInChart=function(x,y) { var option={ MinuteVolBar:true }; return this.PtInBar(x,y,option); } this.DrawSelectedStatus=function() { return this.DrawLinePoint({ MinuteVolBar:true }); } this.Draw=function() { var isHScreen = (this.ChartFrame.IsHScreen === true); if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright = border.BottomEx; } else { var border=this.ChartBorder.GetBorder(); var chartright=border.RightEx; } this.DrawBeforeOpen(); this.DrawMultiDayBeforeOpen(); var xPointCount=this.ChartFrame.XPointCount; var yBottom=this.ChartFrame.GetYFromData(0); var yPrice=this.YClose; //上一分钟的价格 var data=this.Data; var bShowColorBar=MARKET_SUFFIX_NAME.IsShowMinuteColorVolBar(this.Symbol); if (bShowColorBar) this.Canvas.strokeStyle=this.CustomColor; for(var i=data.DataOffset,j=0;ichartright) break; //价格>=上一分钟价格 红色 否则绿色 if (!bShowColorBar) this.Canvas.strokeStyle = this.GetMinuteBarColor(price, yPrice); 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(); if (price) yPrice=price; } this.DrawAfterClose(); this.DrawMultiDayAfterClose(); } //连续交易成交量柱子颜色 this.GetMinuteBarColor=function(price, yPrice) { if (this.BarColorType==1) //通达信模式 { if (price>yPrice) return this.UpColor; else if (price= yPrice ? this.UpColor:this.DownColor; } } this.DrawBeforeOpen=function() { if (this.ChartBorder.LeftExtendWidth<10) return; if (!this.BeforeOpenData) return; this.DrawCallAuction(-1,this.BeforeOpenData,true); } this.DrawAfterClose=function() { if (this.ChartBorder.RightExtendWidth<10) return; if (!this.AfterCloseData) return; this.DrawCallAuction(-1,this.AfterCloseData,false); } this.DrawMultiDayBeforeOpen=function() { if (this.ChartBorder.MultiDayMinute.Count<=1 || this.ChartBorder.MultiDayMinute.Left<=0) return; if (!this.MultiDayBeforeOpenData) return; var offset=0,showDayCount=this.MultiDayBeforeOpenData.length; if (this.DayOffset) { if (IFrameSplitOperator.IsNumber(this.DayOffset.Offset)) offset=this.DayOffset.Offset; if (IFrameSplitOperator.IsNumber(this.DayOffset.ShowDayCount)) showDayCount=this.DayOffset.ShowDayCount; } for(var i=offset,j=0; i= yPrice ? this.UpColor:this.DownColor; 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(); if (item.Price) yPrice=item.Price; } } else if (callAutionData.Ver==2.0 || callAutionData.Ver==3.0) { var range={ Max: callAutionData.VolMax, Min:callAutionData.VolMin } for(var i in callAutionData.Data) { var item=callAutionData.Data[i]; if (!item) continue; if (IFrameSplitOperator.IsPlusNumber(item.Vol[0])) { if (isBeforeOpen) { var x=this.ChartFrame.GetLeftExtendXFromIndex(i,callAutionData); var y=this.ChartFrame.GetLeftExtendYFromData(item.Vol[0],false, { Range:range }); } else { var x=this.ChartFrame.GetRightExtendXFromIndex(i,callAutionData); if (this.ShareAfterVol==1) var y=this.ChartFrame.GetYFromData(item.Vol[0]); else var y=this.ChartFrame.GetRightExtendYFromData(item.Vol[0],false, { Range:range }); } this.Canvas.strokeStyle = this.GetBarColor(item.ColorID); 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(); } if (IFrameSplitOperator.IsPlusNumber(item.Vol[1])) { if (isBeforeOpen) { var x=this.ChartFrame.GetLeftExtendXFromIndex(i,callAutionData); var y=this.ChartFrame.GetLeftExtendYFromData(item.Vol[1],false, { Range:range }); } else { var x=this.ChartFrame.GetRightExtendXFromIndex(i,callAutionData); if (this.ShareAfterVol==1) var y=this.ChartFrame.GetYFromData(item.Vol[1]); else var y=this.ChartFrame.GetRightExtendYFromData(item.Vol[1],false, { Range:range }); } this.Canvas.strokeStyle = this.GetBarColor(item.ColorID); this.Canvas.beginPath(); if (isHScreen) { y-=yBottom; y=border.RightEx-y; this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(border.RightEx,ToFixedPoint(x)); } else { y-=yBottom; y=border.TopEx-y; this.Canvas.moveTo(ToFixedPoint(x),y); this.Canvas.lineTo(ToFixedPoint(x),border.TopEx); } this.Canvas.stroke(); } } } } this.GetBarColor=function(id) { switch(id) { case 0: return this.UnchangeColor; case 1: return this.UpColor; case 2: return this.DownColor; } if (this.BeforeVolColor && Array.isArray(this.BeforeVolColor)) { var index=id-3; if (index>=0 && index0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint=true; var drawCount=0; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (bFirstPoint) { this.Canvas.strokeStyle=this.Color; this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); this.Canvas.restore(); } //无效数不画 this.DrawStraightLine=function() { var bHScreen=(this.ChartFrame.IsHScreen===true); var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } this.Canvas.save(); this.ClipClient(bHScreen); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint=true; var ptFirst=null;; //第1个点 var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.stroke(); bFirstPoint=true; drawCount=0; ptFirst=null; continue; } if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; } var y=this.GetYFromData(value,false); if (x>chartright) break; if (bFirstPoint) { this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; ptFirst={ X:x, Y:y }; } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); } ++drawCount; } if (drawCount>0) { if (drawCount==1 && ptFirst) //如果只有1个点, 画一个像素的横线 { if (bHScreen) this.Canvas.lineTo(ptFirst.Y,ptFirst.X+1*GetDevicePixelRatio()); else this.Canvas.lineTo(ptFirst.X+1*GetDevicePixelRatio(),ptFirst.Y); } this.Canvas.stroke(); } this.Canvas.restore(); } //分段线 this.DrawSectionLine=function() { var bHScreen=(this.ChartFrame.IsHScreen===true); var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } this.Canvas.save(); this.ClipClient(bHScreen); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint=true; var ptFirst=null;; //第1个点 var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.stroke(); bFirstPoint=true; drawCount=0; ptFirst=null; continue; } if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; } var y=this.GetYFromData(value,false); if (x>chartright) break; //断开 if (this.BreakPoint && this.BreakPoint.has(i)) { if (drawCount>0) this.Canvas.stroke(); bFirstPoint=true; drawCount=0; ptFirst=null; } if (bFirstPoint) { this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; ptFirst={ X:x, Y:y }; } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); } ++drawCount; } if (drawCount>0) { if (drawCount==1 && ptFirst) //如果只有1个点, 画一个像素的横线 { if (bHScreen) this.Canvas.lineTo(ptFirst.Y,ptFirst.X+1*GetDevicePixelRatio()); else this.Canvas.lineTo(ptFirst.X+1*GetDevicePixelRatio(),ptFirst.Y); } this.Canvas.stroke(); } this.Canvas.restore(); } } //面积图 支持横屏 function ChartArea() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartArea'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.AreaColor; //面积颜色 this.LineWidth; //线段宽度 this.LineDash; //虚线 this.AreaDirection=0 //0=向下 1=向上 this.DrawSelectedStatus=this.DrawLinePoint; this.PtInChart=this.PtInLine; this.ExportData=this.ExportArrayData; this.GetItemData=this.GetArrayItemData; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.DrawArea(); } //无效数不画 this.DrawArea=function() { var bHScreen=(this.ChartFrame.IsHScreen===true); var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } this.Canvas.save(); this.ClipClient(bHScreen); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; if (this.AreaColor) this.Canvas.fillStyle=this.AreaColor; else this.Canvas.fillStyle=IChartDrawPicture.ColorToRGBA(this.Color,0.6); if (IFrameSplitOperator.IsNonEmptyArray(this.LineDash)) this.Canvas.setLineDash(this.LineDas); //画虚线 var bFirstPoint=true; var ptFirst=null, ptEnd=null //起始结束点 var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.stroke(); if (ptFirst && ptEnd) { if (bHScreen) { if (this.AreaDirection==1) { this.Canvas.lineTo(border.RightEx,ptEnd.X); this.Canvas.lineTo(border.RightEx,ptFirst.X); } else { this.Canvas.lineTo(border.LeftEx,ptEnd.X); this.Canvas.lineTo(border.LeftEx,ptFirst.X); } this.Canvas.closePath(); this.Canvas.fill(); } else { if (this.AreaDirection==1) { this.Canvas.lineTo(ptEnd.X, border.TopEx); this.Canvas.lineTo(ptFirst.X, border.TopEx); } else { this.Canvas.lineTo(ptEnd.X, border.BottomEx); this.Canvas.lineTo(ptFirst.X, border.BottomEx); } this.Canvas.closePath(); this.Canvas.fill(); } } bFirstPoint=true; drawCount=0; ptFirst=null; ptEnd=null; continue; } if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; } var y=this.GetYFromData(value,false); if (x>chartright) break; if (bFirstPoint) { this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; ptFirst={ X:x, Y:y }; } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); ptEnd={ X:x, Y:y }; } ++drawCount; } if (drawCount>0) { if (drawCount==1 && ptFirst) //如果只有1个点, 画一个像素的横线 { if (bHScreen) this.Canvas.lineTo(ptFirst.Y,ptFirst.X+1*GetDevicePixelRatio()); else this.Canvas.lineTo(ptFirst.X+1*GetDevicePixelRatio(),ptFirst.Y); } this.Canvas.stroke(); if (ptFirst && ptEnd) { if (bHScreen) { if (this.AreaDirection==1) { this.Canvas.lineTo(border.RightEx,ptEnd.X); this.Canvas.lineTo(border.RightEx,ptFirst.X); } else { this.Canvas.lineTo(border.LeftEx,ptEnd.X); this.Canvas.lineTo(border.LeftEx,ptFirst.X); } this.Canvas.closePath(); this.Canvas.fill(); } else { if (this.AreaDirection==1) { this.Canvas.lineTo(ptEnd.X, border.TopEx); this.Canvas.lineTo(ptFirst.X, border.TopEx); } else { this.Canvas.lineTo(ptEnd.X, border.BottomEx); this.Canvas.lineTo(ptFirst.X, border.BottomEx); } this.Canvas.closePath(); this.Canvas.fill(); } } } this.Canvas.restore(); } } //散点图 function ChartScatterPlot() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartScatterPlot'; //类名 //默认点配置 this.Color="rgb(255,193,37)"; //点颜色 this.Radius=3; //半径 //this.Data.Data [ {Value:, Radius:半径(可选), Color:颜色(可选), ColorBorder:边框颜色(可选)}, .....] this.TooltipData=[]; this.Draw=function() { this.TooltipData=[]; if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.DrawScatterPlot(); } this.DrawScatterPlot=function() { var bHScreen=(this.ChartFrame.IsHScreen===true); var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var lockRect=this.GetLockRect(); if (lockRect) { if (bHScreen) chartright=lockRect.Top; else chartright=lockRect.Left; } this.Canvas.save(); this.ClipClient(bHScreen); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } if (x>chartright) break; if (Array.isArray(item)) { for(var j=0;jitem.Value) range.Min=item.Value; } } else { if (!IFrameSplitOperator.IsNumber(point.Value)) continue; if (range.Max==null) range.Max=point.Value; if (range.Min==null) range.Min=point.Value; if (range.Maxpoint.Value) range.Min=point.Value; } } return range; } this.GetTooltipData=function(x,y,tooltip) { if (!this.IsShow) return false; if (!IFrameSplitOperator.IsNonEmptyArray(this.TooltipData)) return false; for(var i=this.TooltipData.length-1; i>=0; --i) { var item=this.TooltipData[i]; this.Canvas.beginPath(); this.Canvas.arc(item.X, item.Y, item.Radius, 0, 2 * Math.PI); if (this.Canvas.isPointInPath(x,y)) { JSConsole.Chart.Log('[ChartScatterPlot::GetTooltipData] point', item); tooltip.Data=item; tooltip.ChartPaint=this; tooltip.Type=6; //散点图 return true; } } } } //子线段 function ChartSubLine() { this.newMethod=ChartLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartSubLine'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.LineWidth; //线段宽度 this.DrawType=0; //画图方式 0=无效数平滑 1=无效数不画断开 this.IsDotLine=false; //虚线 this.SubFrame={ Max:null,Min:null }; this.Draw=function() { if (!this.IsShow) return; if (!this.Data || !this.Data.Data) return; this.CalculateDataMaxMin(); switch(this.DrawType) { case 0: return this.DrawLine(); case 1: return this.DrawStraightLine(); } } this.GetYFromData=function(value) { var bHScreen = (this.ChartFrame.IsHScreen === true); if (bHScreen) { if (value <= this.SubFrame.Min) return this.ChartBorder.GetLeftEx(); if (value >= this.SubFrame.Max) return this.ChartBorder.GetRightEx(); var width = this.ChartBorder.GetWidthEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min); return this.ChartBorder.GetLeftEx() + width; } else { if(value<=this.SubFrame.Min) return this.ChartBorder.GetBottomEx(); if(value>=this.SubFrame.Max) return this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx()*(value-this.SubFrame.Min)/(this.SubFrame.Max-this.SubFrame.Min); return this.ChartBorder.GetBottomEx()-height; } } this.CalculateDataMaxMin=function() { this.SubFrame={ Max:null,Min:null }; var bHScreen=(this.ChartFrame.IsHScreen===true); var chartright=this.ChartBorder.GetRight(); if (bHScreen) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (this.SubFrame.Min==null || this.SubFrame.Min>value) this.SubFrame.Min=value; if (this.SubFrame.Max==null || this.SubFrame.Max0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; if (this.IsDotLine) this.Canvas.setLineDash([3,5]); //画虚线 var bFirstPoint=true; var drawCount=0,rate=0; for(var i=firstData.DataOffset,j=firstData.Index;i0) this.Canvas.stroke(); bFirstPoint=true; drawCount=0; continue; } var x=this.ChartFrame.GetXFromIndex(j); var diff=value-firstData.OverlayValue; if (firstData.OverlayValue!=0) rate= 1+ diff/Math.abs(firstData.OverlayValue); else rate=1+diff; var fixedValue=firstData.MainValue*rate; //var fixedValue=value/firstData.OverlayValue*firstData.MainValue; var y=this.GetYFromData(fixedValue); if (x>chartright) break; if (bFirstPoint) { this.Canvas.beginPath(); if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); this.Canvas.restore(); } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; var firstData=this.GetFirstVaildIndex(); if (!firstData) return range; for(var i=firstData.DataOffset,j=firstData.Index; ivalue) range.Min=value; } return range; } } //独立线段 function ChartSingleLine() { this.newMethod=ChartLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartSingleLine'; //类名 this.MaxMin=null; //当前的显示范围 this.Draw=function() { this.MaxMin=null; if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (!this.Data || !this.Data.Data) return; this.MaxMin=this.GetCurrentMaxMin(); if (!this.MaxMin) return; if (!IFrameSplitOperator.IsNumber(this.MaxMin.Max) || !IFrameSplitOperator.IsNumber(this.MaxMin.Min)) return; switch(this.DrawType) { default: return this.DrawStraightLine(); } } //获取当前页的最大最小值 this.GetCurrentMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={ Max:null, Min:null }; for(var i=this.Data.DataOffset,j=0;ivalue) range.Min=value; } return range; } this.GetMaxMin=function() { return { Max:null, Min:null }; } this.GetYFromData=function(value) { var bHScreen = (this.ChartFrame.IsHScreen === true); if (bHScreen) { if (value <= this.MaxMin.Min) return this.ChartBorder.GetLeftEx(); if (value >= this.MaxMin.Max) return this.ChartBorder.GetRightEx(); var width = this.ChartBorder.GetWidthEx() * (value - this.MaxMin.Min) / (this.MaxMin.Max - this.MaxMin.Min); return this.ChartBorder.GetLeftEx() + width; } else { if(value<=this.MaxMin.Min) return this.ChartBorder.GetBottomEx(); if(value>=this.MaxMin.Max) return this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx()*(value-this.MaxMin.Min)/(this.MaxMin.Max-this.MaxMin.Min); return this.ChartBorder.GetBottomEx()-height; } } } //彩色线段 function ChartPartLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartPartLine'; //类名 this.LineWidth; //线段宽度 this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.DrawLine(); } this.DrawLine=function() { var bHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var xPointCount=this.ChartFrame.XPointCount; var isMinute=this.IsMinuteFrame(); this.Canvas.save(); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); var bFirstPoint=true; var drawCount=0; var lastColor; var lastPoint={X:null,Y:null}; var isPerNull=false; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } var value=item.Value; var color=item.RGB; var y=this.ChartFrame.GetYFromData(value); if (x>chartright) break; if (color!=lastColor || isPerNull==true) { if (lastColor && drawCount>0) this.Canvas.stroke(); drawCount=0; lastColor=color; this.Canvas.strokeStyle=color; this.Canvas.beginPath(); if (lastPoint.X!=null && lastPoint.Y!=null) //接着上一个点连线 { if (bHScreen) this.Canvas.moveTo(lastPoint.Y,lastPoint.X); //横屏坐标轴对调 else this.Canvas.moveTo(lastPoint.X,lastPoint.Y); if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); ++drawCount; } else { if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); } } else { if (bHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); ++drawCount; } lastPoint.X=x; lastPoint.Y=y; isPerNull=false; } if (drawCount>0) this.Canvas.stroke(); this.Canvas.restore(); } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; for(var i=this.Data.DataOffset,j=0;iitem.Value) range.Min = item.Value; } return range; } this.ExportData=function(aryKData, option) { var aryValue=[], aryColor=[]; if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { var start=0, end=this.Data.length-1; //限制范围 if (option && option.Start && option.End && IFrameSplitOperator.IsNumber(option.Start.Index) && IFrameSplitOperator.IsNumber(option.End.Index)) { start=option.Start.Index; end=option.End.Index; } for(var i=start ;i<=end && ichartright) return null; if (y>border.BottomEx || y=0; --i) { var value=this.Data.Data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; var yPt=this.GetYFromData(value,false); var xPt=null; if (isMinute) xPt=this.ChartFrame.GetXFromIndex(0); else xPt=xOffset; ptStart.Y=yPt; ptStart.X=xPt; } for(var i=this.Data.DataOffset,j=0;ichartright) break; var xLine=left+(right-left)/2; } var yLine=this.GetYFromData(value,false); if (xLinechartright) break; } if (!IFrameSplitOperator.IsNumber(ptStart.X) || !IFrameSplitOperator.IsNumber(ptStart.Y)) return null; if (!IFrameSplitOperator.IsNumber(ptEnd.X) || !IFrameSplitOperator.IsNumber(ptEnd.Y)) return null; if (x==ptStart.X || y==ptStart.Y) return { Identify:this.Identify, Chart:this }; if (x==ptEnd.X || y==ptEnd.Y) return { Identify:this.Identify, Chart:this }; if (x>=ptStart.X && x<=ptEnd.X && y>=ptStart.Y-3 && y<=ptStart.Y+3) return { Identify:this.Identify, Chart:this }; if (x>=ptEnd.X-3 && x<=ptEnd.X+3 && y>=Math.min(ptStart.Y,ptEnd.Y) && y0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 if (this.DotLine) this.Canvas.setLineDash(this.DotLine); //画虚线 this.Canvas.strokeStyle=this.Color; var bFirstPoint=true; var drawCount=0; var prePoint={ X:null, Y:null }; for(var i=this.Data.DataOffset; i>=0; --i) { var value=this.Data.Data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; var y=this.GetYFromData(value,false); var x=null; if (isMinute) x=this.ChartFrame.GetXFromIndex(0); else x=xOffset; this.Canvas.beginPath(); if (this.IsHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; prePoint.Y=y; prePoint.X=x; } for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } if (x>chartright) break; var value=this.Data.Data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; var y=this.GetYFromData(value,false); if (bFirstPoint) { this.Canvas.beginPath(); if (this.IsHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调 else this.Canvas.moveTo(x,y); bFirstPoint=false; prePoint.X=x; prePoint.Y=y; } else { if (this.IsHScreen) { this.Canvas.lineTo(prePoint.Y,x) this.Canvas.lineTo(y,x); } else { this.Canvas.lineTo(x,prePoint.Y) this.Canvas.lineTo(x,y); } prePoint.X=x; prePoint.Y=y; } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); } this.DrawSelectedStatus=function() { this.DrawLinePoint(); } } //斜率线 DRAWSL() function ChartSlopeLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartSlopeLine'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.IsDotLine=false; this.LineWidth; this.Option; //[ { Slope:slope, Length:len, Direct:direct } ] this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.Canvas.save(); this.Canvas.strokeStyle=this.Color; if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 var left=this.ChartBorder.GetLeft(); var top=this.ChartBorder.GetTopEx(); var right=this.ChartBorder.GetRight(); var bottom=this.ChartBorder.GetBottom(); var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; this.Canvas.beginPath(); this.Canvas.rect(left,top,(right-left),(bottom-top)); this.Canvas.clip(); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x2=Math.sqrt((z*z)/(1+option.Slope*option.Slope)); var y2=x2*option.Slope; this.Canvas.beginPath(); if (option.Direct==2) { this.Canvas.moveTo(x-x2,y+y2); this.Canvas.lineTo(x+x2,y-y2); } else if (option.Direct==1) { this.Canvas.moveTo(x,y); this.Canvas.lineTo(x-x2,y+y2); } else { this.Canvas.moveTo(x,y); this.Canvas.lineTo(x+x2,y-y2); } this.Canvas.stroke(); } this.Canvas.restore(); } } //POINTDOT 圆点 支持横屏 /* SAR的圈圈分成两种颜色,当股价朝向上的方向前进时,SAR位于收盘价线的下方,并且呈现红色的圈圈, 当股价朝下跌的方向前进时,SAR位于收盘价的上方,并且呈现绿色的圈圈。 我们最需要注意的是,股价向上或向下穿越SAR圈圈的讯号,而且是以收盘价的穿越有效。 当价格由下往上穿越今天绿色的SAR时,画面上立即在明天的价格位置显示一个红色的圈圈, 代表股价已经翻红,又代表明天开始,必须从事多头交易,当价格由上往下跌破今天红色的SAR时,画面上立即在明天的价格位置, 显示一个绿色的圈圈,代表股价已经翻绿,又代表明天开始必须从事空头交易。 */ function ChartPointDot() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartPointDot'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.Radius=1; //点半径 this.EnableUpDownColor=false; //是否是红绿点 this.HistoryData; this.ExportData=this.ExportArrayData; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var bHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); if (bHScreen===true) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; this.Canvas.save(); this.ClipClient(bHScreen); this.Canvas.fillStyle=this.Color; var colorDot; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (this.EnableUpDownColor) { var kItem=this.HistoryData.Data[i]; if (kItem.Close>value) colorDot="rgb(255,61,61)"; else colorDot='rgb(0,199,65)'; this.Canvas.fillStyle=colorDot; } this.Canvas.beginPath(); if (bHScreen) this.Canvas.arc(y, x, this.Radius, 0, Math.PI*2, true); else this.Canvas.arc(x, y, this.Radius, 0, Math.PI*2, true); this.Canvas.closePath(); this.Canvas.fill(); } this.Canvas.restore(); } } //通达信语法 STICK 支持横屏 function ChartStick() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color="rgb(255,193,37)"; //线段颜色 this.LineWidth; //线段宽度 this.ClassName='ChartStick'; this.ExportData=this.ExportArrayData; this.DrawLine=function() { if (!this.Data || !this.Data.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); if (isHScreen===true) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; this.Canvas.save(); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); var bFirstPoint=true; var drawCount=0; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (bFirstPoint) { this.Canvas.strokeStyle=this.Color; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(y,x); else this.Canvas.moveTo(x,y); bFirstPoint=false; } else { if (isHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); this.Canvas.restore(); } this.DrawStick=function() { if (!this.Data || !this.Data.Data) return; var bHScreen=(this.ChartFrame.IsHScreen===true); var chartright=this.ChartBorder.GetRight(); if (bHScreen) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var yBottom=this.ChartBorder.GetBottom(); var xLeft=this.ChartBorder.GetLeft(); this.Canvas.save(); this.Canvas.strokeStyle=this.Color; if (this.LineWidth) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); var lineWidth=this.Canvas.lineWidth; for(var i=this.Data.DataOffset,j=0;ichartright) break; this.Canvas.beginPath(); if (bHScreen) { this.Canvas.moveTo(xLeft,x); this.Canvas.lineTo(y,x); this.Canvas.stroke(); } else { var xFix=ToFixedPoint2(lineWidth, x); this.Canvas.moveTo(xFix,y); this.Canvas.lineTo(xFix,yBottom); } this.Canvas.stroke(); } this.Canvas.restore(); } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; this.DrawStick(); } } //通达信语法 LINESTICK 支持横屏 function ChartLineStick() { this.newMethod=ChartStick; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartLineStick'; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } this.DrawStick(); this.DrawLine(); } } //通达信语法 VOLSTICK 支持横屏 function ChartVolStick() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.UpColor=g_JSChartResource.UpBarColor; this.DownColor=g_JSChartResource.DownBarColor; this.HistoryData; //历史数据 this.KLineDrawType=0; this.ClassName='ChartVolStick'; this.BarWidth; //固定宽度 目前只支持宽度为1 this.BarType; //柱子状态 1=实心 0=空心 2=涨实跌空 如果设置了这个属性, 属性KLineDrawType无效 this.BarColorType=0; //0=柱子颜色跟K线走 1=正upcolor 负downcolor this.PtInChart=this.PtInBar; this.DrawSelectedStatus=this.DrawLinePoint; this.ExportData=this.ExportArrayData; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.ChartFrame.IsHScreen===true) { this.HScreenDraw(); return; } var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var xPointCount=this.ChartFrame.XPointCount; var lockRect=this.GetLockRect(); if (lockRect) chartright=lockRect.Left; var isMinute=this.IsMinuteFrame(); var yBottom=this.ChartFrame.GetYFromData(0); this.Canvas.save(); if (dataWidth>=4 && !(this.BarWidth===1)) { yBottom=ToFixedRect(yBottom); for(var i=this.Data.DataOffset,j=0;ichartright) break; var y=this.ChartFrame.GetYFromData(value); var barColor=this.GetBarColor(kItem,value); var bUp=barColor.IsUp; var height=ToFixedRect(Math.abs(yBottom-y)>=1?yBottom-y:1);//高度调整为整数, 如果小于1, 统一使用1 y=yBottom-height; var bSolidBar=this.IsSolidBar(bUp); //实心柱子 if (bSolidBar) { this.Canvas.fillStyle=barColor.Color; this.Canvas.fillRect(ToFixedRect(left),y,ToFixedRect(dataWidth),height); } else { this.Canvas.strokeStyle=barColor.Color; this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),height); this.Canvas.stroke(); } } } else //太细了直接话线 { var preKItem=null; var barColor=null; this.Canvas.linewidth=1*GetDevicePixelRatio(); for(var i=this.Data.DataOffset,j=0;ichartright) break; if (isMinute) barColor=this.GetMinuteBarColor(kItem,preKItem); //分时图颜色单独计算 else barColor=this.GetBarColor(kItem, value); this.Canvas.strokeStyle=barColor.Color; //var x=this.ChartFrame.GetXFromIndex(j); this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(x),y); this.Canvas.lineTo(ToFixedPoint(x),yBottom); this.Canvas.stroke(); preKItem=kItem; } } this.Canvas.restore(); } this.HScreenDraw=function() //横屏画法 { var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartBottom=border.BottomEx; var xPointCount=this.ChartFrame.XPointCount; var lockRect=this.GetLockRect(); if (lockRect) chartBottom=lockRect.Top; var isMinute=this.IsMinuteFrame(); var yBottom=this.ChartFrame.GetYFromData(0); if (dataWidth>=4) { yBottom=ToFixedRect(yBottom); for(var i=this.Data.DataOffset,j=0;ichartBottom) break; var y=this.ChartFrame.GetYFromData(value); var barColor=this.GetBarColor(kItem, value); var bUp=barColor.IsUp; var height=ToFixedRect(y-yBottom); //高度调整为整数 var bSolidBar=this.IsSolidBar(bUp); //实心柱子 if (bSolidBar) { this.Canvas.fillStyle=barColor.Color; this.Canvas.fillRect(yBottom,ToFixedRect(left),height,ToFixedRect(dataWidth)); } else { this.Canvas.strokeStyle=barColor.Color; this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(yBottom),ToFixedPoint(left),height,ToFixedRect(dataWidth)); this.Canvas.stroke(); } } } else //太细了直接话线 { var preKItem=null; var barColor=null; for(var i=this.Data.DataOffset,j=0;ichartBottom) break; if (isMinute) barColor=this.GetMinuteBarColor(kItem,preKItem); //分时图颜色单独计算 else barColor=this.GetBarColor(kItem,value); var bUp=barColor.IsUp; this.Canvas.strokeStyle=barColor.Color; //var x=this.ChartFrame.GetXFromIndex(j); this.Canvas.beginPath(); this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(yBottom,ToFixedPoint(x)); this.Canvas.stroke(); preKItem=kItem; } } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; if (this.ChartFrame.GlobalOption && this.ChartFrame.GlobalOption.IsValueFullRange) { start=0; xPointCount=this.Data.Data.length; } var range={ Min:null, Max:null }; for(var i=start,j=0;ivalue) range.Min=value } if (range.Max>0 && range.Min>0) range.Min=0; else if (range.Max<0 && range.Min<0) range.Max=0; return range; } this.GetBarColor=function(kItem, value) { if (this.BarColorType===1) //更具正负决定柱子颜色 { if (value>=0) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨 else return { Color:this.DownColor, IsUp:false }; } if (kItem.Close>=kItem.Open) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨 else return { Color:this.DownColor, IsUp:false }; } //true=实心 false=空心 this.IsSolidBar=function(bUp) { var bSolidBar=true; //实心柱子 if (this.BarType===0 || this.BarType===1 || this.BarType===2) { if (this.BarType===0) //空心 bSolidBar=false; else if (this.BarType===2) //涨实跌空 bSolidBar=bUp; } else { if (this.KLineDrawType==6) //完全空心柱 bSolidBar=false; else if (bUp && (this.KLineDrawType==1 || this.KLineDrawType==2 || this.KLineDrawType==3)) //空心柱子 bSolidBar=false; } return bSolidBar; } this.GetMinuteBarColor=function(kItem, preItem) { var prePrice=kItem.YClose; if (preItem) prePrice=preItem.Close; if (kItem.Close>=prePrice) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨 else return { Color:this.DownColor, IsUp:false }; } this.GetItemData=function(indexData) { if (!indexData) return null; if (!IFrameSplitOperator.IsNumber(indexData.Index)) return null; if (!this.HistoryData || !IFrameSplitOperator.IsNonEmptyArray(this.HistoryData.Data)) return null; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null; var index=indexData.Index; if (index<0 || index>=this.Data.Data.length || index>=this.HistoryData.Data.length) return null; var item=this.Data.Data[index]; var kItem=this.HistoryData.Data[index]; return [ { Value:item, Color:this.GetBarColor(kItem).Color, Name: this.Name } ]; } } // VERTLINE(HIGH>=HHV(HIGH,20),1)表示在创20天新高画垂直虚线。 // 支持横屏 function ChartVericaltLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartVericaltLine'; //类名 this.LineWidth=2; this.LineCap; this.Draw=function() { if (this.ChartFrame.IsMinSize) return; var isHScreen=this.ChartFrame.IsHScreen==true; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.GetBorder(); var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var top=border.RightEx; var bottom=border.LeftEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var top=border.TopEx; var bottom=border.BottomEx; var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } this.Canvas.save(); this.Canvas.strokeStyle=this.Color; if (this.LineType) this.Canvas.setLineDash(this.LineType); if (this.LineCap) this.Canvas.lineCap = this.LineCap; this.Canvas.beginPath(); var lineWidth=this.Canvas.lineWidth; if (this.LineWidth>0) { lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.lineWidth=lineWidth; } var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.stroke(); this.Canvas.restore(); } this.GetMaxMin=function() { return { Min:null, Max:null }; } } //HORLINE 支持横屏 function ChartHorizontalLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartHorizontalLine'; //类名 this.LineWidth=2; this.LineCap; this.ExtendType=0; //1=表示向左延长,2=表示向右延长,3=表示左右延长 this.Draw=function() { if (this.ChartFrame.IsMinSize) return; var isHScreen=this.ChartFrame.IsHScreen==true; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var border=this.GetBorder(); var xPointCount=this.ChartFrame.XPointCount; if (isHScreen) { var left=border.TopEx; var right=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var left=border.LeftEx var right=border.RightEx; var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } this.Canvas.save(); this.Canvas.strokeStyle=this.Color; if (this.LineType) this.Canvas.setLineDash(this.LineType); if (this.LineCap) this.Canvas.lineCap = this.LineCap; this.Canvas.beginPath(); var lineWidth=this.Canvas.lineWidth; if (this.LineWidth>0) { lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.lineWidth=lineWidth; } var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.stroke(); this.Canvas.restore(); } } //线段 多数据(一个X点有多条Y数据) 支持横屏 function ChartLineMultiData() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartLineMultiData'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.PointColor; //='rgb(255,193,80)'; this.PointRadius; //=2; this.LineWidth; this.Draw=function() { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) 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; this.Canvas.save(); if (IFrameSplitOperator.IsPlusNumber(this.LineWidth)) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); var bFirstPoint=true; var drawCount=0; var aryPoint=[]; var aryValue; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (Array.isArray(lineItem)) aryValue=lineItem; else aryValue=[lineItem]; for(var index=0; index0) this.Canvas.stroke(); this.DrawPoint(aryPoint); this.Canvas.restore(); } this.DrawPoint=function(aryPoint) { if (!this.PointColor) return; if (!IFrameSplitOperator.IsPlusNumber(this.PointRadius)) return; var radius=this.PointRadius*GetDevicePixelRatio(); for(var i=0;ivalue) range.Min=value; } } return range; } } //柱子 支持横屏 function ChartStickLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartStickLine'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.BarType=0; //柱子类型 0=实心 1=空心 -1=画虚线空心柱 this.LineDotted=[3,3]; //虚线设置 this.Width=0; //柱子宽度 0=1 3,50=k线宽度 101=K线宽度+间距宽度 this.SetEmptyBar=function() //设置空心柱子 { if (this.BarType!=1 && this.BarType!=-1) return false; this.Canvas.lineWidth=GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; var emptyBGColor=g_JSChartResource.EmptyBarBGColor; if (emptyBGColor) this.Canvas.fillStyle=emptyBGColor; if (this.BarType==-1) //虚线 { this.Canvas.setLineDash(this.LineDotted); //虚线 } return true; } this.IsEmptyBar=function() { return (this.BarType==1 || this.BarType==-1); } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); var zoomIndex=this.ChartFrame.ZoomIndex; if (isHScreen) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; if (isHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var isMinute=this.IsMinuteFrame(); this.Canvas.save(); var bFillBar=false; var bFillKLine=false; var emptyBGColor=g_JSChartResource.EmptyBarBGColor; if (isMinute) { if (this.Width>1) this.Canvas.lineWidth=2*GetDevicePixelRatio(); else this.Canvas.lineWidth=GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; } else if(this.Width==0) //宽度时0,使用宽度1 { this.SetEmptyBar(); this.Canvas.lineWidth=GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; } else if (this.Width==3 || this.Width==50) //3和50 K线宽度 { if (dataWidth>=4) { bFillKLine=true; this.SetEmptyBar(); if (!this.IsEmptyBar()) this.Canvas.fillStyle=this.Color; this.Canvas.strokeStyle=this.Color; } else //太细了 画竖线 { this.Canvas.lineWidth=GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; } } else if (this.Width==101) { var lineWidth=dataWidth+distanceWidth+1*GetDevicePixelRatio(); this.Canvas.lineWidth=lineWidth; this.Canvas.strokeStyle=this.Color; } else if (this.Width<=3) { var minWidth=2*GetDevicePixelRatio(); var barWidth=dataWidth*(this.Width/3); if (barWidthchartright) break; if (bFillBar) { if (isHScreen) { var left=x-barWidth/2; var width=barWidth; if (this.IsEmptyBar()) //空心 { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(Math.min(y,y2)),ToFixedPoint(left),ToFixedRect(Math.abs(y-y2)),ToFixedRect(width)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(Math.min(y,y2)),ToFixedRect(left),ToFixedRect(Math.abs(y-y2)),ToFixedRect(width)); } } else { var left=x-barWidth/2; var width=barWidth; if (left+width>chartright) width=chartright-left; //不要超过右边框子 if (this.IsEmptyBar()) //空心 { if (emptyBGColor) this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,y2)),ToFixedRect(width),ToFixedRect(Math.abs(y-y2))); this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(Math.min(y,y2)),ToFixedRect(width),ToFixedRect(Math.abs(y-y2))); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,y2)),ToFixedRect(width),ToFixedRect(Math.abs(y-y2))); } } } else if (bFillKLine) { if (this.IsEmptyBar()) //空心 { if (isHScreen) { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(Math.min(y,y2)),ToFixedPoint(xOffset),ToFixedRect(Math.abs(y-y2)),ToFixedRect(dataWidth)); this.Canvas.stroke(); } else { if (emptyBGColor) this.Canvas.fillRect(ToFixedRect(xOffset),ToFixedRect(Math.min(y,y2)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(y-y2))); this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(xOffset),ToFixedPoint(Math.min(y,y2)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(y-y2))); this.Canvas.stroke(); } } else { if (isHScreen) this.Canvas.fillRect(ToFixedRect(Math.min(y,y2)),ToFixedRect(xOffset),ToFixedRect(Math.abs(y-y2)),ToFixedRect(dataWidth)); else this.Canvas.fillRect(ToFixedRect(xOffset),ToFixedRect(Math.min(y,y2)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(y-y2))); } } else { if (isHScreen) { this.Canvas.beginPath(); this.Canvas.moveTo(y,ToFixedPoint(x)); this.Canvas.lineTo(y2,ToFixedPoint(x)); this.Canvas.stroke(); } else { var xFix=parseInt(x.toString())+0.5; this.Canvas.beginPath(); this.Canvas.moveTo(xFix,y); this.Canvas.lineTo(xFix,y2); this.Canvas.stroke(); } } } this.Canvas.restore(); } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; if(!this.Data || !this.Data.Data) return range; for(var i=this.Data.DataOffset,j=0;ivalueMin) range.Min=valueMin; } return range; } } function ChartText() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartText'; //类名 this.TextFont="14px 微软雅黑"; this.Draw=function() { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; for(var i in this.Data.Data) { var value=this.Data.Data[i]; if (value==null) continue; var price=value.Value; var position=value.Position; if (position=='Left') { var x=this.ChartFrame.GetXFromIndex(0); var y=this.ChartFrame.GetYFromData(price); if (x>chartright) continue; this.Canvas.textAlign='left'; this.Canvas.textBaseline='middle'; this.Canvas.fillStyle=value.Color; this.Canvas.font=this.TextFont; this.Canvas.fillText(value.Message,x,y); } } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; if(!this.Data || !this.Data.Data) return range; for(var i in this.Data.Data) { var data=this.Data.Data[i]; if (data==null || isNaN(data.Value)) continue; var value=data.Value; if (range.Max==null) range.Max=value; if (range.Min==null) range.Min=value; if (range.Maxvalue) range.Min=value; } return range; } } /* 文字输出 支持横屏 数组(Data)不为null的数据中输出 this.Text文本 */ function ChartSingleText() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartSingleText'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.TextFont="14px 微软雅黑"; //线段宽度 this.Text; this.TextAlign='left'; this.TextBG; //{ Color:"rgb(0,0,92)", Border:"rgb(205,0,92)", Margin:[0,1,1,1], } // { Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] } this.Direction=0; //0=middle 1=bottom 2=top this.FixedFontSize=-1; //固定字体大小 this.YOffset=0; //连线 this.Position; //指定输出位置 this.ShowOffset={ X:0, Y:0 }; //显示偏移 this.IconFont; //Iconfont this.IconSize= { Max: g_JSChartResource.DRAWICON.Icon.MaxSize, Min:g_JSChartResource.DRAWICON.Icon.MinSize, //图标的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWICON.Icon.Zoom.Type , Value:g_JSChartResource.DRAWICON.Icon.Zoom.Value }, //放大倍数 YOffset:g_JSChartResource.DRAWICON.Icon.YOffset //Direction==2的向下偏移 }; this.TextSize= { Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWICON.Text.FontName, YOffset:g_JSChartResource.DRAWICON.Text.YOffset } this.Font= { DRAWTEXT_FIX:g_JSChartResource.DRAWTEXT_FIX.Font, DRAWNUMBER_FIX: g_JSChartResource.DRAWNUMBER_FIX.Font } this.ExportData=this.ExportBoolData; this.ReloadResource=function(resource) { if (this.Name=="DRAWTEXT") { this.TextSize= { Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWTEXT.FontName, YOffset:g_JSChartResource.DRAWTEXT.YOffset } } else if (this.Name=="DRAWNUMBER") { this.TextSize= { Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWNUMBER.FontName, YOffset:g_JSChartResource.DRAWNUMBER.YOffset } } else if (this.Name=="DRAWTEXT_FIX") { this.Font.DRAWTEXT_FIX=g_JSChartResource.DRAWTEXT_FIX.Font; } else if (this.Name=="DRAWNUMBER_FIX") { this.Font.DRAWNUMBER_FIX=g_JSChartResource.DRAWNUMBER_FIX.Font; } } this.SuperGetMaxMin=this.GetMaxMin; this.GetMaxMin=function() { if ( this.Name=="DRAWTEXT_FIX" || this.Name=='DRAWNUMBER_FIX') //固定位置的 没有大小值 { return { Min:null,Max:null }; } else if (this.Name=="DRAWTEXTREL" || this.Name=="DRAWTEXTABS") { return { Min:null,Max:null }; } else { return this.SuperGetMaxMin(); } } this.DrawRectText=function() { if (!this.DrawData) return; var isHScreen=(this.ChartFrame.IsHScreen===true) var border=this.ChartFrame.GetBorder(); if (this.Name=="DRAWTEXTREL") { if (isHScreen) { var height=border.RightTitle-border.LeftEx; var width=border.BottomEx-border.TopEx; var x=this.DrawData.Point.X/1000*width+border.TopEx; var y=border.RightTitle-this.DrawData.Point.Y/1000*width; } else { var width=border.RightEx-border.LeftEx; var height=border.BottomEx-border.TopTitle; var x=this.DrawData.Point.X/1000*width+border.LeftEx; var y=this.DrawData.Point.Y/1000*height+border.TopTitle; } } else if (this.Name=="DRAWTEXTABS") { if (isHScreen) { var x=this.DrawData.Point.X+border.TopEx; var y=border.RightTitle-this.DrawData.Point.Y; } else { var x=this.DrawData.Point.X+border.LeftEx; var y=this.DrawData.Point.Y+border.TopTitle; } } else { return; } if (this.Direction==1) this.Canvas.textBaseline='bottom'; else if (this.Direction==2) this.Canvas.textBaseline='top'; else this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.font=this.TextFont; this.Canvas.fillStyle=this.Color; this.DrawText(this.DrawData.Text,x,y,isHScreen); } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (this.Name=="DRAWTEXTREL" || this.Name=="DRAWTEXTABS") { this.DrawRectText(); return; } if (this.Position) { this.DrawPosition(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true) var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=this.ChartBorder.GetRight(); var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); this.Canvas.save(); this.ClipClient(this.ChartFrame.IsHScreen); if (isHScreen) { chartright=this.ChartBorder.GetBottom(); top=this.ChartBorder.GetRightEx(); bottom=this.ChartBorder.GetLeftEx(); xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } var xPointCount=this.ChartFrame.XPointCount; var isArrayText=Array.isArray(this.Text); var pixelTatio = GetDevicePixelRatio(); var drawTextInfo={ Text:{ }, Font:{ } }; if (this.Direction==1) { this.Canvas.textBaseline='bottom'; drawTextInfo.Text={ Baseline: 'bottom'}; } else if (this.Direction==2) { this.Canvas.textBaseline='top'; drawTextInfo.Text={ Baseline: 'top'}; } else { this.Canvas.textBaseline='middle'; drawTextInfo.Text={ Baseline: 'middle'}; } if (this.IconFont) { this.Color=this.IconFont.Color; this.Text=this.IconFont.Text; if (this.FixedFontSize>0) var iconSize=this.FixedFontSize; else var iconSize=this.GetDynamicIconSize(dataWidth,distanceWidth,this.IconSize.Max,this.IconSize.Min,this.IconSize.Zoom); this.Canvas.font=iconSize+'px '+this.IconFont.Family; } else { if (this.FixedFontSize>0) this.TextFont=`${this.FixedFontSize}px ${this.TextSize.FontName}`; else this.TextFont=this.GetDynamicFont(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName); this.Canvas.font=this.TextFont; } drawTextInfo.Font={ Height:this.GetFontHeight() }; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } var y=this.ChartFrame.GetYFromData(value,false); if (x>chartright) break; y+=this.ShowOffset.Y; x+=this.ShowOffset.X; this.Canvas.textAlign=this.TextAlign; this.Canvas.fillStyle=this.Color; drawTextInfo.Text.Color=this.Color; drawTextInfo.Text.Align=this.TextAlign; drawTextInfo.X=x; drawTextInfo.Y=y; if (this.YOffset>0 && this.Direction>0) { var yPrice=y; this.Canvas.setLineDash([5,10]); this.Canvas.strokeStyle=this.Color; this.Canvas.beginPath(); if (isHScreen) { if (this.Direction==1) { y=top-this.YOffset*pixelTatio; yPrice+=5*pixelTatio; } else { y=bottom+this.YOffset*pixelTatio; yPrice-=5*pixelTatio; } this.Canvas.moveTo(ToFixedPoint(yPrice),ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(x)); } else { if (this.Direction==1) { y=top+this.YOffset*pixelTatio; yPrice+=5*pixelTatio; } else { y=bottom-this.YOffset*pixelTatio; yPrice-=5*pixelTatio; } this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yPrice)); this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(y)); } this.Canvas.stroke(); this.Canvas.setLineDash([]); } if (isArrayText) { var text=this.Text[i]; if (!text) continue; if (this.Name=='DRAWNUMBER') { if (this.Direction==1) y-=g_JSChartResource.DRAWABOVE.YOffset*pixelTatio; else if (this.Direction==2) y+=this.TextSize.YOffset*pixelTatio; } if (this.Name=="DRAWTEXT") this.DrawTextV2(text,drawTextInfo,isHScreen); else this.DrawText(text,x,y,isHScreen); } else { if (this.Name=='DRAWICON') { if (this.Direction==1) y-=g_JSChartResource.DRAWABOVE.YOffset*pixelTatio; else if (this.Direction==2) { if (this.IconFont) y+=this.IconSize.YOffset*pixelTatio; else y+=this.TextSize.YOffset*pixelTatio; } } else if (this.Name=="DRAWTEXT") { if (this.Direction==1) y-=g_JSChartResource.DRAWABOVE.YOffset*pixelTatio; else if (this.Direction==2) y+=this.TextSize.YOffset*pixelTatio; } if (this.Name=="DRAWTEXT") { this.DrawTextV2(this.Text,drawTextInfo,isHScreen); } else { this.DrawText(this.Text,x,y,isHScreen); } } } this.Canvas.restore(); } this.DrawPosition=function() //绘制在指定位置上 { if (!this.Text) return; var isHScreen=(this.ChartFrame.IsHScreen===true) if (isHScreen) { var y=this.ChartBorder.GetRightEx()-this.ChartBorder.GetWidthEx()*this.Position.Y; var x=this.ChartBorder.GetTop()+this.ChartBorder.GetHeight()*this.Position.X; } else { var x=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*this.Position.X; var y=this.ChartBorder.GetTopEx()+this.ChartBorder.GetHeightEx()*this.Position.Y; } this.Canvas.fillStyle=this.Color; if (this.Name=="DRAWTEXT_FIX") this.Canvas.font=this.Font.DRAWTEXT_FIX; else if (this.Name=="DRAWNUMBER_FIX") this.Canvas.font=this.Font.DRAWNUMBER_FIX; //TYPE:0为左对齐,1为右对齐. if (this.Position.Type==0) this.Canvas.textAlign='left'; else if (this.Position.Type==1) this.Canvas.textAlign='right'; else this.Canvas.textAlign='center'; if (this.Direction==1) this.Canvas.textBaseline='bottom'; else if (this.Direction==2) this.Canvas.textBaseline='top'; else this.Canvas.textBaseline='middle'; if (Array.isArray(this.Text)) { if (!this.Data || !this.Data.Data) return; var xPointCount=this.ChartFrame.XPointCount; for(var i=this.Data.DataOffset,j=0; ichartright) break; var x=left+(right-left)/2; var y=this.GetYFromData(iconItem.Value, false); this.Canvas.fillStyle=iconItem.Color; if (dataWidth>2) x=ToFixedPoint(x); this.DrawTradeIcon(iconItem.Icon,x,y+yOffset, bHScreen); } } this.DrawTradeIcon=function(text,x,y,isHScreen) { if (isHScreen) { this.Canvas.save(); this.Canvas.translate(y, x); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,0,0); this.Canvas.restore(); } else { this.Canvas.fillText(text,x,y); } } this.GetMaxMin=function() { var range={Max:null, Min:null }; if(!this.Data || !this.Data.Data) return range; if (!IFrameSplitOperator.IsNonEmptyArray(this.AryIcon)) return range; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; if (this.ChartFrame.GlobalOption && this.ChartFrame.GlobalOption.IsValueFullRange) { start=0; xPointCount=this.Data.Data.length; } for(var i=start,j=0;iiconItem.Value) range.Min=iconItem.Value; } return range; } } function ChartDrawText() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawText'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.TextFont="14px 微软雅黑"; //线段宽度 this.TextBaseline="middle"; this.TextAlign='left'; this.Text this.TextBG; //{ Color:"rgb(0,0,92)", Border:"rgb(205,0,92)", Margin:[0,1,1,1], } // { Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] } this.FixedFontSize=-1; //固定字体大小 this.YOffset=0; //连线 this.FixedPosition=-1; //固定位置输出 1顶部, 2底部 this.VerticalLine; //垂直线 this.ShowOffset={ X:0, Y:0 }; //显示偏移 this.ExportData=this.ExportBoolData; this.TextSize= { Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWICON.Text.FontName, YOffset:g_JSChartResource.DRAWICON.Text.YOffset } this.ReloadResource=function(resource) { this.TextSize= { Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWTEXT.FontName, YOffset:g_JSChartResource.DRAWTEXT.YOffset } } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true) var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=this.ChartBorder.GetRight(); var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); this.Canvas.save(); this.ClipClient(isHScreen); if (isHScreen) { chartright=this.ChartBorder.GetBottom(); top=this.ChartBorder.GetRightEx(); bottom=this.ChartBorder.GetLeftEx(); xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } var xPointCount=this.ChartFrame.XPointCount; var isArrayText=Array.isArray(this.Text); var drawTextInfo={ Text:{ Color:this.Color, Align:this.TextAlign, Baseline:this.TextBaseline }, Font:{ } }; if (this.FixedFontSize>0) //固定字体大小模式 this.TextFont=`${this.FixedFontSize}px ${this.TextSize.FontName}`; else //动态字体大小 this.TextFont=this.GetDynamicFont(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName); this.Canvas.font=this.TextFont; drawTextInfo.Font={ Height:this.GetFontHeight() }; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } var y; if (this.FixedPosition===1) { y=top; } else if (this.FixedPosition===2) { y=bottom; } else { y=this.ChartFrame.GetYFromData(value,false); } if (x>chartright) break; y+=this.ShowOffset.Y; x+=this.ShowOffset.X; drawTextInfo.X=x; drawTextInfo.Y=y; if (isArrayText) { var text=this.Text[i]; if (!text) continue; this.DrawText(text,drawTextInfo,isHScreen); } else { this.DrawText(this.Text,drawTextInfo,isHScreen); } this.DrawVerticalLine(i, drawTextInfo, isHScreen); } this.Canvas.restore(); } this.DrawText=function(text, drawInfo, isHScreen) { var textWidth=this.Canvas.measureText(text).width; if (isHScreen) { var x=drawInfo.Y; var y=drawInfo.X; if (drawInfo.Text.Align=="right") y=y-textWidth; else if (drawInfo.Text.Align=="center") y=y-textWidth/2; if (drawInfo.Text.Baseline=="top") x-=drawInfo.Font.Height; else if (drawInfo.Text.Baseline=="middle") x-=drawInfo.Font.Height/2; if (this.TextBG && (this.TextBG.Color || this.TextBG.Border)) { var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右 var xRect=x-margin[0]; var yRect=y-margin[2]; var bgWidth=textWidth+margin[2]+margin[3]; var bgHeight=drawInfo.Font.Height+margin[0]+margin[1]; if (this.TextBG.Color) { this.Canvas.fillStyle=this.TextBG.Color; this.Canvas.fillRect(xRect,yRect,bgHeight,bgWidth); } if (this.TextBG.Border) { this.Canvas.strokeStyle=this.TextBG.Border; this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgHeight),ToFixedRect(bgWidth)); } drawInfo.Rect={Bottom:xRect, Top:xRect+bgHeight }; } else { var xRect=x; var bgHeight=drawInfo.Font.Height; drawInfo.Rect={Bottom:xRect, Top:xRect+bgHeight }; } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=drawInfo.Text.Color; this.Canvas.save(); this.Canvas.translate(x, y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,0,0); this.Canvas.restore(); } else { var x=drawInfo.X; var y=drawInfo.Y; if (drawInfo.Text.Align=="right") x=x-textWidth; else if (drawInfo.Text.Align=="center") x=x-textWidth/2; if (drawInfo.Text.Baseline=="top") y+=drawInfo.Font.Height; else if (drawInfo.Text.Baseline=="middle") y+=drawInfo.Font.Height/2; if (this.TextBG && (this.TextBG.Color || this.TextBG.Border)) { var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右 var xRect=x-margin[2]; var yRect=y-drawInfo.Font.Height-margin[1]; var bgWidth=textWidth+margin[2]+margin[3]; var bgHeight=drawInfo.Font.Height+margin[0]+margin[1]; if (this.TextBG.Color) { this.Canvas.fillStyle=this.TextBG.Color; this.Canvas.fillRect(xRect,yRect,bgWidth,bgHeight); } if (this.TextBG.Border) { this.Canvas.strokeStyle=this.TextBG.Border; this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgWidth),ToFixedRect(bgHeight)); } drawInfo.Rect={Top:yRect, Bottom:yRect+bgHeight }; } else { var yRect=y-drawInfo.Font.Height; var bgHeight=drawInfo.Font.Height; drawInfo.Rect={Top:yRect, Bottom:yRect+bgHeight }; } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=drawInfo.Text.Color; this.Canvas.fillText(text,x,y); } } //画连线 this.DrawVerticalLine=function(index, drawTextInfo, isHScreen) { if (!this.VerticalLine) return; var item=this.VerticalLine.Data[index]; if (!item) return; if (!IFrameSplitOperator.IsNumber(item.High)) return; if (!IFrameSplitOperator.IsNumber(item.Low)) return; var yHigh=this.ChartFrame.GetYFromData(item.High); var yLow=this.ChartFrame.GetYFromData(item.Low); var yLine, yLine2; if (isHScreen) { if (drawTextInfo.Rect.Bottom>yHigh) { yLine=drawTextInfo.Rect.Bottom-1; yLine2=yHigh+1; } else if (drawTextInfo.Rect.TopyLow) { yLine=drawTextInfo.Rect.Top-1; yLine2=yLow+1; } else { return; } } this.Canvas.save(); var pixelTatio = GetDevicePixelRatio(); var xLine=drawTextInfo.X; if (this.VerticalLine.LineType==1) { if (this.VerticalLine.LineDotted) this.Canvas.setLineDash(this.VerticalLine.LineDotted); else this.Canvas.setLineDash([5,10]); } if (IFrameSplitOperator.IsPlusNumber(this.VerticalLine.LineWidth)) { this.Canvas.lineWidth=this.VerticalLine.LineWidth*pixelTatio; } this.Canvas.strokeStyle=this.VerticalLine.Color; this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(ToFixedPoint(yLine),ToFixedPoint(xLine)); this.Canvas.lineTo(ToFixedPoint(yLine2),ToFixedPoint(xLine)); } else { this.Canvas.moveTo(ToFixedPoint(xLine),ToFixedPoint(yLine)); this.Canvas.lineTo(ToFixedPoint(xLine),ToFixedPoint(yLine2)); } this.Canvas.stroke(); this.Canvas.restore(); } } function ChartDrawNumber() { this.newMethod=ChartDrawText; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawNumber'; //类名 this.ReloadResource=function(resource) { this.TextSize= { Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数 FontName:g_JSChartResource.DRAWNUMBER.FontName, YOffset:g_JSChartResource.DRAWNUMBER.YOffset } } } //直线 水平直线 只有1个数据 function ChartStraightLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartStraightLine'; //类名 this.Color="rgb(255,193,37)"; //线段颜色 this.Draw=function() { if (!this.Data || !this.Data.Data) return; if (this.Data.Data.length!=1) return; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; var yValue=this.Data.Data[0]; var y=this.ChartFrame.GetYFromData(yValue); var xLeft=this.ChartFrame.GetXFromIndex(0); var xRight=this.ChartFrame.GetXFromIndex(xPointCount-1); var yFix=parseInt(y.toString())+0.5; this.Canvas.beginPath(); this.Canvas.moveTo(xLeft,yFix); this.Canvas.lineTo(xRight,yFix); this.Canvas.strokeStyle=this.Color; this.Canvas.stroke(); } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; if (!this.Data || !this.Data.Data) return range; if (this.Data.Data.length!=1) return range; range.Min=this.Data.Data[0]; range.Max=this.Data.Data[0]; return range; } } /* 水平面积 只有1个数据 Data 数据结构 Value, Value2 区间最大最小值 Color=面积的颜色 Title=标题 TitleColor=标题颜色 支持横屏 */ function ChartStraightArea() { this.newMethod = IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartStraightArea'; //类名 this.Color = "rgb(255,193,37)"; //线段颜色 this.Font ='11px 微软雅黑'; this.Draw = function () { if (this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; if (this.ChartFrame.IsHScreen===true) { this.HScreenDraw(); return; } var dataWidth = this.ChartFrame.DataWidth; var distanceWidth = this.ChartFrame.DistanceWidth; var chartright = this.ChartBorder.GetRight(); var bottom = this.ChartBorder.GetBottom(); var left = this.ChartBorder.GetLeft(); var xPointCount = this.ChartFrame.XPointCount; var xRight = this.ChartFrame.GetXFromIndex(xPointCount - 1); for(let i in this.Data.Data) { let item=this.Data.Data[i]; if (item==null || isNaN(item.Value) || isNaN(item.Value2)) continue; if (item.Color==null) continue; let valueMax=Math.max(item.Value,item.Value2); let valueMin=Math.min(item.Value,item.Value2); var yTop=this.ChartFrame.GetYFromData(valueMax); var yBottom=this.ChartFrame.GetYFromData(valueMin); this.Canvas.fillStyle = item.Color; this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(yTop), ToFixedRect(xRight - left), ToFixedRect(yBottom - yTop)); if(item.Title && item.TitleColor) { this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = item.TitleColor; this.Canvas.font = this.Font; let y = yTop + (yBottom - yTop)/2; this.Canvas.fillText(item.Title, xRight, y); } } } this.HScreenDraw=function() { var bottom = this.ChartBorder.GetBottom(); var top=this.ChartBorder.GetTop(); var height=this.ChartBorder.GetHeight(); for(let i in this.Data.Data) { let item=this.Data.Data[i]; if (item==null || isNaN(item.Value) || isNaN(item.Value2)) continue; if (item.Color==null) continue; let valueMax=Math.max(item.Value,item.Value2); let valueMin=Math.min(item.Value,item.Value2); var yTop=this.ChartFrame.GetYFromData(valueMax); var yBottom=this.ChartFrame.GetYFromData(valueMin); this.Canvas.fillStyle = item.Color; this.Canvas.fillRect(ToFixedRect(yBottom), ToFixedRect(top), ToFixedRect(yTop-yBottom),ToFixedRect(height)); if(item.Title && item.TitleColor) { var xText=yTop + (yBottom - yTop)/2; var yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = item.TitleColor; this.Canvas.font = this.Font; this.Canvas.fillText(item.Title, 0, -2); this.Canvas.restore(); } } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; if (!this.Data || !this.Data.Data) return range; for (let i in this.Data.Data) { let item = this.Data.Data[i]; if (item==null || isNaN(item.Value) || isNaN(item.Value2)) continue; let valueMax=Math.max(item.Value,item.Value2); let valueMin=Math.min(item.Value,item.Value2); if (range.Max==null) range.Max=valueMax; if (range.Min==null) range.Min=valueMin; if (range.MaxvalueMin) range.Min=valueMin; } return range; } } //分钟线 支持横屏 function ChartMinutePriceLine() { this.newMethod=ChartLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartMinutePriceLine'; //类名 this.YClose; this.IsDrawArea=true; //是否画价格面积图 this.AreaColor='rgba(0,191,255,0.1)'; this.IsShowLead=false; this.LeadData; this.UpColor=g_JSChartResource.UpBarColor; this.DownColor=g_JSChartResource.DownBarColor; this.BeforeOpenData; //盘前数据 Data:[] 数据, TotalCount:一共的数据个数 this.BeforeLineColor=g_JSChartResource.Minute.Before.LineColor; this.BeforeAvPriceColor=g_JSChartResource.Minute.Before.AvPriceColor; this.BeforePoint=CloneData(g_JSChartResource.Minute.Before.Point); this.AfterCloseData; //盘后数据 this.AfterLineColor=g_JSChartResource.Minute.After.LineColor; this.AfterAvPriceColor=g_JSChartResource.Minute.After.AvPriceColor; this.AfterPoint=CloneData(g_JSChartResource.Minute.After.Point); this.MultiDayBeforeOpenData; //多日分时图 盘前数据 数组 1天一个 this.MultiDayAfterCloseData; //多日分时图 盘后数据 数组 1天一个 this.ColorLineData; //自定义价格线分段颜色 this.Source; //原始分钟数据 this.PtInChart=this.PtInLine; this.DrawSelectedStatus=this.DrawLinePoint; this.PtInChart=this.PtInLine; this.DrawSelectedStatus=this.DrawLinePoint; this.DayOffset; this.LastPoint={}; //最后一个点的信息 {X, Y, Data:, Value:, DateTime:YYYYMMDDHHMMSS } this.FFMChart; //定制图形 this.DrawType=0; //0=走势图 14=定制图形 this.UpdateLastPoint=function(dateTime, x,y, item) { if (IFrameSplitOperator.IsNumber(this.LastPoint.DateTime) && this.LastPoint.DateTime>dateTime) return; this.LastPoint.DateTime=dateTime; this.LastPoint.X=x; this.LastPoint.Y=y; this.LastPoint.Data=item; this.LastPoint.Value=item.Value; } this.Draw=function() { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } this.LastPoint={}; if (!this.IsShow) return; if (this.DrawType==14) { if (this.FFMChart && this.FFMChart.Draw) this.FFMChart.Draw(this); return; } var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); if (isHScreen===true) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var minuteCount=this.ChartFrame.MinuteCount; var bottom=this.ChartBorder.GetBottom(); var left=this.ChartBorder.GetLeft(); var data=this.Data; this.DrawBeforeOpen(); //盘前 this.DrawMultiDayBeforeOpen(); if (this.IsShowLead) this.DrawLead(); //领先指标 if (!data) return; var bFirstPoint=true; var ptFirst={}; //第1个点 var drawCount=0; var pointCount=0; this.Canvas.save(); if (IFrameSplitOperator.IsPlusNumber(this.LineWidth>0)) this.Canvas.lineWidth=this.LineWidth; for(var i=data.DataOffset,j=0;i=minuteCount) //上一天的数据和这天地数据线段要断开 { bFirstPoint=true; this.Canvas.stroke(); if (this.IsDrawArea) //画面积 { if (isHScreen) { this.Canvas.lineTo(left,x); this.Canvas.lineTo(left,ptFirst.X); this.SetFillStyle(this.AreaColor,this.ChartBorder.GetRightEx(),bottom,this.ChartBorder.GetLeftEx(),bottom); } else { this.Canvas.lineTo(x,bottom); this.Canvas.lineTo(ptFirst.X,bottom); this.SetFillStyle(this.AreaColor, left,this.ChartBorder.GetTopEx(), left,bottom); } this.Canvas.fill(); } pointCount=0; drawCount=0; } } if (drawCount>0) { if (drawCount==1) //如果线段只有1个点 线段无法画出来 直接画点 { this.Canvas.beginPath(); if (isHScreen) this.Canvas.arc(ptFirst.Y, ptFirst.X, 1,0,360, false); else this.Canvas.arc(ptFirst.X, ptFirst.Y, 1,0,360, false); this.Canvas.closePath(); this.Canvas.fillStyle=this.Color; this.Canvas.fill(); } else { this.Canvas.stroke(); if (this.IsDrawArea) //画面积 { if (isHScreen) { this.Canvas.lineTo(left,x); this.Canvas.lineTo(left,ptFirst.X); this.SetFillStyle(this.AreaColor,this.ChartBorder.GetRightEx(),bottom,this.ChartBorder.GetLeftEx(),bottom); } else { this.Canvas.lineTo(x,bottom); this.Canvas.lineTo(ptFirst.X,bottom); this.SetFillStyle(this.AreaColor,left,this.ChartBorder.GetTopEx(), left,bottom); } this.Canvas.fill(); } } } this.Canvas.restore(); this.DrawColorLine(); this.DrawAfterClose(); //收盘集合竞价 this.DrawMultiDayAfterClose(); if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_MINUTE_LAST_POINT); if (event) { var pixelRatio=GetDevicePixelRatio(); var data= { InterLastPoint:{X:this.LastPoint.X, Y:this.LastPoint.Y}, //内部点 给画布用 LastPoint:{X:this.LastPoint.X/pixelRatio, Y:this.LastPoint.Y/pixelRatio}, //外部点 给DOM用 Price:this.LastPoint.Price, Data:this.LastPoint.Data, PixelRatio:pixelRatio, }; event.Callback(event,data,this); } } } //画领先指标 this.DrawLead=function() { if (!this.LeadData) return; var isHScreen=(this.ChartFrame.IsHScreen===true); //if (isHScreen) return; //var dataWidth=this.ChartFrame.DataWidth; //var distanceWidth=this.ChartFrame.DistanceWidth; //var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; var minuteCount=this.ChartFrame.MinuteCount; var bottom=this.ChartBorder.GetBottomEx(); var top=this.ChartBorder.GetTopEx(); if (isHScreen===true) top=this.ChartBorder.GetRightEx(); if (xPointCount>minuteCount) return; var aryLead=[]; //{X: Value:} var max=null, min=null; var yCenter=this.ChartFrame.GetYFromData(this.YClose); var leadHeight=(yCenter-top)/3; var data=this.LeadData; for(var i=data.DataOffset,j=0;ivalue) min=value; aryLead.push({X:x, Value:value}) } if (aryLead.length<=0) return; var maxValue=Math.max(Math.abs(max),Math.abs(min)); for(var i in aryLead) { var item=aryLead[i]; if (item.Value>0) this.Canvas.strokeStyle=this.UpColor; else this.Canvas.strokeStyle=this.DownColor; var y=yCenter-(item.Value*leadHeight/maxValue); var x=ToFixedPoint(item.X); this.Canvas.beginPath(); if (isHScreen===true) { this.Canvas.moveTo(yCenter,x); this.Canvas.lineTo(y,x); } else { this.Canvas.moveTo(x,yCenter); this.Canvas.lineTo(x,y); } this.Canvas.stroke(); } } this.DrawBeforeOpen=function() { if (this.ChartBorder.LeftExtendWidth<10) return; if (!this.BeforeOpenData) return; this.DrawCallAuction(-1, this.BeforeOpenData, true); } this.DrawAfterClose=function() { if (this.ChartBorder.RightExtendWidth<10) return; if (!this.AfterCloseData) return; this.DrawCallAuction(-1, this.AfterCloseData, false); } this.DrawMultiDayBeforeOpen=function() { if (this.ChartBorder.MultiDayMinute.Count<=1 || this.ChartBorder.MultiDayMinute.Left<=0) return; if (!this.MultiDayBeforeOpenData) return; var offset=0, showDayCount=this.MultiDayBeforeOpenData.length; if (this.DayOffset) { if (IFrameSplitOperator.IsNumber(this.DayOffset.Offset)) offset=this.DayOffset.Offset; if (IFrameSplitOperator.IsNumber(this.DayOffset.ShowDayCount)) showDayCount=this.DayOffset.ShowDayCount; } for(var i=offset,j=0; i0) { this.Canvas.stroke(); } } var bFirstPoint=true; var drawCount=0; var aryPoint=[]; for(var i=0; i0) { this.Canvas.stroke(); } if (callAutionData.Ver==2.0 && this.BeforePoint.Radius>0) { this.Canvas.fillStyle=(isBeforeOpen? this.BeforePoint.Color : this.AfterPoint.Color); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.beginPath(); if (isHScreen) this.Canvas.arc(item.Y, item.X, this.BeforePoint.Radius, 0, 2 * Math.PI); else this.Canvas.arc(item.X, item.Y, this.BeforePoint.Radius, 0, 2 * Math.PI); this.Canvas.fill(); } } } this.FindColorLineItem=function(minuteItem) { if (!minuteItem || !this.ColorLineData) return null; for(var i in this.ColorLineData) { var item=this.ColorLineData[i]; if (item.Date==minuteItem.Date && (minuteItem.Time>=item.Start && minuteItem.Time<=item.End)) { return item; } } return null; } //TODO:这个函数比较耗时间 后面再优化吧 this.DrawColorLine=function() { if (!this.ColorLineData|| !this.Source || !this.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var border=this.ChartBorder.GetBorder(); var xPointCount=this.ChartFrame.XPointCount; var minuteCount=this.ChartFrame.MinuteCount; var data=this.Data; var bFirstPoint=true; var ptLast={}; //最后一个点 var ptFirst={}; var drawCount=0; var preColor=null; this.Canvas.save(); for(var i=data.DataOffset,j=0;i0) { this.Canvas.stroke(); bFirstPoint=true; } continue; } if (preColor && preColor!=colorItem.Color) { this.Canvas.stroke(); bFirstPoint=true; /* this.Canvas.strokeStyle=colorItem.Color; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(ptLast.Y,ptLast.X); else this.Canvas.moveTo(ptLast.X,ptLast.Y); bFirstPoint=false; preColor=colorItem.Color; */ } var x=this.ChartFrame.GetXFromIndex(j); var y=this.ChartFrame.GetYFromData(value); if (bFirstPoint) { this.Canvas.strokeStyle=colorItem.Color; if (IFrameSplitOperator.IsNumber(colorItem.LineWidth)) this.Canvas.lineWidth=colorItem.LineWidth; this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(y,x); else this.Canvas.moveTo(x,y); bFirstPoint=false; ptFirst={X:x,Y:y}; preColor=colorItem.Color; } else { if (isHScreen) this.Canvas.lineTo(y,x); else this.Canvas.lineTo(x,y); } ptLast.X=x; ptLast.Y=y; ptLast.Price=value; ++drawCount; } if (drawCount>0) { this.Canvas.stroke(); } this.Canvas.restore(); } this.GetMaxMin=function() { if (this.DrawType==14) { if (this.FFMChart && this.FFMChart.GetMaxMin) return this.FFMChart.GetMaxMin(this); } var xPointCount=this.ChartFrame.XPointCount; var range={}; if (this.YClose==null) return range; if (!this.IsShow) return range; range.Min=this.YClose; range.Max=this.YClose; if (this.ChartBorder.LeftExtendWidth>10 && this.BeforeOpenData) { for(var i in this.BeforeOpenData.Data) { var item=this.BeforeOpenData.Data[i]; if (!item) continue; if (IFrameSplitOperator.IsNumber(item.Price)) { if (range.Max==null) range.Max=item.Price; if (range.Min==null) range.Min=item.Price; if (range.Maxitem.Price) range.Min=item.Price; } //集合竞价均线统计 if (this.BeforeOpenData.Ver==3.0 && IFrameSplitOperator.IsNumber(item.AvPrice)) { if (range.Max==null) range.Max=item.AvPrice; if (range.Min==null) range.Min=item.AvPrice; if (range.Maxitem.AvPrice) range.Min=item.AvPrice; } } } //价格数据 var data=this.Data; for(var i=data.DataOffset,j=0;ivalue) range.Min=value; } if (range.Max==this.YClose && range.Min==this.YClose) { range.Max=this.YClose+this.YClose*0.1; range.Min=this.YClose-this.YClose*0.1; return range; } var distance=Math.max(Math.abs(this.YClose-range.Max),Math.abs(this.YClose-range.Min)); range.Max=this.YClose+distance; range.Min=this.YClose-distance; return range; } this.GetTooltipData=function(x,y,tooltip) { var isHScreen=(this.ChartFrame.IsHScreen===true); if (isHScreen) return false; if (!this.IsShow) return false; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var position=this.ChartBorder.PtInClient(x,y,this.Canvas,isHScreen); if (position!=1) return false; var data=this.Data; var index=this.ChartFrame.GetXData(x); var end=Math.ceil(index); var start=Math.floor(index); if (end>=data.Data.length || start>=data.Data.length) return false; var lineWidth=5; if (end==start) { var value=data.Data[start]; } else { var startValue=data.Data[start]; var endValue=data.Data[end]; var ptStart={X:this.ChartFrame.GetXFromIndex(start), Y:this.ChartFrame.GetYFromData(startValue)}; var ptEnd={X:this.ChartFrame.GetXFromIndex(end), Y:this.ChartFrame.GetYFromData(endValue)}; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth); this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth); this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) { tooltip.Data={ Index:index, Start:{ Index:start, Item:data.Data[start] }, End:{ Index:end, Value:data.Data[end]} }; tooltip.ChartPaint=this; tooltip.Type=5; //走势图线 return true; } } return false; } } //分钟线叠加 支持横屏 function ChartOverlayMinutePriceLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.Color="rgb(65,105,225)"; this.MainData; //主图数据 this.SourceData; //原始数据 this.ClassName="ChartOverlayMinutePriceLine"; this.Title; this.Symbol; //叠加的股票代码 this.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID; this.OverlayType=0; //叠加方式 0=百分比叠加 1=绝对叠加 this.IsCalcuateMaxMin=true; //是否参与计算Y轴的最大最小值 this.SetOption=function(option) { if (option) { if (IFrameSplitOperator.IsNumber(option.OverlayType)) this.OverlayType=option.OverlayType; if (IFrameSplitOperator.IsBool(option.IsCalcuateMaxMin)) this.IsCalcuateMaxMin=option.IsCalcuateMaxMin; } } this.PtInChart=function(x,y) { var option={ MinuteOverlayPrice:true, OverlayType:this.OverlayType }; return this.PtInLine(x, y, option); } this.DrawSelectedStatus=function() { var option={ MinuteOverlayPrice:true, OverlayType:this.OverlayType }; this.DrawLinePoint(option); } this.Draw=function() { if (!this.Data) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; 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===true) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var minuteCount=this.ChartFrame.MinuteCount; this.Canvas.save(); this.ClipClient(isHScreen); var bFirstPoint=true; var drawCount=0; var xOffset=0, showValue=0; var yClose=null, mainYClose=null; var pointCount=0; for(var i=this.Data.DataOffset+xOffset,j=0;i=minuteCount) //上一天的数据和这天地数据线段要断开 { bFirstPoint=true; pointCount=0; if (drawCount>0) this.Canvas.stroke(); drawCount=0; } } if (drawCount>0) this.Canvas.stroke(); this.Canvas.restore(); } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={ Min:null, Max:null }; if (!this.IsCalcuateMaxMin) return range; var minuteCount=this.ChartFrame.MinuteCount; var yClose=null, mainYClose=null; var bFirstPoint=true; var pointCount=0; for(var i=this.Data.DataOffset,j=0;ivalue) range.Min=value; ++pointCount; if (pointCount>=minuteCount) { bFirstPoint=true; pointCount=0; } } //JSConsole.Chart.Log(`[ChartOverlayMinutePriceLine::GetMaxMin] max=${range.Max} min=${range.Min}`); return range; } this.GetTooltipData=function(x,y,tooltip) { var isHScreen=(this.ChartFrame.IsHScreen===true); if (isHScreen) return false; if (!this.IsShow) return false; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; if (!IFrameSplitOperator.IsNumber(this.YClose) || !IFrameSplitOperator.IsNumber(this.MainYClose)) return false; var position=this.ChartBorder.PtInClient(x,y,this.Canvas,isHScreen); if (position!=1) return false; var data=this.Data; var index=this.ChartFrame.GetXData(x); var end=Math.ceil(index); var start=Math.floor(index); if (end>=data.Data.length || start>=data.Data.length) return false; var lineWidth=5; if (end==start) { var value=data.Data[start]; } else { var startValue=data.Data[start].Close startValue=startValue/this.YClose*this.MainYClose; var endValue=data.Data[end].Close endValue=endValue/this.YClose*this.MainYClose; var ptStart={X:this.ChartFrame.GetXFromIndex(start), Y:this.ChartFrame.GetYFromData(startValue)}; var ptEnd={X:this.ChartFrame.GetXFromIndex(end), Y:this.ChartFrame.GetYFromData(endValue)}; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth); this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth); this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) { tooltip.Data={ Index:index, Start:{ Index:start, Item:data.Data[start] }, End:{ Index:end, Value:data.Data[end]} }; tooltip.ChartPaint=this; tooltip.Type=6; //走势图线 //tooltip.Stock={Symbol:this.Symbol, Name:this.Title }; return true; } } return false; } } //分钟持仓线 function ChartMinutePositionLine() { this.newMethod=ChartLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartMinutePositionLine'; //类名 this.Draw=function() { if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.IsShow) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); if (isHScreen===true) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; var minuteCount=this.ChartFrame.MinuteCount; var bottom=this.ChartBorder.GetBottomEx(); var left=this.ChartBorder.GetLeftEx(); var data=this.Data; if (!data) return; var bFirstPoint=true; var ptFirst={}; //第1个点 var ptLast={}; //最后一个点 var drawCount=0; var pointCount=0; this.Canvas.save(); if (IFrameSplitOperator.IsPlusNumber(this.LineWidth>0)) this.Canvas.lineWidth=this.LineWidth; if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 for(var i=data.DataOffset,j=0;i=minuteCount) //上一天的数据和这天地数据线段要断开 { bFirstPoint=true; this.Canvas.stroke(); pointCount=0; drawCount=0; } } if (drawCount>0) { if (drawCount==1) //如果线段只有1个点 线段无法画出来 直接画点 { this.Canvas.beginPath(); if (isHScreen) this.Canvas.arc(ptFirst.Y, ptFirst.X, 1,0,360, false); else this.Canvas.arc(ptFirst.X, ptFirst.Y, 1,0,360, false); this.Canvas.closePath(); this.Canvas.fillStyle=this.Color; this.Canvas.fill(); } else { this.Canvas.stroke(); } } this.Canvas.restore(); } } //分钟信息地雷 支持横屏 function ChartMinuteInfo() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMinuteInfo"; this.Data=new Map() //Map key=date-time, value=[{Date, Time, Title, Type, ID:}] this.SourceData; this.ChartMinutePrice; this.YClose; this.HQChartBorder; this.TextColor=g_JSChartResource.MinuteInfo.TextColor; this.Font=g_JSChartResource.MinuteInfo.Font; this.PointColor=g_JSChartResource.MinuteInfo.PointColor; this.PointRadius=g_JSChartResource.MinuteInfo.PointRadius; this.LineColor=g_JSChartResource.MinuteInfo.LineColor; this.TextBGColor=g_JSChartResource.MinuteInfo.TextBGColor; this.PixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.TextHeight=20; this.TextRectCache=[]; this.InfoDrawCache=[]; this.FrameBottom; this.FrameTop; this.FrameLeft; this.FrameRight; this.YOffset=5; this.IsHScreen=false; this.IsDrawFull=false; //是否全屏画 this.TooltipRect=[]; //Rect this.SetOption=function(option) { if (option.TextColor) this.TextColor=option.TextColor; if (option.TextBGColor) this.TextBGColor=option.TextBGColor; if (option.Font) this.Font=option.Font; if (option.PointColor) this.PointColor=option.PointColor; if (option.LineColor) this.LineColor=option.LineColor; if (option.TextHeight>0) this.TextHeight=option.TextHeight; if (option.IsDrawFull==true) this.IsDrawFull=true; } this.Draw=function() { this.TooltipRect=[]; if (!this.ChartMinutePrice) return; if (!this.Data || this.Data.size<=0) return; this.TextRectCache=[]; this.InfoDrawCache=[]; this.PixelTatio=GetDevicePixelRatio(); this.YOffset=5*this.PixelTatio; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var minuteCount=this.ChartFrame.MinuteCount; this.FrameBottom=this.ChartBorder.GetBottom(); if (this.IsDrawFull && this.HQChartBorder) this.FrameBottom=this.HQChartBorder.GetBottom(); this.FrameTop=this.ChartBorder.GetTop(); this.FrameLeft=this.ChartBorder.GetLeft(); this.FrameRight=this.ChartBorder.GetRight(); if (this.IsHScreen) { this.FrameRight=this.ChartBorder.GetBottom(); this.FrameLeft=this.ChartBorder.GetTop(); this.FrameBottom=this.ChartBorder.GetLeft(); this.FrameTop=this.ChartBorder.GetRight(); } this.YClose=this.ChartMinutePrice.YClose; var data=this.ChartMinutePrice.Source; for(var i=data.DataOffset,j=0;ithis.YClose) xData.X=xData.X.reverse(); var rtBorder={X:null, Y:y, Width:textWidth,Height:textHeight}; if (!isDrawLeft) rtBorder.Y-=rtBorder.Height; this.FixHScreenTextRect(rtBorder,xData); var InfoDrawItem={ Border:rtBorder, Start:{X:x,Y:y}, IsLeft:isDrawLeft, Title:showItem.Title }; if (showItem.Content) InfoDrawItem.Content=showItem.Content; if (showItem.Link) InfoDrawItem.Link=showItem.Link; if (showItem.Color) InfoDrawItem.Color=showItem.Color; if (showItem.BGColor) InfoDrawItem.BGColor=showItem.BGColor; this.InfoDrawCache.push(InfoDrawItem); this.TextRectCache.push(rtBorder); } this.DrawInfoLines=function(item) { var rtBorder=item.Border; var isDrawLeft=item.IsLeft; this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(item.Start.X),item.Start.Y); if (isDrawLeft) { this.Canvas.lineTo(ToFixedPoint(item.Start.X),rtBorder.Y); } else { if (this.IsHScreen) this.Canvas.lineTo(rtBorder.X,rtBorder.Y+rtBorder.Height); else this.Canvas.lineTo(ToFixedPoint(item.Start.X),rtBorder.Y); } this.Canvas.stroke(); this.Canvas.fillStyle = this.PointColor; this.Canvas.beginPath(); this.Canvas.arc(item.Start.X,item.Start.Y, this.PointRadius, 0, 2 * Math.PI); this.Canvas.closePath(); this.Canvas.fill(); } this.DrawInfoText=function(item) { var rtBorder=item.Border; var x=rtBorder.X, y=rtBorder.Y; if (item.BGColor) this.Canvas.fillStyle=item.BGColor else this.Canvas.fillStyle=this.TextBGColor; this.Canvas.fillRect(x, y, rtBorder.Width,rtBorder.Height); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.rect(x,y,rtBorder.Width,rtBorder.Height); this.Canvas.stroke(); if (this.IsHScreen) { this.Canvas.save(); this.Canvas.translate(rtBorder.X,rtBorder.Y); this.Canvas.rotate(90 * Math.PI / 180); x=0;y=0; } this.Canvas.textAlign = 'left' this.Canvas.textBaseline = 'middle'; if (item.Color) this.Canvas.fillStyle=item.Color; else this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; if (this.IsHScreen) this.Canvas.fillText(item.Title, x+2*this.PixelTatio, y-rtBorder.Width/2); else this.Canvas.fillText(item.Title, x+2*this.PixelTatio, y+rtBorder.Height/2); if (this.IsHScreen) this.Canvas.restore(); } this.FixTextRect=function(rect,yData) { for(var k in yData.Y) { var yItem=yData.Y[k]; rect.Y=yItem.Value; var y; for(var j=0;j<10;++j) { var isOverlap=false; for(var i in this.TextRectCache) { var item=this.TextRectCache[i]; if (this.IsOverlap(item, rect)) { isOverlap=true; break; } } if (isOverlap==false) return; y=rect.Y; y+=yItem.Offset; if (y+rect.Height>this.FrameBottom || ythis.FrameTop) break; rect.X=x; } } } this.IsOverlap=function(rc1, rc2) { if (rc1.X + rc1.Width > rc2.X &&rc2.X + rc2.Width > rc1.X &&rc1.Y + rc1.Height > rc2.Y &&rc2.Y + rc2.Height > rc1.Y) return true; else return false; } this.GetMaxMin=function() { var range={Min:null, Max:null}; return range; } this.GetTooltipData=function(x,y,tooltip) { for(var i in this.TooltipRect) { var item=this.TooltipRect[i]; if (!item.Rect) continue; var rect=item.Rect; this.Canvas.beginPath(); this.Canvas.rect(rect.X,rect.Y,rect.Width,rect.Height); if (this.Canvas.isPointInPath(x,y)) { //JSConsole.Chart.Log('[ChartMinuteInfo::GetTooltipData] info ', item); tooltip.Data=item; tooltip.ChartPaint=this; tooltip.Type=3; //异动信息 return true; } } return false; } } //MACD森林线 支持横屏 function ChartMACD() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMACD"; this.UpColor=g_JSChartResource.UpBarColor; this.DownColor=g_JSChartResource.DownBarColor; this.LineWidth=1; this.DrawSelectedStatus=this.DrawLinePoint; this.ExportData=this.ExportArrayData; this.PtInChart=function(x,y) { var dataWidth=this.ChartFrame.DataWidth; var barWidth=this.LineWidth*GetDevicePixelRatio(); if (this.barWidth==50) barWidth=null; else if (barWidth>dataWidth) barWidth=dataWidth; if (barWidth<4) barWidth=4; //宽度太小了点不到 return this.PtInBar(x, y, { BarWidth:barWidth }) } this.DrawBars=function(lineWidth, bUpBar) { var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var isHSCreen=this.ChartFrame.IsHScreen===true; if (isHSCreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var lockRect=this.GetLockRect(); if (lockRect) chartright=lockRect.Top; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var lockRect=this.GetLockRect(); if (lockRect) chartright=lockRect.Left; } if (bUpBar) this.Canvas.strokeStyle=this.UpColor; else this.Canvas.strokeStyle=this.DownColor; var yBottom=this.ChartFrame.GetYFromData(0); this.Canvas.beginPath(); var drawCount=0; for(var i=this.Data.DataOffset,j=0;i=0) continue; } if (isMinute) { var x=this.ChartFrame.GetXFromIndex(j); } else { var left=xOffset; var right=xOffset+dataWidth; if (right>chartright) break; var x=left+(right-left)/2; } if (x>chartright) break; var y=this.ChartFrame.GetYFromData(value); var xFix=ToFixedPoint2(lineWidth, x); //毛边修正 if (isHSCreen) { this.Canvas.moveTo(yBottom,ToFixedPoint(x)); this.Canvas.lineTo(y,ToFixedPoint(x)); } else { this.Canvas.moveTo(xFix,yBottom); this.Canvas.lineTo(xFix,y); } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } var dataWidth=this.ChartFrame.DataWidth; var lineWidth=this.LineWidth*GetDevicePixelRatio(); if (this.LineWidth==50) lineWidth=dataWidth; else if (lineWidth>dataWidth) lineWidth=dataWidth; var backupLineWidth=this.Canvas.lineWidth; this.Canvas.lineWidth=lineWidth; //上下分开画 this.DrawBars(lineWidth, true); this.DrawBars(lineWidth, false); this.Canvas.lineWidth=backupLineWidth; } this.GetItemData=function(indexData) { if (!indexData) return null; if (!IFrameSplitOperator.IsNumber(indexData.Index)) return null; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null; var index=indexData.Index; if (index<0 || index>=this.Data.Data.length) return null; var item=this.Data.Data[index]; return [ { Value:item, Color:item>0 ? this.UpColor:this.DownColor, Name: this.Name } ]; } } function ChartClipColorStick() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartClipColorStick"; this.UpColor=g_JSChartResource.UpBarColor; this.DownColor=g_JSChartResource.DownBarColor; this.LineWidth=1; this.Style=0; //1=同方向 0=上下两个方向 //差值线 this.DownDiffColor=g_JSChartResource.DownBarColor; this.UpDiffColor=g_JSChartResource.UpBarColor; //文字 this.TextLabelConfig= { Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextMargin:{ Left:2, Right:2, Bottom:2, Top:2 }, TextColor:"rgb(230,230,230)", UpColor:"rgb(137,16,19)", DownColor:"rgb(44,104,57)", UnchangeColor:"rgb(111,112,115)", BorderColor:"rgb(0,0,0)", //缓存 LabelWidth:0, TextHeight:0, MaxTextWidth:0, } this.BaseLineColor; //基准线 this.BaseValue=0; this.Super_GetMaxMin=this.GetMaxMin; //父类的方法 this.ValueRange; //{ Max:, Min: } //固定最大最小值 this.IsShowText=false; this.SetOption=function(option) { if (!option) return; if (option.UpColor) this.UpColor=option.UpColor; if (option.DownColor) this.DownColor=option.DownColor; if (option.DownDiffColor) this.DownDiffColor=option.DownDiffColor; if (option.UpDiffColor) this.UpDiffColor=option.UpDiffColor; if (option.BaseLineColor) this.BaseLineColor=option.BaseLineColor; if (IFrameSplitOperator.IsNumber(option.BaseValue)) this.BaseValue=option.BaseValue; if (IFrameSplitOperator.IsNumber(option.Style)) this.Style=option.Style; if (option.ValueRange) this.ValueRange=option.ValueRange; } this.Draw=function() { this.IsShowText=false; this.TextLabelConfig.LabelWidth=0; this.TextLabelConfig.TextHeight=0; this.TextLabelConfig.MaxTextWidth=0; if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var bHScreen=this.ChartFrame.IsHScreen===true; var lineWidth=this.LineWidth*GetDevicePixelRatio(); if (this.LineWidth==50) lineWidth=dataWidth; else if (lineWidth>dataWidth) lineWidth=dataWidth; if (!bHScreen) { var itemWidth=dataWidth+distanceWidth; var bMinute=this.IsMinuteFrame(); if (bMinute) { var border=this.ChartBorder.GetBorder(); itemWidth=(border.Right-border.Left)/(xPointCount-1); } this.Canvas.font=this.TextLabelConfig.Font; this.TextLabelConfig.MaxTextWidth=this.Canvas.measureText("-888").width; this.TextLabelConfig.LabelWidth=this.TextLabelConfig.MaxTextWidth+this.TextLabelConfig.TextMargin.Left+this.TextLabelConfig.TextMargin.Right; this.IsShowText=itemWidth>this.TextLabelConfig.LabelWidth; this.TextLabelConfig.TextHeight=this.Canvas.measureText("擎").width; } this.Canvas.save(); if (IFrameSplitOperator.IsNumber(this.BaseValue) && this.BaseValue!=0) { this.DrawBaseLine(); if (this.BaseValue>0) this.DrawBars(lineWidth, true, true); else this.DrawBars(lineWidth, false, true); } else { //上下分开画 this.DrawBars(lineWidth, true, true); this.DrawBars(lineWidth, false); } this.Canvas.restore(); } this.DrawBars=function(lineWidth, bUpBar, bDrawLabel) { var isMinute=this.IsMinuteFrame(); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var bHScreen=this.ChartFrame.IsHScreen===true; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; var lockRect=this.GetLockRect(); if (lockRect) chartright=lockRect.Top; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var lockRect=this.GetLockRect(); if (lockRect) chartright=lockRect.Left; } var yBottom=this.ChartFrame.GetYFromData(this.BaseValue); var aryBar=[], aryDiffBar=[], aryText=[]; var preValue=null; var start=this.Data.DataOffset; if (start-1>0) preValue=this.Data.Data[start-1]; //上一个数值 for(var i=start,j=0;ichartright) break; var x=left+(right-left)/2; } if (x>chartright) break; var textItem={ X:x, Value:value }; if (IFrameSplitOperator.IsNumber(preValue)) textItem.DiffValue=value-preValue; aryText.push(textItem); preValue=value; if (bUpBar) { if (value<0) continue; } else { if (value>=0) continue; } var bDiffBar=false; var diffValue=null; if (this.BaseValue>0) { if (valuethis.BaseValue) { bDiffBar=true; if (this.Style==1) diffValue=this.BaseValue-(value-this.BaseValue); else diffValue=this.BaseValue+(value-this.BaseValue) } } if (!bDiffBar) { var y=this.ChartFrame.GetYFromData(value); aryBar.push({X:x, Y:y }); } else { var y=this.ChartFrame.GetYFromData(diffValue); aryDiffBar.push({X:x, Y:y }); } } this.Canvas.lineWidth=lineWidth; if (bUpBar) this.Canvas.strokeStyle=this.UpColor; else this.Canvas.strokeStyle=this.DownColor; this.DrawStick(aryBar,lineWidth,yBottom); if (this.BaseValue>0) { this.Canvas.strokeStyle=this.UpDiffColor; this.DrawStick(aryDiffBar,lineWidth,yBottom); } else if (this.BaseValue<0) { this.Canvas.strokeStyle=this.DownDiffColor; this.DrawStick(aryDiffBar,lineWidth,yBottom); } if (this.IsShowText && bDrawLabel) this.DrawStickText(aryText); } this.DrawStick=function(aryData, lineWidth, yBottom) { if (!IFrameSplitOperator.IsNonEmptyArray(aryData)) return; var bHScreen=this.ChartFrame.IsHScreen===true; var drawCount=0; this.Canvas.beginPath(); for(var i=0; i0) this.Canvas.stroke(); } this.DrawBaseLine=function() { if (!IFrameSplitOperator.IsNumber(this.BaseValue) || this.BaseValue==0) return; if (!this.BaseLineColor) return; var bHScreen=this.ChartFrame.IsHScreen===true; var border=this.ChartFrame.GetBorder(); var y=this.ChartFrame.GetYFromData(this.BaseValue); this.Canvas.strokeStyle=this.BaseLineColor; this.Canvas.lineWidth=1*GetDevicePixelRatio(); if (bHScreen) { } else { var yFix=ToFixedPoint(y); this.Canvas.beginPath(); this.Canvas.moveTo(border.Left,yFix); this.Canvas.lineTo(border.Right,yFix); this.Canvas.stroke(); } } this.DrawStickText=function(aryData) { var config=this.TextLabelConfig; this.Canvas.font=config.Font; var border=this.ChartBorder.GetBorder(); var itemHeight=config.TextHeight*2+config.TextMargin.Bottom+config.TextMargin.Top; for(var i=0; i0) bgColor=config.UpColor; else if (value<0) bgColor=config.DownColor; this.DrawTextLabel(value, bgColor, config.BorderColor, config.TextColor, rtDraw, config.TextHeight, config.MaxTextWidth, config.TextMargin); } var value=item.DiffValue; var rtDraw={ Left:xLeft, Width:config.LabelWidth, Bottom:border.TopEx-1, Height:itemHeight }; rtDraw.Right=rtDraw.Left+rtDraw.Width; rtDraw.Top=rtDraw.Bottom-rtDraw.Height; if (IFrameSplitOperator.IsNumber(value)) { var bgColor=config.UnchangeColor; if (value>0) bgColor=config.UpColor; else if (value<0) bgColor=config.DownColor; this.DrawTextLabel(value, bgColor, config.BorderColor, config.TextColor, rtDraw, config.TextHeight, config.MaxTextWidth, config.TextMargin); } } } //数值标签 this.DrawTextLabel=function(value, clrGB, clrBorder, clrText, rtDraw, textHeight, textWidth, textMargin) { if (clrGB) { this.Canvas.fillStyle=clrGB; this.Canvas.fillRect(rtDraw.Left ,rtDraw.Top, (rtDraw.Width), (rtDraw.Height)); } if (clrBorder) { this.Canvas.lineWidth=2; this.Canvas.strokeStyle=clrBorder; this.Canvas.strokeRect(rtDraw.Left, rtDraw.Top, rtDraw.Width, rtDraw.Height); } else { this.Canvas.lineWidth=1; this.Canvas.strokeStyle="rgb(0,0,0)"; this.Canvas.strokeRect(rtDraw.Left, rtDraw.Top, rtDraw.Width, rtDraw.Height); } var aryText=[null, null]; //大于3位数的 2行输出 var sign=""; //负数 if (value<0) { value=Math.abs(value); sign='-'; } if (value>999) { var thousand=parseInt(value/1000); var hundred=parseInt(value%1000); aryText[0]=`${sign}${thousand}`; aryText[1]=`${hundred}`; if (hundred<10) aryText[1]=`00${hundred}`; else if (hundred<100) aryText[1]=`0${hundred}`; } else { aryText[1]=`${sign}${value.toFixed(0)}`; } this.Canvas.textAlign="right"; this.Canvas.textBaseline="top"; var xRight=rtDraw.Right-(rtDraw.Right-rtDraw.Left-textWidth)/2; this.Canvas.fillStyle=clrText; var yText=textMargin.Top+rtDraw.Top; for(var i=0;i0) range.Min=this.BaseValue; else range.Max=this.BaseValue; for(var i=start,j=0;i0) { if (value<0) continue; if (value0) continue; if (value>this.BaseValue) { var diffValue=value-this.BaseValue; if (maxDiffValue==null || maxDiffValuevalue) range.Min=value; } if (this.BaseValue>0) { if (this.Style==1) { if (IFrameSplitOperator.IsNumber(maxDiffValue)) { var value=this.BaseValue+maxDiffValue; if (IFrameSplitOperator.IsNumber(range.Max) || range.Maxvalue) range.Min=value; } } else { if (IFrameSplitOperator.IsNumber(maxDiffValue) && IFrameSplitOperator.IsNumber(range.Max)) range.Max+=maxDiffValue; } } return range; } } //柱子 function ChartBar() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartBar"; this.UpBarColor=g_JSChartResource.UpBarColor; this.DownBarColor=g_JSChartResource.DownBarColor; this.Draw=function() { if (this.ChartFrame.IsMinSize) return; 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 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;ichartright) break; var x=this.ChartFrame.GetXFromIndex(j); var y=this.ChartFrame.GetYFromData(value); if (value>0) this.Canvas.fillStyle=this.UpBarColor; else this.Canvas.fillStyle=this.DownBarColor; //高度调整为整数 var 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;ichartright) 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(); } } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=0; range.Max=null; for(var i=this.Data.DataOffset,j=0;i1 && secondlinePoints.length>1) { this.DrawBand(firstlinePoints, secondlinePoints); } } } this.ClipTop=function(aryFrist) { var isHScreen=this.ChartFrame.IsHScreen; this.Canvas.beginPath(); for(var i=0;i= 0; --i) { this.Canvas.lineTo(arySecond[i].x, arySecond[i].y); } this.Canvas.closePath(); this.Canvas.fillStyle = clrArea; this.Canvas.fill(); } this.DrawBand=function(aryFrist, arySecond) { if (this.FirstColor) { this.Canvas.save(); this.ClipTop(aryFrist); this.DrawArea(aryFrist, arySecond, this.FirstColor); this.Canvas.restore(); } if (this.SecondColor) { this.Canvas.save(); this.ClipBottom(aryFrist); this.DrawArea(aryFrist, arySecond, this.SecondColor); this.Canvas.restore(); } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; for(var i=this.Data.DataOffset,j=0;ivalue.Value2?value.Value:value.Value2; var minData = value.Value minData) range.Min = minData; } return range; } } // 线段围成的面积图 支持横屏 function ChartLineArea() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的 this.ClassName="ChartLineArea"; this.Color='rgb(56,67,99)'; this.IsHScreen=false; this.Draw=function() { if (this.ChartFrame.IsMinSize) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var x = 0, y = 0, y2 = 0; var aryPoint=[]; for(var i=this.Data.DataOffset,j=0;i0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y); } this.Canvas.closePath(); this.Canvas.fill(); } firstPoint=true; pointCount=0; aryLine2=[]; continue; } if (firstPoint) { this.Canvas.beginPath(); this.Canvas.moveTo(item.Line.X, item.Line.Y); firstPoint=false; } else { this.Canvas.lineTo(item.Line.X, item.Line.Y); } aryLine2.push(item); ++pointCount; } if (pointCount>0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y); } this.Canvas.closePath(); this.Canvas.fill(); } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; for(var i=this.Data.DataOffset,j=0;ivalue.Value2?value.Value:value.Value2; var minData = value.Value minData) range.Min = minData; } return range; } } // 线段围成的面积图 支持横屏 function ChartFillRGN() { this.newMethod=ChartLineArea; //派生 this.newMethod(); delete this.newMethod; this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的 this.IsHScreen=false; this.ClassName="ChartFillRGN"; this.DrawRGB=function(aryPoint) { var firstPoint=true; var pointCount=0; var aryLine2=[]; var color=null; for(var i in aryPoint) { var item=aryPoint[i]; if (!item || (color && item.Color!=color) ) { if (pointCount>0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y); } this.Canvas.closePath(); this.Canvas.fillStyle = color; this.Canvas.fill(); } firstPoint=true; pointCount=0; aryLine2=[]; color=null; } if (!item) continue; if (firstPoint) { this.Canvas.beginPath(); this.Canvas.moveTo(item.Line.X, item.Line.Y); firstPoint=false; color=item.Color; } else { this.Canvas.lineTo(item.Line.X, item.Line.Y); } aryLine2.push(item); ++pointCount; } if (pointCount>0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y); } this.Canvas.closePath(); this.Canvas.fillStyle = color; this.Canvas.fill(); } } this.Draw=function() { if (this.ChartFrame.IsMinSize) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var x = 0, y = 0, y2 = 0; var aryPoint=[]; //点坐标 for(var i=this.Data.DataOffset,j=0;iOPEN,RGB(255,0,0),1,RGB(0,255,0)) 表示沿收盘价填充宽度为成交量的区域,区域最大宽度为15像素,阳线时用红色,阴线时用绿色。 function ChartFLOATRGN() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.IsDrawFirst = false; //面积图在K线前面画,否则回挡住K线的 this.ClassName="ChartFLOATRGN"; this.Color='rgb(56,67,99)'; this.IsHScreen=false; this.Draw=function() { if (this.ChartFrame.IsMinSize) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (!this.Data || !this.Data.Data) return; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var x = 0, y = 0, y2 = 0; var aryPoint=[]; //点坐标 for(var i=this.Data.DataOffset,j=0;i0) { var lastItem=aryLine2[aryLine2.length-1]; var firstItem=aryLine2[0]; if (lastItem.RightLine) { this.Canvas.lineTo(lastItem.RightLine.X, lastItem.RightLine.Y); this.Canvas.lineTo(lastItem.RightLine2.X, lastItem.RightLine2.Y); } for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y); } if (firstItem.LeftLine2) { this.Canvas.lineTo(firstItem.LeftLine2.X, firstItem.LeftLine2.Y); } this.Canvas.closePath(); this.Canvas.fillStyle = color; this.Canvas.fill(); } firstPoint=true; pointCount=0; aryLine2=[]; color=null; } if (!item) continue; if (firstPoint) { this.Canvas.beginPath(); if (item.LeftLine) { this.Canvas.moveTo(item.LeftLine.X, item.LeftLine.Y); this.Canvas.lineTo(item.Line.X, item.Line.Y); } else { this.Canvas.moveTo(item.Line.X, item.Line.Y); } firstPoint=false; color=item.Color; } else { this.Canvas.lineTo(item.Line.X, item.Line.Y); } aryLine2.push(item); ++pointCount; } if (pointCount>0) { var lastItem=aryLine2[aryLine2.length-1]; var firstItem=aryLine2[0]; if (lastItem.RightLine) { this.Canvas.lineTo(lastItem.RightLine.X, lastItem.RightLine.Y); this.Canvas.lineTo(lastItem.RightLine2.X, lastItem.RightLine2.Y); } for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y); } if (firstItem.LeftLine2) { this.Canvas.lineTo(firstItem.LeftLine2.X, firstItem.LeftLine2.Y); } this.Canvas.closePath(); this.Canvas.fillStyle = color; this.Canvas.fill(); } this.Canvas.restore(); } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; for(var i=this.Data.DataOffset,j=0;i value) range.Min = value; } return range; } } //线段围城的顶部或底部面积图 TODO:支持横屏 function ChartFillBGRGN() { this.newMethod=ChartFillRGN; //派生 this.newMethod(); delete this.newMethod; this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的 this.IsHScreen=false; this.ClassName="ChartFillBGRGN"; this.DrawVerticalRGN=function() { var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); var y=top, y2=bottom; var aryPoint=[]; //点坐标 for(var i=this.Data.DataOffset,j=0;i0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y); this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y); } this.Canvas.closePath(); this.Canvas.fillStyle = color; this.Canvas.fill(); } firstPoint=true; pointCount=0; aryLine2=[]; color=null; } if (!item) continue; if (firstPoint) { this.Canvas.beginPath(); this.Canvas.moveTo(item.Line.X-halfWidth, item.Line.Y); this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y); firstPoint=false; color=item.Color; } else { this.Canvas.lineTo(item.Line.X-halfWidth, item.Line.Y); this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y); } aryLine2.push(item); ++pointCount; } if (pointCount>0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y); this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y); } this.Canvas.closePath(); this.Canvas.fillStyle = color; this.Canvas.fill(); } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; for(var i=this.Data.DataOffset,j=0;i value) range.Min = value; } return range; } } // 通道面积图 支持横屏 function ChartChannel() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.IsDrawFirst = true; this.ClassName="ChartChannel"; this.IsHScreen=false; //是否是横屏 this.PointCount=0; this.DataWidth=0; this.DistanceWidth=0; this.ChartRight=0; //可以绘制的最右边 this.LineColor='RGB(255,0,0)'; this.LineDotted=[3,3]; this.AreaColor='RGB(255,222,173)'; this.LineWidth=1; this.CalculateData=function() //把数据通过nul值分割开, 并计算坐标 { var data=[]; var lineData=[]; for(var i=this.Data.DataOffset,j=0;i0) { data.push(lineData); lineData=[]; //创建新的一组数据 } continue; } var x=this.ChartFrame.GetXFromIndex(j); if (x>this.ChartRight) break; var y=this.ChartFrame.GetYFromData(item.Value); var y2=this.ChartFrame.GetYFromData(item.Value2); lineData.push({X:x, Y:y,Y2:y2}); } if (lineData.length>0) data.push(lineData); return data; } this.DrawArea=function(lineData) { if (lineData.length<=0) return; this.Canvas.beginPath(); var drawCount=0; var firstItem=lineData[0]; if (this.IsHScreen) this.Canvas.moveTo(firstItem.Y,firstItem.X); else this.Canvas.moveTo(firstItem.X,firstItem.Y); for(var i=1;i=0;--i) { var item=lineData[i]; if (this.IsHScreen) this.Canvas.lineTo(item.Y2,item.X); else this.Canvas.lineTo(item.X,item.Y2); ++drawCount; } this.Canvas.closePath(); this.Canvas.fillStyle = this.AreaColor; this.Canvas.fill(); } this.DrawLine=function(lineData) { this.Canvas.strokeStyle=this.LineColor; for(var k=0;k<2;++k) { var bFirstPoint=true; var drawCount=0; for(var i=0;i0) this.Canvas.stroke(); } } this.Draw=function() { if (this.ChartFrame.IsMinSize) return; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } this.IsHScreen=(this.ChartFrame.IsHScreen===true); this.PointCount=this.ChartFrame.XPointCount; this.DataWidth=this.ChartFrame.DataWidth; this.DistanceWidth=this.ChartFrame.DistanceWidth; if (this.IsHScreen) this.ChartRight=this.ChartBorder.GetBottom(); else this.ChartRight=this.ChartBorder.GetRight(); var drawData=this.CalculateData(); if (!drawData || drawData.length<=0) return; this.Canvas.save(); this.Canvas.lineWidth=this.LineWidth*GetDevicePixelRatio(); this.Canvas.setLineDash(this.LineDotted); //虚线 for(var i=0;ivalue.Value2?value.Value:value.Value2; var minData = value.Value minData) range.Min = minData; } return range; } } //填充背景 支持横屏 function ChartBackground() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartBackground"; this.Color=null; this.ColorAngle=0; //0 竖向 1 横向 this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的 this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Color) return; if (this.Color.length<=0) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); if (this.Color.length==2) { if (this.IsHScreen) { if (this.ColorAngle==0) { var ptStart={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; } else { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() }; } } else { if (this.ColorAngle==0) { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() }; } else { var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() }; var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() }; } } let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y); gradient.addColorStop(0, this.Color[0]); gradient.addColorStop(1, this.Color[1]); this.Canvas.fillStyle=gradient; } else if (this.Color.length==1) { this.Canvas.fillStyle=this.Color[0]; } else { return; } if (this.Name=="DRAWGBK2" || this.Name=="KLINE_BG") { this.DrawRegion(); return; } if (this.IsHScreen) { var left=this.ChartBorder.GetLeftEx(); var top=this.ChartBorder.GetTop(); var width=this.ChartBorder.GetWidthEx(); var height=this.ChartBorder.GetHeight(); } else { var left=this.ChartBorder.GetLeft(); var top=this.ChartBorder.GetTopEx(); var width=this.ChartBorder.GetWidth(); var height=this.ChartBorder.GetHeightEx(); } this.Canvas.fillRect(left, top,width, height); } this.DrawRegion=function() { var xPointCount=this.ChartFrame.XPointCount; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); if (this.IsHScreen) { top=this.ChartBorder.GetRightEx(); bottom=this.ChartBorder.GetLeftEx(); } var aryPoint=[]; //点坐标 for(var i=this.Data.DataOffset,j=0;i0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; if (this.IsHScreen) { this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth); this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth); } else { this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y); this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y); } } this.Canvas.closePath(); this.Canvas.fill(); } firstPoint=true; pointCount=0; aryLine2=[]; color=null; } if (!item) continue; if (firstPoint) { this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(item.Line.X, item.Line.Y-halfWidth); this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth); } else { this.Canvas.moveTo(item.Line.X-halfWidth, item.Line.Y); this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y); } firstPoint=false; color=item.Color; } else { if (this.IsHScreen) { this.Canvas.lineTo(item.Line.X, item.Line.Y-halfWidth); this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth); } else { this.Canvas.lineTo(item.Line.X-halfWidth, item.Line.Y); this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y); } } aryLine2.push(item); ++pointCount; } if (pointCount>0) { for(var j=aryLine2.length-1; j>=0; --j) { var item2=aryLine2[j]; if (this.IsHScreen) { this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth); this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth); } else { this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y); this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y); } } this.Canvas.closePath(); this.Canvas.fill(); } } this.GetMaxMin=function() { return { Min:null, Max:null }; } } //填充部分背景 支持横屏 function ChartBackgroundDiv() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartBackgroundDiv"; this.AryColor; this.ColorType=0; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.AryColor)) return; if (!this.Data || !this.Data.Data) return; var bHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var xPointCount=this.ChartFrame.XPointCount; var border,xOffset, chartright, yTop, yBottom; if (bHScreen) { border=this.ChartBorder.GetHScreenBorder(); xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.BottomEx; yTop=border.LeftEx; yBottom=border.RightEx; } else { border=this.ChartBorder.GetBorder(); xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; chartright=border.RightEx; yTop=border.TopEx; yBottom=border.BottomEx; } var rtBG=null //{ Left:null, Top:null, Right:null, Bottom:null }; for(var i=this.Data.DataOffset,j=0;ichartright) break; if (!item) { if (rtBG) this.DrawDiv(rtBG,bHScreen); rtBG=null; } else { var y=yTop; var y2=yBottom; if (IFrameSplitOperator.IsNonEmptyArray(item.AryValue)) { var value=this.ChartFrame.GetYFromData(item.AryValue[0]); var value2=this.ChartFrame.GetYFromData(item.AryValue[1]); y=Math.min(value, value2); y2=Math.max(value, value2); } if (bHScreen) { if (!rtBG) { rtBG={ Left:y, Right:y2, Top:left, Bottom:right }; } else { rtBG.Bottom=right; if (rtBG.Left>y) rtBG.Left=y; if (rtBG.Righty) rtBG.Top=y; if (rtBG.Bottombottom) { this.Canvas.textBaseline='bottom'; yText=bottom; } this.Canvas.fillStyle = this.Text.Color; this.Canvas.font = this.Text.Font; this.Canvas.fillText(this.Text.Title, x, yText); textWidth=this.Canvas.measureText(this.Text.Title).width+4*GetDevicePixelRatio(); } if (this.Line.Type>0) { if (this.Line.Type==2) //虚线 { this.Canvas.save(); this.Canvas.setLineDash([3,5]); //虚线 } var x=left+textWidth; this.Canvas.strokeStyle=this.Line.Color; this.Canvas.beginPath(); this.Canvas.moveTo(x,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); this.Canvas.stroke(); if (this.Line.Type==2) { this.Canvas.restore(); } } } this.GetMaxMin=function() { var range={Min:null, Max:null}; if (IFrameSplitOperator.IsNumber(this.Price)) { range.Min=this.Price; range.Max=this.Price; } return range; } } // 柱子集合 支持横屏 function ChartMultiBar() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiBar"; this.Bars=[]; // [ {Point:[ {Index, Value, Value2 }, ], Color:, Width: , Type: 0 实心 1 空心 }, ] this.IsHScreen=false; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (!this.Data || this.Data.length<=0) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var dataWidth=this.ChartFrame.DataWidth; var pixelRatio=GetDevicePixelRatio(); var drawBars=[]; for(var i in this.Bars) { var item=this.Bars[i]; var drawPoints={ Point:[], Color:item.Color, Width:dataWidth, Type:0 }; if (item.Type>0) drawPoints.Type=item.Type; if (item.Width>0) { drawPoints.Width=item.Width*pixelRatio; if (drawPoints.Width>dataWidth) drawPoints.Width=dataWidth; } else { if(drawPoints.Width<4) drawPoints.Width=1*pixelRatio; } for(var j in item.Point) { var point=item.Point[j]; if (!IFrameSplitOperator.IsNumber(point.Index)) continue; var index=point.Index-offset; if (index>=0 && index0) drawBars.push(drawPoints) } for(var i in drawBars) { var item=drawBars[i]; if (item.Width>=4) { if (item.Type==1) this.DrawHollowBar(item); else this.DrawFillBar(item); } else { this.DrawLineBar(item); } } } this.DrawLineBar=function(bar) { this.Canvas.strokeStyle=bar.Color; var backupLineWidth=this.Canvas.lineWidth; this.Canvas.lineWidth=bar.Width; for(var i in bar.Point) { var item=bar.Point[i]; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(ToFixedPoint(item.Y),ToFixedPoint(item.X)); this.Canvas.lineTo(ToFixedPoint(item.Y2),ToFixedPoint(item.X)); } else { this.Canvas.moveTo(ToFixedPoint(item.X),ToFixedPoint(item.Y)); this.Canvas.lineTo(ToFixedPoint(item.X),ToFixedPoint(item.Y2)); } this.Canvas.stroke(); } this.Canvas.lineWidth=backupLineWidth; } this.DrawFillBar=function(bar) { this.Canvas.fillStyle=bar.Color; for(var i in bar.Point) { var item=bar.Point[i]; var x=item.X-(bar.Width/2); var y=Math.min(item.Y,item.Y2); var barWidth=bar.Width; var barHeight=Math.abs(item.Y-item.Y2); if (this.IsHScreen) this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(x),ToFixedRect(barHeight),ToFixedRect(barWidth)); else this.Canvas.fillRect(ToFixedRect(x),ToFixedRect(y),ToFixedRect(barWidth),ToFixedRect(barHeight)); } } this.DrawHollowBar=function(bar) //空心柱子 { this.Canvas.strokeStyle=bar.Color; var backupLineWidth=1; for(var i in bar.Point) { var item=bar.Point[i]; var x=item.X-(bar.Width/2); var y=Math.min(item.Y,item.Y2); var barWidth=bar.Width; var barHeight=Math.abs(item.Y-item.Y2); this.Canvas.beginPath(); if (this.IsHScreen) this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(x),ToFixedRect(barHeight),ToFixedRect(barWidth)); else this.Canvas.rect(ToFixedPoint(x),ToFixedPoint(y),ToFixedRect(barWidth),ToFixedRect(barHeight)); this.Canvas.stroke(); } this.Canvas.lineWidth=backupLineWidth; } this.GetMaxMin=function() { var range={ Min:null, Max:null }; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; var end=start+xPointCount; for(var i in this.Bars) { var item=this.Bars[i]; for(var j in item.Point) { var point=item.Point[j]; if (point.Index>=start && point.IndexminValue) range.Min=minValue; } } } return range; } } // 线段集合 支持横屏 function ChartMultiLine() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiLine"; this.Lines=[]; // [ {Point:[ {Index, Value }, ], Color: }, ] this.LineDash; this.LineWidth=1; this.IsHScreen=false; //箭头配置 this.ArrawAngle=35; //三角斜边一直线夹角 this.ArrawLength=10; //三角斜边长度 this.ArrawLineWidth=5; //箭头粗细 this.Arrow={ Start:false, End:false }; //Start=是否绘制开始箭头 <- End=是否绘制结束箭头 -> this.IsFullRangeMaxMin=false; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (!this.Data || this.Data.length<=0) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.Lines)) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var drawLines=[]; var arrowLines=[]; for(var i=0; i0 && index0) { var x=this.ChartFrame.GetXFromIndex(index, false); var y=this.ChartFrame.GetYFromData(point.Value, false); var pointItem={X:x, Y:y, End:true}; drawPoints.Point.push(pointItem); bFirstPoint=true; prePoint=null; } } prePoint=point; } if (drawPoints.Point.length>=2) { drawLines.push(drawPoints); arrowLines.push(drawArrowPoints); } } else { for(var j=0; j=0 && index0) drawPoints.Point[drawPoints.Point.length-1].End=true; //点断开 } } if (drawPoints.Point.length>=2) { drawLines.push(drawPoints); arrowLines.push(drawArrowPoints); } } } var pixelRatio=GetDevicePixelRatio(); this.Canvas.save(); this.ClipClient(this.IsHScreen); //绘制线段 for(var i=0; i0) this.Canvas.stroke(); drawCount=0; } } if (drawCount>0) this.Canvas.stroke(); //绘制箭头 if (arrow.End.length==2 && this.Arrow.End==true) this.DrawArrow(arrow.End[0],arrow.End[1]); if (arrow.Start.length==2 && this.Arrow.Start==true) this.DrawArrow(arrow.Start[1],arrow.Start[0]); } this.DrawArrow=function(ptStart,ptEnd) { //计算箭头 var theta=this.ArrawAngle; //三角斜边一直线夹角 var headlen=this.ArrawLength; //三角斜边长度 var angle = Math.atan2(ptStart.Y - ptEnd.Y, ptStart.X - ptEnd.X) * 180 / Math.PI, angle1 = (angle + theta) * Math.PI / 180, angle2 = (angle - theta) * Math.PI / 180, topX = headlen * Math.cos(angle1), topY = headlen * Math.sin(angle1), botX = headlen * Math.cos(angle2), botY = headlen * Math.sin(angle2); this.Canvas.beginPath(); var arrowX = ptEnd.X + topX; var arrowY = ptEnd.Y + topY; this.Canvas.moveTo(arrowX,arrowY); this.Canvas.lineTo(ptEnd.X, ptEnd.Y); arrowX = ptEnd.X + botX; arrowY = ptEnd.Y + botY; this.Canvas.lineTo(arrowX,arrowY); this.Canvas.setLineDash([]); this.Canvas.lineWidth=this.ArrawLineWidth*GetDevicePixelRatio(); this.Canvas.stroke(); } this.GetMaxMin=function() { if (this.IsFullRangeMaxMin) return this.GetFullRangeMaxMin(); var range={ Min:null, Max:null }; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; var end=start+xPointCount; for(var i in this.Lines) { var line=this.Lines[i]; for(var j in line.Point) { var point=line.Point[j]; if (point.Index>=start && point.Indexpoint.Value) range.Min=point.Value; } } } return range; } //全部数据的最大最小值 this.GetFullRangeMaxMin=function() { var range={ Min:null, Max:null }; if (!IFrameSplitOperator.IsNonEmptyArray(this.Lines)) return range; for(var i=0; ipoint.Value) range.Min=point.Value; } } return range; } } // 线段集合 支持横屏 function ChartMultiPoint() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiPoint"; this.PointGroup=[]; // [ {Point:[ {Index, Value }, ], Color: }, ] this.IsHScreen=false; this.LineWidth=1; this.PointRadius=5; this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || this.Data.length<=0) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.PointGroup)) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var pixel=GetDevicePixelRatio(); this.Canvas.save(); this.ClipClient(this.IsHScreen); for(var i=0; i=0 && index0 && (bgColor || color)) { this.Canvas.lineWidth=lineWidth*pixel; this.Canvas.fillStyle=bgColor; //背景填充颜色 this.Canvas.strokeStyle=color; if (bgColor) this.Canvas.fill(path); if (color) this.Canvas.stroke(path); } } this.Canvas.restore(); } this.GetMaxMin=function() { var range={ Min:null, Max:null }; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; var end=start+xPointCount; for(var i=0; i=start && point.Indexpoint.Value) range.Min=point.Value; } } } return range; } } // 多文本集合 支持横屏 function ChartMultiText() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiText"; this.Texts=[]; //[ {Index:, Value:, Text:, Color:, Font: , Baseline:, Line:{ Color:, Dash:[虚线点], KData:"H/L", Offset:[5,10], Width:线粗细 }} ] this.Font=g_JSChartResource.DefaultTextFont; this.Color=g_JSChartResource.DefaultTextColor; this.IsHScreen=false; //是否横屏 this.BuildKey=function(item) { if (IFrameSplitOperator.IsNumber(item.Time)) { var key=`${item.Date}-${item.Time}`; } else { var key=`${item.Date}`; } return key; } this.GetShowTextData=function() { var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var mapText=new Map(); //key='date-time' value={ Data:[] } for(var i=0; i=0 && indexchartright) break; var x=left+(right-left)/2; var textItem=mapText.get(key); for(var k=0;k=chartright) { this.Canvas.textAlign='right'; x=chartright; } else if (x-textWidth/2yPrice) //文字在下方 { yText-=item.Line.Offset[1]; yPrice+=item.Line.Offset[0] } else if (yText0) this.Canvas.lineWidth=item.Line.Width; //线宽 this.Canvas.strokeStyle = item.Line.Color; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(yText, ToFixedPoint(x)); this.Canvas.lineTo(yPrice,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yText); this.Canvas.lineTo(ToFixedPoint(x),yPrice); } this.Canvas.stroke(); this.Canvas.restore(); } } } } this.Draw=function() { if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; if (!this.Data || this.Data.length<=0) return; if (!this.Texts) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var mapText=this.GetShowTextData(); if (mapText.size<=0) return; this.Canvas.save(); this.ClipClient(this.IsHScreen); this.DrawAllText(mapText); this.Canvas.restore(); } this.GetMaxMin=function() { var range={ Min:null, Max:null }; if (!this.Texts) return range; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; var end=start+xPointCount; for(var i in this.Texts) { var item=this.Texts[i]; if (!IFrameSplitOperator.IsNumber(item.Value)) continue; if (item.Index>=start && item.Indexitem.Value) range.Min=item.Value; } } return range; } } //图标集合(2.0) 支持横屏 function ChartMultiSVGIconV2() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiSVGIconV2"; this.AryIcon; //[ {Index:, Value:, Symbol:, Color:, Baseline:, Line:{ Color:, Dash:[虚线点], KData:"H/L", Offset:[5,10], Width:线粗细 } } ] this.IconSize= { Max: g_JSChartResource.DRAWICON.Icon.MaxSize, Min:g_JSChartResource.DRAWICON.Icon.MinSize , //图标的最大最小值 Zoom:{ Type:g_JSChartResource.DRAWICON.Icon.Zoom.Type , Value:g_JSChartResource.DRAWICON.Icon.Zoom.Value } //放大倍数 }; this.Family; this.Color=g_JSChartResource.DefaultTextColor; this.IsHScreen=false; this.IconRect=[]; //0=序号,1=区域 this.MapCache=null; //key=date/date-time value={ Data:[] } this.BuildKey=function(item) { if (IFrameSplitOperator.IsNumber(item.Time)) return `${item.Date}-${item.Time}`; else return item.Date; } this.BuildCacheData=function() { var mapData=new Map(); this.MapCache=mapData; if (!IFrameSplitOperator.IsNonEmptyArray(this.AryIcon)) return; for(var i=0;ichartright) break; var x=left+(right-left)/2; } this.DrawItem(mapItem, kItem, x, drawInfo); } this.Canvas.restore(); } this.GetKValue=function(kItem, valueName) { switch(valueName) { case "HIGH": case "H": return kItem.High; case "L": case "LOW": return kItem.Low; case "C": case "CLOSE": return kItem.Close; case "O": case "OPEN": return KItem.Open; default: return null; } } this.DrawItem=function(groupItem, kItem, x, drawInfo) { if (!IFrameSplitOperator.IsNonEmptyArray(groupItem.Data)) return; var fontSize=drawInfo.FontSize; var left=drawInfo.Left, right=drawInfo.Right; var dataWidth=drawInfo.DataWidth; //var distanceWidth=drawInfo.DistanceWidth; for(var i=0;iyPrice) //文字在下方 { yText-=item.Line.Offset[1]; yPrice+=item.Line.Offset[0] } else if (yText0) this.Canvas.lineWidth=item.Line.Width; //线宽 this.Canvas.strokeStyle = item.Line.Color; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(yText, ToFixedPoint(x)); this.Canvas.lineTo(yPrice,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint(x),yText); this.Canvas.lineTo(ToFixedPoint(x),yPrice); } this.Canvas.stroke(); this.Canvas.restore(); } } } this.GetTooltipData=function(x,y,tooltip) { if (!IFrameSplitOperator.IsNonEmptyArray(this.IconRect)) return false; for(var i=0; ivalue) range.Min=value; } } return range; } } // 多dom节点 function ChartMultiHtmlDom() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartMultiHtmlDom"; this.Texts=[]; //[ {Index:, Value:, Text: ] Text=dom内容 this.IsHScreen=false; //是否横屏 this.DrawCallback; //function(op, obj) op:1=开始 2=结束 3=绘制单个数据 4=销毁 this.DrawItem=[]; this.EnableDraw=true; //是否允许绘制 this.HQChart; this.IsDestroy=false; //是否已销毁 this.Draw=function() { if (!this.EnableDraw) return; if (this.IsDestroy) return; this.DrawItem=[]; if (this.DrawCallback) this.DrawCallback(1, {Self:this} ); this.DrawDom(); if (this.DrawCallback) this.DrawCallback(2, { Self:this, DrawItem:this.DrawItem } ); } this.OnDestroy=function() { this.IsDestroy=true; if (this.DrawCallback) this.DrawCallback(4, { Self:this } ); } this.DrawDom=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || this.Data.length<=0) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); var pixelTatio = GetDevicePixelRatio(); if (this.HQChart) { var elementLeft=this.HQChart.UIElement.getBoundingClientRect().left; var elementTop=this.HQChart.UIElement.getBoundingClientRect().top; } else { var elementLeft=null,elementTop=null; } for(var i in this.Texts) { var item=this.Texts[i]; if (!item.Text) continue; if (!IFrameSplitOperator.IsNumber(item.Index)) continue; var isMinuteFrame=this.IsMinuteFrame(); var index=item.Index-offset; var kItem=this.Data.Data[item.Index]; //K线数据 var obj={ KData:kItem, Item:item, IsShow:false, Self:this }; if (index>=0 && indexyPrice) //文字在下方 { yText-=item.Line.Offset[1]; yPrice+=item.Line.Offset[0] } else if (yText0) lineWidth=item.Line.Width*pixelRatio; this.Canvas.lineWidth=lineWidth; //线宽 this.Canvas.strokeStyle = item.Line.Color; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(yText, ToFixedPoint(x)); this.Canvas.lineTo(yPrice,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint2(lineWidth,x),yText); this.Canvas.lineTo(ToFixedPoint2(lineWidth,x),yPrice); } this.Canvas.stroke(); this.Canvas.restore(); } } } this.GetMaxMin=function() { var range={ Min:null, Max:null }; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; var end=start+xPointCount; for(var i in this.Texts) { var item=this.Texts[i]; if (!IFrameSplitOperator.IsNumber(item.Index)) continue; if (item.Index>=start && item.Indexitem.Value) range.Min=item.Value; } } return range; } } //绘制SVG图标 function ChartDrawSVG() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartDrawSVG"; this.Family; this.TextFont; this.Texts=[]; //[ { Index:, Value:, Symbol:, Text:, Size: } ] SVG:图标 Text:文字 Size:图标大小 this.IsHScreen=false; //是否横屏 this.IsDestroy=false; //是否已销毁 this.EnableTooltip=true; this.TooltipRect=[]; this.ExcludeArea=null; //排除区域 { Left, Top, Width, Height, Type:0 } this.AutoPosition=null; //{ Direction:0, MaxYOffset:40 } //自动调整Y轴偏移,防止文字重叠 this.AryDrawRect=[]; //已经绘制的区域 this.AutoYOffset=0; //this.Data; 存K线数据 this.Draw=function() { this.TooltipRect=[]; this.AryDrawRect=[]; this.AutoYOffset=0; if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; if (this.IsShowIndexTitleOnly()) return; if (this.IsHideScriptIndex()) return; this.DrawSVG(); } this.DrawDetail=function(rtSVG, data, svgItem) { if (!IFrameSplitOperator.IsNonEmptyArray(data.Content)) return; var lefMargin=2; var rightMargin=2; var itemSpace=2; var rtBorder={ Left:rtSVG.Right, Right:rtSVG.Right, Bottom:rtSVG.Bottom }; var rightBorder=0; //右边的边界 0=div的宽度 1=图形框架边框 if (IFrameSplitOperator.IsNumber(data.ItemSpace)) itemSpace=data.ItemSpace; if (IFrameSplitOperator.IsNumber(data.YOffset)) rtBorder.Bottom+=data.YOffset; if (IFrameSplitOperator.IsNumber(data.XOffset)) rtBorder.Left+=data.XOffset; if (IFrameSplitOperator.IsNumber(data.LeftMargin)) lefMargin=data.LeftMargin; if (IFrameSplitOperator.IsNumber(data.RightMargin)) rightMargin=data.RightMargin; if (IFrameSplitOperator.IsNumber(data.RightBorder)) rightBorder=data.RightBorder; if (data.Font) this.Canvas.font=data.Font; else this.Canvas.font=this.TextFont; this.Canvas.textBaseline='bottom'; this.Canvas.textAlign='left'; var textHeight=this.Canvas.measureText("擎").width+2; rtBorder.Height=textHeight+5; var yText=rtBorder.Bottom-(rtBorder.Height-textHeight)/2; var xText=rtBorder.Left+lefMargin; var aryText=[]; for(var i=0;i0) xText+=itemSpace; var item=data.Content[i]; if (!item.Text) continue; var textWidth=this.Canvas.measureText(item.Text).width+2; aryText.push({ X:xText, Y:yText, Width:textWidth, Data:item }); xText+=textWidth; rtBorder.Right=xText; } rtBorder.Right+=rightMargin; rtBorder.Width=rtBorder.Right-rtBorder.Left; rtBorder.Top=rtBorder.Bottom-rtBorder.Height; var right=this.ChartBorder.GetChartWidth()-1; if (rightBorder==1) right=this.ChartBorder.GetRight(); if (rtBorder.Right>right) //右边显示不下,显示在左边 { rtBorder.Right=rtSVG.Left; if (IFrameSplitOperator.IsNumber(data.XOffset)) rtBorder.Right-=data.XOffset; rtBorder.Left=rtBorder.Right-rtBorder.Width; var xText=rtBorder.Left+lefMargin; for(var i=0;i0) xText+=itemSpace; var item=aryText[i]; item.X=xText; xText+=item.Width; } } if (data.BGColor) { this.Canvas.fillStyle=data.BGColor; this.Canvas.fillRect(rtBorder.Left,rtBorder.Top,rtBorder.Width,rtBorder.Height); } if (data.BorderColor) { this.Canvas.strokeStyle=data.BorderColor; this.Canvas.strokeRect(ToFixedPoint(rtBorder.Left),ToFixedPoint(rtBorder.Top),ToFixedRect(rtBorder.Width),ToFixedRect(rtBorder.Height)); } for(var i=0;iright) //右边显示不下,显示在左边 { rtBorder.Right=rtSVG.Left; if (IFrameSplitOperator.IsNumber(data.XOffset)) rtBorder.Right-=data.XOffset; rtBorder.Left=rtBorder.Right-rtBorder.Width; } return rtBorder; } this.CalculateShowPosition=function(item, pt) { var x=pt.X, y=pt.Y; var svgItem=item.SVG; if (IFrameSplitOperator.IsNumber(svgItem.YOffset)) y+=svgItem.YOffset; var fontSVG=`${svgItem.Size}px ${this.Family}`; this.Canvas.font=fontSVG; var halfSize=svgItem.Size/2; var rtSVG={ Left:x-halfSize, Right:x+halfSize, Top:y-svgItem.Size, Bottom:y, Height:svgItem.Size, Width:svgItem.Size }; if (svgItem.VAlign===0) //top { rtSVG.Top=y; rtSVG.Bottom=rtSVG.Top+svgItem.Size; } else if (svgItem.VAlign===1) //middle { rtSVG.Top=y-svgItem.Size/2; rtSVG.Bottom=rtSVG.Top+svgItem.Size; } if (rtSVG.Top<0) { rtSVG.Top=0; rtSVG.Bottom=svgItem.Size; y=rtSVG.Bottom; } var rtContent=null; if (item.Detail) rtContent=this.GetDetailPosition(rtSVG,item.Detail); var yOffset=0, yMoveStep=-5; if (IFrameSplitOperator.IsNumber(this.AutoPosition.MoveYStep)) yMoveStep=-(Math.abs(this.AutoPosition.MoveYStep)) for(var i=0;i<20;++i) { if (rtSVG && !rtContent) { if (!this.IsRectOverlap(rtSVG)) break; } else if (rtSVG && rtContent) { if (!this.IsRectOverlap(rtSVG) && !this.IsRectOverlap(rtContent)) break; } yOffset+=yMoveStep; if (Math.abs(yOffset)>=this.AutoPosition.MaxYOffset) break; rtSVG.Top+=yMoveStep; rtSVG.Bottom+=yMoveStep; if (rtContent) { rtContent.Top+=yMoveStep; rtContent.Bottom+=yMoveStep; } } pt.X=x; pt.Y=y+yOffset; } this.IsRectOverlap=function(rect) { for(var i=0; i=item.Left && rect.Left<=item.Right) || (rect.Right>=item.Left && rect.Right<=item.Right)) && ((rect.Top>=item.Top && rect.Top<=item.Bottom) || (rect.Bottom>=item.Top && rect.Bottom<=item.Bottom)) ) { return true; } } return false; } this.DrawSVG=function() { if (!this.IsShow || this.ChartFrame.IsMinSize) return; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.Texts)) return; if (!this.Family) return; this.IsHScreen=(this.ChartFrame.IsHScreen===true); var xPointCount=this.ChartFrame.XPointCount; var offset=this.Data.DataOffset; var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); var pixelRatio = GetDevicePixelRatio(); var x=0,y=0; for(var i=0; i=xPointCount) continue; x=this.ChartFrame.GetXFromIndex(index); if (item.Value=="Top") y=top; else if (item.Value=="Bottom") y=bottom; else y=this.ChartFrame.GetYFromData(item.Value, false); if (IFrameSplitOperator.IsNumber(item.YOffset)) y+=item.YOffset; //Y轴偏移 var svgItem=item.SVG; if (IFrameSplitOperator.IsNumber(svgItem.YOffset)) y+=svgItem.YOffset; if (this.AutoPosition) { var pt={ X:x, Y:y }; this.CalculateShowPosition(item, pt); //重新计算位置 x=pt.X; y=pt.Y; } var fontSVG=`${svgItem.Size}px ${this.Family}`; this.Canvas.font=fontSVG; var halfSize=svgItem.Size/2; var textBaseline='bottom'; var rtSVG={ Left:x-halfSize, Right:x+halfSize, Top:y-svgItem.Size, Bottom:y, Height:svgItem.Size, Width:svgItem.Size }; if (svgItem.VAlign===0) { textBaseline="top"; rtSVG.Top=y; rtSVG.Bottom=rtSVG.Top+svgItem.Size; } else if (svgItem.VAlign===1) { textBaseline='middle'; rtSVG.Top=y-svgItem.Size/2; rtSVG.Bottom=rtSVG.Top+svgItem.Size; } if (rtSVG.Top<0) { rtSVG.Top=0; rtSVG.Bottom=svgItem.Size; y=rtSVG.Bottom; } this.Canvas.textBaseline=textBaseline; this.Canvas.textAlign='center'; this.Canvas.fillStyle = svgItem.Color; this.Canvas.fillText(svgItem.Symbol, x, y); this.AryDrawRect.push( {Left:rtSVG.Left, Top:rtSVG.Top, Right:rtSVG.Right, Bottom:rtSVG.Bottom, Type:"SVG", Data:item } ); if (this.EnableTooltip) this.TooltipRect.push({ Rect:rtSVG,Index:i }); //文字 if (item.Text && item.Text.Content && this.TextFont) { var textItem=item.Text; this.Canvas.font=this.TextFont; this.Canvas.fillStyle=textItem.Color; var yText=y; if (IFrameSplitOperator.IsNumber(textItem.YOffset)) yText+=textItem.YOffset; this.Canvas.fillText(textItem.Content, x, yText); } if (item.Detail) { this.DrawDetail(rtSVG,item.Detail, item); } //连线 if (item.Line) { var lineItem=item.Line; var price=null, yPrice=null; var kItem=this.Data.Data[item.Index]; if (lineItem.Value=="Bottom") { yPrice=bottom; } else if (lineItem.Value=="Top") { yPrice=top; } else { switch(lineItem.Value) { case "C": price=kItem.Close; break; case "H": price=kItem.High; break; case "L": price=kItem.Low; break; } if (!IFrameSplitOperator.IsNumber(price)) continue; yPrice=this.ChartFrame.GetYFromData(price); } if (yPrice>=rtSVG.Top && yPrice<=rtSVG.Bottom) continue; var yText; if (yPrice0) lineWidth=lineItem.Width*pixelRatio; this.Canvas.lineWidth=lineWidth; //线宽 this.Canvas.strokeStyle = lineItem.Color; this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(yText, ToFixedPoint(x)); this.Canvas.lineTo(yPrice,ToFixedPoint(x)); } else { this.Canvas.moveTo(ToFixedPoint2(lineWidth,x),yText); this.Canvas.lineTo(ToFixedPoint2(lineWidth,x),yPrice); } this.Canvas.stroke(); this.Canvas.setLineDash([]); } } } this.GetMaxMin=function() { var range={ Min:null, Max:null }; var xPointCount=this.ChartFrame.XPointCount; var start=this.Data.DataOffset; var end=start+xPointCount; if (!IFrameSplitOperator.IsNonEmptyArray(this.Texts)) return range; for(var i=0; i=start && item.Indexitem.Value) range.Min=item.Value; } } return range; } this.GetTooltipData=function(x,y,tooltip) { if (!this.IsShow) return false; for(var i=0;ithis.OXData.Min; price-=this.OXData.BlockSize) { var y=this.ChartFrame.GetYFromData(price); if (this.IsHScreen) { this.Canvas.moveTo(ToFixedPoint(y),border.Top); this.Canvas.lineTo(ToFixedPoint(y), border.Bottom); } else { this.Canvas.moveTo(left,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); } } var xStart=left+g_JSChartResource.FrameLeftMargin; for(var i=xStart;iright) break; var item=this.OXData.Data[i]; this.Canvas.fillStyle=this.Color[item.Type]; var text=this.Text[item.Type]; if (!IFrameSplitOperator.IsNonEmptyArray(item.Data)) continue; for(var j=0; jright) break; var item=this.OXData.Data[i]; this.Canvas.fillStyle=this.Color[item.Type]; var text=this.Text[item.Type]; var rt={ X:xOffset, Width:this.SquareSize }; var maxValue=null, minValue=null; if (!IFrameSplitOperator.IsNonEmptyArray(item.Data)) continue; for(var j=0; jvalue) minValue=value; } rt.Y=this.ChartFrame.GetYFromData(maxValue+this.OXData.BlockSize); rt.Height=this.ChartFrame.GetYFromData(minValue)-rt.Y; var tooltipItem={ Data:item, Rect:rt }; this.TooltipData.push(tooltipItem); } } } this.GetTooltipData=function(x,y,tooltip) { for(var i in this.TooltipData) { var item=this.TooltipData[i]; if (!item.Rect) continue; var rect=item.Rect; this.Canvas.beginPath(); this.Canvas.rect(rect.X,rect.Y,rect.Width,rect.Height); if (this.Canvas.isPointInPath(x,y)) { JSConsole.Chart.Log('[ChartOX::GetTooltipData] item ', item); tooltip.Data=item; tooltip.ChartPaint=this; tooltip.Type=5; //OX指标 return true; } } return false; } this.GetMaxMin=function() { var range={ Min:null, Max:null }; if (this.OXData) { if (IFrameSplitOperator.IsNumber(this.OXData.Max)) range.Max=this.OXData.Max; if (IFrameSplitOperator.IsNumber(this.OXData.Min)) range.Min=this.OXData.Min; } return range; } } //成交量柱子图-可视范围 function ChartVolProfileVisibleRange() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartVolProfileVisibleRange"; this.IsDrawFirst=true; this.IsShowText=true; //是否显示成交量数据 this.VolType=0; //0=up|down bar 1=total bar this.BarPosition=1; //柱子方向 0=左边 1=右边 this.BarWidthRate=0.3; this.VolFont; this.HQChart; this.IsDestroy=false; this.Data=null; this.MaxVol; this.MaxVolPrice; this.VolLineColor=g_JSChartResource.ChartVolProfileVisibleRange.VolLineColor; this.VolLineFont=g_JSChartResource.ChartVolProfileVisibleRange.VolLineFont; this.VolLineTextColor=g_JSChartResource.ChartVolProfileVisibleRange.VolLineTextColor; //value Area this.VAHLineColor=g_JSChartResource.ChartVolProfileVisibleRange.VAHLineColor; this.VAHTextColor=g_JSChartResource.ChartVolProfileVisibleRange.VAHTextColor; this.VALLineColor=g_JSChartResource.ChartVolProfileVisibleRange.VALLineColor; this.VALTextColor=g_JSChartResource.ChartVolProfileVisibleRange.VALTextColor; this.VAFont=g_JSChartResource.ChartVolProfileVisibleRange.VAFont; this.TextConfig= { Color:g_JSChartResource.ChartVolProfileVisibleRange.Text.Color, Family:g_JSChartResource.ChartVolProfileVisibleRange.Text.Family, FontMaxSize:g_JSChartResource.ChartVolProfileVisibleRange.Text.FontMaxSize, FontMinSize:g_JSChartResource.ChartVolProfileVisibleRange.Text.FontMinSize, Color:g_JSChartResource.ChartVolProfileVisibleRange.Text.Color, } this.BarColor= [ g_JSChartResource.ChartVolProfileVisibleRange.UpVolColor, g_JSChartResource.ChartVolProfileVisibleRange.DownVolColor, g_JSChartResource.ChartVolProfileVisibleRange.AreaUpColor, g_JSChartResource.ChartVolProfileVisibleRange.AreaDonwColor ] this.MaxVolLine; this.OnDestroy=function() { this.IsDestroy=true; } this.SetOption=function(option) { if (!option) return; if (IFrameSplitOperator.IsBool(option.IsShowText)) this.IsShowText=option.IsShowText; if (IFrameSplitOperator.IsNumber(option.VolType)) this.IsShowText=option.VolType; if (IFrameSplitOperator.IsNumber(option.BarPosition)) this.BarPosition=option.BarPosition; if (IFrameSplitOperator.IsNumber(option.BarWidthRate)) this.IsShowText=option.BarWidthRate; } this.PtInChart=function(x,y) { if (this.MaxVolLine) { if (x>=this.MaxVolLine.Start.X && x<=this.MaxVolLine.End.X && y>=this.MaxVolLine.Start.Y-5 && y=this.ChartFrame.HorizontalMin && maxVolPrice<=this.ChartFrame.HorizontalMax) aryPrice.push({Price:maxVolPrice, Font:this.VolLineFont, LineColor:this.VolLineColor, LineWidth:2, TextColor:this.VolLineTextColor, Type:1}); if (IFrameSplitOperator.IsNumber(this.Data.VAHPrice) && this.Data.VAHPrice>=this.ChartFrame.HorizontalMin && this.Data.VAHPrice<=this.ChartFrame.HorizontalMax) aryPrice.push({Price:this.Data.VAHPrice, Font:this.VAFont, LineColor:this.VAHLineColor, LineWidth:2, TextColor:this.VAHTextColor, Type:2}); if (IFrameSplitOperator.IsNumber(this.Data.VALPrice) && this.Data.VALPrice>=this.ChartFrame.HorizontalMin && this.Data.VALPrice<=this.ChartFrame.HorizontalMax) aryPrice.push({Price:this.Data.VALPrice, Font:this.VAFont, LineColor:this.VALLineColor, LineWidth:2, TextColor:this.VALTextColor, Type:3}); for(var i=0;i10) //刻度文字 { var defaultfloatPrecision=GetfloatPrecision(this.HQChart.Symbol);//价格小数位数 var text=item.Price.toFixed(defaultfloatPrecision); this.Canvas.font=item.Font; this.Canvas.textAlign = "left"; this.Canvas.textBaseline = "middle"; var fontHeight=this.GetFontHeight(); var textWidth=this.Canvas.measureText(text).width+2*pixelTatio; this.Canvas.fillStyle=item.LineColor; this.Canvas.fillRect(right,yLine-fontHeight/2,textWidth,fontHeight); this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(text,right+1*pixelTatio, yLine); } } } this.DrawVolBar=function() { var cellHeight=this.GetPriceYOffset(this.Data.PriceOffset); var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var top=this.ChartFrame.GetYFromData(this.Data.MaxPrice)-cellHeight/2; var bottom=this.ChartFrame.GetYFromData(this.Data.MinPrice)+cellHeight/2; var width=right-left; var height=bottom-top; var maxBarWidth=width*this.BarWidthRate; if (this.IsShowText) { this.VolFont=this.GetDynamicVolTextFont(cellHeight, maxBarWidth); if (this.VolFont) this.Canvas.font=this.VolFont; } for(var i=0,j=0;ithis.ChartFrame.HorizontalMax) continue; this.DrawVolBarItem(item, left, right, maxBarWidth, cellHeight); } this.DrawPriceLine(); } this.DrawVolBarItem=function(item, left, right, maxBarWidth, cellHeight) { var barLeft=left; var barRight=right; var barTop=this.ChartFrame.GetYFromData(item.Price)-cellHeight/2; var barHeight=cellHeight-1; if (barHeight<1) barHeight=1; if (this.VolType==1) { if (!item.TotalVol) return; if (!IFrameSplitOperator.IsNumber(item.TotalVol.Value)) return; var barWidth=item.TotalVol.Value*maxBarWidth/this.MaxVol; var color; if (IFrameSplitOperator.IsNumber(item.TotalVol.ColorID)) color=this.BarColor[item.TotalVol.ColorID]; else if (item.TotalVol.Color) color=item.TotalVol.Color; this.Canvas.fillStyle=color; if (this.BarPosition==1) { this.Canvas.fillRect(barRight,ToFixedRect(barTop),-barWidth,ToFixedRect(barHeight)); } else { this.Canvas.fillRect(barLeft,ToFixedRect(barTop),barWidth,ToFixedRect(barHeight)); } if (this.IsShowText && this.VolFont) { var text=IFrameSplitOperator.FormatVolString(item.TotalVol.Value, this.HQChart.LanguageID); this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle=this.TextConfig.Color; if (this.BarPosition==1) { this.Canvas.textAlign = 'right'; this.Canvas.fillText(text,right-5,barTop+cellHeight/2); } else { this.Canvas.textAlign = 'left'; this.Canvas.fillText(text,left+5,barTop+cellHeight/2); } } } else { var text=""; for(var i=0;i0) text+="x"; text+=volText; } if (this.IsShowText && this.VolFont) { this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle=this.TextConfig.Color; if (this.BarPosition==1) { this.Canvas.textAlign = 'right'; this.Canvas.fillText(text,right-5,barTop+cellHeight/2); } else { this.Canvas.textAlign = 'left'; this.Canvas.fillText(text,left+5,barTop+cellHeight/2); } } } } this.GetPriceYOffset=function(value) { var frame=this.ChartFrame; var y=frame.ChartBorder.GetHeightEx()*(value)/(frame.HorizontalMax-frame.HorizontalMin); return y; } this.GetDynamicVolTextFont=function(cellHeight, width, fontOption) { var fontSize=parseInt(cellHeight)-2; if (cellHeight<5) fontSize=parseInt(cellHeight); //高度太小了就不要上下间距了 if (fontSize>this.TextConfig.FontMaxSize) fontSize=this.TextConfig.FontMaxSize; else if (fontSize<=0) fontSize=1; if (fontSize0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); var lineWidth=this.Canvas.lineWidth; } var yZero=this.ChartFrame.GetYFromData(0); for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } if (x>chartright) break; if (this.BarType==1) { if (dataWidth>=4) //柱子太细就直接画竖线 this.DrawKBarItem(bars, x, left, right, top, bottom, yZero, dataWidth); else this.DrawBarItem(bars, x, top, bottom, yZero, lineWidth); } else { this.DrawBarItem(bars, x, top, bottom, yZero, lineWidth); } } this.Canvas.restore(); } this.DrawKBarItem=function(aryBar, x, left, right, top, bottom, yZero, barWidth) { var plusValue=0, yPlus=yZero; //正数 var negativeValue=0, yNegative= yZero; //负数 for(var i=0;i0) { plusValue+=item; var y=this.ChartFrame.GetYFromData(plusValue); var rtBar={Left: left, Top:y, Width:barWidth, Height:(yPlus-y)}; yPlus=y; } else { negativeValue+=item; var y=this.ChartFrame.GetYFromData(negativeValue); var rtBar={Left:left, Top:y, Width:barWidth, Height:(yNegative-y)}; yNegative=y; } if (this.IsHScreen) this.Canvas.fillRect(rtBar.Top,rtBar.Left, rtBar.Height, rtBar.Width); else this.Canvas.fillRect(rtBar.Left, rtBar.Top, rtBar.Width, rtBar.Height); } } this.DrawBarItem=function(aryBar,x, top, bottom, yZero, lineWidth) { var x=ToFixedPoint2(lineWidth, x); var plusValue=0, yPlus=yZero; //正数 var negativeValue=0, yNegative=yZero; //负数 for(var i=0;i0) { plusValue+=item; var y=this.ChartFrame.GetYFromData(plusValue); var line={X:x, Y:yPlus, X2:x, Y2:y}; yPlus=y; } else { negativeValue+=item; var y=this.ChartFrame.GetYFromData(negativeValue); var line={X:x, Y:yNegative, X2:x, Y2:y}; yNegative=y; } this.Canvas.beginPath(); if (this.IsHScreen) { this.Canvas.moveTo(line.Y,line.X); this.Canvas.lineTo(line.Y2,line.X2); } else { this.Canvas.moveTo(line.X,line.Y); this.Canvas.lineTo(line.X2,line.Y2); } this.Canvas.strokeStyle=this.BarColor[i]; this.Canvas.stroke(); } } this.GetMaxMin=function() { var xPointCount=this.ChartFrame.XPointCount; var range={}; range.Min=null; range.Max=null; if(!this.Data || !this.Data.Data) return range; for(var i=this.Data.DataOffset,j=0;i0) plusValue+=barValue; else if (barValue<0) negativeValue+=barValue; } if (range.Max==null) { range.Max=plusValue; range.Min=negativeValue; } if (range.MaxnegativeValue) range.Min=negativeValue; } return range; } this.PtInChart=function(x,y) { var option={ StackedBar:true }; if (this.BarType==0) option.BarWidth=4; return this.PtInBar(x,y, option ); } this.DrawSelectedStatus=function() { this.DrawLinePoint({ StackedBar:true }); } } //锁 支持横屏 function ChartLock() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartLock"; this.WidthDiv = 0.2; // 框子宽度占比 this.LockCount = 20; // 锁最新的几个数据 this.BGColor = g_JSChartResource.LockBGColor; this.TextColor = g_JSChartResource.LockTextColor; this.Font = g_JSChartResource.DefaultTextFont; this.Title = '🔒开通权限'; this.LockRect=null; //上锁区域 this.LockID; //锁ID this.Callback; //回调 this.IndexName; //指标名字 this.MinWidth=null; //最小宽度 this.Draw=function(isDraw) { this.LockRect=null; if (this.NotSupportMessage) { this.DrawNotSupportmessage(); return; } if (this.ChartFrame.IsHScreen===true) { this.HScreenDraw(isDraw); return; } var xOffset = this.ChartBorder.GetRight(); var lOffsetWidth = 0; if (this.ChartFrame.Data != null) { var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0; var chartright=this.ChartBorder.GetRight(); var xPointCount=this.ChartFrame.XPointCount; for(var i=this.ChartFrame.Data.DataOffset,j=0;ichartright) break; } lOffsetWidth = (dataWidth + distanceWidth) * this.LockCount; } if (lOffsetWidth == 0) { lOffsetWidth = (xOffset - this.ChartBorder.GetLeft()) * this.WidthDiv; } var lLeft = xOffset - lOffsetWidth; if (lLeft < this.ChartBorder.GetLeft()) lLeft = this.ChartBorder.GetLeft(); var lHeight = this.ChartBorder.GetBottom() - this.ChartBorder.GetTop(); var lWidth = this.ChartBorder.GetRight() - lLeft; if (this.MinWidth>10 && lWidthchartright) break; } lOffsetWidth = (dataWidth + distanceWidth) * this.LockCount; } if (lOffsetWidth == 0) { lOffsetWidth = (xOffset - this.ChartBorder.GetTop()) * this.WidthDiv; } var lLeft = xOffset - lOffsetWidth; if (lLeft < this.ChartBorder.GetTop()) lLeft = this.ChartBorder.GetTop(); var lHeight = this.ChartBorder.GetRight()-this.ChartBorder.GetLeft(); var lWidth = this.ChartBorder.GetBottom() - lLeft; this.Canvas.fillStyle = this.BGColor; this.Canvas.fillRect(this.ChartBorder.GetLeft(), lLeft,lHeight,lWidth); var xCenter = this.ChartBorder.GetLeft() + lHeight / 2; var yCenter = lLeft + lWidth / 2; this.Canvas.save(); this.Canvas.translate(xCenter, yCenter); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.textAlign = 'center'; this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle = this.TextColor; this.Canvas.font = this.Font; this.Canvas.fillText(this.Title, 0, 0); this.Canvas.restore(); this.LockRect={Left:this.ChartBorder.GetLeft(),Top:lLeft,Width:lHeight,Heigh:lWidth}; //保存上锁区域 } //x,y是否在上锁区域 this.GetTooltipData=function(x,y,tooltip) { if (this.LockRect==null) return false; this.Canvas.beginPath(); this.Canvas.rect(this.LockRect.Left,this.LockRect.Top,this.LockRect.Width,this.LockRect.Heigh); if (this.Canvas.isPointInPath(x,y)) { tooltip.Data={ ID:this.LockID, Callback:this.Callback, IndexName:this.IndexName }; tooltip.ChartPaint=this; return true; } return false; } } //买卖盘 function ChartBuySell() { this.newMethod=ChartSingleText; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartBuySell"; this.TextFont=g_JSChartResource.KLineTrain.Font; //"bold 14px arial"; //买卖信息字体 this.LastDataIcon=g_JSChartResource.KLineTrain.LastDataIcon; //{Color:'rgb(0,0,205)',Text:'↓'}; this.BuyIcon=g_JSChartResource.KLineTrain.BuyIcon; //{Color:'rgb(0,0,205)',Text:'B'}; this.SellIcon=g_JSChartResource.KLineTrain.SellIcon; //{Color:'rgb(0,0,205)',Text:'S'}; this.BuySellData=new Map(); //Key=数据索引index Value:Data:[ { Op: 买/卖 0=buy 1=sell, Date:, Time, Price: Vol:}, ] this.IconFont=g_JSChartResource.KLineTrain.IconFont; this.LastDataDrawType=0; //0=画在最后一个数据上 1=画在指定索引上 this.LastDataIndex=-1; this.AddTradeItem=function(tradeItem) { if (this.BuySellData.has(tradeItem.Key)) { var Trade=this.BuySellData.get(tradeItem.Key); Trade.Data.push(tradeItem); } else { this.BuySellData.set(tradeItem.Key, { Data:[tradeItem] }); } } this.ClearTradeData=function() { this.BuySellData=new Map(); } this.Draw=function() { if (!this.Data || !this.Data.Data) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=this.ChartFrame.DataWidth; var distanceWidth=this.ChartFrame.DistanceWidth; var chartright=this.ChartBorder.GetRight(); if (isHScreen===true) chartright=this.ChartBorder.GetBottom(); var xPointCount=this.ChartFrame.XPointCount; if (this.IconFont) { var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 var iconSize=dataWidth+distanceWidth; var minIconSize=18*pixelTatio; if (iconSizechartright) break; var bDrawLastData=false; if (this.LastDataDrawType==1) { if (i==this.LastDataIndex) bDrawLastData=true; } else { if (i==this.Data.Data.length-1) bDrawLastData=true; } if (bDrawLastData) { //最后一个位置 画一个箭头 var x=this.ChartFrame.GetXFromIndex(j); var yHigh=this.ChartFrame.GetYFromData(value.High); this.Canvas.textAlign='center'; this.Canvas.textBaseline='bottom'; if (this.IconFont) { this.Canvas.fillStyle=this.IconFont.Last.Color this.DrawText(this.IconFont.Last.Text,x,yHigh,isHScreen); } else { this.Canvas.fillStyle=this.LastDataIcon.Color; this.Canvas.font=this.TextFont; this.DrawText(this.LastDataIcon.Text,x,yHigh,isHScreen); } } var key=i; if (!this.BuySellData.has(key)) continue; var trade=this.BuySellData.get(key); var yHigh=this.ChartFrame.GetYFromData(value.High); var yLow=this.ChartFrame.GetYFromData(value.Low); var drawInfo=[false, false]; //0=buy 1=sell for(var k in trade.Data) { if (drawInfo[0]==true && drawInfo[1]==true) break; //买卖图标只画一次 var bsItem=trade.Data[k]; if (bsItem.Op==0 && drawInfo[0]==false) //买 标识在最低价上 { this.Canvas.textAlign='center'; this.Canvas.textBaseline='top'; if (this.IconFont) { this.Canvas.fillStyle=this.IconFont.Buy.Color this.DrawText(this.IconFont.Buy.Text,x,yLow,isHScreen); } else { this.Canvas.fillStyle=this.BuyIcon.Color; this.DrawText(this.BuyIcon.Text,x,yLow,isHScreen); } drawInfo[0]=true; } else if (bsItem.Op==1 && drawInfo[1]==false) //卖 标识在最高价上 { this.Canvas.textAlign='center'; this.Canvas.textBaseline='bottom'; if (this.IconFont) { this.Canvas.fillStyle=this.IconFont.Sell.Color this.DrawText(this.IconFont.Sell.Text,x,yHigh,isHScreen); } else { this.Canvas.fillStyle=this.SellIcon.Color; this.DrawText(this.SellIcon.Text,x,yHigh,isHScreen); } drawInfo[1]=true; } } } } } //深度图 function ChartOrderbookDepth() { this.newMethod=IChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName="ChartOrderbookDepth"; this.Data=null; this.AskColor={ Line:g_JSChartResource.DepthChart.AskColor.Line, Area:g_JSChartResource.DepthChart.AskColor.Area } //卖 this.BidColor={ Line:g_JSChartResource.DepthChart.BidColor.Line, Area:g_JSChartResource.DepthChart.BidColor.Area } //买 this.LineWidth=g_JSChartResource.DepthChart.LineWidth; this.Draw=function() { if (!this.Data) return; var lineWidthBackup=this.Canvas.lineWidth; this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.DrawArea(this.Data.Bids, this.BidColor.Line, this.BidColor.Area, true); this.DrawArea(this.Data.Asks, this.AskColor.Line, this.AskColor.Area, false); this.Canvas.lineWidth=lineWidthBackup; } this.DrawArea=function(aryData, colorLine, colorArea, isLeft) { var xRange=this.ChartFrame.VerticalRange; var aryPoint=[]; for(var i in aryData) { var item=aryData[i]; if (isLeft) { if (item.PricexRange.Max) break; } var x=this.ChartFrame.GetXFromIndex(item.Price); var y=this.ChartFrame.GetYFromData(item.Vol); aryPoint.push({X:x,Y:y}); } if (aryPoint.length<=1) return; var left=this.ChartBorder.GetLeft(); var bottom=this.ChartBorder.GetBottom(); var right=this.ChartBorder.GetRight(); this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, bottom); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.lineTo(item.X,item.Y); } this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y); this.Canvas.lineTo(isLeft?left:right,bottom); this.Canvas.lineTo(aryPoint[0].X,bottom); this.Canvas.closePath(); this.Canvas.fillStyle = colorArea; this.Canvas.fill(); this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, bottom); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.lineTo(item.X,item.Y); } this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y); this.Canvas.strokeStyle=colorLine; this.Canvas.stroke(); } this.GetMaxMin=function() { var range={ Min:null, Max:null, XMin:null, XMax:null }; var xRange=this.ChartFrame.VerticalRange; for(var i in this.Data.Asks) { var item=this.Data.Asks[i]; if (item.Price>xRange.Max) break; if (range.XMin==null || range.XMin>item.Price) range.XMin=item.Price; if (range.XMax==null || range.XMaxitem.Vol) range.Min=item.Vol; if (range.Max==null || range.Maxitem.Price) range.XMin=item.Price; if (range.XMax==null || range.XMaxitem.Vol) range.Min=item.Vol; if (range.Max==null || range.Max0) height+=this.LineSpace; var lineWidth=0; if (item.Title) { var textWidth=this.Canvas.measureText(item.Title).width+2; if (maxTitleWidth0) { title=g_JSChartLocalization.GetText('Tooltip-Exchange',this.LanguageID); var value=item.Vol/item.FlowCapital*100; var text=value.toFixed(2)+'%'; aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:this.TitleColor }); } //持仓量 if (MARKET_SUFFIX_NAME.IsFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position)) { title=g_JSChartLocalization.GetText('Tooltip-Position',this.LanguageID); var text=IFrameSplitOperator.FromatIntegerString(item.Position,2,this.LanguageID); aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:this.TitleColor }); } return result; } this.DrawTooltipData=function(titleData) { if (!titleData || !IFrameSplitOperator.IsNonEmptyArray(titleData.AryText)) return; var pixelRatio=GetDevicePixelRatio(); var left=this.GetLeft()+2*pixelRatio; var top=this.GetTop()+3*pixelRatio; if (this.IsHScreen) { this.Canvas.save(); var x=this.GetLeft()+this.Height, y=this.GetTop(); this.Canvas.translate(x, y); this.Canvas.rotate(90 * Math.PI / 180); //x, y 作为原点 left=2*pixelRatio; top=3*pixelRatio; } this.Canvas.textBaseline="top"; var right=left+this.Width-this.Mergin.Right*pixelRatio; left+=this.Mergin.Left*pixelRatio; top+=this.Mergin.Top*pixelRatio; for(var i=0; i0 && MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)) { var value=(item.Close-item.YFClose)/item.YFClose*100; var color = this.KLineTitlePaint.GetColor(value, 0); var text = value.toFixed(2)+'%'; } else if (item.YClose>0) { var value=(item.Close-item.YClose)/item.YClose*100; var color = this.KLineTitlePaint.GetColor(value, 0); var text = value.toFixed(2)+'%'; } else { var text='--.--'; var color=this.KLineTitlePaint.GetColor(0, 0); } this.Canvas.fillStyle=color; this.Canvas.fillText(text,left+labelWidth,top); top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Vol',this.LanguageID); this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(text, left,top); var vol=item.Vol; if (upperSymbol && MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) vol/=100; //A股统一转成手 var text=IFrameSplitOperator.FromatIntegerString(vol,2,this.LanguageID); this.Canvas.fillStyle=this.VolColor; this.Canvas.fillText(text,left+labelWidth,top); if (IFrameSplitOperator.IsNumber(item.Amount)) { top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Amount',this.LanguageID); this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(text, left,top); var text=IFrameSplitOperator.FormatValueString(item.Amount,2,this.LanguageID); this.Canvas.fillStyle=this.AmountColor; this.Canvas.fillText(text,left+labelWidth,top); } //换手率 if (MARKET_SUFFIX_NAME.IsSHSZStockA(this.HQChart.Symbol) && item.FlowCapital>0) { top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Exchange',this.LanguageID); this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(text, left,top); var value=item.Vol/item.FlowCapital*100; var text=value.toFixed(2)+'%'; this.Canvas.fillText(text,left+labelWidth,top); } //持仓量 var upperSymbol=this.HQChart.Symbol.toUpperCase(); if (MARKET_SUFFIX_NAME.IsFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position)) { this.Canvas.fillStyle=this.TitleColor; top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Position',this.LanguageID); this.Canvas.fillText(text, left,top); var text=IFrameSplitOperator.FromatIntegerString(item.Position,2,this.LanguageID); this.Canvas.fillText(text,left+labelWidth,top); } if (this.IsHScreen) this.Canvas.restore(); } */ this.DrawBorder=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=this.GetLeft(); var top=this.GetTop(); this.Canvas.strokeStyle=this.BorderColor; if (isHScreen) this.Canvas.strokeRect(ToFixedPoint(left),ToFixedPoint(top),this.Height,this.Width); else this.Canvas.strokeRect(ToFixedPoint(left),ToFixedPoint(top),ToFixedRect(this.Width),ToFixedRect(this.Height)); } this.DrawBG=function() { var isHScreen=(this.ChartFrame.IsHScreen===true); var left=this.GetLeft(); var top=this.GetTop(); this.Canvas.fillStyle=this.BGColor; if (isHScreen) this.Canvas.fillRect(left,top,this.Height,this.Width); else this.Canvas.fillRect(left,top,this.Width,this.Height); } //设置参数接口 this.SetOption=function(option) { if (option.LineHeight>0) this.LineHeight=option.LineHeight*GetDevicePixelRatio(); if (option.BGColor) this.BGColor=option.BGColor; if (option.LanguageID>0) this.LanguageID=option.LanguageID; } } function MinuteTooltipPaint() { this.newMethod=KLineTooltipPaint; //派生 this.newMethod(); delete this.newMethod; this.ClassName='MinuteTooltipPaint'; this.Left=1*GetDevicePixelRatio(); this.Top=1*GetDevicePixelRatio(); this.YClose; this.IsShowAveragePrice=true; //是否显示均价 this.TitlePaint; this.GetTop=function() { if (this.IsHScreen) { var border=this.ChartBorder.GetHScreenBorder(); if (this.ShowPosition==0) return border.TopEx+this.Left; else return border.BottomEx-this.Width-this.Left; } else { var border=this.ChartBorder.GetBorder(); return border.Top+this.Top; } } this.GetLeft=function() { if (this.IsHScreen) { var border=this.ChartBorder.GetHScreenBorder(); return border.Right-this.Height-this.Top; } else { var border=this.ChartBorder.GetBorder(); if (this.ShowPosition==0) return border.LeftEx+this.Left; else return border.RightEx-this.Width-this.Left; } } this.Draw=function() { if (!this.IsEnableDraw()) return; this.IsHScreen=this.ChartFrame.IsHScreen===true; this.TitlePaint=this.HQChart.TitlePaint[0]; if (!this.TitlePaint) return; var drawData; //{ Type:0=连续交易 1=集合竞价, Data:数据 } var pointInfo=this.TitlePaint.PointInfo; if (pointInfo && (pointInfo.ClientPos==2 || pointInfo.ClientPos==3 || (pointInfo.ClientPos>=200&& pointInfo.ClientPos<=299) || (pointInfo.ClientPos>=300&& pointInfo.ClientPos<=399))) { var auctionData=this.TitlePaint.GetCurrentAuctionData(); if (!auctionData) return; drawData={ Type:1, Data:auctionData }; } else { var minuteData=this.TitlePaint.GetCurrentKLineData(); if (!minuteData) return; drawData={ Type:0, Data:minuteData }; } var titleData=this.GetFormatTitle(drawData); if (!titleData || !IFrameSplitOperator.IsNonEmptyArray(titleData.AryText)) return; this.CalculateTooltipSize(titleData); this.CalculateShowPosition(); this.DrawBG(); this.DrawTooltipData(titleData); this.DrawBorder(); } this.GetFormatTitle=function(data) { if (!data || !data.Data) return; var item; var close, vol, amount; if (data.Type==0) //盘中 { item=data.Data; close=item.Close; vol=item.Vol; amount=item.Amount; } else if (data.Type==1) //盘前 盘后 { item=data.Data.Data; if (!item) return; close=item.Price; } var upperSymbol; if (this.HQChart.Symbol) upperSymbol=this.HQChart.Symbol.toUpperCase(); var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //国内期货, 纽约期货交易所 var defaultfloatPrecision=GetfloatPrecision(this.HQChart.Symbol);//价格小数位数 this.YClose=this.TitlePaint.YClose; this.YClose=item.YClose; if (isFutures && IFrameSplitOperator.IsNumber(item.YClearing)) this.YClose=item.YClearing; var aryText=[]; var result={ AryText:aryText }; var text, title, color; if (IFrameSplitOperator.IsNumber(item.Date)) { text=IFrameSplitOperator.FormatDateString(item.Date); aryText.push({ Text:text, Color:this.DateTimeColor }); } if (IFrameSplitOperator.IsNumber(item.Time)) { text=IFrameSplitOperator.FormatTimeString(item.Time); aryText.push({ Text:text, Color:this.DateTimeColor }); } if (IFrameSplitOperator.IsNumber(close)) //最新 { title=g_JSChartLocalization.GetText('Tooltip-Price',this.LanguageID); color=this.TitlePaint.GetColor(close,this.YClose); text=close.toFixed(defaultfloatPrecision); aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:color }); } var isShowAvPrice=true; if (MARKET_SUFFIX_NAME.IsForeignExchange(upperSymbol)) isShowAvPrice=false; //外汇没有均价 else if (MARKET_SUFFIX_NAME.IsET(upperSymbol) && !MARKET_SUFFIX_NAME.IsETShowAvPrice(upperSymbol)) isShowAvPrice=false; else if (MARKET_SUFFIX_NAME.IsShowAvPrice && !MARKET_SUFFIX_NAME.IsShowAvPrice(upperSymbol)) isShowAvPrice=false; //均价 if (isShowAvPrice && IFrameSplitOperator.IsNumber(item.AvPrice) && this.IsShowAveragePrice) { title=g_JSChartLocalization.GetText('Tooltip-AvPrice',this.LanguageID); var color=this.TitlePaint.GetColor(item.AvPrice,this.YClose); text=item.AvPrice.toFixed(defaultfloatPrecision); aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:color }); } //涨幅 if (IFrameSplitOperator.IsNumber(close) && IFrameSplitOperator.IsNumber(this.YClose)) { title=g_JSChartLocalization.GetText('Tooltip-Increase',this.LanguageID); if (this.YClose===0) { text = '--.--'; color = this.TitleColor; } else { var value=(close-this.YClose)/this.YClose*100; color = this.TitlePaint.GetColor(value, 0); text = value.toFixed(2)+'%'; } aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:color }); } //成交量 if (IFrameSplitOperator.IsNumber(vol)) { title=g_JSChartLocalization.GetText('Tooltip-Vol',this.LanguageID); var text=IFrameSplitOperator.FromatIntegerString(vol,2,this.LanguageID); aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:this.VolColor }); } //成交金额 if (IFrameSplitOperator.IsNumber(amount)) { title=g_JSChartLocalization.GetText('Tooltip-Amount',this.LanguageID); var text=IFrameSplitOperator.FormatValueString(amount,2,this.LanguageID); aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:this.AmountColor }); } if (IFrameSplitOperator.IsNumber(item.Position)) { title=g_JSChartLocalization.GetText('Tooltip-Position',this.LanguageID); var text=IFrameSplitOperator.FormatValueString(item.Position,2,this.LanguageID); aryText.push({Title:title, TitleColor:this.TitleColor, Text:text, Color:this.TitleColor }); } return result; } /* this.DrawTooltipData=function(item) { //JSConsole.Chart.Log('[KLineTooltipPaint::DrawKLineData] ', item); if (!this.HQChart.Symbol) return; var defaultfloatPrecision=GetfloatPrecision(this.HQChart.Symbol);//价格小数位数 var left=this.GetLeft()+2*GetDevicePixelRatio(); var top=this.GetTop()+3*GetDevicePixelRatio(); this.YClose=this.KLineTitlePaint.YClose; var upperSymbol=this.HQChart.Symbol.toUpperCase(); if (this.IsHScreen) { this.Canvas.save(); var x=this.GetLeft()+this.Height, y=this.GetTop(); this.Canvas.translate(x, y); this.Canvas.rotate(90 * Math.PI / 180); //x, y 作为原点 left=2*GetDevicePixelRatio(); top=3*GetDevicePixelRatio(); } this.Canvas.textBaseline="top"; this.Canvas.textAlign="left"; this.Canvas.font=this.Font[0]; var labelWidth=this.Canvas.measureText('擎: ').width; var aryDateTime=item.DateTime.split(' '); if (aryDateTime && aryDateTime.length==2) { var text=IFrameSplitOperator.FormatDateString(aryDateTime[0]); this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(text, left,top); top+=this.LineHeight; text=IFrameSplitOperator.FormatTimeString(aryDateTime[1]); this.Canvas.fillText(text, left,top); } var close=item.Close; var increase=item.Increase; var vol=item.Vol; var amount=item.Amount; if (item.Before) //读取盘前数据 { close=item.Before.Close; increase=item.Before.Increase; vol=item.Before.Vol; amount=item.Before.Amount; } //最新价格 top+=this.LineHeight; this.Canvas.fillStyle=this.TitleColor; text=g_JSChartLocalization.GetText('Tooltip-Price',this.LanguageID); this.Canvas.fillText(text, left,top); var color=this.KLineTitlePaint.GetColor(close,this.YClose); var text=close.toFixed(defaultfloatPrecision); this.Canvas.fillStyle=color; this.Canvas.fillText(text,left+labelWidth,top); var isShowAvPrice=true; if (item.Before) isShowAvPrice=false; //集合竞价均价 else if (MARKET_SUFFIX_NAME.IsForeignExchange(upperSymbol)) isShowAvPrice=false; //外汇没有均价 else if (MARKET_SUFFIX_NAME.IsET(upperSymbol) && !MARKET_SUFFIX_NAME.IsETShowAvPrice(upperSymbol)) isShowAvPrice=false; else if (MARKET_SUFFIX_NAME.IsShowAvPrice && !MARKET_SUFFIX_NAME.IsShowAvPrice(upperSymbol)) isShowAvPrice=false; //均价 if (isShowAvPrice && IFrameSplitOperator.IsNumber(item.AvPrice) && this.IsShowAveragePrice) { top+=this.LineHeight; this.Canvas.fillStyle=this.TitleColor; text=g_JSChartLocalization.GetText('Tooltip-AvPrice',this.LanguageID); this.Canvas.fillText(text, left,top); var color=this.KLineTitlePaint.GetColor(item.AvPrice,this.YClose); var text=item.AvPrice.toFixed(defaultfloatPrecision); this.Canvas.fillStyle=color; this.Canvas.fillText(text,left+labelWidth,top); } //涨幅 top+=this.LineHeight; this.Canvas.fillStyle=this.TitleColor; text=g_JSChartLocalization.GetText('Tooltip-Increase',this.LanguageID); this.Canvas.fillText(text, left,top); var value=(close-this.YClose)/this.YClose*100; var color = this.KLineTitlePaint.GetColor(value, 0); var text = value.toFixed(2)+'%'; this.Canvas.fillStyle=color; this.Canvas.fillText(text,left+labelWidth,top); //成交量 if (IFrameSplitOperator.IsNumber(vol)) { this.Canvas.fillStyle=this.TitleColor; top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Vol',this.LanguageID); this.Canvas.fillText(text, left,top); var text=IFrameSplitOperator.FromatIntegerString(vol,2,this.LanguageID); this.Canvas.fillText(text,left+labelWidth,top); } //成交金额 if (IFrameSplitOperator.IsNumber(amount)) { top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Amount',this.LanguageID); this.Canvas.fillText(text, left,top); var text=IFrameSplitOperator.FormatValueString(amount,2,this.LanguageID); this.Canvas.fillText(text,left+labelWidth,top); } if (IFrameSplitOperator.IsNumber(item.Position)) { top+=this.LineHeight; text=g_JSChartLocalization.GetText('Tooltip-Position',this.LanguageID); this.Canvas.fillText(text, left,top); var text=IFrameSplitOperator.FormatValueString(item.Position,2,this.LanguageID); this.Canvas.fillText(text,left+labelWidth,top); } if (this.IsHScreen) this.Canvas.restore(); } */ } //PC端 分时图tooltip左侧固定 function MinuteLeftTooltipPaint() { this.newMethod=IExtendChartPainting; //派生 this.newMethod(); delete this.newMethod; this.IsDynamic=true; this.IsEraseBG=true; this.DrawAfterTitle=true; this.ClassName='MinuteLeftTooltipPaint'; this.BorderColor=g_JSChartResource.PCTooltipPaint.BorderColor; //边框颜色 this.BGColor=g_JSChartResource.PCTooltipPaint.BGColor; //背景色 this.TitleColor=g_JSChartResource.PCTooltipPaint.TitleColor; //标题颜色 this.DateTimeColor=g_JSChartResource.PCTooltipPaint.DateTimeColor; //日期时间颜色 this.VolColor=g_JSChartResource.PCTooltipPaint.VolColor; //标题成交量 this.AmountColor=g_JSChartResource.PCTooltipPaint.AmountColor; //成交金额 this.PositionColor=g_JSChartResource.PCTooltipPaint.PositionColor; //持仓 this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; this.TitlePaint; this.UpColor=g_JSChartResource.UpTextColor; this.DownColor=g_JSChartResource.DownTextColor; this.UnchagneColor=g_JSChartResource.UnchagneTextColor; this.YClose; this.Mergin={ Left:2, Top:3, Bottom:2, Right:2 }; this.LineHeight=15 //行高 this.FixedWidth; //固定宽度 this.Font=g_JSChartResource.PCTooltipPaint.TitleFont; this.HQChart; //设置参数接口 this.SetOption=function(option) { if (option.BGColor) this.BGColor=option.BGColor; if (option.LanguageID>0) this.LanguageID=option.LanguageID; if (IFrameSplitOperator.IsNumber(option.FixedWidth)) this.FixedWidth=option.FixedWidth; } this.ReloadResource=function(resource) { this.BorderColor=g_JSChartResource.PCTooltipPaint.BorderColor; //边框颜色 this.BGColor=g_JSChartResource.PCTooltipPaint.BGColor; //背景色 this.TitleColor=g_JSChartResource.PCTooltipPaint.TitleColor; //标题颜色 this.DateTimeColor=g_JSChartResource.PCTooltipPaint.DateTimeColor; //日期时间颜色 this.VolColor=g_JSChartResource.PCTooltipPaint.VolColor; //标题成交量 this.AmountColor=g_JSChartResource.PCTooltipPaint.AmountColor; //成交金额 this.UpColor=g_JSChartResource.UpTextColor; this.DownColor=g_JSChartResource.DownTextColor; this.UnchagneColor=g_JSChartResource.UnchagneTextColor; this.Font=g_JSChartResource.PCTooltipPaint.TitleFont; } this.IsEnableDraw=function() { if (!this.HQChart || !this.HQChart.TitlePaint || !this.HQChart.TitlePaint[0]) return false; var pt=this.HQChart.LastPoint; if (!pt) return false; if (this.HQChart.ChartCorssCursor && !this.HQChart.ChartCorssCursor.IsShowCorss) return false; return this.HQChart.IsMouseOnClient(pt.X, pt.Y); } this.Draw=function() { if (!this.IsEnableDraw()) return; this.TitlePaint=this.HQChart.TitlePaint[0]; if (!this.TitlePaint) return; var pointInfo=this.TitlePaint.PointInfo; var drawData; //{ Type:0=连续交易 1=集合竞价, Data:数据 } if (pointInfo && (pointInfo.ClientPos==2 || pointInfo.ClientPos==3 || (pointInfo.ClientPos>=200&& pointInfo.ClientPos<=299) || (pointInfo.ClientPos>=300&& pointInfo.ClientPos<=399))) { var auctionData=this.TitlePaint.GetCurrentAuctionData(); if (!auctionData) return; drawData={ Type:1, Data:auctionData }; } else { var minuteData=this.TitlePaint.GetCurrentKLineData(); if (!minuteData) return; drawData={ Type:0, Data:minuteData }; } this.YClose=this.TitlePaint.YClose; var aryText=this.GetForamtTitle(drawData); if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return; this.Canvas.font=this.Font; this.Canvas.textBaseline = 'top'; this.LineHeight=GetFontHeight(this.Canvas, null, "擎"); var border=this.ChartBorder.GetBorder(); var height=this.LineHeight*aryText.length*2; var rtBorder={Left:1, Top:1, Right:border.Left }; rtBorder.Bottom=rtBorder.Top+height; rtBorder.Width=rtBorder.Right-rtBorder.Left; rtBorder.Height=rtBorder.Bottom-rtBorder.Top; rtBorder.Height+=(this.Mergin.Top+this.Mergin.Bottom); rtBorder.Bottom=rtBorder.Top+rtBorder.Height; if (IFrameSplitOperator.IsNumber(this.FixedWidth)) rtBorder.Width=this.FixedWidth; this.Canvas.fillStyle = this.BGColor; this.Canvas.fillRect(rtBorder.Left,rtBorder.Top,rtBorder.Width,rtBorder.Height); this.Canvas.strokeStyle=this.BorderColor; this.Canvas.strokeRect(ToFixedPoint(rtBorder.Left),ToFixedPoint(rtBorder.Top),ToFixedRect(rtBorder.Width),ToFixedRect(rtBorder.Height)); var right=(rtBorder.Left+rtBorder.Width)-this.Mergin.Right; var left=this.Mergin.Left+rtBorder.Left; var top=this.Mergin.Top+rtBorder.Top; var rtItem={ Left:left, Top:top, Right:right }; rtItem.Width=rtItem.Right-rtItem.Left; for(var i=0;iyclse) return this.UpColor; else if (price0) this.ShowType=option.ShowType; if (option.IsShowX) this.IsShowX=option.IsShowX; if (option.ShowXCount>0) this.ShowXCount=option.ShowXCount; if (option.Width>100) this.Width=option.Width*GetDevicePixelRatio(); if (option.CalculateType>0) this.CalculateType=option.CalculateType; if (IFrameSplitOperator.IsNumber(option.PriceZoom)) this.PriceZoom=option.PriceZoom; } this.ReloadResource=function(resource) { this.PenBorder=g_JSChartResource.FrameBorderPen; this.Font=g_JSChartResource.TitleFont; this.InfoColor=g_JSChartResource.StockChip.InfoColor; this.DayInfoColor=g_JSChartResource.StockChip.DayInfoColor; this.DefaultButton=CloneData(g_JSChartResource.StockChip.DefaultButton); //默认筹码分布图 this.LongButton=CloneData(g_JSChartResource.StockChip.LongButton); //远期筹码分布图 this.RecentButton=CloneData(g_JSChartResource.StockChip.RecentButton); //近期筹码分布图 this.ButtonTooltip=CloneData(g_JSChartResource.Buttons.Tooltip); } this.Draw=function() { this.PixelRatio=GetDevicePixelRatio(); var left=ToFixedPoint(this.ChartBorder.GetRight()+this.Left); var top=ToFixedPoint(this.ChartBorder.GetTop()); var right=ToFixedPoint(left+this.Width-1*this.PixelRatio); var bottom=ToFixedPoint(this.ChartBorder.GetBottom()); var width=right-left; var height=bottom-top; this.ClientRect={Left:left,Top:top,Width:width,Height:height}; if (ChartData.IsTickPeriod(this.HQChart.Period)) //分笔图没有筹码 { this.Canvas.font=this.Font; this.Canvas.fillStyle=this.InfoColor; var x=left+width/2; var y=top+height/2; this.Canvas.textAlign="center"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(this.NotSupportMessage,x,y); this.DrawBorder(); return; } if (this.CalculateChip()) { this.DrawFrame(); this.DrawAllChip(); if (this.ShowType==1|| this.ShowType==2) this.DrawDayChip(); this.CalculateCast(); //计算成本 this.DrawChipInfo(); } else { JSConsole.Chart.Log('[StockChip::Draw] no data'); } this.DrawBorder(); this.SizeChange=false; } this.DrawChipInfo=function() { var bottom=this.ClientRect.Top+this.ClientRect.Height-1; var left=this.ClientRect.Left+2; var right=this.ClientRect.Left+this.ClientRect.Width; this.Canvas.font=this.Font; this.Canvas.fillStyle=this.InfoColor; this.Canvas.textBaseline='bottom'; this.Canvas.textAlign='left'; var lineHeight=this.LineHeight*GetDevicePixelRatio(); var text='70%成本价 --.--'; if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Cast)) text='70%成本价'+ this.Data.Cast[1].MinPrice.toFixed(2)+'-'+this.Data.Cast[1].MaxPrice.toFixed(2)+'集中'+this.Data.Cast[1].Rate.toFixed(2)+'%'; this.Canvas.fillText(text,left,bottom); bottom-=lineHeight; text='90%成本价 --.--'; if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Cast)) text='90%成本价'+ this.Data.Cast[0].MinPrice.toFixed(2)+'-'+this.Data.Cast[0].MaxPrice.toFixed(2)+'集中'+this.Data.Cast[0].Rate.toFixed(2)+'%';; this.Canvas.fillText(text,left,bottom); bottom-=lineHeight; text='平均成本:'+this.Data.ChipInfo.AveragePrice.toFixed(2)+'元'; this.Canvas.fillText(text,left,bottom); bottom-=lineHeight; text=+this.Data.YPrice.toFixed(2)+'处获利盘:'+this.Data.ChipInfo.YProfitRate.toFixed(2)+'%'; this.Canvas.fillText(text,left,bottom); bottom-=lineHeight; text='获利比例:'; this.Canvas.fillText(text,left,bottom); var textWidth=this.Canvas.measureText(text).width+2; var barLeft=left+textWidth; var barWidth=(right-5-barLeft); this.Canvas.strokeStyle=this.ColorNoProfit; this.Canvas.strokeRect(barLeft,bottom-lineHeight,barWidth,lineHeight); this.Canvas.strokeStyle=this.ColorProfit; this.Canvas.strokeRect(barLeft,bottom-lineHeight,barWidth*(this.Data.ChipInfo.ProfitRate/100),lineHeight); text=this.Data.ChipInfo.ProfitRate.toFixed(2)+'%'; this.Canvas.textAlign='center'; this.Canvas.fillText(text,barLeft+barWidth/2,bottom); bottom-=lineHeight; this.Canvas.textAlign='left'; text='成本分布,日期:'+IFrameSplitOperator.FormatDateString(this.Data.SelectData.Date); if (this.Data.SelectData.Time) text+=' '+IFrameSplitOperator.FormatTimeString(this.Data.SelectData.Time); this.Canvas.fillText(text,left,bottom); bottom-=lineHeight; if (this.ShowType!=1 && this.ShowType!=2) return; var right=this.ClientRect.Left+this.ClientRect.Width-1; this.Canvas.textAlign='right'; var textWidth=50; this.Data.DayChip.sort(function(a,b){return b.Day-a.Day;}) for(var i in this.Data.DayChip) { var item=this.Data.DayChip[i]; var rate=0; if (this.Data.ChipInfo && this.Data.ChipInfo.Vol>0) rate=item.Vol/this.Data.ChipInfo.Vol*100; text=item.Day+'周期'+(this.ShowType==1?'前':'内')+'成本'+(IFrameSplitOperator.IsNumber(rate)? (rate.toFixed(2)+'%'):"--.--%"); if (i==0) textWidth=this.Canvas.measureText(text).width+8; this.Canvas.fillStyle=item.Color; this.Canvas.fillRect(right-textWidth,bottom-lineHeight,textWidth,lineHeight); this.Canvas.fillStyle=this.DayInfoColor; this.Canvas.fillText(text,right,bottom); bottom-=lineHeight; } } this.DrawDayChip=function() { var KLineFrame=this.HQChart.Frame.SubFrame[0].Frame; for(var i in this.Data.DayChip) { var aryPoint=[]; var chipData=this.Data.DayChip[i].Chip; if (!chipData) continue; var totalVol=0; for(var j=0;j=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:btnItem, Frame:this, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } else { if (moveonPoint && (moveonPoint.X>=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { color=item.Style.MoveOnColor; if (mouseStatus) mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:btnItem, Frame:this, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } } this.Canvas.fillStyle=color; this.Canvas.font=font; this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(item.Style.Text, xBotton, yButton); this.Buttons.push(btnItem); right=xBotton; } } this.DrawToolbarTooltip=function(mouseOnToolbar) { if (!mouseOnToolbar) return; var left=this.ClientRect.Left; var right=this.ClientRect.Left+this.ClientRect.Width; var key='Toolbar-'+mouseOnToolbar.Item.ID; text=g_JSChartLocalization.GetText(key,0); if (!text) return; var rtButton=mouseOnToolbar.Rect; var xCenter=rtButton.Left+rtButton.Width/2; this.Canvas.font=this.ButtonTooltip.Font; this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; var textWidth=this.Canvas.measureText(text).width+8; var textHeight=this.GetFontHeight(); var bgHeight=textHeight+8; var x=xCenter-textWidth/2; var y=rtButton.Top-bgHeight; if (y<0) y=rtButton.Bottom+1; if (x+textWidth>right) x=right-textWidth-2; this.Canvas.fillStyle=this.ButtonTooltip.ColorBG; this.Canvas.fillRect(x,y,textWidth,bgHeight); //画一个背景色, 不然是一个黑的背景 this.Canvas.fillStyle=this.ButtonTooltip.Color; this.Canvas.fillText(text, x+4,y+bgHeight/2); } this.PtInButtons=function(x,y) //坐标是否在按钮上 { for(var i=0;i=minPrice) { if (MaxVolmaxPrice || price0?totalProfitVol/totalVol*100:0, YProfitRate:totalVol>0?totalYProfitVol/totalVol*100:0 }; if (this.ShowType==0) { this.DrawLines(aryProfitPoint,this.ColorProfit); this.DrawLines(aryNoProfitPoint,this.ColorNoProfit); var averagePrice=this.Data.ChipInfo.AveragePrice; if (averagePrice>0 && averagePrice<=maxPrice && averagePrice>=minPrice) { averagePrice=averagePrice.toFixed(2); this.DrawAveragePriceLine(aryProfitPoint,aryNoProfitPoint,KLineFrame.GetYFromData(averagePrice),this.ColorAveragePrice); } } else //在火焰山模式下, 筹码用一个颜色 { this.DrawLines(aryProfitPoint,this.ColorBG); this.DrawLines(aryNoProfitPoint,this.ColorBG); } } this.CalculateCast=function() //计算 90% 70%的成本价 { if (!this.Data.ChipInfo || !this.Data.ChipInfo.Vol) return; var aryCast= [ {Start:0.05,End:0.95, MaxPrice:0, MinPrice:0, Rate:0}, {Start:0.15,End:0.85, MaxPrice:0, MinPrice:0, Rate:0} ]; var averagePrice=this.Data.ChipInfo.AveragePrice; var totalProfitVol=this.Data.ChipInfo.ProfitVol; var tempVol=0; for(var i=0, castCount=0;iitemCast.Start) { itemCast.MinPrice=price; ++castCount; } if (itemCast.MaxPrice<=0 && rate>itemCast.End) { itemCast.MaxPrice=price; ++castCount; } } } for(var i in aryCast) { var item=aryCast[i]; var addPrice=item.MaxPrice+item.MinPrice; if (addPrice) item.Rate=Math.abs(item.MaxPrice-item.MinPrice)/addPrice*100; } this.Data.Cast=aryCast; } this.DrawArea=function(aryPoint,color) { if (aryPoint.length<=0) return; this.Canvas.fillStyle=color; this.Canvas.beginPath(); this.Canvas.moveTo(this.ClientRect.Left,aryPoint[0].Y); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.lineTo(item.X,item.Y); } this.Canvas.lineTo(this.ClientRect.Left,aryPoint[aryPoint.length-1].Y); this.Canvas.fill(); } this.DrawLines=function(aryPoint,color) { if (aryPoint.length<=0) return; this.Canvas.strokeStyle=color; this.Canvas.beginPath(); for(var i in aryPoint) { var item=aryPoint[i]; this.Canvas.moveTo(this.ClientRect.Left,item.Y); this.Canvas.lineTo(item.X,item.Y); } this.Canvas.stroke(); } this.DrawAveragePriceLine=function(aryProfitPoint,aryNoProfitPoint,y,color) { for(var i in aryProfitPoint) { var item=aryProfitPoint[i]; if (item.Y==y) { this.Canvas.strokeStyle=color; this.Canvas.beginPath(); this.Canvas.moveTo(this.ClientRect.Left,item.Y); this.Canvas.lineTo(item.X,item.Y); this.Canvas.stroke(); return; } } for(var i in aryNoProfitPoint) { var item=aryNoProfitPoint[i]; if (item.Y==y) { this.Canvas.strokeStyle=color; this.Canvas.beginPath(); this.Canvas.moveTo(this.ClientRect.Left,item.Y); this.Canvas.lineTo(item.X,item.Y); this.Canvas.stroke(); return; } } } this.DrawBorder=function() { this.Canvas.strokeStyle=this.PenBorder; this.Canvas.strokeRect(this.ClientRect.Left,this.ClientRect.Top,this.ClientRect.Width,this.ClientRect.Height); } this.EvenlyDistribute=function(aryChip, data) //平均分布 data={Low, High, Vol, MaxVol, MaxPrice, MinPrice } { var low=data.Low, high=data.High, maxPrice=data.MaxPrice, minPrice=data.MinPrice, maxVol=1; if ( (high-low)== 0) return; var averageVol=data.Vol/(high-low); for(var j=low;j<=high && j<=maxPrice;++j) { var index=j-minPrice; aryChip[index]+=averageVol; if (maxVolmiddlePrice;--i,++j) { var y = Math.tan(ANGLE* PI / 180)*j; totalValue+=y aryVol.push({Index:i-minPrice, Value:y}); } if (totalValue>0) { for(var i=0;i=4) return false; //分钟K线不支持, 没时间做,以后再做吧 var count=bindData.DataOffset+parseInt(this.HQChart.CursorIndex); if (count>=bindData.Data.length) count=bindData.Data.length-1; var selData=bindData.Data[count]; var yPrice=selData.Close; var mouseY=this.HQChart.LastPoint.Y; if (mouseY) yPrice=this.HQChart.Frame.SubFrame[0].Frame.GetYData(mouseY); //JSConsole.Chart.Log("[StockChip::CalculateChip]",count,this.HQChart.CursorIndex,selData); const rate=1; var aryVol=[]; var seed=1,vol,maxPrice,minPrice; for(let i=count;i>=0;--i) { var item=bindData.Data[i]; var changeRate=1; //换手率 if (item.FlowCapital>0) changeRate=item.Vol/item.FlowCapital; if (i==count) vol=item.Vol*changeRate; else vol=item.Vol*seed; var dataItem={Vol:vol,High:item.High,Low:item.Low}; aryVol.push(dataItem); seed*=(1-changeRate*rate); if (!maxPrice || maxPriceitem.Low) minPrice=item.Low; } //JSConsole.Chart.Log("[StockChip::CalculateChip]",maxPrice,minPrice); if (!maxPrice || !minPrice) return true; var priceZoom=this.PriceZoom; maxPrice=parseInt(maxPrice*priceZoom); minPrice=parseInt(minPrice*priceZoom); var dataCount=maxPrice-minPrice; var aryChip=new Array() for(let i=0;i<=dataCount;++i) { aryChip.push(0); } var dayChip=[]; var distributeData; if (this.ShowType==2) { var dayChip= [ {Day:100, Color:this.DAY_COLOR[1][5]}, {Day:60, Color:this.DAY_COLOR[1][4]}, {Day:30, Color:this.DAY_COLOR[1][3]}, {Day:20, Color:this.DAY_COLOR[1][2]}, {Day:10, Color:this.DAY_COLOR[1][1]}, {Day:5, Color:this.DAY_COLOR[1][0]} ]; for(let i in aryVol) { var item=aryVol[i]; var high=parseInt(item.High*priceZoom); var low=parseInt(item.Low*priceZoom); var averageVol=item.Vol; if (high-low>0) averageVol=item.Vol/(high-low); if (averageVol<=0.000000001) continue; for(var k=0;k=0;--i) { var item=aryVol[i]; var high=parseInt(item.High*priceZoom); var low=parseInt(item.Low*priceZoom); var averageVol=item.Vol; if (high-low>0) averageVol=item.Vol/(high-low); if (averageVol<=0.000000001) continue; for(var k=0;k0) averageVol=item.Vol/(high-low); if (averageVol<=0.000000001) continue; distributeData={Low:low, High:high, Vol:item.Vol, MaxPrice:maxPrice, MinPrice:minPrice}; this.CalculateDistribute(aryChip, distributeData); } } if (!distributeData) return false; this.Data={AllChip:aryChip, MaxVol:distributeData.MaxVol, MaxPrice:maxPrice, MinPrice:minPrice,SelectData:selData, DayChip:dayChip, YPrice:yPrice}; return true; } this.DrawFrame=function() //X轴成交量坐标 { if (this.IsShowX==false) return; if (this.Data.MaxVol<=0) return; var isDrawXFrame=this.HQChart.Frame.SubFrame.length===1 ? false:true; //是否画X轴,如果只有1个窗口就不画 var KLineFrame=this.HQChart.Frame.SubFrame[0].Frame; var chartBorder=KLineFrame.ChartBorder; var bottom=ToFixedPoint(chartBorder.GetBottomEx()+1); if (!isDrawXFrame) bottom=this.ClientRect.Top+this.ClientRect.Height; var left=this.ClientRect.Left; var right=left+this.ClientRect.Width; this.Canvas.strokeStyle=this.PenBorder; this.Canvas.beginPath(); if (isDrawXFrame) { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } var showCount=this.ShowXCount; var maxValue=this.Data.MaxVol; var perValue=Math.floor(maxValue/showCount); this.Canvas.font=this.Font; this.Canvas.textBaseline='top'; this.Canvas.fillStyle=this.InfoColor; var xOffset=10*GetDevicePixelRatio(); for(var i=1;i<=showCount;++i) { var vol=perValue*i; var x=(vol/this.Data.MaxVol)*this.ClientRect.Width+this.ClientRect.Left; x=ToFixedPoint(x); if (i==showCount) //最后一个刻度不要画线了 { this.Canvas.textAlign='right'; var text=IFrameSplitOperator.FormatValueString(maxValue, 1); this.Canvas.fillText(text,x,bottom+2); } else { this.Canvas.moveTo(x,this.ClientRect.Top); this.Canvas.lineTo(x,bottom); this.Canvas.textAlign='center'; var text=IFrameSplitOperator.FormatValueString(vol, 1); var textWidth=this.Canvas.measureText(text).width; this.Canvas.fillText(text,Math.floor(x-textWidth*0.25),bottom+2); } } this.Canvas.stroke(); } } //窗口分割 function FrameSplitPaint() { this.newMethod=IExtendChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='FrameSplitPaint'; this.LineColor='rgb(255,0,0)'; this.TextColor="rgb(255,0,0)"; this.LineWidth=2; this.Font='bold '+18*GetDevicePixelRatio() +"px 微软雅黑"; this.TextTopOffset=10*GetDevicePixelRatio(); //设置参数接口 this.SetOption=function(option) { if (option) { if (option.LineColor) this.LineColor=option.LineColor; if (option.TextColor) this.TextColor=option.TextColor; if (option.Font) this.Font=option.Font; if (IFrameSplitOperator.IsNumber(option.LineWidth)) this.LineWidth=option.LineWidth; if (IFrameSplitOperator.IsNumber(option.TextTopOffset)) this.TextTopOffset=option.TextTopOffset; } } this.Draw=function() { if (!this.HQChart) return; if (this.HQChart.Period!=0 && this.HQChart.Period!=1) return; if (!this.HQChart.ChartPaint[0]) return; var data=this.HQChart.ChartPaint[0].Data; if (!data) return; this.Data=data; if (!this.ChartFrame || !this.ChartFrame.SubFrame) return; var subFrame=this.ChartFrame.SubFrame[0].Frame; if (!subFrame) return; var isHScreen=(subFrame.IsHScreen===true); var dataWidth=subFrame.DataWidth; var distanceWidth=subFrame.DistanceWidth; var xPointCount=subFrame.XPointCount; var lineWidth=this.LineWidth * GetDevicePixelRatio(); if (isHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var drawHeight=border.ChartHeight-border.TopTitle-5*GetDevicePixelRatio(); } this.Canvas.save(); this.Canvas.lineWidth=lineWidth; this.Canvas.font=this.Font; this.Canvas.textAlign='center'; this.Canvas.textBaseline='top'; var preQuarter={ Left:border.LeftEx, Top:ToFixedPoint2(lineWidth,border.TopTitle), Height:drawHeight, LineWidth:lineWidth }; for(var i=this.Data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; if (!preQuarter.DateInfo) { preQuarter.DateInfo=dateInfo; preQuarter.Right=x; } else { var preDateInfo=preQuarter.DateInfo; if (preDateInfo.Year!=dateInfo.Year || preDateInfo.Quarter!=dateInfo.Quarter) { preQuarter.Right=x; this.DrawQuarter(preQuarter); preQuarter.Left=x; preQuarter.Right=null; preQuarter.DateInfo=dateInfo; } else { preQuarter.Right=x; } } } this.DrawQuarter(preQuarter); this.Canvas.restore(); } this.DrawQuarter=function(quarterInfo) { if (!IFrameSplitOperator.IsNumber(quarterInfo.Left) || !IFrameSplitOperator.IsNumber(quarterInfo.Right)) return; var left=ToFixedPoint2(quarterInfo.LineWidth,quarterInfo.Left); var right=ToFixedPoint2(quarterInfo.LineWidth,quarterInfo.Right); var drawWidth=right-left; this.Canvas.strokeStyle=this.LineColor; this.Canvas.strokeRect(left, quarterInfo.Top, drawWidth, quarterInfo.Height); var date=quarterInfo.DateInfo; var shortYear=date.Year%100; if (shortYear<10) var strYear='0'+shortYear; else var strYear=shortYear.toString(); var text=`${strYear}年${date.Quarter}季度`; var textWidth = this.Canvas.measureText(text).width; if (textWidth<(drawWidth+5)) { var x=left+drawWidth/2; var y=quarterInfo.Top+this.TextTopOffset; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,x,y); } } this.GetQuarter=function(date) { if (!IFrameSplitOperator.IsNumber(date)) return null; var year=parseInt(date/10000); var month=parseInt((date%10000)/100); switch(month) { case 1: case 2: case 3: var quarter=1; break; case 4: case 5: case 6: var quarter=2; break; case 7: case 8: case 9: var quarter=3; break; case 10: case 11: case 12: var quarter=4; break; default: return null; } return { Year:year, Month:month, Quarter:quarter }; } } //区间选择选中范围背景 function RectSelectPaint() { this.newMethod=IExtendChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='RectSelectPaint'; this.LineColor=g_JSChartResource.RectSelect.LineColor; //竖线 this.LineWidth=g_JSChartResource.RectSelect.LineWidth; this.LineDotted=g_JSChartResource.RectSelect.LineDotted; this.AreaColor=g_JSChartResource.RectSelect.AreaColor; //面积 this.SubAreaColor=g_JSChartResource.RectSelect.SubAreaColor; //标记图标 this.MarkConfig= { Family:g_JSChartResource.RectSelect.Mark.Family, Text:g_JSChartResource.RectSelect.Mark.Text, Color:g_JSChartResource.RectSelect.Mark.Color, Size:g_JSChartResource.RectSelect.Mark.Size, IsShow:false, Position: { Index:g_JSChartResource.RectSelect.Mark.Position.Index, Top:g_JSChartResource.RectSelect.Mark.Position.Top } } this.FirstPoint; this.SecondPoint; this.CenterPoint; this.PreventClose=false; //如果外面有div,可以设置成true, 有外面控制 this.SpaceReselected=false; //空格重选 this.SubClient={ FirstPoint:null, SecondPoint:null, Start:null, End:null }; this.StartDate; //{ Date:, Index: } this.EndDate; //{ Date:, Index: } this.CenterDate; //{ Date:, Index: } this.HQChart; this.DragRect; //拖拽边框区域数组 [] this.ShowRangeText= { Enable:false, Position:0, //0顶部 1=中间 2=底部 Font:g_JSChartResource.RectSelect.RangeTextFont, Color:g_JSChartResource.RectSelect.RangeTextColor, BGColor:g_JSChartResource.RectSelect.RangeTextBGColor, SubPosition:0, SubFont:g_JSChartResource.RectSelect.RangeTextSubFont, SubColor:g_JSChartResource.RectSelect.RangeTextSubColor, SubBGColor:g_JSChartResource.RectSelect.RangeTextSubBGColor, }; this.BorderCache; this.IsOnlyOnePoint=false; //空格选中区间,单点模式 this.IsFullFrame=false; //区间选择包含子窗口 //设置参数接口 this.SetOption=function(option) { if (option) { if (option.LineColor) this.LineColor=option.LineColor; if (option.AreaColor) this.AreaColor=option.AreaColor; if (IFrameSplitOperator.IsBool(option.SpaceReselected)) this.SpaceReselected=option.SpaceReselected; if (option.ShowRangeText) { var item=option.ShowRangeText; if (IFrameSplitOperator.IsBool(item.Enable)) this.ShowRangeText.Enable=item.Enable; if (IFrameSplitOperator.IsNumber(item.Position)) this.ShowRangeText.Position=item.Position; if (IFrameSplitOperator.IsNumber(item.SubPosition)) this.ShowRangeText.SubPosition=item.SubPosition; } if (option.Mark) { var item=option.Mark; if (IFrameSplitOperator.IsBool(item.IsShow)) this.MarkConfig.IsShow=item.IsShow; if (item.Position) { if (IFrameSplitOperator.IsNumber(item.Position.Index)) this.MarkConfig.Position.Index=item.Position.Index; if (item.Position.Top) this.MarkConfig.Position.Top=item.Position.Top; } } } } this.ReloadResource=function(resource) { this.LineColor=g_JSChartResource.RectSelect.LineColor; //竖线 this.LineWidth=g_JSChartResource.RectSelect.LineWidth; this.LineDotted=g_JSChartResource.RectSelect.LineDotted; this.AreaColor=g_JSChartResource.RectSelect.AreaColor; //面积 this.ShowRangeText.Font=g_JSChartResource.RectSelect.RangeTextFont; this.ShowRangeText.Color=g_JSChartResource.RectSelect.RangeTextColor; this.ShowRangeText.BGColor=g_JSChartResource.RectSelect.RangeTextBGColor; } this.IsMinuteChart=function() { var className=this.HQChart.ClassName; var isMinuteChart=(className=="MinuteChartContainer" || className=="MinuteChartHScreenContainer") ? true:false; return isMinuteChart; } this.GetKData=function() { if (!this.HQChart) return null; var isMinuteChart=this.IsMinuteChart(); var data=null; if (isMinuteChart) { if (!this.HQChart.SourceData) return null; data=this.HQChart.SourceData; } else { if (!this.HQChart.ChartPaint[0]) return null; data=this.HQChart.ChartPaint[0].Data; if (!data) return null; } return data; } this.GetPointCount=function() { var count=0; if (this.FirstPoint) ++count; if (this.SecondPoint) ++count; return count; } this.DateToNumber=function(value, isMinuteChart) { if (isMinuteChart) { if (IFrameSplitOperator.IsNumber(value.Date)) return value.Date*10000+value.Time; else return value.Time; } else { var period=this.HQChart.Period; if (ChartData.IsDayPeriod(period, true)) return value.Date; //YYYYMMDD else if (ChartData.IsMinutePeriod(period, true)) return value.Date*10000+value.Time; //YYYYMMDDHHMM else if (ChartData.IsSecondPeriod(period) || ChartData.IsTickPeriod(period)) return value.Date*1000000+value.Time; //YYYYMMDDHHMMSS else if (ChartData.IsMilliSecondPeriod(period) ) return value.Date*1000000000+value.Time; //YYYYMMDDHHMMSSFFF } return null; } this.GetSelectRectDataByOnePoint=function() { if (!this.FirstPoint) return null; var data=this.GetKData(); if (!data) return null; var isMinuteChart=this.IsMinuteChart(); var firstDate=this.DateToNumber(this.FirstPoint,isMinuteChart); var selectData={ Start:null, End:null, Data:data }; for(var i=0;iselectData.End) { var temp=selectData.Start; selectData.Start=selectData.End; selectData.End=temp; } return selectData; } } return null; } this.SortPoint=function() { var isMinuteChart=this.IsMinuteChart(); this.CenterData=null; if (this.FirstPoint && !this.SecondPoint) { this.StartDate={ Date:this.DateToNumber(this.FirstPoint,isMinuteChart), Index:0 }; } else if (this.FirstPoint && this.SecondPoint) { var firstValue=this.DateToNumber(this.FirstPoint,isMinuteChart); var secondValue=this.DateToNumber(this.SecondPoint,isMinuteChart); if (firstValue=this.EndDate.Date) { this.SubClient.Start=null; this.SubClient.End=null; } else { if (this.SubClient.Start.Datethis.EndDate.Date) this.SubClient.End.Date=this.EndDate.Date; } } } } this.GetCenterPoint=function() { if (!this.FirstPoint || !this.SecondPoint) return null; if (!IFrameSplitOperator.IsNumber(this.FirstPoint.DataIndex)) return null; if (!IFrameSplitOperator.IsNumber(this.SecondPoint.DataIndex)) return null; var count=this.FirstPoint.DataIndex-this.SecondPoint.DataIndex; if (Math.abs(count)<3) return null; var centerIndex=parseInt(this.FirstPoint.DataIndex+(this.SecondPoint.DataIndex-this.FirstPoint.DataIndex)/2); if (centerIndex<0) return null; var data=this.GetKData(); if (!data || !data.Data) return null; var kItem=data.Data[centerIndex]; if (!kItem) return null; return { Date:kItem.Date, Time:kItem.Time, DataIndex:centerIndex }; } this.MovePoint=function(offset) { if (!this.FirstPoint || !this.SecondPoint) return false; var data=this.GetKData(); if (!data || !data.Data) return false; var dataIndex=this.FirstPoint.DataIndex+offset; var kItem=data.Data[dataIndex]; if (!kItem) return false; var firstPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; var dataIndex=this.SecondPoint.DataIndex+offset; var kItem=data.Data[dataIndex]; if (!kItem) return false; var secondPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; var dataIndex=this.CenterPoint.DataIndex+offset; var kItem=data.Data[dataIndex]; if (!kItem) return false; var centerPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; this.FirstPoint=firstPoint; this.SecondPoint=secondPoint; this.CenterPoint=centerPoint; return true; } this.MoveSubRect=function(step, isLeft) { if (!this.FirstPoint || !this.SecondPoint) return false; if (!this.SubClient || !this.SubClient.FirstPoint || !this.SubClient.SecondPoint) return false; var data=this.GetKData(); if (!data || !data.Data) return false; //区间范围 var startIndex=Math.min(this.FirstPoint.DataIndex,this.SecondPoint.DataIndex); var endIndex=Math.max(this.FirstPoint.DataIndex,this.SecondPoint.DataIndex); var subStartPoint=this.SubClient.FirstPoint; var subEndPoint=this.SubClient.SecondPoint; if (this.SubClient.FirstPoint.DataIndex>this.SubClient.SecondPoint.DataIndex) { var subStartPoint=this.SubClient.SecondPoint; var subEndPoint=this.SubClient.FirstPoint; } var subStartIndex=subStartPoint.DataIndex; var subEndIndex=subEndPoint.DataIndex; if (isLeft) { if (subStartIndex<=startIndex) return false; subStartIndex-=step; subEndIndex-=step; } else { if (subEndPoint.DataIndex>=endIndex) return false; subStartIndex+=step; subEndIndex+=step; } var bChanged=false; if (subStartIndex!=subStartPoint.DataIndex) { subStartPoint.DataIndex=subStartIndex; var kItem=data.Data[subStartIndex]; subStartPoint.Date=kItem.Date; subStartPoint.Time=kItem.Time; bChanged=true; } if (subEndIndex!=subStartPoint.DataIndex) { subEndPoint.DataIndex=subEndIndex; var kItem=data.Data[subEndIndex]; subEndPoint.Date=kItem.Date; subEndPoint.Time=kItem.Time; bChanged=true; } return bChanged } this.SetPoint=function(kItem, option) { var dataIndex=null; if (option) { if (IFrameSplitOperator.IsNumber(option.DataIndex)) dataIndex=option.DataIndex; } if (option && IFrameSplitOperator.IsNumber(option.Index)) { switch(option.Index) { case 0: this.FirstPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; this.CenterPoint=this.GetCenterPoint(); return true; case 1: this.SecondPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; this.CenterPoint=this.GetCenterPoint(); return true; case 2: //中心偏移 var offset=dataIndex-this.CenterPoint.DataIndex; //this.CenterPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; if (Math.abs(offset)>0) return this.MovePoint(offset); return false; case 3: this.SubClient.FirstPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; return true; case 4: this.SubClient.SecondPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; return true; default: return false; } } else { if (this.IsOnlyOnePoint) { this.FirstPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; return true; } if (!this.FirstPoint) { this.FirstPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; return true; } if (!this.SecondPoint) { this.SecondPoint={ Date:kItem.Date, Time:kItem.Time, DataIndex:dataIndex }; this.CenterPoint=this.GetCenterPoint(); return true; } return false; } } this.ClearPoint=function() { if (this.PreventClose) return false; var bRedraw=false; if (this.FirstPoint) { this.FirstPoint=null; bRedraw=true; } if (this.SecondPoint) { this.SecondPoint=null; bRedraw=true; } this.SubClient.FirstPoint=null; this.SubClient.SecondPoint=null; return bRedraw; } this.Draw=function() { this.BorderCache=null; this.StartDate=null; this.EndDate=null; this.CenterDate=null; this.DragRect=[]; this.SubClient.Start=null; this.SubClient.End=null; if (!this.FirstPoint && !this.SecondPoint) return; this.SortPoint(); var data=this.GetKData(); if (!data) return; this.Data=data; if (!this.ChartFrame || !this.ChartFrame.SubFrame) return; var subFrame=this.ChartFrame.SubFrame[0].Frame; if (!subFrame) return; var isHScreen=(subFrame.IsHScreen===true); var dataWidth=subFrame.DataWidth; var distanceWidth=subFrame.DistanceWidth; var xPointCount=subFrame.XPointCount; if (isHScreen) { var border=subFrame.GetBorder(); var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.BottomEx; this.BorderCache=border; } else { var border=subFrame.GetBorder(); if (this.IsFullFrame) border=this.ChartFrame.ChartBorder.GetBorder(); //全部指标窗口选中 var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; var drawHeight=border.ChartHeight-border.TopTitle-5*GetDevicePixelRatio(); var top=border.TopEx; var bottom=border.BottomEx; this.BorderCache=border; } this.Canvas.save(); var isDayPeriod=ChartData.IsDayPeriod(this.HQChart.Period,true); var isMinuteChart=this.IsMinuteChart(); var startPoint=null, endPoint=null, subStartPoint=null, subEndPoint=null; var startDate=null, startEnd=null; var aryLines=[]; for(var i=this.Data.DataOffset,j=0;iitem.X) { this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; x=item.X+2; rtBG.X=item.X; } else { this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; x=item.X-2; rtBG.X=item.X-textWidth; } } else if (item.Type==1) //第2个点 { if (textWidth>(border.Right-item.X)) { this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; x=item.X-2; rtBG.X=item.X-textWidth; } else { this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; x=item.X+2; rtBG.X=item.X; } } if (postion==1) { y=item.Top+(item.Bottom-item.Top)/2; if (item.Type==3) y+=textHeight; rtBG.Y=y-textHeight/2; } else if (postion==2) { y=item.Bottom; rtBG.Y=y-textHeight/2; } else { y=item.Top; rtBG.Y=y-textHeight/2; } if (bgColor) { this.Canvas.fillStyle=bgColor; this.Canvas.fillRect(ToFixedPoint(rtBG.X),ToFixedPoint(rtBG.Y),ToFixedRect(rtBG.Width),ToFixedRect(rtBG.Height)); } if (textColor) { this.Canvas.fillStyle=textColor; this.Canvas.fillText(text,x,y,textWidth); } } } } this.DrawLines=function(aryLines) { if (!IFrameSplitOperator.IsNonEmptyArray(aryLines)) return; var lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.lineWidth=lineWidth; for(var i=0;ithis.StartDate.Date && startEnd.Datebottom) rtSelect.Top=bottom; if (rtSelect.Bottombottom) rtSelect.Bottom=bottom; if (rtSelect.Leftright) rtSelect.Left=right; if (rtSelect.Rightright) rtSelect.Right=right; rtSelect.Width=rtSelect.Right-rtSelect.Left; rtSelect.Height=rtSelect.Bottom-rtSelect.Top; switch(this.ShowMode) { case 1: this.DrawUnselectedMaskMode(rtSelect,rtClient); break; case 2: this.DrawFullselectedMode(rtSelect,rtClient); break; default: this.DrawSelectedBorderMode(rtSelect); break; } this.IsClearCanvas=false; } } //深度图 支持横屏 /* 数据格式: [ { Data:[ {X,Y}, ], Type: 1=Up 2=Down 0=Default, LineColor: AreaColor: TextColor: Range:{X:{Max,Min:}, Y:{Max:,Min:} } Height:高度 百分比, Order:"ASC", //DESC=降序 ASC=升序 IsShowCorssCursor:true/false; //是否显示十字光标的提示信息 }, ] */ function DepthMapPaint() { this.newMethod=IExtendChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='DepthMapPaint'; this.LineColor=g_JSChartResource.DepthMapPaint.LineColor; this.AreaColor=CloneData(g_JSChartResource.DepthMapPaint.AreaColor); this.TextColor=g_JSChartResource.DepthMapPaint.TextColor; this.TextBGColor=g_JSChartResource.DepthMapPaint.TextBGColor; //this.Width=200*GetDevicePixelRatio(); this.FrameID=0; this.ID=Guid(); //唯一的ID this.IsDynamic=false; this.IsCallbackDraw=true; //在回调函数里绘制, 不在Draw()中绘制 this.YRange; //Y值范围 this.WidthRate=0.8; //最大使用宽度 0-1 this.IsShow=true; /* this.Data=[ { Data: [ {X:100,Y:20}, {X:110,Y:30}, {X:120,Y:40},{X:130,Y:50} ], Type:1, Range:{ X:{Max:130, Min:100}, Y:{ Max:50, Min:0} }, Height:0.5, LineColor:'rgba(255,106,106,0.6)', AreaColor:['rgba(255,106,106,0.5)','rgba(255,106,106,0.4)','rgba(255,106,106,0.3)','rgba(255,106,106,0.2)'], IsASC:false, //true=升序 false=降序 }, { Data: [ {X:100,Y:20}, {X:110,Y:30}, {X:120,Y:40},{X:130,Y:50} ], Type:2, Range:{ X:{Max:130, Min:100}, Y:{ Max:50, Min:0} }, Height:0.5, IsASC:true, //true=升序 false=降序 }, { Data:[ {X:11.60, Y:50}, {X:11.65, Y:80}, {X:11.68, Y:85},{X:11.70, Y:55}], Type:0, DrawType:0 , //0=面积 1=横线 Range:{ Y:{ Max:100, Min:0} }, LineColor:'rgba(255,165,0,0.6)', AreaColor:['rgba(255,165,0,0.5)','rgba(255,165,0,0.4)','rgba(255,165,0,0.3)','rgba(255,165,0,0.2)'] } ]; */ this.SetOption=function(option) //设置 { if (option.FrameID>0) this.FrameID=option.FrameID; if (IFrameSplitOperator.IsObjectExist(option.ID)) this.ID=option.ID; if (option.IsShowCorssCursor) this.IsShowCorssCursor=option.IsShowCorssCursor; if (IFrameSplitOperator.IsNumber(option.WidthRate)) this.WidthRate=option.WidthRate; } this.Draw=function() { if (!this.Data) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data)) return; if (!this.ChartFrame || !this.ChartFrame.SubFrame || this.ChartFrame.SubFrame.length<=this.FrameID) return; var isHScreen=(this.ChartFrame.IsHScreen===true); var frame=this.ChartFrame.SubFrame[this.FrameID].Frame; var chartBorder=frame.ChartBorder; var height=chartBorder.GetHeightEx(); var left=chartBorder.GetRight(); var top=chartBorder.GetTopEx(); var bottom=chartBorder.GetBottomEx(); var width=this.ChartBorder.Right*this.WidthRate; if (isHScreen) { left=chartBorder.GetBottom(); top=chartBorder.GetRight(); bottom=chartBorder.GetLeft(); var width=this.Width; if (width>this.ChartBorder.Bottom) width=this.ChartBorder.Bottom; } var rtClient={ Left:left, Top:top, Right:left+width, Bottom:bottom, Height:height, Width:width }; this.YRange={ Max:null, Min:0 }; for(var i=0; i0 && item.Height<=1) rtClient.Height=height*item.Height; else rtClient.Height=height; if (item.Type==1) { rtClient.Top=top; rtClient.Bottom=top+rtClient.Height; this.DrawUpArea(item,rtClient); } else if (item.Type==2) { rtClient.Bottom=bottom; rtClient.Top=rtClient.Bottom-rtClient.Height; this.DrawDownArea(item,rtClient); } else { rtClient.Top=top; rtClient.Bottom=bottom; this.DrawDefaultArea(item,rtClient); } } } this.CalculateYRange=function(drawData, yRange) { for(var i in drawData.Data) { var item=drawData.Data[i]; if (yRange.Max==null || yRange.Maxitem.Y) yRange.Min=item.Y; } } this.GetXFromData=function(value, rtClient, minMax) //获取X轴坐标 { var width = rtClient.Width * (value - minMax.Min) / (minMax.Max - minMax.Min); return rtClient.Left + width; } this.GetYFromData=function(value, rtClient, minMax, isASC) { if (isASC) { var height = rtClient.Height * (value - minMax.Min) / (minMax.Max - minMax.Min); return rtClient.Bottom - height; } else { var height = rtClient.Height * (value - minMax.Min) / (minMax.Max - minMax.Min); return rtClient.Top + height; } } this.DrawDefaultArea=function(drawData, rtClient) { var frame=this.ChartFrame.SubFrame[this.FrameID].Frame; var yRange=(drawData.Range && drawData.Range.Y) ? drawData.Range.Y : this.YRange; var aryPoint=[]; for(var i=0; iframe.HorizontalMax || item.X0) { if (drawData.DrawType==1) this.DrawHLine(aryPoint,lineColor,rtClient); else this.DrawLine(aryPoint,lineColor, areaColor,rtClient); } } this.DrawUpArea=function(drawData,rtClient) { var aryPoint=[]; for(var i in drawData.Data) { var item=drawData.Data[i]; var x=this.GetXFromData(item.Y,rtClient,drawData.Range.Y); var y=this.GetYFromData(item.X,rtClient,drawData.Range.X,drawData.IsASC); aryPoint.push({X:x,Y:y}); } var lineColor=drawData.LineColor? drawData.LineColor: this.LineColor; var areaColor=drawData.AreaColor? drawData.AreaColor: this.AreaColor; if (aryPoint.length>0) this.DrawLine(aryPoint,lineColor, areaColor,rtClient); } this.DrawDownArea=function(drawData,rtClient) { var aryPoint=[]; for(var i in drawData.Data) { var item=drawData.Data[i]; var x=this.GetXFromData(item.Y,rtClient,drawData.Range.Y); var y=this.GetYFromData(item.X,rtClient,drawData.Range.X,drawData.IsASC); aryPoint.push({X:x,Y:y}); } var lineColor=drawData.LineColor? drawData.LineColor: this.LineColor; var areaColor=drawData.AreaColor? drawData.AreaColor: this.AreaColor; if (aryPoint.length>0) this.DrawLine(aryPoint,lineColor, areaColor,rtClient); } this.DrawHLine=function(aryPoint, lineColor, rtClient) { var isHScreen=(this.ChartFrame.IsHScreen===true); this.Canvas.strokeStyle=lineColor; this.Canvas.beginPath(); var drawCount=0; for(var i=0; i0) this.Canvas.stroke(); } this.DrawLine=function(aryPoint,lineColor, areaColor,rtClient) { var isHScreen=(this.ChartFrame.IsHScreen===true); var bFirstPoint=true; var drawCount=0; this.Canvas.strokeStyle=lineColor; for(var i in aryPoint) { var item=aryPoint[i]; if (bFirstPoint) { this.Canvas.beginPath(); if (isHScreen) this.Canvas.moveTo(item.Y,item.X); else this.Canvas.moveTo(item.X,item.Y); bFirstPoint=false; } else { if (isHScreen) this.Canvas.lineTo(item.Y,item.X); else this.Canvas.lineTo(item.X,item.Y); } ++drawCount; } if (drawCount>0) this.Canvas.stroke(); //面积 var firstPoint=aryPoint[0]; var lastPoint=aryPoint[aryPoint.length-1]; if (isHScreen) { this.Canvas.lineTo(lastPoint.Y,rtClient.Left); this.Canvas.lineTo(firstPoint.Y,rtClient.Left); } else { this.Canvas.lineTo(rtClient.Left,lastPoint.Y); this.Canvas.lineTo(rtClient.Left,firstPoint.Y); } this.Canvas.closePath(); if (Array.isArray(areaColor)) { if (isHScreen) { let gradient = this.Canvas.createLinearGradient(this.ChartBorder.GetRightEx(),this.ChartBorder.GetTop(), this.ChartBorder.GetLeft(),this.ChartBorder.GetTop()); gradient.addColorStop(0, areaColor[0]); gradient.addColorStop(1, areaColor[1]); this.Canvas.fillStyle=gradient; } else { let gradient = this.Canvas.createLinearGradient(rtClient.Right,rtClient.Top, rtClient.Left,rtClient.Top); var offset=1/areaColor.length; for(var i=0; ifirst.X*zoom && xchartright) break; if (max==null || maxdata.Low) min=data.Low; } if (!IFrameSplitOperator.IsNumber(max) || !IFrameSplitOperator.IsNumber(min)) return; this.Range.Max=max; this.Range.Min=min; this.DrawBackground(); } this.DrawBackground=function() { var start=this.Range.Min; var border=this.KLineFrame.ChartBorder.GetBorder(); var bottom=this.KLineFrame.GetYFromData(start,false); var left=border.Right; var right=left+this.BGWidth; this.Canvas.font=this.Font; this.Canvas.textBaseline = 'top'; this.Canvas.textAlign = 'left'; for(var i=0;ithis.KLineFrame.HorizontalMax) break; var top=this.KLineFrame.GetYFromData(start+item.Value, false); this.Canvas.fillStyle=item.Color; this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(top),ToFixedRect(right-left),ToFixedRect(bottom-top)); if (item.Text && item.TextColor) { this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(item.Text,right+1,top); } bottom=top; //AuotRightWidth } //点位差 var value=this.Range.Max-this.Range.Min; var floatPrecision=GetfloatPrecision(this.HQChart.Symbol); var text=value.toFixed(floatPrecision); var x=this.KLineFrame.GetYFromData(this.Range.Max,false); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(x)); this.Canvas.lineTo(ToFixedPoint(right), ToFixedPoint(x)); this.Canvas.stroke(); var textWidth=this.Canvas.measureText(text).width+4; var textHeight=this.Canvas.measureText("擎").width+2; var rtBG={ Left: right+1, Top:x-textHeight, Width:textWidth, Height:textHeight }; if (this.DiffValueBGColor) { this.Canvas.fillStyle=this.DiffValueBGColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); } this.Canvas.textBaseline = 'bottom'; this.Canvas.fillStyle=this.DiffValutTextColor; this.Canvas.fillText(text,rtBG.Left+1,x); } } //背景图 支持横屏 function BackgroundPaint() { this.newMethod=IExtendChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='BackgroundPaint'; this.IsDynamic=false; this.IsCallbackDraw=true; //在回调函数里绘制, 不在Draw()中绘制 this.FrameID=0; this.Data; //背景数据 { Start:, End:, Color:[] } this.ID=Guid(); //唯一的ID /* this.Data= [ { Start:{ Date:20181201 }, End:{ Date:20181230 }, Color:'rgb(44,55,44)' } , { Start:{ Date:20190308 }, End:{ Date:20190404 }, Color:['rgb(44,55,255)','rgb(200,55,255)'] } ] */ this.ChartSubFrame; this.ChartBorder; this.KData; this.Period; this.XPointCount=0; this.SetOption=function(option) //设置 { if (option.FrameID>0) this.FrameID=option.FrameID; if (IFrameSplitOperator.IsObjectExist(option.ID)) this.ID=option.ID; } this.Draw=function() { if (!this.Data || !this.HQChart) return; if (!this.ChartFrame || !this.ChartFrame.SubFrame || this.ChartFrame.SubFrame.length<=this.FrameID) return; var klineChart=this.HQChart.ChartPaint[0]; if (!klineChart || !klineChart.Data) return; this.ChartSubFrame=this.ChartFrame.SubFrame[this.FrameID].Frame; this.ChartBorder=this.ChartSubFrame.ChartBorder; this.KData=klineChart.Data; this.Period=this.HQChart.Period; if (!this.KData || this.KData.Data.length<=0) return; var isHScreen=(this.ChartSubFrame.IsHScreen===true); this.XPointCount=this.ChartSubFrame.XPointCount; var xPointCount=this.ChartSubFrame.XPointCount; var firstKItem=this.KData.Data[this.KData.DataOffset]; var endIndex=this.KData.DataOffset+xPointCount-1; if (endIndex>=this.KData.Data.length) endIndex=this.KData.Data.length-1; var endKItem=this.KData.Data[endIndex]; var showData=this.GetShowData(firstKItem,endKItem); if (!showData || showData.length<=0) return; var kLineMap=this.BuildKLineMap(); var bottom=this.ChartBorder.GetBottomEx(); var top=this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx(); if (isHScreen) { top=this.ChartBorder.GetRightEx(); bottom=this.ChartBorder.GetLeftEx(); height=this.ChartBorder.GetWidthEx(); } for(var i in showData) { var item=showData[i]; var rt=this.GetBGCoordinate(item,kLineMap); if (!rt) continue; if (Array.isArray(item.Color)) { var gradient; if (isHScreen) gradient = this.Canvas.createLinearGradient(bottom,rt.Left, top, rt.Left); else gradient = this.Canvas.createLinearGradient(rt.Left,top, rt.Left,bottom); var offset=1/item.Color.length; for(var i in item.Color) { gradient.addColorStop(i*offset, item.Color[i]); } this.Canvas.fillStyle=gradient; } else { this.Canvas.fillStyle=item.Color; } if (isHScreen) this.Canvas.fillRect(ToFixedRect(bottom),ToFixedRect(rt.Left),ToFixedRect(height),ToFixedRect(rt.Width)); else this.Canvas.fillRect(ToFixedRect(rt.Left),ToFixedRect(top),ToFixedRect(rt.Width),ToFixedRect(height)); } } this.GetShowData=function(first, end) { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data)) return null; var aryData=[]; for(var i=0;i=first.Date && item.Start.Date<=end.Date) showItem.Start=item.Start; if (item.End.Date>=first.Date && item.End.Date<=end.Date) showItem.End=item.End; if (item.Start.Dateend.Date) { showItem.Start=first; showItem.End=end; } if (showItem.Start || showItem.End) { showItem.Color=item.Color; aryData.push(showItem); } } //JSConsole.Chart.Log('[BackgroundPaint::GetShowData] aryData ', aryData); return aryData; } this.BuildKLineMap=function() { var isHScreen=(this.ChartSubFrame.IsHScreen===true); var dataWidth=this.ChartSubFrame.DataWidth; var distanceWidth=this.ChartSubFrame.DistanceWidth; var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; if (isHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=this.ChartBorder.GetRight(); if (isHScreen) chartright=this.ChartBorder.GetBottom(); var mapKLine={ Data:new Map() ,Start:null, End:null } ; //Key: date / date time, Value:索引 for(var i=this.KData.DataOffset,j=0; ichartright) break; var x=left+(right-left)/2; if (j==0) mapKLine.XLeft=left; mapKLine.XRight=right; var value={ Index:i, ShowIndex:j , X:x, Right:right, Left:left, Date:kItem.Date }; if (ChartData.IsMinutePeriod(this.Period,true)) { var key=`Date:${kItem.Date} Time:${kItem.Time}`; value.Time=kItem.Time; } else { var key=`Date:${kItem.Date}`; } mapKLine.Data.set(key,value); //保存下起始和结束位置 if (j==0) mapKLine.Start=value; mapKLine.End=value; } return mapKLine; } this.GetBGCoordinate=function(item,kLineMap) { var xLeft=null, xRight=null; var isMinutePeriod=ChartData.IsMinutePeriod(this.Period,true); var bSingleDate=false; //JSConsole.Chart.Log('[BackgroundPaint::GetBGCoordinate] item ', item); if (isMinutePeriod) { if (item.Start && item.End && item.Start.Date==item.End.Date && item.Start.Time==item.End.Time) bSingleDate=true; } else { if (item.Start && item.End && item.Start.Date==item.End.Date) bSingleDate=true; } if (bSingleDate) { if (isMinutePeriod) var key=`Date:${item.Start.Date} Time:${item.Start.Time}`; else var key=`Date:${item.Start.Date}`; if (!kLineMap.Data.has(key)) return null; var findItem=kLineMap.Data.get(key); xLeft=findItem.Left; xRight=findItem.Right; return { Left:xLeft, Right:xRight, Width:xRight-xLeft }; } if (item.Start) { if (isMinutePeriod) var key=`Date:${item.Start.Date} Time:${item.Start.Time}`; else var key=`Date:${item.Start.Date}`; if (kLineMap.Data.has(key)) { var findItem=kLineMap.Data.get(key); xLeft=findItem.Left; } else { if (isMinutePeriod) { if (item.Start.Dateitem.Start.Date || (value.Date==item.Start.Date && value.Time>item.Start.Time)) { xLeft=value.Left; break; } } } } else { if (item.Start.Date<=kLineMap.Start.Date) { xLeft=kLineMap.Start.Left; } else { for(var kItem of kLineMap.Data) { var value=kItem[1]; if (value.Date>item.Start.Date) { xLeft=value.Left; break; } } } } } } else { xLeft=kLineMap.XLeft; } if (item.End) { if (isMinutePeriod) var key=`Date:${item.End.Date} Time:${item.End.Time}`; else var key=`Date:${item.End.Date}`; if (kLineMap.Data.has(key)) { var findItem=kLineMap.Data.get(key); xRight=findItem.Right; } else { if (isMinutePeriod) { if (item.End.Date=kLineMap.End.Time) ) { xRight=kLineMap.End.Right; } else { var previousX=null; for(var kItem of kLineMap.Data) { var value=kItem[1]; if (value.Date>item.End.Date || (value.Date==item.End.Date && value.Time>item.End.Time) ) { xRight=previousX; break; } previousX=value.Right; } } } else { if (item.End.Dateitem.End.Date) { xRight=previousX; break; } previousX=value.Right; } } } } } else { xRight=kLineMap.XRight; } if (xLeft==null || xRight==null) return null; return { Left:xLeft, Right:xRight, Width:xRight-xLeft }; } } function MinuteBackgroundPaint() { this.newMethod=IExtendChartPainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='MinuteBackgroundPaint'; this.IsDynamic=true; this.IsCallbackDraw=false; //在回调函数里绘制, 不在Draw()中绘制 this.HQChart; this.Data; //背景数据 { [Date:, Text:, TextColor:, Font: } //this.Data=[ {Date:20210421, Text:"测试测试测试!!!!!"}]; this.Font=g_JSChartResource.DefaultTextFont; this.TextColor=g_JSChartResource.DefaultTextColor; this.MerginTop=20; this.ID=Guid(); //唯一的ID this.FrameID=0; this.SetOption=function(option) //设置 { if (!option) return; if (option.Font) this.Font=option.Font; if (IFrameSplitOperator.IsObjectExist(option.ID)) this.ID=option.ID; if (option.FrameID>0) this.FrameID=option.FrameID; if (option.MerginTop>0) this.MerginTop=option.MerginTop; } this.Draw=function() { if (!this.Data || !this.HQChart) return; if (!this.ChartFrame || !this.ChartFrame.SubFrame || this.ChartFrame.SubFrame.length<=this.FrameID) return; var subFrameItem=this.ChartFrame.SubFrame[this.FrameID]; if (!subFrameItem || !subFrameItem.Frame) return; var subFrame=subFrameItem.Frame; var minuteData=this.HQChart.SourceData; if (!minuteData) return; var xPointCount=subFrame.XPointCount; var preDate=0; var range=null; var mapDate=new Map(); for(var i=minuteData.DataOffset,j=0;i0) this.FrameID=option.FrameID; } this.Draw=function() { if (!this.HQChart) return; var hisData=this.HQChart.ChartOperator_Temp_GetHistroyData();; if (!hisData) return; //数据还没有到达 if (!IFrameSplitOperator.IsNonEmptyArray(hisData.Data)) return; if (this.IsKDataChange(hisData)) { this.BuildCacheData(hisData); } if (!IFrameSplitOperator.IsNonEmptyArray(this.Data)) return; var mainFrame=this.HQChart.Frame.SubFrame[0].Frame; var bHScreen=(this.ChartFrame.IsHScreen===true); var dataWidth=mainFrame.DataWidth; var distanceWidth=mainFrame.DistanceWidth; var xPointCount=mainFrame.XPointCount; if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var preID=null; var aryBG=[]; var bgItem=null; for(var i=hisData.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; var xStart=left-distanceWidth/2; var xEnd=right+distanceWidth/2; var id=item.ID; if (!IFrameSplitOperator.IsNumber(id)) continue; if (preID==null) { bgItem={ Start:{ X:xStart }, End:{ X:xEnd }, ColorIndex:id, Count:1, IsStart:false, IsEnd:false }; preID=id; if (i-1>=0) { var preItem=this.Data[i-1]; if (preItem && preItem.ID!=id) bgItem.IsStart=true; } } else if (preID!=id) { bgItem.End.X=xStart; bgItem.IsEnd=true; aryBG.push(bgItem); bgItem={ Start:{ X:xStart }, End:{ X:xEnd }, ColorIndex:id, Count:1, IsStart:true, IsEnd:false }; preID=id; } else { bgItem.End.X=xEnd; ++bgItem.Count; } } if (bgItem && bgItem.Count>=2) aryBG.push(bgItem); this.Canvas.save(); this.DrawBG(aryBG); this.Canvas.restore(); } this.DrawBG=function(aryBG) { if (!IFrameSplitOperator.IsNonEmptyArray(aryBG)) return; var bHScreen=(this.ChartFrame.IsHScreen===true); if (bHScreen) { var border=this.ChartBorder.GetHScreenBorder(); var top=border.RightEx; var bottom=border.Left; var height=bottom-top; } else { var border=this.ChartBorder.GetBorder(); var top=border.TopEx; var bottom=border.BottomEx; var height=bottom-top; } var bDrawSplitLine=false; if (this.SplitLine.Color) bDrawSplitLine=true; var lineCount=0; for(var i=0;i=1) { if (this.SplitLine.Width>=1) this.Canvas.linewidth=this.SplitLine.Width; if (this.SplitLine.Dash) this.Canvas.setLineDash(this.SplitLine.Dash); if (this.SplitLine.Color) this.Canvas.strokeStyle=this.SplitLine.Color; this.Canvas.stroke(); } } this.IsKDataChange=function(hisData) { if (!this.KDataFeature) return true; if (this.KDataFeature.Symbol!=this.HQChart.Symbol) return true; if (this.KDataFeature.Period!=this.HQChart.Period) return true; if (this.KDataFeature.DataCount!=hisData.Data.length) return true; return false; } this.BuildCacheData=function(hisData) { var period=this.HQChart.Period; if (!this.MapPeriod.has(period)) { this.Data=[]; this.KDataFeature={ Symbol:this.HQChart.Symbol, Period:period, DataCount:hisData.Data.length }; return; } var splitType=this.MapPeriod.get(period).SplitType; //1=month 2=year 3=day 4=1hour var startDate=0; var index=-1; this.Data=[]; for(var i=0;i0) svgButtonWidth+=this.ButtonConfig.SVG.MerginLeft; } var buttonWidth=textWidth+svgButtonWidth+this.ButtonConfig.Mergin.Left+this.ButtonConfig.Mergin.Right; var rtButton={ Left:xBotton, Top:rtBG.Top, Bottom:rtBG.Bottom, Height:rtBG.Height, Width:buttonWidth }; rtButton.Right=rtButton.Left+rtButton.Width; //鼠标是否在按钮上 var bgColor=this.ButtonConfig.BGColor.Default; var titleColor=this.ButtonConfig.TitleColor.Default; if (moveonPoint && (moveonPoint.X>=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { bgColor=this.ButtonConfig.BGColor.MoveOn; titleColor=this.ButtonConfig.TitleColor.MoveOn; if (mouseStatus) mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:item, Frame:frame, Point:{X:moveonPoint.X, Y:moveonPoint.Y}, ID:"TitleButton" }; } if (this.SelectedID && this.SelectedID==item.ID) { bgColor=this.ButtonConfig.BGColor.Selected; titleColor=this.ButtonConfig.TitleColor.Selected; } if (bgColor) { this.Canvas.fillStyle=bgColor; this.Canvas.fillRect(rtButton.Left,rtButton.Top,rtButton.Width,rtButton.Height); } if (this.ButtonConfig.BorderColor) { this.Canvas.strokeStyle=this.ButtonConfig.BorderColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(rtButton.Right),rtButton.Top); this.Canvas.lineTo(ToFixedPoint(rtButton.Right),rtButton.Bottom); this.Canvas.stroke(); } if (item.Title) { this.Canvas.fillStyle=titleColor; var xText=rtButton.Left+(rtButton.Width-svgButtonWidth)/2; //居中 var yText=rtButton.Top+this.ButtonConfig.Mergin.Top+(rtButton.Height-this.ButtonConfig.Mergin.Top-this.ButtonConfig.Mergin.Bottom)/2; this.Canvas.fillText(item.Title,xText,yText); } var rtSVG=null; if (item.SVGButton && item.SVGButton.Symbol) { this.Canvas.font=svgFont; this.Canvas.fillStyle=titleColor; var xText=rtButton.Right-this.ButtonConfig.SVG.Size/2-this.ButtonConfig.Mergin.Right; this.Canvas.fillText(item.SVGButton.Symbol,xText,yText); this.Canvas.font=font; rtSVG={Left:rtButton.Right-this.ButtonConfig.Mergin.Right-this.ButtonConfig.SVG.Size, Top:rtButton.Top, Width:this.ButtonConfig.SVG.Size, Height:this.ButtonConfig.SVG.Size}; rtSVG.Right=rtSVG.Left+rtSVG.Width; rtSVG.Bottom=rtSVG.Top+rtSVG.Height; } //{ Rect:rtButton, ID:item.ID, Data:item, RectSVG:rtSVG } if (textWidth>0 && svgButtonWidth>0) { var rtText={ Left:rtButton.Left, Top:rtButton.Top, Bottom:rtButton.Bottom }; rtText.Right=rtText.Left+textWidth+this.ButtonConfig.Mergin.Left+this.ButtonConfig.SVG.MerginLeft/2; var cacheItem={ Rect:rtText, ID:item.ID, Data:item, RectCell:rtButton, ButtonType:0 }; this.AryRectButton.push(cacheItem); var rtSVG={Left:rtText.Right, Right:rtButton.Right, Top:rtButton.Top, Bottom:rtButton.Bottom }; var cacheItem={ Rect:rtSVG, ID:item.ID, Data:item, RectCell:rtButton, ButtonType:1 }; this.AryRectButton.push(cacheItem); } else { var cacheItem={ Rect:rtButton, ID:item.ID, Data:item, RectCell:rtButton }; //RectCell 全部的大小 if (textWidth>0) cacheItem.ButtonType=0; else if (svgButtonWidth>0) cacheItem.ButtonType=1; this.AryRectButton.push(cacheItem); } xBotton+=buttonWidth+1; } if (this.BorderColor) { this.Canvas.strokeStyle=this.BorderColor; this.Canvas.beginPath(); this.Canvas.moveTo(border.Left,ToFixedPoint(border.BottomEx)); this.Canvas.lineTo(border.Right,ToFixedPoint(border.BottomEx)); this.Canvas.stroke(); } } this.GetFrame=function() { if (!this.ChartFrame) return null; if (this.FrameID>=0) { var subFrame=this.ChartFrame.SubFrame[this.FrameID]; if (!subFrame || !subFrame.Frame) return null; return subFrame.Frame; } return null; } this.GetTitleFont=function(height) { var config=this.ButtonConfig.Font; var fontSize=height*GetDevicePixelRatio(); if (IFrameSplitOperator.IsPlusNumber(config.Size)) fontSize=config.Size; var font=`${fontSize}px ${config.Family}`; return font; } this.GetSVGFont=function(height) { var config=this.ButtonConfig.SVG; var fontSize=height*GetDevicePixelRatio(); if (IFrameSplitOperator.IsPlusNumber(config.Size)) fontSize=config.Size; var font=`${fontSize}px ${config.Family}`; return font; } this.PtInButtons=function(x,y) { for(var i=0;irect.Left && xrect.Top && ythis.MinLineHeight) lineHeight=ary.Height; var bAddNewItem=true; //是否需要加入新弹幕 var bRemoveFirst=false; //是否删除第1个数据 for(var j=0;j0) //最后一个数据了 判断是否需要增加弹幕 { bAddNewItem=false; if (!item.TextWidth) { if (item.Font && item.Font.Name) canves.font=item.Font.Name; else canves.font=obj.Font; item.TextWidth=canves.measureText(playItem.Text+'擎擎').width; } if (item.X>=item.TextWidth) bAddNewItem=true; } else if (j==0) { bRemoveFirst=false; if (!item.TextWidth) { if (item.Font && item.Font.Name) canves.font=item.Font.Name; else canves.font=obj.Font; item.TextWidth=canves.measureText(playItem.Text+'擎擎').width; } if (item.X>width+item.TextWidth) bRemoveFirst=true; } item.X+=this.Step; } if(isMoveStep && bAddNewItem && this.Cache.length>0) //最后一个数据了 判断是否需要增加弹幕 { var cacheItem=this.Cache.shift(); var newItem={ X:0, Text:cacheItem.Text, Color:cacheItem.Color , Font:cacheItem.Font, Info:cacheItem.Info }; ary.Data.push(newItem); } if (isMoveStep && bRemoveFirst && ary.Data.length>0) { var removeItem=ary.Data.shift(); this.OnItemPlayEnd(obj.HQChart,removeItem); } yOffset+=lineHeight; } return list; } //根据高度计算播放队列个数 this.CacluatePlayLine=function(height) { this.Height=height; var lineCount=parseInt(height/this.MinLineHeight); if (this.PlayList.lengthlineCount) { var removeCount=this.PlayList.length-lineCount; for(var i=0;i0) this.BarrageList.Step=option.Step; if (option.MinLineHeight) this.Barrage.MinLineHeight=option.MinLineHeight; } } this.DrawHScreen=function() { var height=this.ChartBorder.GetWidth(); var left=this.ChartBorder.GetTop(); var right=this.ChartBorder.GetBottom(); var top=this.ChartBorder.GetRightEx(); var wdith=this.ChartBorder.GetChartWidth(); if (height!=this.BarrageList.Height) this.BarrageList.CacluatePlayLine(height); this.Canvas.textBaseline="middle"; this.Canvas.textAlign="left"; var play=this.BarrageList.GetPlayList({Canves:this.Canvas, Right:right, Left:left, Font:this.Font, IsMoveStep:this.IsMoveStep, HQChart:this.HQChart}); this.IsMoveStep=false; if (!play) return; this.Canvas.save(); this.Canvas.translate(this.ChartBorder.GetChartHeight(), 0); this.Canvas.rotate(90 * Math.PI / 180); for(var i=0;i0) fontHeight=item.Font.Height; var yOffset=item.Y+parseInt((item.Height-fontHeight)/2); this.Canvas.fillText(item.Text, right-item.X,top+yOffset); } this.Canvas.restore(); } this.Draw=function() { if (this.ChartFrame.IsHScreen) { this.DrawHScreen(); return; } var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var top=this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeight(); if (height!=this.BarrageList.Height) this.BarrageList.CacluatePlayLine(height); this.Canvas.textBaseline="middle"; this.Canvas.textAlign="left"; var play=this.BarrageList.GetPlayList({Canves:this.Canvas, Right:right, Left:left, Font:this.Font, IsMoveStep:this.IsMoveStep, HQChart:this.HQChart}); this.IsMoveStep=false; if (!play) return; for(var i=0;i0) fontHeight=item.Font.Height; var yOffset=item.Y+parseInt((item.Height-fontHeight)/2); this.Canvas.fillText(item.Text, right-item.X,top+yOffset); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////// //坐标分割 // // //////////////////////////////////////////////////////////////////////////////////////////////////// //Y轴自定义刻度类型ID var JSCHART_CUSTOM_YCOORDINATE_ID= { LATEST_VALUE_ID:0, //最新价格刻度 FIXED_VALUE_ID:1, //固定价格刻度 PAGE_LAST_PRICE_ID:2, //当前屏最后一个K线收盘价刻度 PAGE_DATA_INCREASE:3, //当前屏数据涨幅 PAGE_LAST_INDEX_VALUE_ID:4, //指标前屏最后一个数据刻度 PAGE_LAST_OVERLAY_INDEX_VALUE_ID:5, //叠加指标前屏最后一个数据刻度 }; function IFrameSplitOperator() { this.ChartBorder; //边框信息 this.Frame; //框架信息 this.FrameSplitData; //坐标轴分割方法 this.SplitCount=5; //刻度个数 this.StringFormat=0; //刻度字符串格式 2=原始格式 this.IsShowLeftText=true; //显示左边刻度 this.IsShowRightText=true; //显示右边刻度 this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; this.GetEventCallback; //事件回调 this.GetKLineChartCallback; //获取K线图形 ////////////////////// // data.Min data.Max data.Interval data.Count // this.IntegerCoordinateSplit=function(data) { var splitItem=this.FrameSplitData.Find(data.Interval); if (!splitItem) return false; if (data.Interval==splitItem.FixInterval) return true; var fixMax=data.Max, fixMin=data.Min; var maxValue=data.Max/splitItem.FixInterval; var minValue=data.Min/splitItem.FixInterval; //调整到整数倍数,不能整除的 +1 if (IFrameSplitOperator.IsFloat(maxValue)) fixMax=parseInt((maxValue+0.5).toFixed(0))*splitItem.FixInterval; if (IFrameSplitOperator.IsFloat(minValue)) fixMin=parseInt((minValue-0.5).toFixed(0))*splitItem.FixInterval; if (data.Min==0) fixMin=0; //最小值是0 不用调整了. if (fixMin<0 && data.Min>0) fixMin=0; //都是正数的, 最小值最小调整为0 var count=0; for(var i=fixMin;(i-fixMax)<0.00000001;i+=splitItem.FixInterval) { ++count; } data.Interval=splitItem.FixInterval; data.Max=fixMax; data.Min=fixMin; data.Count=count; return true; } this.Filter=function(aryInfo, keepZero, filterType) { if (this.SplitCount <= 0 || aryInfo.length <= 0 || aryInfo.length <= this.SplitCount) return aryInfo; //分割线比预设的多, 过掉一些 var filter = parseInt(aryInfo.length / this.SplitCount); if (filter <= 1) filter = 2; var data = []; if (filterType==1) { for (var i = 0; i < aryInfo.length; i += filter) { data.push(aryInfo[i]); } } else { for (var i = 0; i < aryInfo.length; i += filter) { if (i + filter >= aryInfo.length && i != aryInfo.length - 1) //最后一个数据放进去 { data.push(aryInfo[aryInfo.length - 1]); } else { data.push(aryInfo[i]); } } } if (this.SplitCount == 2 && data.length>2) //之显示第1个和最后一个刻度 { for(var i=1;i= '1' && char <= '9') return false; } return true; } //当前屏K线起始和结束的信息 this.GetKLinePageInfo=function() { if (!this.GetKLineChartCallback) return null; var chart=this.GetKLineChartCallback(); if (!chart || !chart.Data || !(chart.Data.DataOffset>=0)) return null; if (!IFrameSplitOperator.IsNonEmptyArray(chart.Data.Data)) return null; var aryKData=chart.Data.Data; var startIndex=chart.Data.DataOffset; var endIndex=chart.Data.DataOffset+chart.ChartFrame.XPointCount-1; if (endIndex>=aryKData.length) endIndex=aryKData.length-1; var result= { Start:{ Item:aryKData[startIndex], Index:startIndex }, End:{ Item:aryKData[endIndex], Index:endIndex }, IsLast:endIndex==aryKData.length-1 }; return result; } //当前屏最新指标数据 this.CustomLatestIndexDataCoordinate=function(option) { var pageInfo=this.GetKLinePageInfo(); //获取当前屏信息 if (!pageInfo) return; if (!this.HQChart) return; var event=null; if (this.GetEventCallback) event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_INDEX_Y_LABEL); var endIndex=pageInfo.End.Index; var floatPrecision=2; if (IFrameSplitOperator.IsNumber(this.FloatPrecision)) floatPrecision=this.FloatPrecision; for(var i=0, j=0;i0) { var nullText='-.'; for(var i=0;i0){ var numFloat = num.split('.')[1]; var numM = num.split('.')[0]; while (numM.length > 3) { result = ',' + numM.slice(-3) + result; numM = numM.slice(0, numM.length - 3); } if (numM) { result = numM + result + '.' + numFloat; } }else{ while (num.length > 3) { result = ',' + num.slice(-3) + result; num = num.slice(0, num.length - 3); } if (num) { result = num + result; } } return result; } //数据输出格式化 floatPrecision=小数位数 IFrameSplitOperator.FormatValueString=function(value, floatPrecision,languageID) { /* if (value==null || isNaN(value)) { if (floatPrecision>0) { var nullText='-.'; for(var i=0;i-0.00000000001) { return "0"; } var absValue = Math.abs(value); if (languageID===JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID) { if (absValue < 10000) return value.toFixed(floatPrecision); else if (absValue < 1000000) return (value/1000).toFixed(floatPrecision)+"K"; else if (absValue < 1000000000) return (value/1000000).toFixed(floatPrecision)+"M"; else if (absValue < 1000000000000) return (value/1000000000).toFixed(floatPrecision)+"B"; else return (value/1000000000000).toFixed(floatPrecision)+"T"; } else if (languageID===JSCHART_LANGUAGE_ID.LANGUAGE_TRADITIONAL_CHINESE_ID) //繁体 { if (absValue < 10000) return value.toFixed(floatPrecision); else if (absValue < 100000000) return (value/10000).toFixed(floatPrecision)+"萬"; else if (absValue < 1000000000000) return (value/100000000).toFixed(floatPrecision)+"億"; else return (value/1000000000000).toFixed(floatPrecision)+"萬億"; } else { if (absValue < 10000) return value.toFixed(floatPrecision); else if (absValue<1000000) return (value/10000).toFixed(floatPrecision)+"万"; else if (absValue < 100000000) return (value/10000).toFixed(floatPrecision)+"万"; else if (absValue < 1000000000000) return (value/100000000).toFixed(floatPrecision)+"亿"; else return (value/1000000000000).toFixed(floatPrecision)+"万亿"; } */ return IFrameSplitOperator.FormatValueStringV2(value, floatPrecision, floatPrecision, languageID); } //数据输出格式化 floatPrecision=原始小数位数 floatPrecision2=转换成'万','亿'..的小数位 IFrameSplitOperator.FormatValueStringV2=function(value, floatPrecision, floatPrecision2, languageID) { if (value==null || isNaN(value)) { if (floatPrecision>0) { var nullText='-.'; for(var i=0;i-0.00000000001) { return "0"; } var absValue = Math.abs(value); if (languageID===JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID) { if (absValue < 10000) return value.toFixed(floatPrecision); else if (absValue < 1000000) return (value/1000).toFixed(floatPrecision2)+"K"; else if (absValue < 1000000000) return (value/1000000).toFixed(floatPrecision2)+"M"; else if (absValue < 1000000000000) return (value/1000000000).toFixed(floatPrecision2)+"B"; else return (value/1000000000000).toFixed(floatPrecision2)+"T"; } else if (languageID===JSCHART_LANGUAGE_ID.LANGUAGE_TRADITIONAL_CHINESE_ID) //繁体 { if (absValue < 10000) return value.toFixed(floatPrecision); else if (absValue < 100000000) return (value/10000).toFixed(floatPrecision2)+"萬"; else if (absValue < 1000000000000) return (value/100000000).toFixed(floatPrecision2)+"億"; else return (value/1000000000000).toFixed(floatPrecision2)+"萬億"; } else { if (absValue < 10000) return value.toFixed(floatPrecision); else if (absValue<1000000) return (value/10000).toFixed(floatPrecision2)+"万"; else if (absValue < 100000000) return (value/10000).toFixed(floatPrecision2)+"万"; else if (absValue < 1000000000000) return (value/100000000).toFixed(floatPrecision2)+"亿"; else return (value/1000000000000).toFixed(floatPrecision2)+"万亿"; } return ''; } //成交量显示 IFrameSplitOperator.FormatVolString=function(value,languageID) { var absValue = Math.abs(value); if (absValue<100000) return value.toFixed(0); else if (absValue<10000000) return (value/10000).toFixed(1)+"万"; else if (absValue<100000000) return (value/10000).toFixed(0)+"万"; else if (absValue<1000000000) return (value/100000000).toFixed(2)+"亿"; else if (absValue < 1000000000000) return (value/100000000).toFixed(1)+"亿"; else return (value/1000000000000).toFixed(1)+"万亿"; } //整形输出格式化 floatPrecision=小数位数 IFrameSplitOperator.FromatIntegerString=function(value, floatPrecision,languageID) { if (value<10000 && IFrameSplitOperator.IsInteger(value)) floatPrecision=0; //<10000的整形 去掉小数位数 return IFrameSplitOperator.FormatValueString(value, floatPrecision,languageID); } IFrameSplitOperator.NumberToString=function(value) { if (value<10) return '0'+value.toString(); return value.toString(); } //毫秒格式 固定3位, 不足前面自动补0 IFrameSplitOperator.MillisecondToString=function(value) { if (value<10) return '00'+value.toString(); else if (value<100) return '0'+value.toString(); else return value.toString(); } IFrameSplitOperator.FormatDateString=function(value,format, languageID) { var year=parseInt(value/10000); var month=parseInt(value/100)%100; var day=value%100; switch(format) { case 'MM-DD': return IFrameSplitOperator.NumberToString(month) + '-' + IFrameSplitOperator.NumberToString(day); case "MM/DD": return `${IFrameSplitOperator.NumberToString(month)}/${IFrameSplitOperator.NumberToString(day)}`; case "MM/DD/W": var date=new Date(year,month-1,day); var week=g_JSChartLocalization.GetText(WEEK_NAME[date.getDay()],languageID); return `${IFrameSplitOperator.NumberToString(month)}/${IFrameSplitOperator.NumberToString(day)}/${week}`; case "YYYY-MM": return `${year}-${IFrameSplitOperator.NumberToString(month)}`; case "YYYY/MM/DD": return year.toString() + '/' + IFrameSplitOperator.NumberToString(month) + '/' + IFrameSplitOperator.NumberToString(day); case "YYYY/MM/DD/W": { var date=new Date(year,month-1,day); var week=g_JSChartLocalization.GetText(WEEK_NAME[date.getDay()],languageID); return year.toString() + '/' + IFrameSplitOperator.NumberToString(month) + '/' + IFrameSplitOperator.NumberToString(day)+"/"+ week.toString(); } case "DD/MM/YYYY": return IFrameSplitOperator.NumberToString(day) + '/' + IFrameSplitOperator.NumberToString(month) + '/' + year.toString(); default: //YYYY-MM-DD return year.toString() + '-' + IFrameSplitOperator.NumberToString(month) + '-' + IFrameSplitOperator.NumberToString(day); } } IFrameSplitOperator.FormatTimeString=function(value, format) //format hh:mm:ss { if (format=='HH:MM:SS') { var hour=parseInt(value/10000); var minute=parseInt((value%10000)/100); var second=value%100; return IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute) + ':' + IFrameSplitOperator.NumberToString(second); } else if (format=="hh:mm") { var hour=parseInt(value/10000); var minute=parseInt((value%10000)/100); var second=value%100; return IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute); } else if (format=='HH:MM') { var hour=parseInt(value/100); var minute=value%100; return IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute); } else if (format=="HH:MM:SS.fff") { var millisecond=value%1000; var dateTime=parseInt(value/1000); var hour=parseInt(dateTime/10000); var minute=parseInt((dateTime%10000)/100); var second=dateTime%100; return `${IFrameSplitOperator.NumberToString(hour)}:${IFrameSplitOperator.NumberToString(minute)}:${IFrameSplitOperator.NumberToString(second)}.${IFrameSplitOperator.MillisecondToString(millisecond)}`; } else { if (value<10000) { var hour=parseInt(value/100); var minute=value%100; return IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute); } else { var hour=parseInt(value/10000); var minute=parseInt((value%10000)/100); var second=value%100; return IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute) + ':' + IFrameSplitOperator.NumberToString(second); } } } //报告格式化 IFrameSplitOperator.FormatReportDateString=function(value) { var year=parseInt(value/10000); var month=parseInt(value/100)%100; var monthText; switch(month) { case 3: monthText="一季度报"; break; case 6: monthText="半年报"; break; case 9: monthText="三季度报"; break; case 12: monthText="年报"; break; } return year.toString()+ monthText; } IFrameSplitOperator.FormatDateTimeString=function(value,isShowDate,isShowTime) { var aryValue=value.split(' '); if (aryValue.length<2) return ""; var result=""; if (isShowDate) { var date=parseInt(aryValue[0]); var year=parseInt(date/10000); var month=parseInt(date%10000/100); var day=date%100; var text=year.toString() +'-'+ (month<10? ('0'+month.toString()) :month.toString()) +'-'+ (day<10? ('0'+day.toString()):day.toString()); result+=text; } if (isShowTime) { var time=parseInt(aryValue[1]); if (time<10000) { var minute=time%100; var hour=parseInt(time/100); var text=IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute); if (result.length>0) result+=" "; result+=text; } else { var hour=parseInt(time/10000); var minute=parseInt((time%10000)/100); var second=time%100; var text=IFrameSplitOperator.NumberToString(hour)+':'+ IFrameSplitOperator.NumberToString(minute) + ':' + IFrameSplitOperator.NumberToString(second); if (result.length>0) result+=" "; result+=text; } } return result; } //字段颜色格式化 IFrameSplitOperator.FormatValueColor = function (value, value2) { if (value != null && value2 == null) //只传一个值的 就判断value正负 { if (value == 0) return 'PriceNull'; else if (value > 0) return 'PriceUp'; else return 'PriceDown'; } //2个数值对比 返回颜色 if (value == null || value2 == null) return 'PriceNull'; if (value == value2) return 'PriceNull'; else if (value > value2) return 'PriceUp'; else return 'PriceDown'; } IFrameSplitOperator.IsNumber=function(value) { if (value==null) return false; if (isNaN(value)) return false; return typeof(value)=='number'; } //批量判断是否是数值类型 IFrameSplitOperator.IsNumberV2=function(...aryValue) { if (!aryValue) return false; if (aryValue.length==0) return false; for(const value of aryValue) { if (value==null) return false; if (isNaN(value)) return false; if (typeof(value)!='number') return false; } return true; } //判断是否是正数 IFrameSplitOperator.IsPlusNumber=function(value) { if (value==null) return false; if (isNaN(value)) return false; return value>0; } //是否是整形 IFrameSplitOperator.IsInteger=function(x) { return (typeof x === 'number') && (x % 1 === 0); } //判断字段是否存在 IFrameSplitOperator.IsObjectExist=function(obj) { if (obj===undefined) return false; if (obj==null) return false; return true; } //是否时bool IFrameSplitOperator.IsBool=function(value) { if (value===true || value===false) return true; return false; } IFrameSplitOperator.IsString=function(value) { var type=typeof(value); if (type=='string') return true; return false; } //是否是非空的数组 IFrameSplitOperator.IsNonEmptyArray=function(ary) { if (!ary) return false; if (!Array.isArray(ary)) return false; return ary.length>0; } IFrameSplitOperator.IsFloat=function(value) { if (value===undefined) return false; if (value==null) return false; if (isNaN(value)) return false; return value!=parseInt(value); } //是否有效 IFrameSplitOperator.IsVaild=function(value) { if (isNaN(value)) return false; if (value==null) return false; if (value===undefined) return false; return true; } IFrameSplitOperator.IsUndefined=function(value) { return value===undefined; } IFrameSplitOperator.IsObject=function(value) { return value instanceof Object; } IFrameSplitOperator.RemoveZero=function(strValue) { while(strValue.length>0) { var index=strValue.length-1; var ch=strValue[index]; if (ch=="0") { strValue=strValue.substr(0,index); } else if (ch==".") { strValue=strValue.substr(0,index); break; } else { break; } } return strValue; } function FrameSplitKLinePriceY() { this.newMethod=IFrameSplitOperator; //派生 this.newMethod(); delete this.newMethod; this.CoordinateType=0; //坐标类型 0=普通坐标 1=百分比坐标 (右边坐标刻度) 2=对数对标 3=等比坐标 4=等分坐标 5=黄金分割 this.Symbol; this.Data; //K线数据 (计算百分比坐标) this.FrameSplitData2; //坐标轴分割方法(计算百分比刻度) this.FloatPrecision=null; //小数位数 (设置了就使用这个位数,否则使用品种对应的小数位数) this.Period; //周期 this.KLineChart; this.Custom=[]; //[{Type:0}]; 定制刻度 0=显示最后的价格刻度 this.SplitType=0; //0=自动分割 1=固定分割 2=分笔图价格分割 this.DefaultSplitType=0; this.DefaultYMaxMin; //{ Max:null, Min:null }; //指定最大,最小, Y轴范围必须比最大值大, 比最小值小 this.FixedYMaxMin; //{ Max, Min} 固定Y轴最大最小值 this.EnableZoomUpDown=false; //上下左右拖拽 this.LastMaxMin; //当前显示的最高最低范围 this.PercentageTextFormat=0; //0=显示第1行 1=显示2行 2=单行格式: 价格/百分比 this.IsEnableDragY=function() { return this.CoordinateType==0 || this.CoordinateType==1; } this.Operator=function() { var splitData={}; splitData.Max=this.Frame.HorizontalMax; splitData.Min=this.Frame.HorizontalMin; splitData.Count=this.SplitCount; if (this.Frame.YMaxMin) //原始的数据范围 { var item=this.Frame.YMaxMin; if (IFrameSplitOperator.IsNumber(item.Max) && IFrameSplitOperator.IsNumber(item.Min)) { splitData.Max=item.Max; splitData.Min=item.Min; } } if (splitData.Max==splitData.Min) //如果一样上下扩大下 { splitData.Max+=splitData.Max*0.01; splitData.Min-=splitData.Min*0.01 } var isFixedMaxMin=(this.FixedYMaxMin && IFrameSplitOperator.IsNumber(this.FixedYMaxMin.Max) && IFrameSplitOperator.IsNumber(this.FixedYMaxMin.Min)); if (isFixedMaxMin) { splitData.Max=this.FixedYMaxMin.Max; splitData.Min=this.FixedYMaxMin.Min; //JSConsole.Chart.Log(`[FrameSplitKLinePriceY::Operator] FixedYMaxMin.Max=${this.FixedYMaxMin.Max} FixedYMaxMin.Min=${this.FixedYMaxMin.Min} `); } else if (this.DefaultYMaxMin) //指定最小的Y轴范围 { var range=this.DefaultYMaxMin; if (IFrameSplitOperator.IsNumber(range.Max)) { if (splitData.Min>range.Max) splitData.Min=range.Max; else if (splitData.Maxrange.Min) splitData.Min=range.Min; } } splitData.Interval=(splitData.Max-splitData.Min)/(splitData.Count-1); var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 var width=this.Frame.ChartBorder.GetChartWidth(); //画布的宽度 var isPhoneModel=width<450*pixelTatio; var defaultfloatPrecision=GetfloatPrecision(this.Symbol); if (isPhoneModel && MARKET_SUFFIX_NAME.IsSHSZIndex(this.Symbol)) defaultfloatPrecision = 0; //手机端指数不显示小数位数,太长了 if (this.FloatPrecision!=null) defaultfloatPrecision=this.FloatPrecision; JSConsole.Chart.Log(`[FrameSplitKLinePriceY::Operator] Max=${splitData.Max} Min=${splitData.Min} Count=${splitData.Count} isPhoneModel=${isPhoneModel} defaultfloatPrecision=${defaultfloatPrecision} `); this.Frame.Logarithmic=null; this.Frame.MultiTextFormat=0; var bFilter=true; //是否需要通过高度过滤刻度 splitData.IsFixedMaxMin=isFixedMaxMin; splitData.IsFilter=bFilter; if (ChartData.IsTickPeriod(this.Period)) { this.SplitTickData(splitData,defaultfloatPrecision); bFilter=splitData.IsFilter; } else if (FrameSplitKLinePriceY.SplitCustom) { FrameSplitKLinePriceY.SplitCustom(this,splitData,defaultfloatPrecision); //自定义分割 bFilter=false; } else { switch(this.CoordinateType) { case 1: if (!this.SplitPercentage(splitData,defaultfloatPrecision,isFixedMaxMin)) { this.SplitDefault(splitData,defaultfloatPrecision,isFixedMaxMin); } else { this.Frame.MultiTextFormat=this.PercentageTextFormat; bFilter=false; } break; case 3: //等比坐标 +10%/-10% 涨幅分割 if (!this.SplitIncrease(splitData,defaultfloatPrecision)) this.SplitDefault(splitData,defaultfloatPrecision); else bFilter=false; break; case 4: //等分坐标 this.SplitAverage(splitData,defaultfloatPrecision); bFilter=false; break; case 5: //黄金分割 this.SplitGoldenSection(splitData,defaultfloatPrecision); bFilter=false; break; case 2: //对数坐标 if (this.SplitLogarithmic(splitData,defaultfloatPrecision)) { bFilter=false; } else { this.SplitDefault(splitData,defaultfloatPrecision); } break; default: if (this.SplitType==1) { this.SplitFixed(splitData,defaultfloatPrecision); bFilter=false; } else if (this.SplitType==2) { this.SplitFixedV2(splitData,defaultfloatPrecision); bFilter=false; } else { this.SplitDefault(splitData,defaultfloatPrecision,isFixedMaxMin); } break; } } this.CustomCoordinate(defaultfloatPrecision); if (bFilter) this.Frame.HorizontalInfo = this.Filter(this.Frame.HorizontalInfo,false); this.Frame.HorizontalMax=splitData.Max; this.Frame.HorizontalMin=splitData.Min; if (this.EnableZoomUpDown==true && !this.FixedYMaxMin) this.FixedYMaxMin={ Max:splitData.Max, Min:splitData.Min }; /* for(var i=0;i=splitData.Min;value-=splitData.Interval) { var price=(value+1)*firstOpenPrice; if (pricemaxValue) continue; var item=new CoordinateInfo(); item.Value=price; if (this.IsShowLeftText) item.Message[0]=price.toFixed(floatPrecision); //左边价格坐标 if (this.IsShowRightText) { var strPrice=price.toFixed(floatPrecision); var text=(value*100).toFixed(2); //右边百分比 text=IFrameSplitOperator.RemoveZero(text); text+='%'; item.Message[1]=[text,strPrice]; item.ExtendData=textColor; } aryHorizontal.push(item); } aryHorizontal.sort((left, right)=> { return left.Value - right.Value; }); this.Frame.HorizontalInfo=aryHorizontal; splitData.Min=minValue; //最大最小值调整 splitData.Max=maxValue; return true; } //等比坐标 当前屏最后第2根K线的收盘加为基准, 上下涨幅10%分割 this.SplitIncrease=function(splitData,floatPrecision) { var basePrice=this.GetLast2ndClose(); if (!IFrameSplitOperator.IsNumber(basePrice)) return false; this.IntegerCoordinateSplit(splitData); this.Frame.HorizontalInfo=[]; var increase=g_JSChartResource.FrameSplitIncrease.Increase; var aryHorizontal=[]; for(var price=basePrice; pricesplitData.Min; price=price*(1-increase)) { var item= new CoordinateInfo(); item.Value=price; var text=price.toFixed(floatPrecision); if (this.IsShowLeftText) item.Message[0]=text; if (this.IsShowRightText) item.Message[1]=text; aryHorizontal.push(item); } this.Frame.HorizontalInfo=aryHorizontal; return true; } //等分坐标:以画面显示的最高价、最低价为基准,对这个区域N等分,显示分割的数值线 this.SplitAverage=function(splitData,floatPrecision) { var max=splitData.Max; var min=splitData.Min; //this.IntegerCoordinateSplit(splitData); this.Frame.HorizontalInfo=[]; var count=g_JSChartResource.FrameSplitAverage.Count; var interval=(max-min)/count; for(var i=0;i<=count;++i) { var item=new CoordinateInfo(); item.Value=min+interval*i; var text=item.Value.toFixed(floatPrecision); if (this.IsShowLeftText) item.Message[0]=text; if (this.IsShowRightText) item.Message[1]=text; this.Frame.HorizontalInfo[i]=item; } } this.SplitGoldenSection=function(splitData,floatPrecision) { var max=splitData.Max; var min=splitData.Min; //this.IntegerCoordinateSplit(splitData); this.Frame.HorizontalInfo=[]; var aryHorizontal=[]; var GOLDEN_ARRAY=g_JSChartResource.FrameGoldenSection.Golden; for(var i in GOLDEN_ARRAY) { var value=(max-min)*GOLDEN_ARRAY[i]+min; item=new CoordinateInfo(); item.Value=value; var text=value.toFixed(floatPrecision); if (this.IsShowLeftText) item.Message[0]=text; if (this.IsShowRightText) item.Message[1]=text; aryHorizontal.push(item); } this.Frame.HorizontalInfo=aryHorizontal; } this.SplitLogarithmic=function(splitData,floatPrecision) //对数坐标 { var minInterval=g_JSChartResource.FrameLogarithmic.MinInterval; //最小间距 var firstOpenPrice=this.GetFirstOpenPrice(); //获取当前屏第1个K线的开盘价 if (!IFrameSplitOperator.IsNumber(firstOpenPrice)) return false; var height=this.ChartBorder.GetHeightEx(); var ARRAY_INCREASE=[0.01, 0.02, 0.04, 0.08, 0.1, 0.2]; var increase=ARRAY_INCREASE[ARRAY_INCREASE.length-1]; for(var i=0; iminInterval) { increase=value; break; } } var aryUp=[]; var price=firstOpenPrice; var i=increase; do { var item={ Start:price }; price=firstOpenPrice*(1+i); item.End=price; aryUp.push(item); i+=increase; } while(pricesplitData.Min); var min=price; splitData.Max=max; splitData.Min=min; JSConsole.Chart.Log("[FrameSplitKLinePriceY::SplitLogarithmic] up, down", aryUp, aryDown); this.Frame.HorizontalInfo=[]; var item=new CoordinateInfo(); item.Value=firstOpenPrice; item.Font=g_JSChartResource.FrameLogarithmic.OpenPriceFont; var strText=item.Value.toFixed(floatPrecision); if (this.IsShowLeftText) item.Message[0]=strText; //左边价格坐标 if (this.IsShowRightText) item.Message[1]=strText; //右边价格坐标 this.Frame.HorizontalInfo.push(item); for(var i in aryUp) { var item=new CoordinateInfo(); item.Value=aryUp[i].End; var strText=item.Value.toFixed(floatPrecision); if (this.IsShowLeftText) item.Message[0]=strText; //左边价格坐标 if (this.IsShowRightText) item.Message[1]=strText; //右边价格坐标 this.Frame.HorizontalInfo.push(item); } for(var i in aryDown) { var item=new CoordinateInfo(); item.Value=aryDown[i].End; var strText=item.Value.toFixed(floatPrecision); if (this.IsShowLeftText) item.Message[0]=strText; //左边价格坐标 if (this.IsShowRightText) item.Message[1]=strText; //右边价格坐标 this.Frame.HorizontalInfo.splice(0,0,item); } this.Frame.Logarithmic={ Up:aryUp, Down:aryDown, OpenPrice:firstOpenPrice }; return true; } this.SplitDefault=function(splitData,floatPrecision,isFixedMaxMin) //默认坐标 { //固定最大最小值 不自动调整范围 if (!isFixedMaxMin) this.IntegerCoordinateSplit(splitData); this.Frame.HorizontalInfo=[]; for(var i=0,value=splitData.Min;i=0) dec=item.FloatPrecision; var latestItem=this.GetLatestPrice(dec, item); if (latestItem) { if (item.Type==JSCHART_CUSTOM_YCOORDINATE_ID.LATEST_VALUE_ID) lastCoordinate=latestItem; else if (item.Type==JSCHART_CUSTOM_YCOORDINATE_ID.PAGE_LAST_PRICE_ID) pageLastCoordinate=latestItem; else this.Frame.CustomHorizontalInfo.push(latestItem); } } else if (item.Type==JSCHART_CUSTOM_YCOORDINATE_ID.FIXED_VALUE_ID) //固定刻度 { this.CustomFixedCoordinate(item); } else if (item.Type==JSCHART_CUSTOM_YCOORDINATE_ID.PAGE_LAST_INDEX_VALUE_ID) //当前屏指标最后一个数据 { this.CustomLatestIndexDataCoordinate(item); } } //当前页最后一个数据和最新数据刻度如果相同,只显示一个 if (lastCoordinate || pageLastCoordinate) { if (lastCoordinate && pageLastCoordinate && pageLastCoordinate.IsLast===true) { this.Frame.CustomHorizontalInfo.unshift(lastCoordinate); } else { if (lastCoordinate) this.Frame.CustomHorizontalInfo.unshift(lastCoordinate); if (pageLastCoordinate) this.Frame.CustomHorizontalInfo.push(pageLastCoordinate); } } } this.GetLatestPrice=function(floatPrecision,option) { if (!this.Data || !this.Data.Data) return null; if (this.Data.Data.length<=0) return null; var latestItem=this.Data.Data[this.Data.Data.length-1]; var isLast=true; if (option.Type==2) //当前屏最后的价格 { var pageInfo=this.GetKLinePageInfo(); if (pageInfo) { latestItem=pageInfo.End.Item; isLast=pageInfo.IsLast; } } var info=new CoordinateInfo(); info.Type=0; if (option && IFrameSplitOperator.IsNumber(option.Type)) info.Type=option.Type; info.Value=latestItem.Close; info.TextColor=g_JSChartResource.FrameLatestPrice.TextColor; info.LineType=2; //虚线 var strPrice=latestItem.Close.toFixed(floatPrecision); //颜色 if (latestItem.Close>latestItem.Open) info.LineColor=g_JSChartResource.FrameLatestPrice.UpBarColor; else if (latestItem.Close0) info.LineColor=g_JSChartResource.FrameLatestPrice.UpBarColor; else if (value<0) info.LineColor=g_JSChartResource.FrameLatestPrice.DownBarColor; else info.LineColor=g_JSChartResource.FrameLatestPrice.UnchagneBarColor; info.Value=pageInfo.End.Item.Close; isLast=pageInfo.IsLast; } } } if (option.DateTime=='HH:MM' && ChartData.IsMinutePeriod(this.Period,true)) { var strTime=IFrameSplitOperator.FormatTimeString(latestItem.Time,option.DateTime); var aryText=[{Text:strPrice}, { Text:strTime} ]; if (option.Position=='left') info.Message[0]=aryText; else info.Message[1]=aryText; } else if (IFrameSplitOperator.IsBool(option.CountDown)) //倒计时 { var aryText=[ {Text:strPrice}, { Type:1 } ]; if (option.Position=='left') info.Message[0]=aryText; else info.Message[1]=aryText; } else { if (option.Position=='left') info.Message[0]=strPrice else info.Message[1]=strPrice; } if (IFrameSplitOperator.IsNumber(option.LineType)) info.LineType=option.LineType; if (IFrameSplitOperator.IsPlusNumber(option.LineWidth)) info.LineWidth=option.LineWidth; if (option.LineDash) info.LineDash=option.LineDash; if (option.IsShowLine==false) info.LineType=-1; info.IsLast=isLast;//是否是最后一个数据 if (!isLast || option.PositionEx===1) { var config={}; if (!isLast) config.EmptyBGColor=g_JSChartResource.FrameLatestPrice.EmptyBGColor; if (option.PositionEx===1) config.Position=1; //强制画在内部 info.ExtendData={ Custom:config }; } return info; } this.GetFirstOpenPrice=function() //获取显示第1个数据的开盘价 { if (!this.Data) return null; var xPointCount=this.Frame.XPointCount; for(var i=this.Data.DataOffset,j=0;i=this.Data.Data.length) endIndex=this.Data.Data.length-1; var price=null; for(var i=endIndex, count=0; i>=0 && i=2) break; } return price; } this.CustomFixedCoordinate=function(option) //固定坐标刻度 { var defaultfloatPrecision=GetfloatPrecision(this.Symbol); for(var i=0; i0) fixMin=0; //都是正数的, 最小值最小调整为0 var count=0; for(var i=fixMin;(i-fixMax)<0.00000001;i+=splitItem.FixInterval) { ++count; } data.Interval=splitItem.FixInterval; data.Max=fixMax; data.Min=fixMin; data.Count=count; return true; } } function FrameSplitY() { this.newMethod=IFrameSplitOperator; //派生 this.newMethod(); delete this.newMethod; this.SplitCount=3; //刻度个数 this.FloatPrecision = 2; //坐标小数位数(默认2) this.FLOATPRECISION_RANGE=[1,0.1,0.01,0.001,0.0001]; this.SplitType=0; //0=自动分割 1=固定分割 2=堆积图(0-100) this.FilterType=0; //自动分割过滤算法 this.DefaultSplitType=0; this.Custom=[]; //[{Type:0}]; 定制刻度 this.DefaultYMaxMin; //{ Max:null, Min:null }; //指定最大,最小, Y轴范围必须比最大值大, 比最小值小 this.EnableRemoveZero=g_JSChartResource.Frame.EnableRemoveZero; this.LineType=null; //线段样式 this.IgnoreYValue = null; //在这个数组里的数字不显示在刻度上 this.FixedYMaxMin; //{ Max, Min} 固定Y轴最大最小值 this.EnableZoomUpDown=false; this.IsBeforeData=false; this.BeforeOpenData; this.IsAfterData=false; this.AfterCloseData; this.ShareAfterVol=0; this.MultiDayBeforeOpenData; this.MultiDayAfterCloseData; this.OverlayIdentify; this.HQChart; this.OverlayIndex; //叠加指标信息 this.IsEnableDragY=function() { return true; } this.Reset=function() //重置 { this.EnableRemoveZero=g_JSChartResource.Frame.EnableRemoveZero; this.StringFormat=g_JSChartResource.Frame.StringFormat; } this.SetOption=function(option) { if (!option) return; if (IFrameSplitOperator.IsNumber(option.FloatPrecision)) this.FloatPrecision=option.FloatPrecision; if (IFrameSplitOperator.IsNumber(option.StringFormat)) this.StringFormat=option.StringFormat; if (IFrameSplitOperator.IsBool(option.EnableRemoveZero)) this.EnableRemoveZero=option.EnableRemoveZero; } this.GetFloatPrecision=function(value,floatPrecision) { if (value>this.FLOATPRECISION_RANGE[0]) return floatPrecision; if (floatPrecision<0) return 2; for(;floatPrecisionthis.FLOATPRECISION_RANGE[floatPrecision]) break; } return floatPrecision; } this.Operator=function() { var splitData={}; splitData.Max=this.Frame.HorizontalMax; splitData.Min=this.Frame.HorizontalMin; if (this.Frame.YMaxMin) //原始的数据范围 { var item=this.Frame.YMaxMin; if (IFrameSplitOperator.IsNumber(item.Max) && IFrameSplitOperator.IsNumber(item.Min)) { splitData.Max=item.Max; splitData.Min=item.Min; } } if (splitData.Max==splitData.Min) //如果一样上下扩大下 { if (splitData.Max==0) { splitData.Max=1; splitData.Min=-1; } else { splitData.Max+=splitData.Max*0.01; splitData.Min-=splitData.Min*0.01; } } var isFixedMaxMin=false; if (this.FixedYMaxMin && IFrameSplitOperator.IsNumber(this.FixedYMaxMin.Max) && IFrameSplitOperator.IsNumber(this.FixedYMaxMin.Min)) isFixedMaxMin=true; if (isFixedMaxMin) { splitData.Max=this.FixedYMaxMin.Max; splitData.Min=this.FixedYMaxMin.Min; } else if (this.DefaultYMaxMin) //指定最小的Y轴范围 { var range=this.DefaultYMaxMin; if (IFrameSplitOperator.IsNumber(range.Max)) { if (splitData.Min>range.Max) splitData.Min=range.Max; else if (splitData.Maxrange.Min) splitData.Min=range.Min; } } if(this.Frame.YSpecificMaxMin) { splitData.Count=this.Frame.YSpecificMaxMin.Count; splitData.Interval=(splitData.Max-splitData.Min)/(splitData.Count-1); } else if (this.SplitType==1 || isFixedMaxMin) { splitData.Count=this.SplitCount; splitData.Interval=(splitData.Max-splitData.Min)/(splitData.Count-1); } else if (this.SplitType==2) { splitData.Max=100; splitData.Min=0; splitData.Count=this.SplitCount; splitData.Interval=(splitData.Max-splitData.Min)/(splitData.Count-1); } else { splitData.Count=this.SplitCount; splitData.Interval=(splitData.Max-splitData.Min)/(splitData.Count-1); this.IntegerCoordinateSplit(splitData); } this.Frame.HorizontalMax=splitData.Max; this.Frame.HorizontalMin=splitData.Min; this.Frame.HorizontalInfo=[]; if (this.Frame.YSplitScale) //固定坐标 { for(var i in this.Frame.YSplitScale) { var value=this.Frame.YSplitScale[i]; var coordinate=new CoordinateInfo(); coordinate.Value=value; if (IFrameSplitOperator.IsNumber(this.LineType)) coordinate.LineType=this.LineType; var absValue=Math.abs(value); if (absValue<0.0000000001) { coordinate.Message[1]=0; } else if (absValue0 && splitData.Min<0), this.FilterType); this.RightFrameSplitY(); this.MainOverlayFrameSplitY(); //主图Y轴绑定叠加Y轴坐标 this.CallAcutionSplitY(this.SplitCount,splitData); if (this.EnableRemoveZero) this.RemoveZero(this.Frame.HorizontalInfo); this.DynamicMessageText(); this.Frame.HorizontalMax=splitData.Max; this.Frame.HorizontalMin=splitData.Min; if (this.EnableZoomUpDown==true && !this.FixedYMaxMin) this.FixedYMaxMin={ Max:splitData.Max, Min:splitData.Min }; this.ReservedHeight(splitData); //预留高度 if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SPLIT_YCOORDINATE); if (event && event.Callback) { var data={ID:this.Frame.Identify, Frame:this.Frame }; if (this.OverlayIdentify) data.OverlayIdentify=this.OverlayIdentify; event.Callback(event,data,this); } } } this.FormatValueString=function(value) { var text; if (this.StringFormat==1) //手机端格式 如果有万,亿单位了 去掉小数 { var floatPrecision=this.FloatPrecision; if (IFrameSplitOperator.IsNumber(value) && Math.abs(value) > 1000) floatPrecision=0; text=IFrameSplitOperator.FormatValueString(value,floatPrecision,this.LanguageID); } else if (this.StringFormat==2) //原始数据输出 { text=`${value.toFixed(this.FloatPrecision)}`; } else { var absValue=Math.abs(value); if (absValue<0.0000000001) { text=0; } else if (absValue !setValue.has(item.Value)); } this.DynamicMessageText=function() { if (this.SplitType==2) { for(var i=0;ithis.MinTextDistance && barDistance>=this.MinBarDistance) { var time=IFrameSplitOperator.FormatTimeString(this.Frame.Data.Data[index].Time); infoData={Value:index-xOffset, Text:time}; } if (infoData) { var info= new CoordinateInfo(); info.Value=infoData.Value; if (this.ShowText) info.Message[0]=infoData.Text; if (info.Value==0) info.LineType=-1; //第1个分割线不画 this.Frame.VerticalInfo.push(info); textDistance=0; barDistance=0; if (i==0) textDistance=-(this.MinTextDistance/2); } } } this.SplitSecond=function() //根据时间分割 { this.Frame.VerticalInfo=[]; var itemWidth=this.Frame.DistanceWidth+this.Frame.DataWidth; var xOffset=this.Frame.Data.DataOffset; var xPointCount=this.Frame.XPointCount; var textDistance=0; var barDistance=0; for(var i=0, index=xOffset; ithis.MinTextDistance && barDistance>=this.MinBarDistance) { var time=IFrameSplitOperator.FormatTimeString(this.Frame.Data.Data[index].Time,"HH:MM:SS"); infoData={Value:index-xOffset, Text:time}; } if (infoData) { var info= new CoordinateInfo(); info.Value=infoData.Value; if (this.ShowText) info.Message[0]=infoData.Text; this.Frame.VerticalInfo.push(info); textDistance=0; barDistance=0; if (i==0) textDistance=-(this.MinTextDistance/2); } } } this.SplitMilliSecond=function() { this.Frame.VerticalInfo=[]; var itemWidth=this.Frame.DistanceWidth+this.Frame.DataWidth; var xOffset=this.Frame.Data.DataOffset; var xPointCount=this.Frame.XPointCount; var textDistance=0; var barDistance=0; for(var i=0, index=xOffset; ithis.MinTextDistance && barDistance>=this.MinBarDistance) { var time=IFrameSplitOperator.FormatTimeString(this.Frame.Data.Data[index].Time,"HH:MM:SS.fff"); infoData={Value:index-xOffset, Text:time}; } if (infoData) { var info= new CoordinateInfo(); info.Value=infoData.Value; if (this.ShowText) info.Message[0]=infoData.Text; this.Frame.VerticalInfo.push(info); textDistance=0; barDistance=0; if (i==0) textDistance=-(this.MinTextDistance/2); } } } this.SplitDate=function() //根据日期分割 { this.Frame.VerticalInfo=[]; var xOffset=this.Frame.Data.DataOffset; var xPointCount=this.Frame.XPointCount; var lastYear=null, lastMonth=null; var minDistance=12; var monthCount=0; for(var i=0, index=xOffset, distance=minDistance;ithis.YClose) info.LineColor=g_JSChartResource.FrameLatestPrice.UpBarColor; else if (priceitem.Price) range.Min=item.Price; } //集合竞价均线统计 if (callAuctionData.Ver==3.0 && IFrameSplitOperator.IsNumber(item.AvPrice)) { if (range.Max==null) range.Max=item.AvPrice; if (range.Min==null) range.Min=item.AvPrice; if (range.Maxitem.AvPrice) range.Min=item.AvPrice; } } } //多日分时图 集合竞价数据 this.GetMultiDayBeforeOpenData=function() { if (!this.MultiDayBeforeOpenData || !IFrameSplitOperator.IsNonEmptyArray(this.MultiDayBeforeOpenData)) return null; if (!this.DayOffset) return this.MultiDayBeforeOpenData; if (!IFrameSplitOperator.IsNumber(this.DayOffset.Offset) || !IFrameSplitOperator.IsNumber(this.DayOffset.ShowDayCount)) return null; if (this.GlobalOption && this.GlobalOption.IsValueFullRange===true) return this.MultiDayBeforeOpenData; var showCount= this.DayOffset.ShowDayCount; var offset=this.DayOffset.Offset; var aryData=this.MultiDayBeforeOpenData.slice(offset, offset+showCount); return aryData; } this.GetMultiDayAfterCloseData=function() { if (!this.MultiDayAfterCloseData || !IFrameSplitOperator.IsNonEmptyArray(this.MultiDayAfterCloseData)) return null; if (!this.DayOffset) return this.MultiDayAfterCloseData; if (!IFrameSplitOperator.IsNumber(this.DayOffset.Offset) || !IFrameSplitOperator.IsNumber(this.DayOffset.ShowDayCount)) return null; if (this.GlobalOption && this.GlobalOption.IsValueFullRange===true) return this.MultiDayAfterCloseData; var showCount= this.DayOffset.ShowDayCount; var offset=this.DayOffset.Offset; var aryData=this.MultiDayAfterCloseData.slice(offset, offset+showCount); return aryData; } this.GetMaxMin=function() //计算图中所有的数据的最大最小值 { var max=this.YClose; var min=this.YClose; var data=this.Data; var isBerforeData=false; if (this.SourceData) { data=this.SourceData; isBerforeData=true; } if (this.DayCount>1) //多日 { var offset=this.DayOffset.DataOffset; var showDataCount=this.DayOffset.ShowDataCount; if (this.GlobalOption && this.GlobalOption.IsValueFullRange===true) { offset=0; showDataCount=data.Data.length; } for(var i=offset, j=0; ivalue) min=value; } if (this.AverageData) { for(var i=offset,j=0; ithis.AverageData.Data[i]) min=this.AverageData.Data[i]; } } } else { for(var i=0;ivalue) min=value; } if (this.AverageData) { for(var i=0;ithis.AverageData.Data[i]) min=this.AverageData.Data[i]; } } } for(var i in this.OverlayChartPaint) { var item=this.OverlayChartPaint[i]; //if (item.Status!=OVERLAY_STATUS_ID.STATUS_FINISHED_ID) continue; var range=item.GetMaxMin(); if (range.Max && range.Max>max) max=range.Max; if (range.Min && range.Minthis.LimitPrice.Min) min=this.LimitPrice.Min; } if (IFrameSplitOperator.IsNumber(this.High) && IFrameSplitOperator.IsNumber(this.Low)) { if (maxthis.Low) min=this.Low; } var range={ Max:null, Min:null }; if (this.IsAfterData && this.AfterCloseData) { this.GetCallAuctionMaxMin(this.AfterCloseData,range); } if (this.IsBeforeData && this.BeforeOpenData) { this.GetCallAuctionMaxMin(this.BeforeOpenData,range); } var multiDayBeforeOpenData=this.GetMultiDayBeforeOpenData(); if (multiDayBeforeOpenData && this.ChartBorder.MultiDayMinute.Count>1 && this.ChartBorder.MultiDayMinute.Left>0) { for(var i=0;i1 && this.ChartBorder.MultiDayMinute.Right>0) { for(var i=0;irange.Min) min=range.Min; //叠加指标 var overlayRange=this.GetOverlayMaxMin(); if (overlayRange) { if (IFrameSplitOperator.IsNumber(overlayRange.Max) && overlayRange.Max>max) max=overlayRange.Max; if (IFrameSplitOperator.IsNumber(overlayRange.Min) && overlayRange.Minvalue.Min ) range.Min=value.Min; } } return range; } this.USASplit=function(range) { var max=range.Max; var min=range.Min; if (max==min) { max=max+max*0.1; min=min-min*0.1; } else { var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 var height=this.Frame.ChartBorder.GetHeight(); //画布的高度 var spacePrice=5*pixelTatio*(max-min)/height; max+=spacePrice; min-=spacePrice; if (min<0) min=range.Min; } var showCount=this.SplitCount; var distance=(max-min)/(showCount-1); const minDistance=[1, 0.1, 0.01, 0.001, 0.0001]; var defaultfloatPrecision=GetfloatPrecision(this.Symbol); if (distance0) coordinate.TextColor=g_JSChartResource.UpTextColor; else if (per<0) coordinate.TextColor=g_JSChartResource.DownTextColor; if (this.IsShowRightText) { if (this.RightTextFormat==1) coordinate.Message[1]=strPrice; else coordinate.Message[1]=IFrameSplitOperator.FormatValueString(per,2)+'%'; //百分比 } } this.Frame.HorizontalInfo.push(coordinate); } if (this.YClose>min && this.YClose0? xcoordinateData.MiddleCount: parseInt(minuteCount/2); var xcoordinate = xcoordinateData.Data; this.Frame.XPointCount=minuteCount*this.DayCount; //计算一共显示的数据个数 this.Frame.MinuteCount=minuteCount; this.Frame.VerticalInfo=[]; if (this.Frame.GlobalOption) { var item=this.Frame.GlobalOption; if (IFrameSplitOperator.IsNumber(item.XDateFormat)) this.DateFormat=item.XDateFormat; } if (this.DayCount<=1) { //设置成1日的数据 this.DayOffset.DataOffset=0; this.DayOffset.ShowDataCount=minuteCount; this.DayOffset.PageInfo=null; for(var i=0; i=0 && j=200 && this.ClientPos<=299) { return this.GetMultiDayBeforeOpenXIndex(); } else if (this.ClientPos>=300 && this.ClientPos<=399) { return this.GetMultiDayAfterCloseXIndex(); } return false; } this.GetBeforeOpenXIndex=function() { if (!IFrameSplitOperator.IsNumber(this.Value)) return false; if (!this.BeforeOpenData || !this.BeforeOpenData.Data) return false; var index=this.Frame.GetLeftExtendXData(this.Value, this.BeforeOpenData); index=parseInt(index.toFixed(0)); if (index>=0 && index=this.BeforeOpenData.Data.length) index=this.BeforeOpenData.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=this.BeforeOpenData.Data[i]; if (IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) { for(var i=index+1; i=multiDayBeforeOpenData.length) return false; var dayData=multiDayBeforeOpenData[dayIndex]; var indexData=this.Frame.GetLeftExtendXData(this.Value, multiDayBeforeOpenData); if (!indexData || !IFrameSplitOperator.IsNumber(indexData.DataIndex)) return false; var index=parseInt(indexData.DataIndex.toFixed(0)); var dayIndex=indexData.DayIndex; if (index>=0 && index=dayData.Data.length) index=dayData.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=dayData.Data[i]; if (item && IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) return false; this.Item=item; this.DataIndex=findIndex; this.DayIndex=dayIndex; this.X=this.Frame.GetLeftExtendXFromIndex(findIndex, dayData); //调整X轴坐标 return true; } this.GetAfterCloseXIndex=function() { if (!IFrameSplitOperator.IsNumber(this.Value)) return false; if (!this.AfterCloseData || !this.AfterCloseData.Data) return false; var index=this.Frame.GetRightExtendXData(this.Value, this.AfterCloseData); index=parseInt(index.toFixed(0)); if (index>=0 && index=this.AfterCloseData.Data.length) index=this.AfterCloseData.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=this.AfterCloseData.Data[i]; if (IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) { for(var i=index+1; i=multiDayAfterCloseData.length) return; var dayData=multiDayAfterCloseData[dayIndex]; var indexData=this.Frame.GetRightExtendXData(this.Value, multiDayAfterCloseData); if (!indexData) return; var index=parseInt(indexData.DataIndex.toFixed(0)); var dayIndex=indexData.DayIndex; if (index>=0 && index=dayData.Data.length) index=dayData.Data.length-1; var findIndex=-1; for(var i=index; i>=0; --i) { var item=dayData.Data[i]; if (item && IFrameSplitOperator.IsNumber(item.Price)) { findIndex=i; break; } } if (findIndex<0) return false; this.Item=item; this.DataIndex=findIndex; this.DayIndex=dayIndex; this.X=this.Frame.GetRightExtendXFromIndex(findIndex, dayData); //调整X轴坐标 return true; } } /////////////////////////////////////////////////////////////////////////////////////////////////// //十字光标 function ChartCorssCursor() { this.ClassName="ChartCorssCursor"; this.Frame; this.Canvas; //画布 this.HPenColor=g_JSChartResource.CorssCursorHPenColor; //水平线颜色 this.HPenType=0; //水平线样式 0=虚线 1=实线 this.VPenColor=g_JSChartResource.CorssCursorVPenColor; //垂直线颜色 this.VPenType=0; //垂直线颜色 0=虚线 1=实线 2=K线宽度 this.VLineType=0; //垂直线 0=默认指标标题栏不画, 1=指标标题栏也画 this.Font=g_JSChartResource.CorssCursorTextFont; //字体 this.TextColor=g_JSChartResource.CorssCursorTextColor; //文本颜色 this.TextBGColor=g_JSChartResource.CorssCursorBGColor; //文本背景色 this.BorderColor=g_JSChartResource.CorssCursorBorderColor; //边框颜色 this.XRangeBGColor=g_JSChartResource.CorssCursorXRangeBGColor; this.TextHeight=20; //文本字体高度 this.LastPoint; this.LastValue; //{ Y:{ Value:, Extend: } } this.CursorIndex; this.IsOnlyDrawKLine=false; //是否只能画在K线上 (手机端) this.IsOnlyDrawMinute=false; //是否只能画在走势图价格线上 this.IsFixXLastTime=false; //是否修正X轴,超出当前时间的,X轴调整到当前最后的时间. this.IsDrawXRangeBG=false; //是否绘制十字光标背景 this.EnableNewIndex=false; //分时图是否使用最新的索引结构 (由外部chart容器传入) this.CorssCursorIndex; //分时图新版本的索引结构 (由外部chart容器传入) this.PointX; this.PointY; this.StringFormatX; this.StringFormatY; this.ShowTextMode={ Left:1, Right:1, Bottom:1 }; //0=不显示 1=显示在框架外 2=显示在框架内 this.TextFormat= { Right:0 }; //0=默认 1=价格显示(分时图才有用) this.IsShowCorss=true; //是否显示十字光标 this.IsShow=true; this.IsShowClose=false; //Y轴始终显示收盘价 this.ClientPos=-1; this.CallAcutionXOperator; this.EnableKeyboard=false; //是否支持键盘隐藏显示 this.OnChangeStatusCallback; //状态切换以后回调 this.RightButton= { Enable:false, Rect:null, BGColor:g_JSChartResource.CorssCursor.RightButton.BGColor , PenColor:g_JSChartResource.CorssCursor.RightButton.PenColor, Icon:g_JSChartResource.CorssCursor.RightButton.Icon }; this.RightMargin={ Left:2, Right:2, Top:4, Bottom:3 }; CopyMarginConfig(this.RightMargin, g_JSChartResource.CorssCursor.RightMargin); //内部使用 this.Close=null; //收盘价格 this.Status=0; //当前状态 0=隐藏 1=显示 this.ReloadResource=function(resource) { this.Font=g_JSChartResource.CorssCursorTextFont; //字体 this.HPenColor=g_JSChartResource.CorssCursorHPenColor; //水平线颜色 this.VPenColor=g_JSChartResource.CorssCursorVPenColor; //垂直线颜色 this.TextColor=g_JSChartResource.CorssCursorTextColor; //文本颜色 this.TextBGColor=g_JSChartResource.CorssCursorBGColor; //文本背景色 this.BorderColor=g_JSChartResource.CorssCursorBorderColor; //边框颜色 this.XRangeBGColor=g_JSChartResource.CorssCursorXRangeBGColor; } this.GetCloseYPoint=function(index) { if (!this.StringFormatX.Data) return null; var data = this.StringFormatX.Data; if (!data.Data || data.Data.length <= 0) return null; var dataIndex = data.DataOffset + index; if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1; if (dataIndex < 0) return null; var klineData = data.Data[dataIndex]; if (!klineData) return null; this.Close=klineData.Close; var yPoint = this.Frame.GetYFromData(this.Close); return yPoint; } this.GetMinuteCloseYPoint=function(index) { if (this.EnableNewIndex && this.CorssCursorIndex) { if (!this.StringFormatX || !this.StringFormatX.GetMinuteCloseYPoint) return null; var closeData=this.StringFormatX.GetMinuteCloseYPoint(this.CorssCursorIndex); if (!closeData) return null; this.Close=closeData.Price; return closeData.Y; } else { if (!IFrameSplitOperator.IsNumber(index)) return null; index=parseInt(index); if (!this.StringFormatX.Data) return null; var data = this.StringFormatX.Data; if (!data.Data || data.Data.length <= 0) return null; var dataIndex = data.DataOffset + index; if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1; if (dataIndex < 0) return null; var close = data.Data[dataIndex]; if (!IFrameSplitOperator.IsNumber(index)) return null; this.Close=close; var yPoint = this.Frame.GetYFromData(this.Close); return yPoint; } } this.GetDateTimeRange=function(index, option) { if (!IFrameSplitOperator.IsNumber(index)) return null; index=parseInt(index); var data = this.StringFormatX.Data; if (!data.Data || data.Data.length <= 0) return null; var dataIndex = data.DataOffset + index; if (dataIndex>=data.Data.length || dataIndex<0) return null; if (!this.Frame || !this.Frame.SubFrame[0] || !this.Frame.SubFrame[0].Frame) return null; var frame=this.Frame.SubFrame[0].Frame; var dataWidth=frame.DataWidth; var distanceWidth=frame.DistanceWidth; var xPointCount=frame.XPointCount; var kItem = data.Data[dataIndex]; if (!kItem) return null; var date=kItem.Date*1000000; var time=parseInt(kItem.Time/100)*100; var startTime=date+time; var endTime=date+time+59; var endIndex=dataIndex; for(var i=dataIndex; iendTime) break; if (i-data.DataOffset>=xPointCount) break; endIndex=i; } var startIndex=dataIndex; for(var i=dataIndex;i>=0 && i>=data.DataOffset;--i) { var item=data.Data[i]; var dateTime=item.Date*1000000+item.Time; if (dateTime10) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { this.Canvas.rect(border.Left,border.Top,border.Right-border.Left,border.TopEx-border.Top); } else { this.Canvas.rect(border.Left,border.Top,border.LeftEx-border.Left,border.Bottom-border.Top); } if (this.Canvas.isPointInPath(x,y)) return 2; } if (this.Frame.ChartBorder.RightExtendWidth>10) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { this.Canvas.rect(border.Left,border.BottomEx,border.Right-border.Left,border.Bottom-border.BottomEx); } else { this.Canvas.rect(border.RightEx,border.Top,border.Right-border.RightEx,border.Bottom-border.Top); } if (this.Canvas.isPointInPath(x,y)) return 3; } return -1; } this.GetFontHeight=function(font) { return GetFontHeight(this.Canvas, font, "擎"); } this.Draw=function() { this.Status=0; this.RightButton.Rect=null; this.LastValue=null; if (!this.LastPoint) return; this.Close=null; var x=this.LastPoint.X; var y=this.LastPoint.Y; var clientPos=this.PtInClient(x,y); this.PointY=null; this.PointY==null; this.ClientPos=clientPos; if (clientPos<=0) return; if (this.Frame.IsHScreen===true) { this.HScreenDraw(); return; } var border=this.Frame.ChartBorder.GetBorder(); var left=border.Left var right=border.Right; var top=border.TopTitle; var bottom=border.Bottom; var rightWidth=this.Frame.ChartBorder.Right; var chartRight=border.ChartWidth; if (this.IsOnlyDrawKLine) //手机端 十字只能画在K线上 { x=this.Frame.GetXFromIndex(this.CursorIndex); if (this.IsShowClose) { var yPoint = this.GetCloseYPoint(this.CursorIndex); if (yPoint != null) y=yPoint; } } else if (this.IsOnlyDrawMinute) { var yPoint = this.GetMinuteCloseYPoint(this.CursorIndex); if (yPoint != null) y=yPoint; } if (this.CallAcutionXOperator) { this.CallAcutionXOperator.Value=x; this.CallAcutionXOperator.Point={X:x, Y:y}; this.CallAcutionXOperator.ClientPos=clientPos; if (this.CallAcutionXOperator.Operator()) { x=this.CallAcutionXOperator.X; } } if (this.IsFixXLastTime) { var value=this.FixMinuteLastTimeXPoint(this.CursorIndex) if (value) { x=value.X; this.CursorIndex=value.Index; } } this.PointY=[[left,y],[right,y]]; this.PointX=[[x,top],[x,bottom]]; //十字线 if (this.IsShowCorss) { var rangeBG=null; if (this.IsDrawXRangeBG) { rangeBG=this.GetDateTimeRange(this.CursorIndex); } var pixel=GetDevicePixelRatio(); if (this.HPenType==1 || this.HPenType==0) //0=实线 1=虚线 { this.Canvas.strokeStyle=this.HPenColor; if (this.HPenType==0) this.Canvas.setLineDash([3*pixel,2*pixel]); //虚线 //this.Canvas.lineWidth=0.5 this.Canvas.beginPath(); this.Canvas.moveTo(left,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); this.Canvas.stroke(); if (this.HPenType==0) this.Canvas.setLineDash([]); } this.Canvas.save(); this.Canvas.strokeStyle=this.VPenColor; if (this.VPenType==0) { this.Canvas.setLineDash([3*pixel,2*pixel]); //虚线 } else if (this.VPenType==2) { let barWidth=this.Frame.SubFrame[0].Frame.DataWidth; //和K线一样宽度 if (barWidth>2*pixel) this.Canvas.lineWidth=barWidth; } this.Canvas.beginPath(); if (this.VLineType==1) { if (rangeBG) { this.Canvas.fillStyle=this.XRangeBGColor; this.Canvas.fillRect(rangeBG.XStart, border.Top, (rangeBG.XEnd-rangeBG.XStart),(border.Bottom-border.Top)); } this.Canvas.moveTo(ToFixedPoint(x),border.Top); this.Canvas.lineTo(ToFixedPoint(x),border.Bottom); } else { if (this.Frame.SubFrame.length>0) { for(var i in this.Frame.SubFrame) { var frame=this.Frame.SubFrame[i].Frame; var subBorder=frame.ChartBorder.GetBorder(); top=subBorder.TopTitle; bottom=subBorder.Bottom; if (rangeBG) { this.Canvas.fillStyle=this.XRangeBGColor; this.Canvas.fillRect(rangeBG.XStart, top, (rangeBG.XEnd-rangeBG.XStart),(bottom-top)); } this.Canvas.moveTo(ToFixedPoint(x),top); this.Canvas.lineTo(ToFixedPoint(x),bottom); } } else { this.Canvas.moveTo(ToFixedPoint(x),top); this.Canvas.lineTo(ToFixedPoint(x),bottom); } } this.Canvas.stroke(); this.Canvas.restore(); } var xValue=this.Frame.GetXData(x); var yValueExtend={}; var yValue=this.Frame.GetYData(y,yValueExtend); if ( (this.IsOnlyDrawMinute || this.IsShowClose) && this.Close != null) yValue=this.Close; this.LastValue={ Y:{ Value:yValue, Extend:yValueExtend }}; //缓存十字光标对应的数值 //this.StringFormatX.Value=xValue; this.StringFormatX.Value=this.CursorIndex; this.StringFormatX.Point={X:x, Y:y}; this.StringFormatX.ClientPos=clientPos; this.StringFormatY.Value=yValue; this.StringFormatY.RValue=yValueExtend.RightYValue; //右侧子坐标 this.StringFormatY.FrameID=yValueExtend.FrameID; this.StringFormatY.Point={X:x, Y:y}; this.StringFormatY.ClientPos=clientPos; this.Canvas.font=this.Font; var textHeight=this.GetFontHeight(); if (textHeight>this.TextHeight) this.TextHeight=textHeight; //Y轴 if ( ((this.ShowTextMode.Left==1 && this.Frame.ChartBorder.Left>=30) || this.ShowTextMode.Left==2 || (this.ShowTextMode.Right==1 && this.Frame.ChartBorder.Right>=30) || this.ShowTextMode.Right==2 ) && this.StringFormatY.Operator() ) { var text=this.StringFormatY.Text; this.Canvas.font=this.Font; var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 var textSize={ Width:textWidth, Height:this.TextHeight, Text:[] }; var buttonData={Y:y, YValue:yValue, FrameID:yValueExtend.FrameID }; if (this.Frame.ChartBorder.Left>=30 && this.ShowTextMode.Left==1) { if (left=30 && this.ShowTextMode.Right==1) { var isOverlayIndex=false; //是否有叠加子坐标 var overlayIndexInterval=null; //子坐标间距 if (yValueExtend.FrameID>=0) { var frame=this.Frame.SubFrame[yValueExtend.FrameID]; isOverlayIndex=frame.OverlayIndex.length>0; overlayIndexInterval=null if (isOverlayIndex) { for(var i=0;i<=frame.OverlayIndex.length;++i) { var item=frame.OverlayIndex[i]; if (!item || !item.Frame) continue; if (item.Frame.IsShow===false) continue; if (!item.Frame.GetXHorizontal) continue; var overlayLeft=item.Frame.GetXHorizontal(); overlayIndexInterval=overlayLeft-right; break; } } } //叠加坐标 if (isOverlayIndex && textSize.Width>overlayIndexInterval && overlayIndexInterval>0) //大于子坐标宽度 { var drawRight=right+overlayIndexInterval; if (drawRight>chartRight) drawRight=chartRight; var itemLeft=drawRight-2-textSize.Width; this.DrawTextBGRect(itemLeft,yTop,textSize.Width,textSize.Height); this.DrawComplexTextV2(itemLeft, yTop, complexText, textSize); if (this.RightButton.Enable) this.DrawRightButton(yTop, itemLeft,this.TextHeight,this.TextHeight,buttonData); } else if (rightWidth0) { var yOffset=0; for(var i in this.StringFormatY.RExtendText) { var item=this.StringFormatY.RExtendText[i]; var rText='--.--' if (item.YText) rText=item.YText; else if (IFrameSplitOperator.IsNumber(item.Y)) rText=item.Y.toFixed(0); var rTextWidth=this.Canvas.measureText(rText).width+4; //前后各空2个像素 if (rightWidth=right) { this.DrawTextBGRect(right-textWidth,yTop,textWidth,this.TextHeight); this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,right-2,yCenter,textWidth); } else { this.DrawTextBGRect(x-textWidth/2,yTop,textWidth,this.TextHeight); this.Canvas.textAlign="center"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,x,yCenter,textWidth); } } } //子坐标Y轴 if (yValueExtend.FrameID>=0) { var frame=this.Frame.SubFrame[yValueExtend.FrameID]; var overlayLeft=right; this.Canvas.font=this.Font; for(var i=0; ichartRight) break; var yValue=item.Frame.GetYData(y); var text=IFrameSplitOperator.FormatValueString(yValue,2); var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 /* for(var j=2;j>=0;--j) { var text=IFrameSplitOperator.FormatValueString(yValue,j); var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 if (textWidth2*pixel) this.Canvas.lineWidth=barWidth; } this.Canvas.beginPath(); if (this.VLineType==1) { this.Canvas.moveTo(left,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); } else { if (this.Frame.SubFrame.length>0) { for(var i in this.Frame.SubFrame) { var frame=this.Frame.SubFrame[i].Frame; var subBorder=frame.ChartBorder.GetHScreenBorder(); this.Canvas.moveTo(subBorder.Left,ToFixedPoint(y)); this.Canvas.lineTo(subBorder.RightEx,ToFixedPoint(y)); } } else { this.Canvas.moveTo(left,ToFixedPoint(y)); this.Canvas.lineTo(right,ToFixedPoint(y)); } } this.Canvas.stroke(); this.Canvas.restore(); } var xValue=this.Frame.GetXData(y); var yValueExtend={}; var yValue=this.Frame.GetYData(x,yValueExtend); this.StringFormatX.Value=xValue; this.StringFormatX.Point={X:x, Y:y}; this.StringFormatX.ClientPos=this.ClientPos; this.StringFormatY.Value=yValue; this.StringFormatY.FrameID=yValueExtend.FrameID; this.StringFormatY.RValue=yValueExtend.RightYValue; //右侧子坐标 this.StringFormatY.Point={X:x, Y:y}; this.StringFormatY.ClientPos=this.ClientPos; this.Canvas.font=this.Font; var textHeight=this.GetFontHeight(); if (textHeight>this.TextHeight) this.TextHeight=textHeight; if ( ((this.ShowTextMode.Left==1 && this.Frame.ChartBorder.Top>=30) || this.ShowTextMode.Left==2 || (this.ShowTextMode.Right==1 && this.Frame.ChartBorder.Bottom>=30) || this.ShowTextMode.Right==2) && this.StringFormatY.Operator() ) { var text=this.StringFormatY.Text; this.Canvas.font=this.Font; var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 if (this.Frame.ChartBorder.Top>=30 && this.ShowTextMode.Left==1) { var xText=x; var yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle=this.TextBGColor; if (top>=textWidth) { this.Canvas.fillRect(0,-(this.TextHeight/2),-textWidth,this.TextHeight); this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,-2,0,textWidth); } else { this.Canvas.fillRect((textWidth-top),-(this.TextHeight/2),-textWidth,this.TextHeight); this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,(textWidth-top)-2,0,textWidth); } this.Canvas.restore(); } else if (this.ShowTextMode.Left==2) { var xText=x; var yText=top; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle=this.TextBGColor; this.Canvas.fillRect(0,-(this.TextHeight/2),textWidth,this.TextHeight); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,2,0,textWidth); this.Canvas.restore(); } if (this.StringFormatY.RText) { text=this.StringFormatY.RText; var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 } if (this.Frame.ChartBorder.Bottom>=30 && this.ShowTextMode.Right==1) { var xText=x; var yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle=this.TextBGColor; if (bottomWidth>textWidth) { this.Canvas.fillRect(0,-(this.TextHeight/2),textWidth,this.TextHeight); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,2,0,textWidth); } else { this.Canvas.fillRect((bottomWidth-textWidth),-(this.TextHeight/2),textWidth,this.TextHeight); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,(bottomWidth-textWidth)+2,0,textWidth); } if (this.StringFormatY.RExtendText && this.StringFormatY.RExtendText.length>0) { var yOffset=0; for(var i in this.StringFormatY.RExtendText) { var item=this.StringFormatY.RExtendText[i]; var rText='--.--' if (item.YText) rText=item.YText; else if (IFrameSplitOperator.IsNumber(item.Y)) rText=item.Y.toFixed(0); var rTextWidth=this.Canvas.measureText(rText).width+4; //前后各空2个像素 this.Canvas.fillStyle=item.TextBGColor; if (bottomWidth>rTextWidth) { this.Canvas.fillRect(0,yOffset+this.TextHeight/2,rTextWidth,this.TextHeight); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(rText,2,yOffset+this.TextHeight,rTextWidth); } else { var rTextLeft=bottomWidth-rTextWidth; this.Canvas.fillRect(rTextLeft,yOffset+this.TextHeight/2,rTextWidth,this.TextHeight); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(rText,rTextLeft+2,yOffset+this.TextHeight,rTextWidth); } yOffset+=this.TextHeight; } } this.Canvas.restore(); } else if (this.ShowTextMode.Right==2) { var xText=x; var yText=bottom; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillStyle=this.TextBGColor; this.Canvas.fillRect(0,-(this.TextHeight/2),-textWidth,this.TextHeight); this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,-2,0,textWidth); this.Canvas.restore(); } } //X轴 Bottom=8 自定义X轴文字位置 if ((this.ShowTextMode.Bottom===1 || this.ShowTextMode.Bottom==8) && this.StringFormatX.Operator()) { var text=this.StringFormatX.Text; this.Canvas.font=this.Font; this.Canvas.fillStyle=this.TextBGColor; var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 var xText=left; var bShowText=true; if (this.ShowTextMode.Bottom==8) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_CORSSCURSOR_POSITION); if (event && event.Callback) { var sendData={ XText:xText, Height:this.TextHeight, IsShowText:bShowText }; event.Callback(event, sendData, this); xText=sendData.XText; bShowText=sendData.IsShowText; } } if (bShowText) { if (y-textWidth/2<3) //左边位置不够了, 顶着左边画 { var yText=y; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillRect(0,0,textWidth,this.TextHeight); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,2,this.TextHeight/2,textWidth); this.Canvas.restore(); } else if (y+textWidth/2>=bottom) { var yText=y; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillRect(-textWidth,0,textWidth,this.TextHeight); this.Canvas.textAlign="right"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,-2,this.TextHeight/2,textWidth); this.Canvas.restore(); } else { var yText=y; this.Canvas.save(); this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.fillRect(-textWidth/2,0,textWidth,this.TextHeight); this.Canvas.textAlign="center"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,0,this.TextHeight/2,textWidth); this.Canvas.restore(); } } } this.Status=1; } //data={ e:e, PreventDefault:false, KeyID, Draw:是否需要重绘 } this.OnKeyDown=function(data) { if (!this.EnableKeyboard) return; var keyID=data.KeyID; if (keyID==27) //ESC 隐藏十字线 { if (!this.IsShowCorss) return; this.IsShowCorss=false; data.Draw=true; if (this.OnChangeStatusCallback) this.OnChangeStatusCallback({ Type:1, IsShowCorss:this.IsShowCorss }, this); } else if (keyID==37 || keyID==39) //left, right 显示十字线 { if (this.IsShowCorss) return; this.IsShowCorss=true; data.Draw=true; if (this.OnChangeStatusCallback) this.OnChangeStatusCallback({ Type:1, IsShowCorss:this.IsShowCorss }, this); } } } //////////////////////////////////////////////////////////////////////////////// //深度图十字光标 function DepthChartCorssCursor() { this.Frame; this.HQChart; this.Canvas; //画布 this.Data; this.Symbol; this.HPenType=0; //水平线样式 0=虚线 1=实线 this.VPenType=0; //垂直线颜色 0=虚线 1=实线 this.LineDash=g_JSChartResource.DepthCorss.LineDash; this.IsShowTooltip=true; this.AskColor=g_JSChartResource.DepthCorss.AskColor.Line; //卖 this.BidColor=g_JSChartResource.DepthCorss.BidColor.Line; //买 this.LineWidth=g_JSChartResource.DepthCorss.LineWidth; this.ClassName="DepthChartCorssCursor"; this.Tooltip= { Border: { Top:g_JSChartResource.DepthCorss.Tooltip.Border.Top, Left:g_JSChartResource.DepthCorss.Tooltip.Border.Left, Right:g_JSChartResource.DepthCorss.Tooltip.Border.Right, Bottom:g_JSChartResource.DepthCorss.Tooltip.Border.Bottom, ItemSpace: g_JSChartResource.DepthCorss.Tooltip.Border.ItemSpace }, Font:g_JSChartResource.DepthCorss.Tooltip.Font, TextColor:g_JSChartResource.DepthCorss.Tooltip.TextColor, BGColor:g_JSChartResource.DepthCorss.Tooltip.BGColor }; // Width: Height: this.Font=g_JSChartResource.CorssCursorTextFont; //字体 this.TextColor=g_JSChartResource.CorssCursorTextColor; //文本颜色 this.TextBGColor=g_JSChartResource.CorssCursorBGColor; //文本背景色 this.TextHeight=20; //文本字体高度 this.LastPoint; this.PointX; this.PointY; this.StringFormatX; this.StringFormatY; this.IsShowCorss=true; //是否显示十字光标 this.IsShow=true; //this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; //多语言 this.GetVol=function(price, isAsk) { if (!this.Data) return null; var aryData=isAsk? this.Data.Asks:this.Data.Bids; if (!aryData || !Array.isArray(aryData) || aryData.length<=0) return null; for(var i in aryData) { var item=aryData[i]; if (item.Price==price) return item.Vol; } return null; } this.Draw=function() { this.Status=0; if (!this.LastPoint) return; if (!this.Data) return; if (!this.IsShow) return; var x=this.LastPoint.X; var y=this.LastPoint.Y; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); this.PointY=null; this.PointY==null; if (!isInClient) return; if (this.Frame.IsHScreen===true) { return; } var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); var top=this.Frame.ChartBorder.GetTopTitle(); var bottom=this.Frame.ChartBorder.GetBottom(); var rightWidth=this.Frame.ChartBorder.Right; var chartRight=this.Frame.ChartBorder.GetChartWidth(); var xValue=this.Frame.GetXData(x); var xInfo=this.Frame.GetXFromPrice(xValue); //调整价格到有数据的点上 if (!xInfo) return; var yVol=this.GetVol(xInfo.Price, xInfo.IsAsk); y=this.Frame.GetYFromData(yVol); //调整Y轴, 让它在线段上 xInfo.Vol=yVol; xInfo.Y=y; this.PointY=[[left,y],[right,y]]; this.PointX=[[x,top],[x,bottom]]; if (this.IsShowCorss) { if (xInfo.IsAsk) this.Canvas.strokeStyle=this.AskColor; else this.Canvas.strokeStyle=this.BidColor; var lineWidthBackup=this.Canvas.lineWidth; var pixel=GetDevicePixelRatio(); this.Canvas.lineWidth=this.LineWidth*pixel; var lineWidth=this.Canvas.lineWidth; if (this.HPenType==1 || this.HPenType==0) //0=实线 1=虚线 { if (this.HPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线 var yFix=ToFixedPoint2(lineWidth, y); this.Canvas.beginPath(); this.Canvas.moveTo(left,yFix); this.Canvas.lineTo(right,yFix); this.Canvas.stroke(); if (this.HPenType==0) this.Canvas.setLineDash([]); } if (this.VPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线 var xFix=ToFixedPoint2(lineWidth, xInfo.X); this.Canvas.beginPath(); this.Canvas.moveTo(xFix,top); this.Canvas.lineTo(xFix,bottom); this.Canvas.stroke(); if (this.VPenType==0) this.Canvas.setLineDash([]); this.Canvas.lineWidth=lineWidthBackup; } if (this.HQChart) { var event=this.HQChart.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_DEPTH_TOOLTIP); if (event) { event.Callback(event,xInfo,this); } } if (this.IsShowTooltip) { var aryText=this.GetFormatTooltip(xInfo); this.DrawTooltip(aryText,xInfo); } } //[{Title:, TitleColor:, Text:, Color:}] this.GetFormatTooltip=function(drawData) { var aryText=[]; var floatPrecision=2; if (this.Symbol) floatPrecision=GetfloatPrecision(this.Symbol); //价格小数位数 var item= { Title:g_JSChartLocalization.GetText('Depth-Price',this.HQChart.LanguageID), TitleColor:this.Tooltip.TextColor, Text:drawData.Price.toFixed(floatPrecision), Color:this.Tooltip.TextColor }; aryText.push(item); var item= { Title:g_JSChartLocalization.GetText('Depth-Sum',this.HQChart.LanguageID), TitleColor:this.Tooltip.TextColor, Text:drawData.Vol.toFixed(4), Color:this.Tooltip.TextColor }; aryText.push(item); return aryText; } this.DrawTooltip=function(aryText, data) { if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return; this.Canvas.font=this.Tooltip.Font; var maxWidth=0, lineCount=0, itemCount=0; for(var i=0;i=chartRight) left=data.X-this.Tooltip.Width; if (top=multiDayBeforeOpenData.length) return false; var dayData=multiDayBeforeOpenData[dayIndex]; var range={ Max:dayData.VolMax, Min:dayData.VolMin }; var y=this.Frame.IsHScreen? this.Point.X: this.Point.Y; var value=item.Frame.GetLeftExtendYData(y,false,{ Range:range } ); var defaultfloatPrecision=2; //价格小数位数 if (IFrameSplitOperator.IsNumber(value)) { this.RText=this.Text=IFrameSplitOperator.FormatValueString(value,defaultfloatPrecision,this.LanguageID); } } this.GetMultiDayAfterClose=function() { if (!this.Frame) return false; var item=this.Frame.SubFrame[this.FrameID]; if (!item || !item.Frame) return false; var multiDayAfterCloseData=this.GetMultiDayAfterCloseData(); if (!multiDayAfterCloseData || !IFrameSplitOperator.IsNonEmptyArray(multiDayAfterCloseData)) return; var dayIndex=this.ClientPos-300; if (dayIndex<0 || dayIndex>=multiDayAfterCloseData.length) return false; var dayData=multiDayAfterCloseData[dayIndex]; var range={ Max:dayData.VolMax, Min:dayData.VolMin }; var y=this.Frame.IsHScreen? this.Point.X: this.Point.Y; var value=item.Frame.GetRightExtendYData(y,false,{ Range:range } ); var defaultfloatPrecision=2; //价格小数位数 if (IFrameSplitOperator.IsNumber(value)) { this.RText=this.Text=IFrameSplitOperator.FormatValueString(value,defaultfloatPrecision,this.LanguageID); } } this.Operator=function() { this.RText=null; this.RComplexText=null; this.RExtendText=[]; if (IFrameSplitOperator.IsString(this.RValue)) this.RText=this.RValue; if (!this.Value) return false; this.PercentageText=null; var defaultfloatPrecision=2; //价格小数位数 if (this.FrameID==0) //第1个窗口显示原始价格 { var defaultfloatPrecision=GetfloatPrecision(this.Symbol); if (this.PriceFormatType==1) this.Text=IFrameSplitOperator.FormatValueThousandsString(this.Value,defaultfloatPrecision); else this.Text=this.Value.toFixed(defaultfloatPrecision); if (this.YClose>0) this.PercentageText=((this.Value-this.YClose)*100/this.YClose).toFixed(2); //走势图右边坐标显示百分比 this.GetExtendPaintData(defaultfloatPrecision); } else if (this.FrameID==1) { if (this.DataFormatType==1) { this.Text=IFrameSplitOperator.FormatValueThousandsString(this.Value,defaultfloatPrecision); if (IFrameSplitOperator.IsNumber(this.RValue)) this.RText=IFrameSplitOperator.FormatValueString(this.RValue,defaultfloatPrecision,this.LanguageID); } else { this.Text=IFrameSplitOperator.FormatValueString(this.Value,defaultfloatPrecision,this.LanguageID); if (IFrameSplitOperator.IsNumber(this.RValue)) this.RText=IFrameSplitOperator.FormatValueString(this.RValue,defaultfloatPrecision,this.LanguageID); } if (this.ClientPos==2) { this.GetBeforeOpen(); } else if (this.ClientPos==3) { if (this.ShareAfterVol==0 || this.ShareAfterVol==2) this.GetAfterClose(); } else if (this.ClientPos>=200 && this.ClientPos<=299) { this.GetMultiDayBeforeOpen(); } else if (this.ClientPos>=300 && this.ClientPos<=399 ) { if (this.ShareAfterVol==0 || this.ShareAfterVol==2) this.GetMultiDayAfterClose(); } } else { if (this.DataFormatType==1) this.Text=IFrameSplitOperator.FormatValueThousandsString(this.Value,defaultfloatPrecision); else this.Text=IFrameSplitOperator.FormatValueString(this.Value,defaultfloatPrecision,this.LanguageID); if (IFrameSplitOperator.IsNumber(this.RValue)) this.RText=IFrameSplitOperator.FormatValueString(this.RValue,defaultfloatPrecision,this.LanguageID); } if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_CORSSCURSOR_Y_TEXT); if (event) { var data={ Value:this.Value, FrameID:this.FrameID, PreventDefault:false }; event.Callback(event,data,this); if (data.PreventDefault==true) return false; } } return true; } //深度图刻度 this.GetExtendPaintData=function(floatPrecision) { var value=parseInt(this.Value*ZOOM_VALUE[floatPrecision]); for(var i in this.ExtendChartPaint) { var item=this.ExtendChartPaint[i]; if (item.ClassName=='DepthMapPaint' && item.FrameID==this.FrameID) { var aryData=item.GetYValueByXValue(value,floatPrecision); for(var j in aryData) { this.RExtendText.push(aryData[j]); } } } } } function HQDateStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.DateFormatType=0; //0=YYYY-MM-DD 1=YYYY/MM/DD 2=YYYY/MM/DD/W 3=DD/MM/YYYY this.LanguageID=0; this.Operator=function() { if (!IFrameSplitOperator.IsNumber(this.Value)) return false; if (!this.Data) return false; var index=this.Value; index=parseInt(index.toFixed(0)); if (this.Data.DataOffset+index>=this.Data.Data.length) return false; var currentData = this.Data.Data[this.Data.DataOffset+index]; var dateFormatString="YYYY-MM-DD"; if (this.DateFormatType==1) dateFormatString="YYYY/MM/DD"; else if (this.DateFormatType==2) dateFormatString="YYYY/MM/DD/W"; else if (this.DateFormatType==3) dateFormatString="DD/MM/YYYY"; this.Text=IFrameSplitOperator.FormatDateString(currentData.Date, dateFormatString,this.LanguageID); if (ChartData.IsMinutePeriod(this.Data.Period,true) ) // 分钟周期 { var time = IFrameSplitOperator.FormatTimeString(currentData.Time); this.Text = this.Text + " " + time; } else if (ChartData.IsSecondPeriod(this.Data.Period)) { var time = IFrameSplitOperator.FormatTimeString(currentData.Time,'HH:MM:SS'); this.Text = this.Text + " " + time; } else if (ChartData.IsMilliSecondPeriod(this.Data.Period)) { var time = IFrameSplitOperator.FormatTimeString(currentData.Time,'HH:MM:SS.fff'); this.Text = this.Text + " " + time; } else if (ChartData.IsTickPeriod(this.Data.Period)) //分笔 { var time = IFrameSplitOperator.FormatTimeString(currentData.Time); this.Text = this.Text + " " + time; } if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_CORSSCURSOR_X_TEXT); if (event) { var data={ Item:currentData, Period:this.Data.Period, Date:currentData.Date, Time:currentData.Time,Index:this.Data.DataOffset+index, PreventDefault:false }; event.Callback(event,data,this); if (data.PreventDefault==true) return false; } } return true; } } function HQMinuteTimeStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.ClassName="HQMinuteTimeStringFormat"; this.Frame; this.Symbol; this.Point; this.ClientPos=-1; this.BeforeOpenData; //单日分时图 盘前数据 this.AfterCloseData; //单日分时图 收盘数据 this.MultiDayBeforeOpenData; //多日分时图 盘前数据 this.MultiDayAfterCloseData; //多日分时图 收盘数据 this.GetEventCallback this.GetBeforeOpen=function() { if (!this.BeforeOpenData || !this.BeforeOpenData.Data) return false; var x=this.Frame.IsHScreen==true?this.Point.Y:this.Point.X; var index=this.Frame.GetLeftExtendXData(x, this.BeforeOpenData); index=parseInt(index.toFixed(0)); if (index>=this.BeforeOpenData.Data.length) return false; var item=this.BeforeOpenData.Data[index]; this.Text=this.FormatCallAcutionDateTime(item, this.BeforeOpenData); return true; } this.GetAfterClose=function() { if (!this.AfterCloseData || !this.AfterCloseData.Data) return false; var x=this.Frame.IsHScreen==true?this.Point.Y:this.Point.X; var index=this.Frame.GetRightExtendXData(x, this.AfterCloseData); index=parseInt(index.toFixed(0)); if (index>=this.AfterCloseData.Data.length) return false; var item=this.AfterCloseData.Data[index]; this.Text=this.FormatCallAcutionDateTime(item, this.AfterCloseData); return true; } this.GetMultiDayBeforeOpen=function() { var multiDayBeforeOpenData=this.GetMultiDayBeforeOpenData(); if (!multiDayBeforeOpenData) return false; if (this.Frame.ChartBorder.MultiDayMinute.Count<=1 || this.Frame.ChartBorder.MultiDayMinute.Left<=0) return false; var x=this.Frame.IsHScreen==true?this.Point.Y:this.Point.X; var index=this.Frame.GetLeftExtendXData(x, multiDayBeforeOpenData); if (!index) return false; if (index.DayIndex>=multiDayBeforeOpenData.length) return false; var dayItem=multiDayBeforeOpenData[index.DayIndex]; index.DataIndex=parseInt(index.DataIndex.toFixed(0)); if (index.DataIndex>=dayItem.Data.length || index.DataIndex<0) return false; var item=dayItem.Data[index.DataIndex]; this.Text=this.FormatCallAcutionDateTime(item, dayItem); return true; } this.GetMultiDayAfterClose=function() { var multiDayAfterCloseData=this.GetMultiDayAfterCloseData(); if (!multiDayAfterCloseData) return false; if (this.Frame.ChartBorder.MultiDayMinute.Count<=1 || this.Frame.ChartBorder.MultiDayMinute.Right<=0) return false; var x=this.Frame.IsHScreen==true?this.Point.Y:this.Point.X; var index=this.Frame.GetRightExtendXData(x, multiDayAfterCloseData); if (!index) return false; if (index.DayIndex>=multiDayAfterCloseData.length) return false; var dayItem=multiDayAfterCloseData[index.DayIndex]; index.DataIndex=parseInt(index.DataIndex.toFixed(0)); if (index.DataIndex>=dayItem.Data.length) return false; var item=dayItem.Data[index.DataIndex]; this.Text=this.FormatCallAcutionDateTime(item, dayItem); return true; } this.FormatCallAcutionDateTime=function(item, callAcutionData) { var time=item.Time; if (callAcutionData.Ver==1.0) return IFrameSplitOperator.FormatTimeString(time,"HH:MM"); else return IFrameSplitOperator.FormatTimeString(time,"HH:MM:SS"); } this.Operator=function() { if (this.ClientPos==2) return this.GetBeforeOpen(); else if (this.ClientPos==3) return this.GetAfterClose(); else if (this.ClientPos>=200 && this.ClientPos<=299) return this.GetMultiDayBeforeOpen(); else if (this.ClientPos>=300 && this.ClientPos<=399) return this.GetMultiDayAfterClose(); if (!IFrameSplitOperator.IsNumber(this.Value)) return false; var index=Math.abs(this.Value); index=parseInt(index.toFixed(0)); var showIndex=index; if (this.Frame && this.Frame.MinuteCount) showIndex=index%this.Frame.MinuteCount; var timeStringData=g_MinuteTimeStringData; var timeData=timeStringData.GetTimeData(this.Symbol); if (!timeData) return false; if (showIndex<0) showIndex=0; else if (showIndex>timeData.length) showIndex=timeData.length-1; if (this.Frame && index>=this.Frame.XPointCount) showIndex=timeData.length-1; var time=timeData[showIndex]; this.Text=IFrameSplitOperator.FormatTimeString(time); if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_CORSSCURSOR_X_TEXT); if (event) { var data={ Time:time, Index:showIndex, PreventDefault:false }; event.Callback(event,data,this); if (data.PreventDefault==true) return false; } } return true; } this.GetMinuteCloseYPoint=function(cursorIndexData) { var type=cursorIndexData.Type; if (type==1 || type==2 || type==3) //单日 1=主图 2=盘前 3=盘后 { if (type==1) { if (!this.Data || this.Data.Data.length <= 0) return null; var index=cursorIndexData.DataIndex; if (index<0 || index>=this.Data.Data.length) index=this.Data.Data.length-1; var close = this.Data.Data[index]; var yPoint = this.Frame.GetYFromData(close); return { Price:close, Y:yPoint }; } else if (type==2) { if (!this.BeforeOpenData || !this.BeforeOpenData.Data) return false; if (cursorIndexData.DataIndex<0 || cursorIndexData.DataIndex>=this.BeforeOpenData.Data.length) return null; var item=this.BeforeOpenData.Data[cursorIndexData.DataIndex]; var close=item.Price; var yPoint = this.Frame.GetYFromData(close); return { Price:close, Y:yPoint }; } else if (type==3) { if (!this.AfterCloseData || !this.AfterCloseData.Data) return false; if (cursorIndexData.DataIndex<0 || cursorIndexData.DataIndex>=this.AfterCloseData.Data.length) return null; var item=this.AfterCloseData.Data[cursorIndexData.DataIndex]; var close=item.Price; var yPoint = this.Frame.GetYFromData(close); return { Price:close, Y:yPoint }; } } else if (type==10 || type==20 || type==30) //多日 10=主图 20=盘前 30=盘后 { if (type==10) { if (!this.Data || this.Data.Data.length <= 0) return null; var index=this.Frame.MinuteCount*cursorIndexData.DayIndex+cursorIndexData.DataIndex; if (index<0 || index>=this.Data.Data.length) index=this.Data.Data.length-1; var close = this.Data.Data[index]; var yPoint = this.Frame.GetYFromData(close); return { Price:close, Y:yPoint }; } else if (type==20) { var multiDayBeforeOpenData=this.GetMultiDayBeforeOpenData(); if (!multiDayBeforeOpenData) return null; if (cursorIndexData.DayIndex<0 || cursorIndexData.DayIndex>=multiDayBeforeOpenData.length) return null; var dayItem=multiDayBeforeOpenData[cursorIndexData.DayIndex]; if (cursorIndexData.DataIndex<0 || cursorIndexData.DataIndex>=dayItem.Data.length) return null; var item=dayItem.Data[cursorIndexData.DataIndex]; var close=item.Price; var yPoint = this.Frame.GetYFromData(close); return { Price:close, Y:yPoint }; } else if (type==30) { var multiDayAfterCloseData=this.GetMultiDayAfterCloseData(); if (!multiDayAfterCloseData) return null; if (cursorIndexData.DayIndex<0 || cursorIndexData.DayIndex>=multiDayAfterCloseData.length) return null; var dayItem=multiDayAfterCloseData[cursorIndexData.DayIndex]; if (cursorIndexData.DataIndex<0 || cursorIndexData.DataIndex>=dayItem.Data.length) return null; var item=dayItem.Data[cursorIndexData.DataIndex]; var close=item.Price; var yPoint = this.Frame.GetYFromData(close); return { Price:close, Y:yPoint }; } } return null; } } //行情tooltip提示信息格式 var WEEK_NAME=["日","一","二","三","四","五","六"]; function HistoryDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.ClassName="HistoryDataStringFormat"; this.Symbol; this.UpColor=g_JSChartResource.UpTextColor; this.DownColor=g_JSChartResource.DownTextColor; this.UnchagneColor=g_JSChartResource.UnchagneTextColor; this.VolColor=g_JSChartResource.Title.VolColor; this.AmountColor=g_JSChartResource.Title.AmountColor; this.TurnoverRateColor=g_JSChartResource.Title.TurnoverRateColor; this.PositionColor=g_JSChartResource.Title.PositionColor; this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; this.LineCount=0; //一共几行 this.LineHeight=g_JSChartResource.PCTooltip.LineHeight; //单行高度 this.Width=157; //宽度 this.Height=this.LineHeight*5; //高度 this.Operator=function() { var data=this.Value.Data; if (!data) return false; this.Width=157; if (this.LanguageID==JSCHART_LANGUAGE_ID.LANGUAGE_ENGLISH_ID) this.Width=180; var titleData=this.GetFormatTitle(data); if (!titleData) return false; var outData=this.GenerateTitleHtml(titleData); if (!outData) return false; this.Text=outData.Html; this.Height=outData.LineCount*this.LineHeight; return true; /* var date=new Date(parseInt(data.Date/10000),(data.Date/100%100-1),data.Date%100); var strDate=IFrameSplitOperator.FormatDateString(data.Date); var title2=g_JSChartLocalization.GetText(WEEK_NAME[date.getDay()],this.LanguageID); var isTickPeriod=ChartData.IsTickPeriod(this.Value.ChartPaint.Data.Period); if (ChartData.IsMinutePeriod(this.Value.ChartPaint.Data.Period,true)) // 分钟周期 { title2=IFrameSplitOperator.FormatTimeString(data.Time); } else if (ChartData.IsSecondPeriod(this.Value.ChartPaint.Data.Period) || isTickPeriod) { title2=IFrameSplitOperator.FormatTimeString(data.Time,'HH:MM:SS'); } var upperSymbol=this.Symbol.toUpperCase(); var defaultfloatPrecision=GetfloatPrecision(this.Symbol);//价格小数位数 var increase=null; if (data.YClose>0) increase=(data.Close-data.YClose)/data.YClose*100; if (isTickPeriod) { var strText= ""+strDate+"  "+title2+""+ ""+g_JSChartLocalization.GetText('DivTooltip-Price',this.LanguageID)+""+ ""+data.Open.toFixed(defaultfloatPrecision)+"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-Increase',this.LanguageID)+""+ (increase==null? ""+'--'+"
" : ""+increase.toFixed(2)+'%'+"
"); this.LineCount=4; } else if (data.IsNonTrade) //非交易日就显示日期 { var strText= `${strDate}  ${title2}`; this.LineCount=2; } else { var vol=data.Vol; if (upperSymbol && MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) vol/=100; //A股统一转成手 var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_TITLE_COLOR); var strText= ""+strDate+"  "+title2+""+ ""+g_JSChartLocalization.GetText('DivTooltip-Open',this.LanguageID)+""+ ""+ (IFrameSplitOperator.IsNumber(data.Open)? data.Open.toFixed(defaultfloatPrecision):'--') +"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-High',this.LanguageID)+""+ ""+ (IFrameSplitOperator.IsNumber(data.High)? data.High.toFixed(defaultfloatPrecision):'--') +"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-Low',this.LanguageID)+""+ ""+ (IFrameSplitOperator.IsNumber(data.Low)? data.Low.toFixed(defaultfloatPrecision):'--') +"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-Close',this.LanguageID)+""+ ""+ (IFrameSplitOperator.IsNumber(data.Close)? data.Close.toFixed(defaultfloatPrecision):'--') +"
"+ //" 前收: "+IFrameSplitOperator.FormatValueString(data.YClose,2)+"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-Vol',this.LanguageID)+""+ ""+ (IFrameSplitOperator.IsNumber(vol)? IFrameSplitOperator.FormatValueString(vol,2,this.LanguageID):'--') +"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-Amount',this.LanguageID)+""+ ""+ (IFrameSplitOperator.IsNumber(data.Amount)? IFrameSplitOperator.FormatValueString(data.Amount,2,this.LanguageID):'--') +"
"+ ""+g_JSChartLocalization.GetText('DivTooltip-Increase',this.LanguageID)+""+ (increase==null? ""+'--'+"
" : ""+increase.toFixed(2)+'%'+"
"); this.LineCount=8; if(MARKET_SUFFIX_NAME.IsSHSZStockA(this.Symbol) && data.FlowCapital>0) //换手率 { var value=data.Vol/data.FlowCapital*100; strText+= ""+g_JSChartLocalization.GetText('DivTooltip-Exchange',this.LanguageID)+"" + ""+value.toFixed(2)+'%'+"
"; ++this.LineCount; } if (MARKET_SUFFIX_NAME.IsFutures(upperSymbol) && IFrameSplitOperator.IsNumber(data.Position)) { strText+= ""+g_JSChartLocalization.GetText('DivTooltip-Position',this.LanguageID)+"" + ""+data.Position+"
"; ++this.LineCount; } //叠加股票 if (this.Value.ChartPaint.Name=="Overlay-KLine") { var title=""+this.Value.ChartPaint.Title+""; strText=title+strText; ++this.LineCount; } } this.Text=strText; this.Height=this.LineCount*this.LineHeight; return true; */ } this.GenerateTitleHtml=function(data) { var lineCount=0; var strHtml="", text; if (data.Name) { text=`${data.Name}`; strHtml+=text; ++lineCount; } if (data.Title) { if (Array.isArray(data.Title)) { for(var i=0;i${item}`; strHtml+=text; ++lineCount; } } else { text=`${data.Title}`; strHtml+=text; ++lineCount; } } if (IFrameSplitOperator.IsNonEmptyArray(data.AryText)) { for(var i=0;i0) strHtml+='
'; var text=`${item.Title}${item.Text}`; strHtml+=text; ++lineCount; } } return { Html:strHtml, LineCount:lineCount }; } this.GetFormatTitle=function(data) { if (!data) return null; var upperSymbol=this.Symbol.toUpperCase(); var defaultfloatPrecision=GetfloatPrecision(this.Symbol);//价格小数位数 var date=new Date(parseInt(data.Date/10000),(data.Date/100%100-1),data.Date%100); var strDate=IFrameSplitOperator.FormatDateString(data.Date); var title=strDate,value; var isTickPeriod=ChartData.IsTickPeriod(this.Value.ChartPaint.Data.Period); if (ChartData.IsDayPeriod(this.Value.ChartPaint.Data.Period,true)) //日线 { value=g_JSChartLocalization.GetText(WEEK_NAME[date.getDay()],this.LanguageID); title=`${strDate}  ${value}`; } else if (ChartData.IsMinutePeriod(this.Value.ChartPaint.Data.Period,true)) // 分钟周期 { value=IFrameSplitOperator.FormatTimeString(data.Time); title=`${strDate}  ${value}`; } else if (ChartData.IsSecondPeriod(this.Value.ChartPaint.Data.Period) || isTickPeriod) { value=IFrameSplitOperator.FormatTimeString(data.Time,'HH:MM:SS'); title=`${strDate}  ${value}`; } else if (ChartData.IsMilliSecondPeriod(this.Value.ChartPaint.Data.Period)) { value=IFrameSplitOperator.FormatTimeString(data.Time,'HH:MM:SS.fff'); title= [ `${strDate}  ${g_JSChartLocalization.GetText(WEEK_NAME[date.getDay()],this.LanguageID)}`, value ]; } var result={ AryText:null, Title:title, Name:null }; if (isTickPeriod) { var aryText= [ { Title:g_JSChartLocalization.GetText('DivTooltip-Price',this.LanguageID), Text:IFrameSplitOperator.IsNumber(data.Open)? data.Open.toFixed(defaultfloatPrecision):'--', Color:this.GetColor(data.Open,data.YClose) }, ]; if (IFrameSplitOperator.IsNumber(data.YClose)) { var increase=(data.Close-data.YClose)/data.YClose*100; var item= { Title:g_JSChartLocalization.GetText('DivTooltip-Increase',this.LanguageID), Text:`${increase.toFixed(2)}%`, Color:this.GetColor(increase,0) } aryText.push(item); } result.AryText=aryText; } else if (data.IsNonTrade) { } else { var vol=data.Vol; if (upperSymbol && MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) vol/=100; //A股统一转成手 var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_TITLE_COLOR); var aryText= [ { Title:g_JSChartLocalization.GetText('DivTooltip-Open',this.LanguageID), Text:IFrameSplitOperator.IsNumber(data.Open)? data.Open.toFixed(defaultfloatPrecision):'--', Color:this.GetPriceColor("DivTooltip-Open",data.Open,data.YClose,data,eventUnchangeKLine), }, { Title:g_JSChartLocalization.GetText('DivTooltip-High',this.LanguageID), Text:IFrameSplitOperator.IsNumber(data.High)? data.High.toFixed(defaultfloatPrecision):'--', Color:this.GetPriceColor("DivTooltip-High",data.High,data.YClose,data,eventUnchangeKLine) }, { Title:g_JSChartLocalization.GetText('DivTooltip-Low',this.LanguageID), Text:IFrameSplitOperator.IsNumber(data.Low)? data.Low.toFixed(defaultfloatPrecision):'--', Color:this.GetPriceColor('DivTooltip-Low',data.Low,data.YClose,data,eventUnchangeKLine) }, { Title:g_JSChartLocalization.GetText('DivTooltip-Close',this.LanguageID), Text:IFrameSplitOperator.IsNumber(data.Close)? data.Close.toFixed(defaultfloatPrecision):'--', Color:this.GetPriceColor('DivTooltip-Close',data.Close,data.YClose,data,eventUnchangeKLine) }, { Title:g_JSChartLocalization.GetText('DivTooltip-Vol',this.LanguageID), Text:IFrameSplitOperator.IsNumber(vol)? IFrameSplitOperator.FormatValueString(vol,2,this.LanguageID):'--', Color:this.VolColor }, { Title:g_JSChartLocalization.GetText('DivTooltip-Amount',this.LanguageID), Text:IFrameSplitOperator.IsNumber(data.Amount)? IFrameSplitOperator.FormatValueString(data.Amount,2,this.LanguageID):'--', Color:this.AmountColor } ]; if (IFrameSplitOperator.IsNumber(data.YClose)) { var increase=(data.Close-data.YClose)/data.YClose*100; var item= { Title:g_JSChartLocalization.GetText('DivTooltip-Increase',this.LanguageID), Text:`${increase.toFixed(2)}%`, Color:this.GetColor(increase,0) } aryText.push(item); } if(MARKET_SUFFIX_NAME.IsSHSZStockA(this.Symbol) && data.FlowCapital>0) //换手率 { var value=data.Vol/data.FlowCapital*100; var item= { Title:g_JSChartLocalization.GetText('DivTooltip-Exchange',this.LanguageID), Text:`${value.toFixed(2)}%`, Color:this.TurnoverRateColor } aryText.push(item); } if (MARKET_SUFFIX_NAME.IsFutures(upperSymbol) && IFrameSplitOperator.IsNumber(data.Position)) { var item= { Title:g_JSChartLocalization.GetText('DivTooltip-Position',this.LanguageID), Text:`${data.Position}`, Color:this.PositionColor } } //叠加股票 if (this.Value.ChartPaint.Name=="Overlay-KLine") { result.Name=this.Value.ChartPaint.Title; } result.AryText=aryText; } return result; } this.GetColor=function(price,yclse) { if(price>yclse) return this.UpColor; else if (price"; if(infoList.length > 8) { var strBox="
共"+infoList.length+"条
"; html+=strBox; } this.Text=html; return true; } this.DefaultFormat=function(item) { var strDate=IFrameSplitOperator.FormatDateString(item.Date); if (IFrameSplitOperator.IsNumber(item.Time)) { var strTime=IFrameSplitOperator.FormatTimeString(item.Time); strDate+=" "+strTime; } var strText=`${strDate}   ${item.Title}`; return strText; } //大宗交易 this.BlockTradingFormat=function(item) { var showPriceInfo = item.ExtendData; var strDate=IFrameSplitOperator.FormatDateString(item.Date); var strText=""+strDate+"  成交价: "+showPriceInfo.Price.toFixed(2)+"收盘价: "+showPriceInfo.ClosePrice.toFixed(2)+ "
溢折价率: "+ showPriceInfo.Premium.toFixed(2)+"%成交量(万股): "+showPriceInfo.Vol.toFixed(2)+"
"; return strText; } //龙虎榜 this.TradeDetailFormat=function(item) { /*var detail= [ "日价格涨幅偏离值达到9.89%", "日价格涨幅偏离值达格涨幅偏离值达格涨幅偏离值达到9.89%" ] */ var detail=item.ExtendData.Detail; //格式:日期 上榜原因: detail[0].TypeExplain // detail[1].TypeExplain // 一周后涨幅: xx 四周后涨幅: xx var strDate=IFrameSplitOperator.FormatDateString(item.Date); var reasons = []; for(var i in detail) { reasons += ""+detail[i].TypeExplain+"
" // reasons += detail[i] + "
" } var strText= ""+strDate+"   上榜原因:  "+reasons+"
一周后涨幅: "+ item.ExtendData.FWeek.Week1.toFixed(2)+ "%   四周后涨幅: "+ item.ExtendData.FWeek.Week4.toFixed(2)+"%
"; return strText; } //调研 this.ResearchFormat=function(item) { var levels=item.ExtendData.Level; var recPerson=''; if(levels.length==0) { recPerson = "一般调研" } else { for(var j in levels) { if(levels[j]==0) recPerson+="证券代表   "; else if(levels[j]==1) recPerson+="董秘   "; else if(levels[j]==2) recPerson+="总经理   "; else if(levels[j]==3) recPerson+="董事长   "; } recPerson='接待:   '+recPerson; } var researchType=''; if (item.ExtendData.Type && item.ExtendData.Type!='其他') { researchType='   '+''+item.ExtendData.Type+''; if (levels.length==0) recPerson=''; } var strDate=IFrameSplitOperator.FormatDateString(item.Date); var strText=""+strDate+"   "+researchType+recPerson+""; return strText; } //业绩预测 this.PerformanceForecastFormat=function(item) { var reportDate=item.ExtendData.ReportDate; var year=parseInt(reportDate/10000); //年份 var day=reportDate%10000; //比较 这个去掉年份的日期 var reportType; if(day == 1231){ reportType = "年报" }else if(day == 331){ reportType = "一季度报" }else if(day == 630){ reportType = "半年度报" }else if(day == 930){ reportType = "三季度报" } var weekData=""; if (item.ExtendData.FWeek) { if (item.ExtendData.FWeek.Week1!=null) weekData+="一周后涨幅:"+ item.ExtendData.FWeek.Week1.toFixed(2)+"%"; if (item.ExtendData.FWeek.Week4!=null) weekData+=" 四周后涨幅:"+ item.ExtendData.FWeek.Week4.toFixed(2)+"%"; if (weekData.length>0) weekData="
  "+weekData+""; } var strDate=IFrameSplitOperator.FormatDateString(item.Date); var strText=""+strDate+"  "+year+reportType+item.Title+" "+weekData+""; return strText; } this.GetColor=function(price) { if(price>0) return this.UpColor; else if (price<0) return this.DownColor; else return this.UnchagneColor; } } //交易信息提示信息格式 function KLineTradeDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.Width=120; this.Operator=function() { var data=this.Value.Data; if (!data) return false; var item=data.Data; var title=`${item.Name}${item.Param}:`; var content; if (item.Type==1) content=`买入`; else content=`卖出`; this.Text=title+content; return true; } } //分时图异动信息格式化 function MinuteInfoDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.Width=200; this.Operator=function() { var data=this.Value.Data; if (!data) return false; var item=data.Data.Item; var strTime=IFrameSplitOperator.FormatTimeString(item.Time); var time=`${strTime} `; var content=`${item.Title}`; if (item.Content) content=`${item.Content}`; this.Text=time+content; return true; } } function IconDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.Width=200; this.Operator=function() { if (!this.Value || !this.Value.Data) return false; var data=this.Value.Data; if (!data.Item) return false; if (!data.Item.Text) return false; this.Text=data.Item.Text; return true; } } function ChartDrawSVGDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.Width=200; this.Operator=function() { if (!this.Value || !this.Value.Data) return false; var data=this.Value.Data; if (!data.Item) return false; if (!data.Item.Tooltip || !data.Item.Tooltip.Text) return false; this.Text=data.Item.Tooltip.Text; return true; } } //分时图异动信息格式化 function ChartOXDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.Width=200; this.Period=0; this.Operator=function() { var data=this.Value.Data; if (!data || !data.Data) return false; if (ChartData.IsDayPeriod(this.Period, true)) { var strStartDate=IFrameSplitOperator.FormatDateString(data.Data.Start.Date); var strEndDate=IFrameSplitOperator.FormatDateString(data.Data.End.Date); if (strStartDate==strEndDate) { this.Text=`${strStartDate}`; return true; } var content=`起始时间:${strStartDate}`; var content2=`结束时间:${strEndDate}`; this.Text=content+"
"+content2; return true; } else if (ChartData.IsMinutePeriod(this.Period, true)) { var strStartDate=IFrameSplitOperator.FormatDateString(data.Data.Start.Date); var strStartTime=IFrameSplitOperator.FormatTimeString(data.Data.Start.Time,"HH:MM"); var strEndDate=IFrameSplitOperator.FormatDateString(data.Data.End.Date); var strEndTime=IFrameSplitOperator.FormatTimeString(data.Data.End.Time,"HH:MM"); var content=`起始时间:${strStartDate} ${strStartTime}`; var content2=`结束时间:${strEndDate} ${strEndTime}`; this.Text=content+"
"+content2; return true; } return false; } } function ScatterPlotDataStringFormat() { this.newMethod=IChangeStringFormat; //派生 this.newMethod(); delete this.newMethod; this.Width=200; this.Operator=function() { var data=this.Value.Data; if (!data || !data.Data) return false; if (!IFrameSplitOperator.IsNonEmptyArray(data.Data.Tooltip)) return false; this.Text=""; for(var i=0;i${item}`; this.Text+=content+"
"; } return true; } } function DivTooltipDataForamt() { this.DataMap=new Map( [ ["KLineTradeDataStringFormat", { Create:function() { return new KLineTradeDataStringFormat(); } }], ["MinuteInfoDataStringFormat", { Create:function() { return new MinuteInfoDataStringFormat(); } }], ["HistoryDataStringFormat", { Create:function() { return new HistoryDataStringFormat(); } }], ["KLineInfoDataStringFormat", { Create:function() { return new KLineInfoDataStringFormat(); } }], ["IconDataStringFormat", { Create:function() { return new IconDataStringFormat(); } }], ["ChartOXDataStringFormat", { Create:function() { return new ChartOXDataStringFormat(); } }], ["ScatterPlotDataStringFormat", { Create:function() { return new ScatterPlotDataStringFormat(); }}], ["ChartDrawSVGDataStringFormat", { Create:function() { return new ChartDrawSVGDataStringFormat(); }}], ["CorssCursor_XStringFormat", { Create:function() { return new HQDateStringFormat(); } }], ["CorssCursor_YStringFormat", { Create:function() { return new HQPriceStringFormat(); } }], ["CorssCursor_Minute_XStringFormat", { Create:function() { return new HQMinuteTimeStringFormat(); }} ] ] ); this.Create=function(name) { if (!this.DataMap.has(name)) return null; var item=this.DataMap.get(name); return item.Create(); } } var g_DivTooltipDataForamt=new DivTooltipDataForamt(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 标题 // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function IChartTitlePainting() { this.Frame; this.Data=new Array(); this.Canvas; //画布 this.IsDynamic=false; //是否是动态标题 this.Position=0; //标题显示位置 0 框架里的标题 1 框架上面 this.CursorIndex; //数据索引 this.LastPoint; //鼠标位置 this.Font=g_JSChartResource.TitleFont; this.Title; //固定标题(可以为空) this.TitleColor=g_JSChartResource.DefaultTextColor; this.ClassName='IChartTitlePainting'; this.DrawStatus; this.GetEventCallback; this.GlobalOption; this.ReloadResource=function() { this.Font=g_JSChartResource.TitleFont; this.TitleColor=g_JSChartResource.DefaultTextColor; } } //var PERIOD_NAME=["日线","周线","月线","年线","1分","5分","15分","30分","60分","季线","分笔", "2小时","4小时","双周","",""]; var RIGHT_NAME=['不复权','前复权','后复权']; function DynamicKLineTitlePainting() { this.newMethod=IChartTitlePainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='DynamicKLineTitlePainting'; this.IsDynamic=true; this.IsShow=true; //是否显示 this.Period; //周期 this.UpColor=g_JSChartResource.UpTextColor; this.DownColor=g_JSChartResource.DownTextColor; this.UnchagneColor=g_JSChartResource.UnchagneTextColor; this.VolColor=g_JSChartResource.Title.VolColor; this.AmountColor=g_JSChartResource.Title.AmountColor; this.DateTimeColor=g_JSChartResource.Title.DateTimeColor; this.NameColor = g_JSChartResource.Title.NameColor; this.SettingColor=g_JSChartResource.Title.SettingColor; //周期 复权 this.TurnoverRateColor=g_JSChartResource.Title.TurnoverRateColor; //换手率 this.PositionColor=g_JSChartResource.Title.PositionColor; //持仓 this.Symbol; this.Name; this.SpaceWidth=2*GetDevicePixelRatio(); //获取设备的分辨率; this.OverlayChartPaint; //叠加画法 this.IsShowName=true; //是否显示股票名称 this.IsShowSettingInfo=true; //是否显示设置信息(周期 复权) this.IsShowDateTime=true; //是否显示日期 this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; this.OnDrawEvent; this.OnMouseMoveEvent; this.HQChart; this.ReloadResource=function() { this.Font=g_JSChartResource.TitleFont; this.TitleColor=g_JSChartResource.DefaultTextColor; this.UpColor=g_JSChartResource.UpTextColor; this.DownColor=g_JSChartResource.DownTextColor; this.UnchagneColor=g_JSChartResource.UnchagneTextColor; this.VolColor=g_JSChartResource.Title.VolColor; this.AmountColor=g_JSChartResource.Title.AmountColor; this.DateTimeColor=g_JSChartResource.Title.DateTimeColor; this.NameColor = g_JSChartResource.Title.NameColor; this.SettingColor=g_JSChartResource.Title.SettingColor; this.TurnoverRateColor=g_JSChartResource.Title.TurnoverRateColor; //换手率 this.PositionColor=g_JSChartResource.Title.PositionColor; //持仓 } this.GetCurrentKLineData=function() //获取当天鼠标位置所在的K线数据 { if (this.CursorIndex==null || !this.Data) return null; if (this.Data.length<=0) return null; var index=this.CursorIndex; index=parseInt(index.toFixed(0)); var dataIndex=this.Data.DataOffset+index; if (dataIndex>=this.Data.Data.length) dataIndex=this.Data.Data.length-1; if (dataIndex<0) return null; var item=this.Data.Data[dataIndex]; return item; } this.GetFormatTitle=function(data) { if (!data || !data.Data) return; var defaultfloatPrecision=GetfloatPrecision(this.Symbol);//价格小数位数 var upperSymbol=this.Symbol.toUpperCase(); var item=data.Data; var aryText=[]; var result={ AryText:aryText }; if (this.IsShowName) aryText.push({ Text:this.Name, Color:this.NameColor }); if (this.IsShowSettingInfo) { var periodName=''; if (this.Data.Period>CUSTOM_MINUTE_PERIOD_START && this.Data.Period<=CUSTOM_MINUTE_PERIOD_END) periodName=(this.Data.Period-CUSTOM_MINUTE_PERIOD_START)+g_JSChartLocalization.GetText('自定义分钟',this.LanguageID); else if (this.Data.Period>CUSTOM_DAY_PERIOD_START && this.Data.Period<=CUSTOM_DAY_PERIOD_END) periodName=(this.Data.Period-CUSTOM_DAY_PERIOD_START)+g_JSChartLocalization.GetText('自定义日线',this.LanguageID); else if (this.Data.Period>CUSTOM_SECOND_PERIOD_START && this.Data.Period<=CUSTOM_SECOND_PERIOD_END) periodName=(this.Data.Period-CUSTOM_SECOND_PERIOD_START)+g_JSChartLocalization.GetText('自定义秒',this.LanguageID); else if (this.Data.Period>CUSTOM_MILLISECOND_PERIOD_START&& this.Data.Period<=CUSTOM_MILLISECOND_PERIOD_END) periodName=(this.Data.Period-CUSTOM_MILLISECOND_PERIOD_START)+g_JSChartLocalization.GetText('自定义毫秒',this.LanguageID); else periodName=g_JSChartLocalization.GetText(ChartData.GetPeriodName(this.Data.Period),this.LanguageID); var rightName=g_JSChartLocalization.GetText(RIGHT_NAME[this.Data.Right],this.LanguageID); var text="("+periodName+" "+rightName+")"; if (!MARKET_SUFFIX_NAME.IsEnableRight(this.Data.Period, this.Symbol, this.HQChart.RightFormula)) text="("+periodName+")"; aryText.push({ Text:text, Color:this.SettingColor }); } var text=this.GetKLineCalculateTitle(); if (text) aryText.push({ Text:text, Color:this.NameColor }); if (this.IsShowDateTime) //是否显示日期 { var text=IFrameSplitOperator.FormatDateString(item.Date); aryText.push({ Text:text, Color:this.DateTimeColor }); } var isTickPeriod=ChartData.IsTickPeriod(this.Period); if (ChartData.IsMinutePeriod(this.Period,true) && IFrameSplitOperator.IsNumber(item.Time)) { var text=IFrameSplitOperator.FormatTimeString(item.Time); aryText.push({ Text:text, Color:this.DateTimeColor }); } else if (ChartData.IsSecondPeriod(this.Period) && IFrameSplitOperator.IsNumber(item.Time)) { var text=IFrameSplitOperator.FormatTimeString(item.Time, "HH:MM:SS"); aryText.push({ Text:text, Color:this.DateTimeColor }); } else if (ChartData.IsMilliSecondPeriod(this.Period) && IFrameSplitOperator.IsNumber(item.Time)) { var text=IFrameSplitOperator.FormatTimeString(item.Time, "HH:MM:SS.fff"); aryText.push({ Text:text, Color:this.DateTimeColor }); } else if (isTickPeriod) { var text=IFrameSplitOperator.FormatTimeString(item.Time, "HH:MM:SS"); aryText.push({ Text:text, Color:this.DateTimeColor }); } if (isTickPeriod) { var color=this.GetColor(item.Open,item.YClose); var text=g_JSChartLocalization.GetText('KTitle-Price',this.LanguageID)+item.Open.toFixed(defaultfloatPrecision); aryText.push({ Text:text, Color:color}); if (IFrameSplitOperator.IsNumber(item.YClose) && item.YClose!=0) { var value=(item.Close-item.YClose)/item.YClose*100; var color = this.GetColor(value, 0); var text = g_JSChartLocalization.GetText('KTitle-Increase',this.LanguageID) + value.toFixed(2)+'%'; aryText.push({ Text:text, Color:color}); } return result; } if (item.IsNonTrade) return result; //非交易日 没数据 不显示 var eventUnchangeKLine=null; //定制平盘K线颜色事件 if (this.GetEventCallback) eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_TITLE_COLOR); if (IFrameSplitOperator.IsNumber(item.Open)) { var color=this.GetColor(item.Open,item.YClose); var text=g_JSChartLocalization.GetText('KTitle-Open',this.LanguageID)+item.Open.toFixed(defaultfloatPrecision); if (item.Open==item.YClose && eventUnchangeKLine) { var sendData={ Item:item, TitleName:"KTitle-Open", DefaultColor:color, TitleColor:null }; if (this.OnUnchangeTitleColor(eventUnchangeKLine, sendData)) color=sendData.TitleColor; } aryText.push({ Text:text, Color:color}); } if (IFrameSplitOperator.IsNumber(item.High)) { var color=this.GetColor(item.High,item.YClose); var text=g_JSChartLocalization.GetText('KTitle-High',this.LanguageID)+item.High.toFixed(defaultfloatPrecision); if (item.High==item.YClose && eventUnchangeKLine) { var sendData={ Item:item, TitleName:"KTitle-High", DefaultColor:color, TitleColor:null }; if (this.OnUnchangeTitleColor(eventUnchangeKLine, sendData)) color=sendData.TitleColor; } aryText.push({ Text:text, Color:color}); } if (IFrameSplitOperator.IsNumber(item.Low)) { var color=this.GetColor(item.Low,item.YClose); var text=g_JSChartLocalization.GetText('KTitle-Low',this.LanguageID)+item.Low.toFixed(defaultfloatPrecision); if (item.Low==item.YClose && eventUnchangeKLine) { var sendData={ Item:item, TitleName:"KTitle-Low", DefaultColor:color, TitleColor:null }; if (this.OnUnchangeTitleColor(eventUnchangeKLine, sendData)) color=sendData.TitleColor; } aryText.push({ Text:text, Color:color}); } if (IFrameSplitOperator.IsNumber(item.Close)) { var color=this.GetColor(item.Close,item.YClose); var text=g_JSChartLocalization.GetText('KTitle-Close',this.LanguageID)+item.Close.toFixed(defaultfloatPrecision); if (item.Close==item.YClose && eventUnchangeKLine) { var sendData={ Item:item, TitleName:"KTitle-Close", DefaultColor:color, TitleColor:null }; if (this.OnUnchangeTitleColor(eventUnchangeKLine, sendData)) color=sendData.TitleColor; } aryText.push({ Text:text, Color:color}); } //涨幅 if (item.YFClose>0 && MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)) { var value=(item.Close-item.YFClose)/item.YFClose*100; var color = this.GetColor(value, 0); var text = g_JSChartLocalization.GetText('KTitle-Increase',this.LanguageID) + value.toFixed(2)+'%'; aryText.push({ Text:text, Color:color}); } else if (item.YClose>0) { var value=(item.Close-item.YClose)/item.YClose*100; var color = this.GetColor(value, 0); var text = g_JSChartLocalization.GetText('KTitle-Increase',this.LanguageID) + value.toFixed(2)+'%'; aryText.push({ Text:text, Color:color}); } if (IFrameSplitOperator.IsNumber(item.Vol)) //成交量 { var vol=item.Vol; if (upperSymbol && MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) vol/=100; //A股原始单位股, 转成股 var text=g_JSChartLocalization.GetText('KTitle-Vol',this.LanguageID)+IFrameSplitOperator.FromatIntegerString(vol,2,this.LanguageID); aryText.push({ Text:text, Color:this.VolColor}); } if (IFrameSplitOperator.IsNumber(item.Amount)) //成交金额 { var text=g_JSChartLocalization.GetText('KTitle-Amount',this.LanguageID)+IFrameSplitOperator.FormatValueString(item.Amount,2,this.LanguageID); aryText.push({ Text:text, Color:this.AmountColor}); } if (MARKET_SUFFIX_NAME.IsSHSZStockA(this.Symbol) && item.FlowCapital>0) //A股有换手率 { var value=item.Vol/item.FlowCapital*100; //成交量/流通A股*100 var text=g_JSChartLocalization.GetText('KTitle-Exchange',this.LanguageID)+IFrameSplitOperator.FormatValueString(value,2,this.LanguageID)+'%'; aryText.push({ Text:text, Color:this.TurnoverRateColor}); } if (MARKET_SUFFIX_NAME.IsFutures(upperSymbol) && IFrameSplitOperator.IsNumber(item.Position)) //持仓量 { var text=g_JSChartLocalization.GetText('KTitle-Position',this.LanguageID)+item.Position; aryText.push({ Text:text, Color:this.PositionColor}); } //叠加股票的名字 if (IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) { for(var i=0;i=this.Data.Data.length) dataIndex=this.Data.Data.length-1; if (dataIndex<0) { this.OnDrawEventCallback(null); return; } if (this.IsShowLastData()) //鼠标不在图形上 显示最后一条数据 { dataIndex=this.Data.Data.length-1; } var item=this.Data.Data[dataIndex]; this.OnDrawEventCallback(item); this.Canvas.save(); this.DrawItem(item); this.Canvas.restore(); } this.OnDrawEventCallback=function(drawData) { var bDrawEvent=(this.OnDrawEvent && this.OnDrawEvent.Callback); var bMouseMoveEvent= (this.OnMouseMoveEvent && this.OnMouseMoveEvent.Callback); if (!bDrawEvent && !bMouseMoveEvent) return; var data={ Draw: drawData, Name:this.ClassName}; if (this.Data && this.Data.Data) { var index=Math.abs(this.CursorIndex); index=parseInt(index.toFixed(0)); var dataIndex=this.Data.DataOffset+index; var dataCount=this.Data.Data.length; data.DataIndex=dataIndex; data.DataCount=dataCount; } //叠加股票 if (IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) { data.OverlayStock=[]; for(var i=0; iyclse) return this.UpColor; else if (price right) return false; if (this.IsShow) this.Canvas.fillText(title, position.Left, position.Bottom, textWidth); position.Left += textWidth + this.SpaceWidth; return true; } //计算K线指标标题信息 this.GetKLineCalculateTitle=function() { if (!this.HQChart) return null; var klineCalulate=this.HQChart.GetKLineCalulate(); if (!klineCalulate || !klineCalulate.GetTitle) return null; return klineCalulate.GetTitle(); } this.IsShowLastData=function() { var isShow=false; if (this.DrawStatus && this.DrawStatus.IsTitleShowLatestData) { var status=this.DrawStatus; if (!IFrameSplitOperator.IsNumber(status.FrameID) || status.FrameID<0) isShow=true; else if (status.CorssCursorTouchEnd && status.IsOnTouch==false) isShow=true; } return isShow; } } function DynamicMinuteTitlePainting() { this.newMethod=DynamicKLineTitlePainting; //派生 this.newMethod(); delete this.newMethod; this.ClassName='DynamicMinuteTitlePainting'; this.SpaceWidth=1*GetDevicePixelRatio(); this.YClose; this.IsShowDate=false; //标题是否显示日期 this.IsShowTime=true; //标题是否显示时间 this.IsShowName=true; //标题是否显示股票名字 this.IsShowAveragePrice=true; //是否显示均线价格 this.OverlayChartPaint; //叠加画法 this.LanguageID=JSCHART_LANGUAGE_ID.LANGUAGE_CHINESE_ID; this.LastShowData; //保存最后显示的数据 给tooltip用 this.OnDrawEvent; this.PointInfo=null; this.IsAlwaysShowLastData=false; //始终显示最后一个数据 this.ShowLastDataFormat=0; //0=默认 1=更新时间替换时间 this.MultiDayBeforeOpenData; //多日分时图 盘前数据 this.MultiDayAfterCloseData; //多日分时图 收盘数据 this.TitleBaseLine=1; //0=top 1=middle 2=bottom this.TimeFormat; //显示时间格式 "HH:MM:SS", "hh:MM", "HH:MM:SS.fff" this.CallAuctionShowTitle=new Set( [ "MTitle-AC-Price", "MTitle-AC-Vol", "MTitle-AC-NotMatchVol", "MTitle-AC-Increase", "MTitle-AC-AvPrice" ]); this.GetCurrentKLineData=function() //获取当天鼠标位置所在的K线数据 { if (this.LastShowData) return this.LastShowData; if (this.CursorIndex==null || !this.Data) return null; if (this.Data.length<=0) return null; var index=Math.abs(this.CursorIndex); index=parseInt(index.toFixed(0)); var dataIndex=this.Data.DataOffset+index; if (dataIndex>=this.Data.Data.length) dataIndex=this.Data.Data.length-1; if (dataIndex<0) return null; var item=this.Data.Data[dataIndex]; return item; } this.GetCurrentAuctionData=function() //获取当前鼠标所在位置的盘前盘后数据 { var isHScreen=this.Frame.IsHScreen===true; //空数据 返回坐标信息 var emptyData={ ClientPos:this.PointInfo.ClientPos, X:this.PointInfo.Point.X, Y:this.PointInfo.Point.Y }; if (this.PointInfo.ClientPos==2) { if (!this.BeforeOpenData) return emptyData; if (!this.CallAcutionXOperator) return emptyData; this.CallAcutionXOperator.Value=isHScreen?this.PointInfo.Point.Y:this.PointInfo.Point.X; this.CallAcutionXOperator.Point={X:this.PointInfo.Point.X, Y:this.PointInfo.Point.Y}; this.CallAcutionXOperator.ClientPos=this.PointInfo.ClientPos; if (!this.CallAcutionXOperator.Operator()) return emptyData; var callbackData={Explain:"BeforeOpen", Data:null, DataIndex:null, DataTotalCount:this.BeforeOpenData.TotalCount }; callbackData.DataIndex=this.CallAcutionXOperator.DataIndex; callbackData.Data=this.CallAcutionXOperator.Item; callbackData.Ver=this.BeforeOpenData.Ver; return callbackData; } else if (this.PointInfo.ClientPos==3) { if (!this.AfterCloseData) return emptyData; if (!this.CallAcutionXOperator) return emptyData; this.CallAcutionXOperator.Value=isHScreen?this.PointInfo.Point.Y:this.PointInfo.Point.X; this.CallAcutionXOperator.Point={X:this.PointInfo.Point.X, Y:this.PointInfo.Point.Y}; this.CallAcutionXOperator.ClientPos=this.PointInfo.ClientPos; if (!this.CallAcutionXOperator.Operator()) return emptyData; var callbackData={Explain:"AfterClose", Data:null, DataIndex:null, DataTotalCount:this.AfterCloseData.TotalCount }; callbackData.DataIndex=this.CallAcutionXOperator.DataIndex; callbackData.Data=this.CallAcutionXOperator.Item; callbackData.Ver=this.AfterCloseData.Ver; return callbackData; } else if (this.PointInfo.ClientPos>=200 && this.PointInfo.ClientPos<=299) { if (!this.MultiDayBeforeOpenData || !IFrameSplitOperator.IsNonEmptyArray(this.MultiDayBeforeOpenData) ) return emptyData; var x=this.Frame.IsHScreen==true?this.PointInfo.Point.Y:this.PointInfo.Point.X; this.CallAcutionXOperator.Value=x; this.CallAcutionXOperator.Point={X:this.PointInfo.Point.X, Y:this.PointInfo.Point.Y}; this.CallAcutionXOperator.ClientPos=this.PointInfo.ClientPos; if (!this.CallAcutionXOperator.Operator()) return emptyData; var dayItem=this.MultiDayBeforeOpenData[this.CallAcutionXOperator.DayIndex]; var callbackData={Explain:"MultiDayBeforeOpen", Data:null, DataIndex:null }; callbackData.DataIndex=this.CallAcutionXOperator.DataIndex; callbackData.DayIndex=this.CallAcutionXOperator.DayIndex; callbackData.Data=this.CallAcutionXOperator.Item; callbackData.Ver=dayItem.Ver; return callbackData; } else if (this.PointInfo.ClientPos>=300 && this.PointInfo.ClientPos<=399) { if (!this.MultiDayAfterCloseData || !IFrameSplitOperator.IsNonEmptyArray(this.MultiDayAfterCloseData) ) return emptyData; var x=this.Frame.IsHScreen==true?this.PointInfo.Point.Y:this.PointInfo.Point.X; this.CallAcutionXOperator.Value=x; this.CallAcutionXOperator.Point={X:this.PointInfo.Point.X, Y:this.PointInfo.Point.Y}; this.CallAcutionXOperator.ClientPos=this.PointInfo.ClientPos; if (!this.CallAcutionXOperator.Operator()) return emptyData; var dayItem=this.MultiDayAfterCloseData[this.CallAcutionXOperator.DayIndex]; var callbackData={Explain:"MultiDayAfterClose", Data:null, DataIndex:null }; callbackData.DataIndex=this.CallAcutionXOperator.DataIndex; callbackData.DayIndex=this.CallAcutionXOperator.DayIndex; callbackData.Data=this.CallAcutionXOperator.Item; callbackData.Ver=dayItem.Ver; return callbackData; } return emptyData; } this.GetLatestKLineData=function(bCallAuction) //获取最新一个K线数据 bCallAuction=是否包含集合竞价数据 { var beforeItem=null; var beforeDataVer=1; var beforeExplain; if (IFrameSplitOperator.IsNonEmptyArray(this.MultiDayBeforeOpenData)) { var item=this.MultiDayBeforeOpenData[this.MultiDayBeforeOpenData.length-1]; if (item && IFrameSplitOperator.IsNonEmptyArray(item.Data)) { beforeDataVer=item.Ver; beforeItem=item.Data[item.Data.length-1]; beforeExplain="MultiDayBeforeOpen"; } } else if (this.BeforeOpenData && IFrameSplitOperator.IsNonEmptyArray(this.BeforeOpenData.Data)) { beforeItem=this.BeforeOpenData.Data[this.BeforeOpenData.Data.length-1]; beforeDataVer=this.BeforeOpenData.Ver; beforeExplain="BeforeOpen"; } var afterItem=null; var afterDataVer=1; var afterExplain if (IFrameSplitOperator.IsNonEmptyArray(this.MultiDayAfterCloseData)) { var item=this.MultiDayAfterCloseData[this.MultiDayAfterCloseData.length-1]; if (item && IFrameSplitOperator.IsNonEmptyArray(item.Data)) { afterDataVer=item.Ver; afterItem=item.Data[item.Data.length-1]; afterExplain="MultiDayAfterClose"; if (item.Data.length==item.TotalCount) afterItem=null; //收盘以后,显示最后的1分钟价格就可以 } } else if (this.AfterOpenData && IFrameSplitOperator.IsNonEmptyArray(this.AfterOpenData.Data)) { afterItem=this.AfterOpenData.Data[this.AfterOpenData.Data.length-1]; afterDataVer=this.AfterOpenData.Ver; afterExplain="AfterClose" } var dataItem=null; if (this.Data && IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { var count=this.Data.Data.length; dataItem=this.Data.Data[count-1]; } if (!beforeItem && !afterItem && !dataItem) return null; if (!bCallAuction) return { Type:0, Data:dataItem }; if (!dataItem) return { Type:1 , Data:beforeItem ,Ver: beforeDataVer, Explain:beforeExplain }; if (beforeItem && dataItem) //盘前数据 { if (beforeItem.Date>dataItem.Date || (beforeItem.Date==dataItem.Date && beforeItem.Time>dataItem.Time && beforeDataVer==1.0) || (beforeItem.Date==dataItem.Date && parseInt(beforeItem.Time>dataItem.Time) && beforeDataVer==2.0)) return { Type:2, Data:beforeItem, Ver: beforeDataVer, Explain:beforeExplain}; } if (afterItem && dataItem) //盘后数据 { if (afterItem.Date>=dataItem.Date) return { Type:1, Data:afterItem, Ver:afterDataVer, Explain:afterExplain }; } return { Type:0 ,Data:dataItem }; } this.GetFormatTitle=function(data) //{ Data:, IsLastOne: } { if (!data || !data.Data) return; var upperSymbol=this.Symbol.toUpperCase(); var defaultfloatPrecision=GetfloatPrecision(this.Symbol); //价格小数位数 var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //国内期货, 纽约期货交易所 var item=data.Data; var isLastOne=data.IsLastOne; var aryText=[]; //{Color:, Text: } if(this.IsShowName) aryText.push({Text:this.Name, Color:this.NameColor}); if (this.IsShowDate || this.IsShowTime) { var bShowUpdateTime=false; //是否显示了更新时间 if (isLastOne && this.ShowLastDataFormat==1) { if (this.Data && this.Data.UpdateTime && IFrameSplitOperator.IsNumber(this.Data.UpdateTime.Date) && IFrameSplitOperator.IsNumber(this.Data.UpdateTime.Time)) { var text=IFrameSplitOperator.FormatTimeString(this.Data.UpdateTime.Time, "HH:MM:SS"); aryText.push({Text:text, Color:this.DateTimeColor}); bShowUpdateTime=true; } } if (!bShowUpdateTime) { if (this.TimeFormat) //指定时间格式 { var strDate=null, strTime=null, text=null; if (this.IsShowDate) strDate=IFrameSplitOperator.FormatDateString("YYYY-MM-DD", item.Date); if (this.IsShowTime) strTime=IFrameSplitOperator.FormatTimeString(item.Time,this.TimeFormat); if (strDate && strTime) text=`${strDate} ${strTime}`; else if (strDate) text=strDate; else if (strTime) text=strTime; if (text) aryText.push({Text:text, Color:this.DateTimeColor}); } else { var text=IFrameSplitOperator.FormatDateTimeString(item.DateTime,this.IsShowDate, this.IsShowTime); aryText.push({Text:text, Color:this.DateTimeColor}); } } } var close=item.Close; var increase=item.Increase; var vol=item.Vol; var amount=item.Amount; var yClose=item.YClose; if (!IFrameSplitOperator.IsNumber(yClose)) yClose=this.YClose; if (isFutures && IFrameSplitOperator.IsNumber(item.YClearing)) yClose=item.YClearing; //期货使用昨结算 if (IFrameSplitOperator.IsNumber(close)) { var color=this.GetColor(close,yClose); var text=g_JSChartLocalization.GetText('MTitle-Close',this.LanguageID)+close.toFixed(defaultfloatPrecision); aryText.push({Text:text, Color:color}); } if (IFrameSplitOperator.IsNumber(increase)) { var color=this.GetColor(increase,0); var text=g_JSChartLocalization.GetText('MTitle-Increase',this.LanguageID)+increase.toFixed(2)+'%'; aryText.push({Text:text, Color:color}); } var isShowAvPrice=true; var upperSymbol=this.Symbol.toUpperCase(); if (MARKET_SUFFIX_NAME.IsET(upperSymbol) && !MARKET_SUFFIX_NAME.IsETShowAvPrice(upperSymbol)) isShowAvPrice=false; else if (MARKET_SUFFIX_NAME.IsShowAvPrice && !MARKET_SUFFIX_NAME.IsShowAvPrice(upperSymbol)) isShowAvPrice=false; if (IFrameSplitOperator.IsNumber(item.AvPrice) && isShowAvPrice && this.IsShowAveragePrice) { var color=this.GetColor(item.AvPrice,yClose); var text=g_JSChartLocalization.GetText('MTitle-AvPrice',this.LanguageID)+item.AvPrice.toFixed(defaultfloatPrecision); aryText.push({Text:text, Color:color}); } if (IFrameSplitOperator.IsNumber(vol)) { var text=g_JSChartLocalization.GetText('MTitle-Vol',this.LanguageID)+IFrameSplitOperator.FromatIntegerString(vol,2,this.LanguageID); aryText.push({Text:text, Color:this.VolColor}); } if (IFrameSplitOperator.IsNumber(amount)) { var text=g_JSChartLocalization.GetText('MTitle-Amount',this.LanguageID)+IFrameSplitOperator.FormatValueString(amount,2,this.LanguageID); aryText.push({Text:text, Color:this.AmountColor}); } if (IFrameSplitOperator.IsNumber(item.Position)) { var text=g_JSChartLocalization.GetText('MTitle-Position',this.LanguageID)+IFrameSplitOperator.FromatIntegerString(item.Position,2,this.LanguageID); aryText.push({Text:text, Color:this.VolColor}); } if (isLastOne && this.ShowLastDataFormat==0) //显示数据最后的更新时间 { if (this.Data && this.Data.UpdateTime && IFrameSplitOperator.IsNumber(this.Data.UpdateTime.Date) && IFrameSplitOperator.IsNumber(this.Data.UpdateTime.Time)) { var text=g_JSChartLocalization.GetText('MTitle-UpdateTime',this.LanguageID)+IFrameSplitOperator.FormatTimeString(this.Data.UpdateTime.Time, "HH:MM:SS"); aryText.push({Text:text, Color:this.DateTimeColor}); } } //叠加股票的名字 if (IFrameSplitOperator.IsNonEmptyArray(this.OverlayChartPaint)) { for(var i=0; i=200&& this.PointInfo.ClientPos<=299) || (this.PointInfo.ClientPos>=300&& this.PointInfo.ClientPos<=399) ) ) { //集合竞价区域 this.Canvas.save(); this.DrawCallAuction(); this.Canvas.restore(); return; } if (!this.Data || !this.Data.Data || this.Data.Data.length<=0) { this.DrawNone(); return; } if (this.CursorIndex==null && !(this.GlobalOption && this.GlobalOption.IsDisplayLatest)) { this.DrawNone(); return; } this.Canvas.font=this.Font; this.SpaceWidth = this.Canvas.measureText('0').width; var isShowLastData=false; if (this.DrawStatus && this.DrawStatus.IsTitleShowLatestData) { var status=this.DrawStatus; if (!IFrameSplitOperator.IsNumber(status.FrameID) || status.FrameID<0) isShowLastData=true; else if (status.CorssCursorTouchEnd && status.IsOnTouch==false) isShowLastData=true; } else if (this.GlobalOption && this.GlobalOption.IsDisplayLatest) { isShowLastData=true; } var isLastOne=false; if (isShowLastData) { var item=null; var lastItem=this.GetLatestKLineData(true); if (lastItem && lastItem.Type==0) item=lastItem.Data; isLastOne=true; } else { //var index=Math.abs(this.CursorIndex-0.5); var index=this.CursorIndex; index=parseInt(index.toFixed(0)); var dataIndex=index+this.Data.DataOffset; if (dataIndex>=this.Data.Data.length) dataIndex=this.Data.Data.length-1; var item=this.Data.Data[dataIndex]; if (dataIndex==this.Data.Data.length-1) isLastOne=true; } this.LastShowData=item; this.Canvas.save(); this.OnDrawEventCallback(item); if (this.IsAlwaysShowLastData) { this.DrawLastDataItem(); } else { this.DrawItem(item,isLastOne); } this.Canvas.restore(); } this.DrawCallAuctionItem=function(callAuctionItem, isLastOne) { if (!callAuctionItem) return; var item=callAuctionItem.Data; var dataVersion=callAuctionItem.Ver; var isHScreen=this.Frame.IsHScreen===true; var border=this.Frame.GetBorder(); var left=border.Left; var bottom=border.Top-this.Frame.ChartBorder.Top/2; //var defaultfloatPrecision=GetfloatPrecision(this.Symbol);//价格小数位数 var bDraw=true; if (isHScreen) { var left=2; var bottom=this.Frame.ChartBorder.Right/2; //上下居中显示 var xText=border.ChartWidth; var yText=border.Top; this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); } else { if (this.Frame.ChartBorder.Top<5) bDraw=false; } this.Canvas.textAlign="left"; this.Canvas.font=this.Font; if (this.TitleBaseLine==0) //上 { this.Canvas.textBaseline="top"; bottom=2*GetDevicePixelRatio(); } else if (this.TitleBaseLine==2) //下 { this.Canvas.textBaseline="bottom"; var bottom=border.Top } else //中 { this.Canvas.textBaseline="middle"; } var position = { Left: left, Bottom: bottom, IsHScreen: isHScreen }; var titleData=this.FormatCallAuctionTitle(callAuctionItem); if (bDraw && titleData && IFrameSplitOperator.IsNonEmptyArray(titleData.AryText)) { for(var i=0;ithis.TitleRect.Left && xthis.TitleRect.Top && y0) text+=','; text+=year.toString(); switch(quarter) { case 1: text+='一季报 '; break; case 2: text+='半年报 '; break; case 3: text+='三季报 '; break; case 4: text+='年报 '; break; } text+=this.FormatValue(value,format); } return text; } this.FromatMultiDataLine=function(value, dataInfo) { var text=""; if (Array.isArray(value)) { for(var i=0;i0) text+=','; text+=strValue; } } else { if (value.Type!=0 && IFrameSplitOperator.IsNumber(value.Value)) { text=this.FormatValue(value.Value,dataInfo); } } if (text.length<=0) return null; return text; } //多变量输出 this.FromatStackedBarTitle=function(aryBar, dataInfo) { if (!IFrameSplitOperator.IsNonEmptyArray(aryBar)) return null; if (!IFrameSplitOperator.IsNonEmptyArray(dataInfo.Color)) return null; var aryText=[]; for(var i=0;ibottom) return aryText; var yPrice=this.Frame.GetYData(pt.Y); var find=null; for(var i=0; i=item.Price-dataInfo.Data.PriceOffset/2 && yPrice=lockRect.Left) return; if (isShowLastData) return; } var rtText={ Left:left, Right:left }; if (this.IsMinuteFrame && this.PointInfo && ( this.PointInfo.ClientPos==2 || this.PointInfo.ClientPos==3 || (this.PointInfo.ClientPos>=200&& this.PointInfo.ClientPos<=299) || (this.PointInfo.ClientPos>=300&& this.PointInfo.ClientPos<=399) )) { var result={ PreventDefault:false } this.DrawMainCallAuction({ Left:left, Right:right, Bottom:bottom }, rtText, result); if (result.PreventDefault===false) this.DrawMainIndexTitle({ Left:left, Right:right, Bottom:bottom }, isShowLastData, rtText); } else { this.DrawMainIndexTitle({ Left:left, Right:right, Bottom:bottom }, isShowLastData, rtText); } left=rtText.Left; if (this.Explain) //说明信息 { this.Canvas.fillStyle=this.TitleColor; var text="说明:"+this.Explain; var textWidth=this.Canvas.measureText(text).width+2; if (left+textWidth=item.Data.Data.length) dataIndex=item.Data.Data.length-1; if (dataIndex<0) return null; } if (item.DataType=="ChartMultiLine") //多线段数据 { aryText=this.ForamtMultiLineTitle(dataIndex, item); if (!aryText) return null; return { Text:null, ArrayText:aryText }; } else if (item.DataType=="ChartMultiPoint") { aryText=this.ForamtMultiPointTitle(dataIndex, item); if (!aryText) return null; return { Text:null, ArrayText:aryText }; } value=item.Data.Data[dataIndex]; if (value==null && item.ChartClassName=="ChartStepLine") //当前值无效,上一个值延续 { preVaildItem=this.GetPreVaildItem(item.Data.Data, dataIndex); if (!preVaildItem) return null; preText=this.FormatValue(preVaildItem.Item,item); if (item.Name) { var dyValue=this.GetDynamicOutValue(item.Name, preText); if (dyValue) preText=dyValue; } valueText=`--(${preText})`; return { Text:valueText, ArrayText:aryText }; } if (value==null) return null; if (item.DataType=="HistoryData-Vol") { value=value.Vol; valueText=this.FormatValue(value,item); } else if (item.DataType=="MultiReport") { valueText=this.FormatMultiReport(value,item); } else if (item.DataType=="MULTI_POINT_LINE") { valueText=this.FromatMultiDataLine(value, item); if (!valueText) return null; } else if (item.DataType=="ChartStackedBar") { aryText=this.FromatStackedBarTitle(value, item); if (!aryText) return null; return { Text:null, ArrayText:aryText }; } else if (g_ScriptIndexChartFactory.Has(item.DataType)) //外部挂接 { var find=g_ScriptIndexChartFactory.Get(item.DataType); if (find && find.FormatTitleCallback) return find.FormatTitleCallback(value, item, dataIndex); } else { if (this.GetEventCallback) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_INDEX_OUT_TEXT); if (event) { var data= { Item:item, Index:titleIndex, Data:this.Data, FrameID:this.Frame.Identify, DataIndex:dataIndex, Value:value, Out:null }; event.Callback(event,data,this); if (data.Out) return data.Out; } } if (item.DataType=="ChartBand") //默认不输出 return null; var arrowSuper=null; //独立颜色 if (this.IsShowUpDownArrow) { var preValue=null; if (dataIndex-1>=0) preValue=item.Data.Data[dataIndex-1]; if (IFrameSplitOperator.IsNumber(preValue)) { if (preValue>value) arrowSuper={ Text:'↓', TextColor:this.UpDownArrowConfig.DownColor }; else if (preValueright) break; if (titleItem.BG) //背景 { var textHeight=this.Canvas.measureText("擎").width+2; var rtBG={ Left:left, Top:bottom-textHeight/2, Width:textWidth, Height:textHeight }; this.Canvas.fillStyle=titleItem.BG; this.Canvas.fillRect(rtBG.Left,rtBG.Top-1, rtBG.Width, rtBG.Height); this.Canvas.fillStyle=titleItem.Color; this.Canvas.fillText(text,rtBG.Left+1,bottom,indexTextWidth); left+=indexTextWidth; if (IFrameSplitOperator.IsNonEmptyArray(titleItem.TextEx)) { for(var n=0; nright) break; this.Canvas.fillText(text,left,bottom,textWidth); left+=textWidth; } } rtText.Left=left; } //集合竞价 this.DrawMainCallAuction=function(positionInfo, rtText, result) { if (!this.IsShowMainIndexTitle) return; if (!this.MainTitlePaint) return; var auctionData=this.MainTitlePaint.GetCurrentAuctionData(); //集合竞价分时数据 if (!auctionData || !auctionData.Data) return; if (!this.GetEventCallback) return; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_CALL_AUCTION_INDEX_TITLE); if (!event) return; var data={ AuctionData:auctionData, Data:this.Data, FrameID:this.Frame.Identify, Out:null, PreventDefault:false }; event.Callback(event,data,this); result.PreventDefault=data.PreventDefault; if (!IFrameSplitOperator.IsNonEmptyArray(data.Out)) return; var left=positionInfo.Left; var right=positionInfo.Right; var bottom=positionInfo.Bottom; var pixelRatio=GetDevicePixelRatio(); var aryText=data.Out; //[{Text:, Color, Space:间距 }] for(var i=0; iright) break; if (item.BGColor) //背景 { var textHeight=this.Canvas.measureText("擎").width+2; var rtBG={ Left:left, Top:bottom-textHeight/2, Width:textWidth, Height:textHeight }; this.Canvas.fillStyle=item.BGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top-1, rtBG.Width, rtBG.Height); left+=1; } this.Canvas.fillStyle=item.Color; this.Canvas.fillText(item.Text,left,bottom,textWidth); left+=textWidth; if (IFrameSplitOperator.IsPlusNumber(item.Space)) left+=item.Space*pixelRatio; } rtText.Left=left; } this.GetCallAuctionTitleItem=function(item, titleIndex, auctionData) { if (item.IsShow===false) return null; if (item.IsVisible===false) return null; if (!item || !item.Data || !item.Data.Data) return null; if (g_ScriptIndexChartFactory.Has(item.DataType)) //外部挂接 { var find=g_ScriptIndexChartFactory.Get(item.DataType); if (find && find.FormatTitleCallback) return find.FormatTitleCallback(value, item, dataIndex); } } //获取上一个有效数据 this.GetPreVaildItem=function(data, start) { for(var i=start; i>=0;--i) { var item=data[i]; if (item) return { Item:item, Index:i }; } return null; } this.DrawSelectedLine=function(left, bottom, textWidth) { this.Canvas.save(); var fontHeight=this.GetFontHeight(); this.Canvas.strokeStyle=this.SelectedColor; var lineWidth=4; var lineBottom=ToFixedPoint2(lineWidth, (bottom+fontHeight/2)); this.Canvas.lineWidth=lineWidth; this.Canvas.beginPath(); this.Canvas.moveTo(left,lineBottom); this.Canvas.lineTo(left+textWidth,lineBottom); this.Canvas.stroke(); this.Canvas.restore(); } this.DrawOverlayIndexSingleLine=function(moveonPoint, mouseStatus) //叠加指标1个指标一行 { var pixelRatio=GetDevicePixelRatio(); var border=this.Frame.GetBorder(); if (this.Frame.IsHScreen===true) { var left=1; var top=2*pixelRatio; var right=this.Frame.ChartBorder.GetHeight(); var bottom=this.Frame.ChartBorder.GetWidthEx(); } else { var top=border.TopTitle+2*pixelRatio; if (!this.IsShowMainIndexTitle) top=this.Frame.ChartBorder.GetTop()+2*pixelRatio; var left=this.Frame.ChartBorder.GetLeft()+this.MerginLeft; var right=border.Right; var bottom=border.Bottom; } var lineSpace=this.OverlayIndexType.LineSpace*pixelRatio; var x=left, y=top; var fontHeight=GetFontHeight(this.Canvas,this.Font,"擎"); y=top+fontHeight/2; for(item of this.OverlayIndex) { var overlayItem=item[1]; var overlayID=item[0]; var toolbarInfo={ Width:0, YCenter:y, ID:overlayID }; this.DrawOverlayToolbar(overlayItem,toolbarInfo,moveonPoint, mouseStatus); if (!overlayItem.IsShowIndexTitle) continue; if (!overlayItem.Frame.IsShowIndexTitle) continue; x=left+toolbarInfo.Width; this.Canvas.font=this.Font; this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; if (overlayItem.Title && this.IsShowOverlayIndexName) { var textWidth=this.Canvas.measureText(overlayItem.Title).width+2; if ((x+textWidth)=item.Data.Data.length) dataIndex=item.Data.Data.length-1; if (dataIndex<0) continue; value=item.Data.Data[dataIndex]; if (value==null) continue; if (item.DataType=="HistoryData-Vol") { value=value.Vol; valueText=this.FormatValue(value,item); } else if (item.DataType=="MultiReport") { valueText=this.FormatMultiReport(value,item); } else if (item.DataType=="ChartStackedBar") { aryText=this.FromatStackedBarTitle(value, item); if (!aryText) continue; } else { valueText=this.FormatValue(value,item); } } if (aryText) { var text; for(var k=0;kright) break; if (this.OverlayIndexType.BGColor) { this.Canvas.fillStyle=this.OverlayIndexType.BGColor; var rtBG={Left:x, Top:y-fontHeight/2, Width:textWidth, Height: fontHeight+lineSpace }; //保存下标题的坐标 this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); } this.Canvas.fillStyle=titleItem.Color; this.Canvas.fillText(text,x,y,textWidth); x+=textWidth; } } else { var text=valueText; if (item.Name) { var dyTitle=this.GetDynamicOutName(item.Name,overlayID); if (dyTitle) text=dyTitle+":"+valueText; else text=item.Name+":"+valueText; } var textWidth=this.Canvas.measureText(text).width+2; //后空2个像素 if ((x+textWidth)>right) break; if (this.OverlayIndexType.BGColor) { this.Canvas.fillStyle=this.OverlayIndexType.BGColor; var rtBG={Left:x, Top:y-fontHeight/2, Width:textWidth, Height: fontHeight+lineSpace }; //保存下标题的坐标 this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); } this.Canvas.fillStyle=item.Color; this.Canvas.fillText(text,x,y,textWidth); x+=textWidth; } } y+=fontHeight+lineSpace; if ((y+fontHeight+lineSpace)>=bottom) break; } } this.DrawOverlayIndex=function(left) //叠加指标标题 { var bottom=this.Frame.ChartBorder.GetTop()+this.Frame.ChartBorder.TitleHeight/2; //上下居中显示 var right=this.Frame.ChartBorder.GetRight(); if (this.Frame.IsHScreen===true) { bottom=-this.Frame.ChartBorder.TitleHeight/2; right=this.Frame.ChartBorder.GetHeight(); } if (left>right) return; var spaceWidth=5*GetDevicePixelRatio(); var drawLeft=left; var indexCount=0; for(item of this.OverlayIndex) { if (indexCount>0) left+=spaceWidth; var overlayItem=item[1]; var overlayID=item[0]; if (overlayItem.Title && this.IsShowOverlayIndexName) { this.Canvas.fillStyle=this.TitleColor; var textWidth=this.Canvas.measureText(overlayItem.Title).width+2; drawLeft=left; left+=textWidth; if (left>right) break; this.Canvas.fillText(overlayItem.Title,drawLeft,bottom,textWidth); if (this.IsSelectedChart(overlayID)) this.DrawSelectedLine(drawLeft, bottom, textWidth); } for(var i in overlayItem.Data) { var item=overlayItem.Data[i]; if (!item || !item.Data || !item.Data.Data || !item.Name) continue; if (item.Data.Data.length<=0) continue; var value=null; var valueText=null; if (item.DataType=="StraightLine") //直线只有1个数据 { value=item.Data.Data[0]; valueText=this.FormatValue(value,item); } else { var index=Math.abs(this.CursorIndex-0.5); index=parseInt(index.toFixed(0)); if (this.IsKLineFrame) index=this.CursorIndex; var dataIndex=item.Data.DataOffset+index; if (dataIndex>=item.Data.Data.length) dataIndex=item.Data.Data.length-1; if (dataIndex<0) continue; value=item.Data.Data[dataIndex]; if (value==null) continue; if (item.DataType=="HistoryData-Vol") { value=value.Vol; valueText=this.FormatValue(value,item); } else if (item.DataType=="MultiReport") { valueText=this.FormatMultiReport(value,item); } else { valueText=this.FormatValue(value,item); } } this.Canvas.fillStyle=item.Color; var text=item.Name+":"+valueText; var textWidth=this.Canvas.measureText(text).width+2; //后空2个像素 drawLeft=left; left+=textWidth; if (left>right) break; this.Canvas.fillText(text,drawLeft,bottom,textWidth); } if (left>right) break; ++indexCount; } } this.HScreenDraw=function() { var border=this.Frame.ChartBorder.GetHScreenBorder(); var xText=this.Frame.ChartBorder.GetRightTitle(); var yText=border.TopEx; this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); var left=1; var bottom=-this.Frame.ChartBorder.TitleHeight/2; //上下居中显示 var right=this.Frame.ChartBorder.GetHeight(); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.font=this.Font; var pixelRatio=GetDevicePixelRatio(); if (this.Title && this.IsShowIndexName) { var textWidth=this.Canvas.measureText(this.Title).width+2; if (this.IsDrawTitleBG) { var title=this.Title; var textWidth=this.Canvas.measureText(title).width; var arrowWidth=0; if (this.IsShowNameArrow && this.NameArrowConfig) { arrowWidth=this.Canvas.measureText(this.NameArrowConfig.Symbol).width; if (IFrameSplitOperator.IsNumber(this.NameArrowConfig.Space)) arrowWidth+=this.NameArrowConfig.Space; } var bgHeight=this.Canvas.measureText("擎").width+4*pixelRatio; var bgWidth=textWidth+arrowWidth+4*pixelRatio; this.TitleRect= { Top:border.Top, Left:this.Frame.ChartBorder.GetRightTitle()+this.Frame.ChartBorder.TitleHeight/2-bgHeight/2, Width:bgHeight, Height:bgWidth }; //保存下标题的坐标 this.Canvas.fillStyle=this.BGColor; var drawRect={ Left:left, Top:bottom-bgHeight/2, Width:bgWidth, Height:bgHeight }; this.Canvas.fillRect(drawRect.Left,drawRect.Top,drawRect.Width,drawRect.Height); if (this.BGBorderColor) { this.Canvas.strokeStyle=this.BGBorderColor; this.Canvas.strokeRect(ToFixedPoint(drawRect.Left),ToFixedPoint(drawRect.Top),ToFixedRect(drawRect.Width),ToFixedRect(drawRect.Height)); } var xText=left+2*pixelRatio; this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(title,xText,bottom); xText+=textWidth; if (this.IsShowNameArrow && this.NameArrowConfig) { if (IFrameSplitOperator.IsNumber(this.NameArrowConfig.Space)) xText+=this.NameArrowConfig.Space; this.Canvas.fillStyle=this.NameArrowConfig.Color; this.Canvas.fillText(this.NameArrowConfig.Symbol,xText,bottom); } left+=bgWidth+2*pixelRatio; left+=this.TitleSpace; } else { this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(this.Title,left,bottom); left+=textWidth; left+=this.TitleSpace; } } if (this.ArgumentsText && this.IsShowIndexName) { var textWidth=this.Canvas.measureText(this.ArgumentsText).width+2; this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(this.ArgumentsText,left,bottom,textWidth); left+=textWidth; left+=this.TitleSpace; } var isShowLastData=this.IsShowLastData(); var lockRect=this.Frame.GetLockRect(); if (lockRect) //指标上锁区域不显示动态标题 { var index=Math.abs(this.CursorIndex-0.5); if (this.IsKLineFrame) index=this.CursorIndex; var x=this.Frame.GetXFromIndex(index.toFixed(0)); if (x>=lockRect.Top) return; if (isShowLastData) return; } for(var i in this.Data) { var item=this.Data[i]; var outText=this.GetTitleItem(item, isShowLastData); if (!outText) continue; var valueText=outText.Text; var aryText=outText.ArrayText; if (aryText) { var text; for(var k=0;kright) break; this.Canvas.fillStyle=titleItem.Color; this.Canvas.fillText(text,left,bottom,textWidth); left+=textWidth; } } else { this.Canvas.fillStyle=item.Color; var text=valueText; if (item.Name) { var dyTitle=this.GetDynamicOutName(item.Name); if (dyTitle) text=dyTitle+":"+valueText; else text=item.Name+":"+valueText; } var space=this.ParamSpace*GetDevicePixelRatio(); var textWidth=this.Canvas.measureText(text).width+space; //后空2个像素 if ((left+textWidth)>right) break; this.Canvas.fillText(text,left,bottom,textWidth); left+=textWidth; } } if (this.Explain) //说明信息 { this.Canvas.fillStyle=this.TitleColor; var text="说明:"+this.Explain; var textWidth=this.Canvas.measureText(text).width+2; if (left+textWidth=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { if (this.BGBorderMoveOnColor) borderColor=this.BGBorderMoveOnColor; if (mouseStatus) { var btnItem={ ID:JSCHART_BUTTON_ID.INDEX_NAME_BUTTON }; mouseStatus.MouseOnToolbar={ ID:"IndexNameButton", Rect:rtButton, Item:btnItem, Frame:this.Frame, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } } if (this.Canvas.roundRect && this.NameButtonStyle==1) //判断下是否支持roundRect { this.Canvas.beginPath(); this.Canvas.roundRect(ToFixedPoint(rtButton.Left), ToFixedPoint(rtButton.Top), ToFixedRect(rtButton.Width), ToFixedRect(rtButton.Height), [roundRadius]); this.Canvas.closePath(); this.Canvas.fillStyle=this.BGColor; this.Canvas.fill(); if (borderColor) { this.Canvas.strokeStyle=borderColor; this.Canvas.stroke(); } } else { this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(rtButton.Left, rtButton.Top, rtButton.Width, rtButton.Height); if (borderColor) { this.Canvas.strokeStyle=borderColor; this.Canvas.strokeRect(ToFixedPoint(rtButton.Left), ToFixedPoint(rtButton.Top), ToFixedRect(rtButton.Width), ToFixedRect(rtButton.Height), [roundRadius]); } } var xText=rtButton.Left+roundRadius+2*pixelRatio; this.Canvas.fillStyle=this.TitleColor; this.Canvas.fillText(title,xText,rtButton.YCenter); xText+=textWidth; if (this.IsShowNameArrow && this.NameArrowConfig) { if (IFrameSplitOperator.IsNumber(this.NameArrowConfig.Space)) xText+=this.NameArrowConfig.Space; this.Canvas.fillStyle=this.NameArrowConfig.Color; this.Canvas.fillText(this.NameArrowConfig.Symbol,xText,rtButton.YCenter); } } //绘制按钮 this.DrawButton=function(item, rtButton, moveonPoint, mouseStatus) { var size=item.Style.Size; if (IFrameSplitOperator.IsNumber(item.Style.YMoveOffset)) rtButton.YCenter+=item.Style.YMoveOffset; var font=`${size}px ${item.Style.Family}`; rtButton.Top=rtButton.YCenter-size/2; rtButton.Width=size+item.Style.MerginLeft; rtButton.Height=size; rtButton.Bottom=rtButton.Top+rtButton.Height; rtButton.Right=rtButton.Left+rtButton.Width; var color=item.Style.Color; if (moveonPoint && (moveonPoint.X>=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom)) { color=item.Style.MoveOnColor; if (mouseStatus) mouseStatus.MouseOnToolbar={ ID:"TitleButton", Rect:rtButton, Item:item, Frame:this.Frame, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; } this.Canvas.fillStyle=color; this.Canvas.font=font; this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(item.Style.Text, rtButton.Left, rtButton.YCenter); return true; } this.DrawToolbar=function(toolbarInfo, moveonPoint, mouseStatus) { toolbarInfo.Width=0; if (!this.Frame || !this.Frame.GetLeftToolbar) return; var aryButton=this.Frame.GetLeftToolbar(); if (!IFrameSplitOperator.IsNonEmptyArray(aryButton)) return; if (this.Frame.IsHScreen===true) { } else { var border=this.Frame.GetBorder(); var right=border.Right-3; var left=border.Left+3; var yCenter=toolbarInfo.YCenter; for(var i=0;i0) toolbarInfo.Width+=3; } } this.DrawOverlayToolbar=function(overlayItem, toolbarInfo, moveonPoint, mouseStatus) { toolbarInfo.Width=0; if (!overlayItem || !overlayItem.Frame || !overlayItem.Frame.GetLeftToolbar) return; var frame=overlayItem.Frame; var aryButton=frame.GetLeftToolbar({ Overlay:overlayItem, OverlayID:toolbarInfo.ID }); if (!IFrameSplitOperator.IsNonEmptyArray(aryButton)) return; if (this.Frame.IsHScreen===true) { } else { var border=frame.GetBorder(); var right=border.Right-3; var left=border.Left+3; var yCenter=toolbarInfo.YCenter; for(var i=0;i0) toolbarInfo.Width+=3; } } this.PtInButtons=function(x,y) { for(var i=0;irect.Left && xrect.Top && y0) this.LineWidth=option.LineWidth; if (option.AreaColor) this.AreaColor=option.AreaColor; if (option.PointColor) this.PointColor=option.PointColor; if (option.MoveOnPointColor) this.MoveOnPointColor=option.MoveOnPointColor; if (option.PointRadius) this.PointRadius=option.PointRadius; if (IFrameSplitOperator.IsNumber(option.SquareSize)) this.SquareSize=option.SquareSize; if (IFrameSplitOperator.IsBool(option.IsShowPoint)) this.IsShowPoint=option.IsShowPoint; if (IFrameSplitOperator.IsNumber(option.LimitFrameID)) this.LimitFrameID=option.LimitFrameID; if (IFrameSplitOperator.IsBool(option.EnableCtrlMove)) this.EnableCtrlMove=option.EnableCtrlMove; if (IFrameSplitOperator.IsBool(option.IsShowYCoordinate)) this.IsShowYCoordinate=option.IsShowYCoordinate; } this.ReloadResource=function(resource) { if (!resource) { this.PointColor=g_JSChartResource.DrawPicture.PointColor[0]; this.MoveOnPointColor=g_JSChartResource.DrawPicture.PointColor[1]; this.PointBGColor=g_JSChartResource.DrawPicture.PointColor[2]; } } this.SetLineWidth=function() { this.BackupLineWidth=null; if (this.LineWidth>0) { this.BackupLineWidth=this.Canvas.lineWidth; this.Canvas.lineWidth=this.LineWidth*GetDevicePixelRatio(); } } this.GetFontHeight=function(font) { return GetFontHeight(this.Canvas, font, "擎"); } this.RestoreLineWidth=function() { if (this.BackupLineWidth!=null) { this.Canvas.lineWidth=this.BackupLineWidth; } } //磁吸K线 this.PointMagnetKLine=function() { if (!this.IsSupportMagnet) return false; if (!this.Frame) return false; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") return false; if (this.Frame.Identify!=0) return false; var pointIndex=-1; if (this.Status==2) pointIndex=1; else if (this.Status==1) pointIndex=0; else if (IFrameSplitOperator.IsNumber(this.MovePointIndex)) pointIndex=this.MovePointIndex; if (pointIndex<0) return false; if (this.Option && this.Option.Magnet && this.Option.Magnet.Enable) { var option= { IsFixedX:false, Magnet: { Enable:true, PointIndex:pointIndex, Distance:this.Option.Magnet.Distance, Type:this.Option.Magnet.Type } } return this.AdjustPoint(this.Point,option) } return false; } //Point => Value this.PointToValue=function() { if (!this.Frame) return false; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") { return this.PointToValue_Minute(); } else { return this.PointToValue_KLine(); } } this.PointToKLine=function(aryPoint) { if (!this.Frame) return null; var data=this.Frame.Data; if (!data) return null; var kLine=[]; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i in aryPoint) { var item=aryPoint[i]; var xValue=parseInt(this.Frame.GetXData(item.Y))+data.DataOffset; var yValue=this.Frame.GetYData(item.X); var valueItem={ XValue:xValue, YValue:yValue }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; kLine[i]=valueItem; } } else { for(var i in aryPoint) { var item=aryPoint[i]; var index=parseInt(this.Frame.GetXData(item.X,false)); var xValue=index+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) { xValue=data.Data.length-1; index=xValue-data.DataOffset; } var yValue=this.Frame.GetYData(item.Y,false); var valueItem={ XValue:xValue, YValue:yValue, XIndex:index }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; kLine[i]=valueItem; } } return kLine; } this.PointToValue_KLine=function() { if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i=0; i=data.Data.length) xValue=data.Data.length-1; var yValue=this.Frame.GetYData(item.Y,false); var valueItem={ XValue:xValue, YValue:yValue }; var kline=data.Data[xValue]; valueItem.DateTime={ Date:kline.Date }; if (IFrameSplitOperator.IsNumber(kline.Time)) valueItem.DateTime.Time=kline.Time; this.Value[i]=valueItem; } } return true; } this.PointToValue_Minute=function() { if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i=0; i=data.Data.length) //超过当前数据,直接读固定时间 { var index=xValue%xDatetime.length; var dataIndex=data.Data.length-1; var valueItem={ XValue:xValue, YValue:yValue }; var minuteItem=data.Data[dataIndex]; var timeItem=xDatetime[index]; valueItem.DateTime={ Date:minuteItem.Date, Time:timeItem }; this.Value[i]=valueItem; } else { var valueItem={ XValue:xValue, YValue:yValue }; var minuteItem=data.Data[xValue]; valueItem.DateTime={ Date:minuteItem.Date, Time:minuteItem.Time }; this.Value[i]=valueItem; } } } return true; } this.IsPointIn=function(x, y, option) { return false; } //Value => Point this.ValueToPoint=function() { if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; //this.UpdateXValue(); var isHScreen=this.Frame.IsHScreen; this.Point=[]; for(var i=0; i=0) valueItem.XValue=findItem.Index; } } //重置X索引数据 this.ResetXValue=function() { for(var i=0; i0) { var xEnd=this.Frame.GetXFromIndex(endIndex-1,false); for(var i=0;ixEnd) return true; } } else if (xStep<0) { var xStart=this.Frame.GetXFromIndex(startIndex,false); for(var i=0;i=showCount) ++invaildX; var pt=new Point(); if (isHScreen) //横屏X,Y对调 { pt.Y=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false); pt.X=this.Frame.GetYFromData(item.YValue,false); } else { pt.X=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false); pt.Y=this.Frame.GetYFromData(item.YValue,false); } drawPoint.push(pt); } if (option && option.IsCheckX===true) { if (invaildX==this.Value.length) return null; } } else //移动中 { for(var i=0;i=0) { option.Magnet= { Enable:true, PointIndex:pointIndex, Distance:this.Option.Magnet.Distance, Type:this.Option.Magnet.Type } } } this.AdjustPoint(drawPoint,option) } } return drawPoint; } //修正X, Y轴坐标 this.AdjustPoint=function(aryPoint, option) { if (!this.Frame) return false; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") return false; return this.AdjustPoint_KLine(aryPoint, option); } this.AdjustPoint_KLine=function(aryPoint, option) { if (!option) return false; if (!this.Frame) return false; var data=this.Frame.Data; if (!data) return false; var isHScreen=this.Frame.IsHScreen; if (isHScreen) { for(var i=0; i=data.Data.length) xValue=data.Data.length-1; if (option.IsFixedX) { index=xValue-data.DataOffset; item.X=this.Frame.GetXFromIndex(index,false); } //磁吸 if (option.Magnet && option.Magnet.Enable && i==option.Magnet.PointIndex) { var kline=data.Data[xValue]; var aryKValue=[kline.Open, kline.High, kline.Low, kline.Close]; var yMinDistance=null, yKLine=null; for(var j=0; jvalue) { yMinDistance=value; yKLine=yPrice; } } if (option.Magnet.Type==1) //只能在K线上 { if (IFrameSplitOperator.IsNumber(yKLine)) item.Y=yKLine; } else { if (yMinDistancethis.Frame.HorizontalMax || yValue0) { var b2=bottom-ptStart.Y; var a2=a*b2/b; var pt=new Point(); pt.X=ptStart.X+a2; pt.Y=bottom; result.End=pt; var b2=ptEnd.Y-top; var a2=a*b2/b; var pt2=new Point(); pt2.Y=top; pt2.X=ptEnd.X-a2; result.Start=pt2; } else { var b2=bottom-ptStart.Y; var a2=Math.abs(a)*b2/b; var pt=new Point(); pt.X=ptStart.X-a2;; pt.Y=bottom; result.End=pt; var b2=ptEnd.Y-top; var a2=Math.abs(a)*b2/b; var pt2=new Point(); pt2.Y=top; pt2.X=ptEnd.X+a2; result.Start=pt2; } return result; } //计算2个点线的,点0->点1->延长线的点 this.CalculateExtendLineEndPoint=function(aryPoint) { var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); var bottom=this.Frame.ChartBorder.GetBottomEx(); var top=this.Frame.ChartBorder.GetTopEx(); var a=aryPoint[1].X-aryPoint[0].X; var b=aryPoint[1].Y-aryPoint[0].Y; if (a>0) { var a1=right-aryPoint[0].X; var b1=a1*b/a; var y=b1+aryPoint[0].Y; if (y>=top && y<=bottom) { var pt=new Point(); pt.X=right; pt.Y=y; return pt; } if (b>0) { var b2=bottom-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=bottom; return pt2; } else if (b==0) { var pt2=new Point(); pt2.X=right; pt2.Y=aryPoint[0].Y; return pt2; } else { var b2=top-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=top; return pt2; } } else { var a1=aryPoint[0].X-left; var b1=a1*b/Math.abs(a); var y=b1+aryPoint[0].Y; if (y>=top && y<=bottom) { var pt=new Point(); pt.X=left; pt.Y=y; return pt; } if (b>0) { var b2=bottom-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=bottom; return pt2; } else if (b==0) { var pt2=new Point(); pt2.X=left; pt2.Y=aryPoint[0].Y; return pt2; } else { var b2=top-aryPoint[0].Y; var a2=a*b2/b; var x=a2+aryPoint[0].X; var pt2=new Point(); pt2.X=x; pt2.Y=top; return pt2; } } } //坐标是否在点上 返回在第几个点上 this.IsPointInXYValue=function(x, y, option) { if (!this.Frame) return -1; var data=this.Frame.Data; if (!data) return -1; if (!this.Value) return -1; var radius=5; if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom; else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom; var isHScreen=this.Frame.IsHScreen; radius*=GetDevicePixelRatio(); for(var i=0;i=0) return value; value=this.IsPointInLine(x,y,option); if (value>=0) return 100; return -1; } this.DrawLine=function(ptStart,ptEnd,isDottedline) { if (isDottedline) this.Canvas.setLineDash([5,10]); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); if (isDottedline) this.Canvas.setLineDash([]); } this.CreateLineData=function(ptStart,ptEnd) { var line={Start:new Point(), End:new Point()}; line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=ptEnd.Y; line.End.X=ptEnd.X; return line; } //导出成存储格式 this.ExportStorageData=function() { var storageData= { ClassName:this.ClassName, Symbol:this.Symbol, Guid:this.Guid, Period:this.Period,Value:[] , FrameID:this.Frame.Identify, LineColor:this.LineColor, AreaColor:this.AreaColor, LineWidth:this.LineWidth, Right:this.Right, EnableSave:this.EnableSave, IsShowYCoordinate:this.IsShowYCoordinate }; for(var i=0; iaryPoint[i].X) xMin=aryPoint[i].X; if (yMaxaryPoint[i].Y) yMin=aryPoint[i].Y; aryData.push({X:aryPoint[i].X, Y:aryPoint[i].Y}); } var data= { X: { Max: { X:xMax }, Min: { X:xMin} }, Y: { Max: { Y:yMax}, Min: { Y:yMin} }, Points: aryData //所有的点 }; return data; } } this.GetXYCoordinate_default=function() { if (this.IsFrameMinSize()) return null; if (!this.IsShow) return null; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); return this.PointRange(drawPoint); } this.GetXYCoordinate=function() { return null; } this.CopyData_default=function() { if (!this.Frame) return null; var data=this.ExportStorageData(); if (!data) return null; var dataOffset=0; if (this.Frame.ClassName=="MinuteFrame" || this.Frame.Class=="MinuteHScreenFrame") { } else { var kData=this.Frame.Data; if (!kData) return null; dataOffset=kData.DataOffset; } var height=this.Frame.ChartBorder.GetHeight(); var yFirst=this.Frame.ChartBorder.GetBottomEx()-this.Point[0].Y; for(var i=0;i=text.length) { pos=text.length-1; count=pos-endPos; } var subText=text.slice(endPos,endPos+count); var textWidth=this.Canvas.measureText(subText).width; if (textWidth>maxWidth) { for(var i=count; i>=0 ;--i) { subText=text.slice(endPos, endPos+i); textWidth=this.Canvas.measureText(subText).width; if (textWidthmaxWidth) { subText=text.slice(endPos, endPos+i-1); aryText.push({Text:subText}); endPos+=i-1; bFind=true; break; } } if (!bFind) { aryText.push({Text:subText}); endPos=text.length-1; } } else { aryText.push({Text:subText}); endPos+=count; } } return { AryText:aryText }; } this.CloneArrayText=function(aryText) { if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return []; var aryValue=[]; for(var i=0;i y1) return 270; if (x2 > x1 && y2 == y1) return 0; if (x2 < x1 && y2 == y1) return 180; if (x2 > x1 && y2 > y1) //第四象限 return 360 - angle; if (x2 < x1 && y2 > y1) //第三象限 return 180 + angle; if (x2 < x1 && y2 < y1) //第二象限 return 180 - angle; return angle; } //复制 //this.CopyData=function() { } //this.PtInButtons=function(x, y) { } //计算标签页大小 this.CalculateLabelSize=function(labelInfo) { var config=labelInfo.Config; this.Canvas.font=config.Font; this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; var lineHeight=this.Canvas.measureText("擎").width+2; var maxWidth=0, lineCount=0, labelHeight=config.Mergin.Top+config.Mergin.Bottom; for(var i=0;i0) labelHeight+=config.LineSpace; var item=labelInfo.AryText[i]; item.NameWidth=0; item.TextWidth=0; if (item.Name) item.NameWidth=this.Canvas.measureText(item.Name).width+2; if (item.Text) item.TextWidth=this.Canvas.measureText(item.Text).width+2; var itemWidth=item.NameWidth+item.TextWidth; if (maxWidth0) yText+=config.LineSpace; if (item.Name) { this.Canvas.fillStyle=item.NameColor; this.Canvas.fillText(item.Name,xText,yText); } if (item.Text) { var xOut=xText+item.NameWidth; if (config.TextAlign==1) //右对齐 xOut=rtBG.Right-config.Mergin.Right-item.TextWidth; this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(item.Text,xOut ,yText); } yText+=labelInfo.LineHeight; } } } IChartDrawPicture.ColorToRGBA=function(color,opacity) { var reg = /^(rgb|RGB)/; if (reg.test(color)) { var strHex = "#"; var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); // 把RGB的3个数值变成数组 // 转成16进制 for (var i = 0; i < colorArr.length; i++) { var hex = Number(colorArr[i]).toString(16); if (hex === "0") hex += hex; strHex += hex; } color=strHex; } return "rgba(" + parseInt("0x" + color.slice(1, 3)) + "," + parseInt("0x" + color.slice(3, 5)) + "," + parseInt("0x" + color.slice(5, 7)) + "," + opacity + ")"; } IChartDrawPicture.RGBToHex=function(rgb) { // Choose correct separator let sep = rgb.indexOf(",") > -1 ? "," : " "; // Turn "rgb(r,g,b)" into [r,g,b] rgb = rgb.substr(4).split(")")[0].split(sep); let r = (+rgb[0]).toString(16), g = (+rgb[1]).toString(16), b = (+rgb[2]).toString(16); if (r.length == 1) r = "0" + r; if (g.length == 1) g = "0" + g; if (b.length == 1) b = "0" + b; return "#" + r + g + b; } //16进制颜色转rgb IChartDrawPicture.HexToRGB=function(color) { color = color.toLowerCase(); var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; if (color && reg.test(color)) { if (color.length === 4) { var sColorNew = "#"; for (var i=1; i<4; i+=1) { sColorNew += color.slice(i, i+1).concat(color.slice(i, i+1)); } color = sColorNew; } //处理六位的颜色值 var sColorChange = []; for (var i=1; i<7; i+=2) { sColorChange.push(parseInt("0x"+color.slice(i, i+2))); } return "rgb(" + sColorChange.join(",") + ")"; } return null; } IChartDrawPicture.ArrayDrawPricture= [ { Name:"线段", ClassName:'ChartDrawPictureLine', Create:function() { return new ChartDrawPictureLine(); } }, { Name:"射线", ClassName:'ChartDrawPictureHaflLine', Create:function() { return new ChartDrawPictureHaflLine(); } }, { Name:"箭头", ClassName:"ChartDrawArrowLine", Create:function() { return new ChartDrawArrowLine(); } }, { Name:"水平线", ClassName:'ChartDrawPictureHorizontalLine', Create:function() { return new ChartDrawPictureHorizontalLine(); }}, { Name:"水平射线", ClassName:"ChartDrawPictureHorizontalRay", Create:function() { return new ChartDrawPictureHorizontalRay(); }}, { Name:"趋势线", ClassName:'ChartDrawPictureTrendLine', Create:function() { return new ChartDrawPictureTrendLine(); }}, { Name:"矩形", ClassName:'ChartDrawPictureRect', Create:function() { return new ChartDrawPictureRect(); }}, { Name:"圆弧线", ClassName:'ChartDrawPictureArc', Create:function() { return new ChartDrawPictureArc(); }}, { Name:"M头W底", ClassName:'ChartDrawPictureWaveMW', Create:function() { return new ChartDrawPictureWaveMW(); }}, { Name:"头肩型", ClassName:"ChartDrawHeadShouldersBT", Create:function() { return new ChartDrawHeadShouldersBT(); }}, { Name:"平行线", ClassName:'ChartDrawPictureParallelLines', Create:function() { return new ChartDrawPictureParallelLines(); }}, { Name:"平行通道", ClassName:'ChartDrawPictureParallelChannel', Create:function() { return new ChartDrawPictureParallelChannel(); }}, { Name:"价格通道线", ClassName:'ChartDrawPicturePriceChannel', Create:function() { return new ChartDrawPicturePriceChannel(); }}, { Name:"文本", ClassName:'ChartDrawPictureText', Create:function() { return new ChartDrawPictureText(); }}, { Name:"江恩角度线", ClassName:'ChartDrawPictureGannFan', Create:function() { return new ChartDrawPictureGannFan(); }}, { Name:"江恩角度线2", ClassName:'ChartDrawPictureGannFan', Create:function() { return new ChartDrawPictureGannFanV2(); }}, { Name:"阻速线", ClassName:'ChartDrawPictureResistanceLine', Create:function() { return new ChartDrawPictureResistanceLine(); }}, { Name:"阻速线2", ClassName:'ChartDrawPictureResistanceLineV2', Create:function() { return new ChartDrawPictureResistanceLineV2(); }}, { Name:"黄金分割", ClassName:'ChartDrawPictureGoldenSection', Create:function() { return new ChartDrawPictureGoldenSection(); }}, { Name:"百分比线", ClassName:'ChartDrawPicturePercentage', Create:function() { return new ChartDrawPicturePercentage(); }}, { Name:"波段线", ClassName:'ChartDrawPictureWaveBand', Create:function() { return new ChartDrawPictureWaveBand(); }}, { Name:"三角形", ClassName:'ChartDrawPictureTriangle', Create:function() { return new ChartDrawPictureTriangle(); }}, { Name:"对称角度", ClassName:'ChartDrawPictureSymmetryAngle', Create:function() { return new ChartDrawPictureSymmetryAngle(); }}, { Name:"圆", ClassName:'ChartDrawPictureCircle', Create:function() { return new ChartDrawPictureCircle(); }}, { Name:"平行四边形", ClassName:'ChartDrawPictureQuadrangle', Create:function() { return new ChartDrawPictureQuadrangle(); }}, { Name:"斐波那契周期线", ClassName:'ChartDrawPictureFibonacci', Create:function() { return new ChartDrawPictureFibonacci(); }}, { Name:"线形回归线", ClassName:"ChartDrawLinearRegression", Create:function() { return new ChartDrawLinearRegression(); } }, { Name:"线形回归带", ClassName:"ChartDrawLinearRegression", Create:function() { return new ChartDrawLinearRegression({ IsShowMaxMinLine:true }); } }, { Name:"延长线形回归带", ClassName:"ChartDrawLinearRegression", Create:function() { return new ChartDrawLinearRegression({ IsShowMaxMinLine:true, IsShowExtendLine:true }); } }, { Name:"尺子", ClassName:"ChartDrawRuler", Create:function() { return new ChartDrawRuler(); } }, { Name:"标价线", ClassName:"ChartDrawPriceLine", Create:function() { return new ChartDrawPriceLine(); } }, { Name:"标价线2", ClassName:"ChartDrawPriceLineV2", Create:function() { return new ChartDrawPriceLineV2(); } }, { Name:"垂直线", ClassName:"ChartDrawVerticalLine", Create:function() { return new ChartDrawVerticalLine(); } }, { Name:"十字线", ClassName:"ChartDrawCrosshair", Create:function() { return new ChartDrawCrosshair(); } }, { Name:"波浪尺", ClassName:"ChartDrawWaveRuler", Create:function() { return new ChartDrawWaveRuler(); } }, { Name:"AB波浪尺", ClassName:"ChartDrawWaveRuler2Point", Create:function() { return new ChartDrawWaveRuler2Point(); } }, { Name:"箱型线", ClassName:"ChartDrawBox", Create:function() { return new ChartDrawBox(); } }, { Name:"2点画图例子", ClassName:"ChartDrawTwoPointDemo", Create:function() { return new ChartDrawTwoPointDemo(); } }, { Name:"3点画图例子", ClassName:"ChartDrawThreePointDemo", Create:function() { return new ChartDrawThreePointDemo(); } }, { Name:"水平线段", ClassName:"ChartDrawHLineSegment", Create:function() { return new ChartDrawHLineSegment();} }, { Name:"平行射线", ClassName:"ChartDrawParallelRaysLines", Create:function() { return new ChartDrawParallelRaysLines();}}, { ClassName:'ChartDrawPictureIconFont', Create:function() { return new ChartDrawPictureIconFont(); }}, //涂鸦 不绑定K线坐标 { Name:"涂鸦线段", ClassName:'ChartDrawGraffitiLine', Create:function() { return new ChartDrawGraffitiLine(); } }, { Name:"固定范围成交量分布图", ClassName:"ChartDrawVolProfile", Create:function() { return new ChartDrawVolProfile(); }}, { Name:"DisjointChannel", ClassName:"ChartDrawDisjontChannel", Create:function() { return new ChartDrawDisjontChannel();}}, { Name:"FlatTop", ClassName:"ChartDrawFlatTop", Create:function() { return new ChartDrawFlatTop();}}, { Name:"水平线2", ClassName:"ChartDrawHLine", Create:function() { return new ChartDrawHLine(); }}, { Name:"MonitorLine", ClassName:"ChartDrawMonitorLine", Create:function() { return new ChartDrawMonitorLine(); }}, //trading view样式 { Name:"Note", ClassName:"ChartDrawNote", Create:function() { return new ChartDrawNote(); } }, { Name:"AnchoredText", ClassName:"ChartDrawAnchoredText", Create:function() { return new ChartDrawAnchoredText();} }, { Name:"PriceLabel", ClassName:"ChartDrawPriceLabel", Create:function() { return new ChartDrawPriceLabel();} }, { Name:"PriceNote", ClassName:"ChartDrawPriceNote", Create:function() { return new ChartDrawPriceNote();} }, { Name:"FibWedge", ClassName:"ChartDrawFibWedge", Create:function(){ return new ChartDrawFibWedge(); }}, { Name:"FibRetracement", ClassName:"ChartFibRetracement", Create:function() { return new ChartFibRetracement(); }}, //斐波那契回测 { Name:"FibSpeedResistanceFan", ClassName:"ChartFibSpeedResistanceFan", Create:function() { return new ChartFibSpeedResistanceFan(); }}, //斐波那契扇形 { Name:"PriceRange", ClassName:"ChartPriceRange", Create:function() { return new ChartPriceRange(); }}, { Name:"DateRange", ClassName:"ChartDateRange", Create:function() { return new ChartDateRange(); }}, { Name:"DatePriceRange", ClassName:"ChartDatePriceRange", Create:function() { return new ChartDatePriceRange(); }}, { Name:"InfoLine", ClassName:"ChartInfoLine", Create:function() { return new ChartInfoLine(); }}, { Name:"TrendAngle", ClassName:"ChartTrendAngle", Create:function() { return new ChartTrendAngle(); }}, { Name:"ArrowMarker", ClassName:"ChartArrowMarker", Create:function() { return new ChartArrowMarker(); } }, { Name:"BarsPattern", ClassName:"ChartBarsPattern", Create:function() { return new ChartBarsPattern(); } }, ]; IChartDrawPicture.MapIonFont=new Map( [ ["icon-arrow_up", { Text:'\ue683', Color:'#318757', Family:"iconfont"}], ["icon-arrow_down", { Text:'\ue681', Color:'#db563e', Family:"iconfont"}], ["icon-arrow_right", { Text:'\ue682', Color:'#318757', Family:"iconfont"}], ["icon-arrow_left", { Text:'\ue680',Color:'#318757', Family:"iconfont"}] ]); IChartDrawPicture.GetDrawPictureByName=function(value) { for(var i in IChartDrawPicture.ArrayDrawPricture) { var item=IChartDrawPicture.ArrayDrawPricture[i]; if (item.Name==value) return item; } return null; } IChartDrawPicture.GetDrawPictureByClassName=function(value) { for(var i in IChartDrawPicture.ArrayDrawPricture) { var item=IChartDrawPicture.ArrayDrawPricture[i]; if (item.ClassName==value) return item; } return null; } //注册一个新的画图工具 {Name:中文名字, ClassName:类名, Create:function()} IChartDrawPicture.RegisterDrawPicture=function(obj) { if (!obj.Name || !obj.ClassName || !obj.Create) return false; var item={ Name:obj.Name, ClassName:obj.ClassName, Create:obj.Create }; IChartDrawPicture.ArrayDrawPricture.push(item); JSConsole.Chart.Log('[IChartDrawPicture.RegisterDrawPicture] registered new draw picture class. item=',item); return true; } //注册一个新图标 {Name:, Text: , Color:, Family:} IChartDrawPicture.RegisterIonFont=function(obj) { if (!obj.Name || !obj.Text || !obj.Family) return false; var isOverwirte=IChartDrawPicture.MapIonFont.has(obj.Name); IChartDrawPicture.MapIonFont.set(obj.Name, obj); JSConsole.Chart.Log('[IChartDrawPicture.RegisterIonFont] registered new icon font, obj=, isOverwirte=',obj, isOverwirte); return true; } IChartDrawPicture.CreateChartDrawPicture=function(obj) //创建画图工具 { var item=IChartDrawPicture.GetDrawPictureByClassName(obj.ClassName); if (!item) return null; var chartDraw=item.Create(); //TODO:后面都放到每一个SetOptin里面 if (obj.Period>=0) chartDraw.Period=obj.Period; if (obj.Right>=0) chartDraw.Right=obj.Right; if (obj.Guid) chartDraw.Guid=obj.Guid; if (obj.Symbol) chartDraw.Symbol=obj.Symbol; if (obj.Value) chartDraw.Value=obj.Value; if (obj.Text) chartDraw.Text=obj.Text; if (obj.LineColor) chartDraw.LineColor=obj.LineColor; if (obj.AreaColor) chartDraw.AreaColor=obj.AreaColor; if (obj.FontOption) chartDraw.FontOption=obj.FontOption; if (obj.Label) chartDraw.Label=obj.Label; if (obj.LineWidth>0) chartDraw.LineWidth=obj.LineWidth; if (obj.EnableMove===false) chartDraw.EnableMove=obj.EnableMove; if (IFrameSplitOperator.IsBool(obj.EnableSave)) chartDraw.EnableSave=obj.EnableSave; if (IFrameSplitOperator.IsNumber(obj.ChannelWidth)) chartDraw.ChannelWidth=obj.ChannelWidth; if (IFrameSplitOperator.IsBool(obj.IsShowYCoordinate)) chartDraw.IsShowYCoordinate=obj.IsShowYCoordinate; if (chartDraw.SetOption) chartDraw.SetOption(obj); return chartDraw; } //画图工具-线段 function ChartDrawPictureLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureLine'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.IsShowYCoordinate=false; this.CopyData=this.CopyData_default; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:false} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); this.RestoreLineWidth(); /* if (this.IsSelected) { this.Canvas.strokeStyle='rgba(255,0,0,0.5)'; this.Canvas.lineWidth=20 * GetDevicePixelRatio(); this.Canvas.stroke(); } */ var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.GetYCoordinatePoint=function() { if (this.IsFrameMinSize()) return null; if (!this.IsShow) return null; if (this.Status<2) return null; if(!this.Point.length || !this.Frame) return null; if (this.Status!=10) return null; //完成 var aryPoint=[]; for(var i=0; i Point this.ValueToPoint=function() { if (!this.Frame) return false; var isHScreen=this.Frame.IsHScreen; this.Point=[]; for(var i in this.Value) { var item=this.Value[i]; var pt=new Point(); if (isHScreen) { pt.Y=item.XValue; pt.X=this.Frame.GetYFromData(item.YValue); } else { pt.X=item.XValue; pt.Y=this.Frame.GetYFromData(item.YValue,false); } this.Point[i]=pt; } } this.UpdateXValue=function() //通过datetime更新x的索引 { } this.CalculateDrawPoint=function(option) { if (this.Status<2) return null; if(!this.Point.length || !this.Frame) return null; var drawPoint=[]; if (this.Status==10) { var isHScreen=this.Frame.IsHScreen; for(var i in this.Value) { var item=this.Value[i]; var pt=new Point(); if (isHScreen) //横屏X,Y对调 { pt.Y=item.XValue; pt.X=this.Frame.GetYFromData(item.YValue,false); } else { pt.X=item.XValue; pt.Y=this.Frame.GetYFromData(item.YValue,false); } drawPoint.push(pt); } } else { drawPoint=this.Point; } return drawPoint; } //坐标是否在点上 返回在第几个点上 this.IsPointInXYValue=function(x,y,option) { if (!this.Frame) return -1; if (!this.Value) return -1; var radius=5; if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom; else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom; var isHScreen=this.Frame.IsHScreen; radius*=GetDevicePixelRatio(); for(var i=0;ithis.InsideLineConfig.MaxWidth) this.InsideWidth=this.InsideLineConfig.MaxWidth; if (this.OutWidth>this.OutLineConfig.MaxWidth) this.OutWidth=this.OutLineConfig.MaxWidth; } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.CalculateLineWidth(ptStart, ptEnd); //计算箭头 的两条边线坐标 var outArrow=this.CalculatePoint(this.OutLineConfig.Angle, ptStart, ptEnd, this.OutWidth); var insideArrow=this.CalculatePoint(this.InsideLineConfig.Angle, ptStart, ptEnd, this.InsideWidth); this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(insideArrow.Top.X,insideArrow.Top.Y); this.Canvas.lineTo(outArrow.Top.X,outArrow.Top.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.lineTo(outArrow.Bottom.X,outArrow.Bottom.Y); this.Canvas.lineTo(insideArrow.Bottom.X,insideArrow.Bottom.Y); this.Canvas.lineTo(ptStart.X,ptStart.Y); this.Canvas.strokeStyle=this.LineColor; this.Canvas.stroke(); this.Canvas.closePath(); this.Canvas.fillStyle=this.AreaColor; this.Canvas.fill(); /* if (this.IsSelected) { this.Canvas.strokeStyle='rgba(255,0,0,0.5)'; this.Canvas.lineWidth=20 * GetDevicePixelRatio(); this.Canvas.stroke(); } */ var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint([ptStart,ptEnd]); //画点 this.Canvas.restore(); } } //画图工具-射线 function ChartDrawPictureHaflLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureHaflLine'; this.GetXYCoordinate=this.GetXYCoordinate_default; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.FullLine; this.IsPointIn=function(x, y, option) { var result=this.IsPointIn_XYValue_Line(x,y,option); if (result>=0) return result; if (!this.FullLine) return result; var ptStart=this.FullLine.Start; var ptEnd=this.FullLine.End; var pixel=GetDevicePixelRatio(); var lineWidth=5*pixel; this.Canvas.beginPath(); if (ptStart.X==ptEnd.X) //竖线 { this.Canvas.moveTo(ptStart.X-lineWidth,ptStart.Y); this.Canvas.lineTo(ptStart.X+lineWidth,ptStart.Y); this.Canvas.lineTo(ptEnd.X+lineWidth,ptEnd.Y); this.Canvas.lineTo(ptEnd.X-lineWidth,ptEnd.Y); } else { this.Canvas.moveTo(ptStart.X,ptStart.Y+lineWidth); this.Canvas.lineTo(ptStart.X,ptStart.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y-lineWidth); this.Canvas.lineTo(ptEnd.X,ptEnd.Y+lineWidth); } this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) return 100; return result; } this.Draw=function() { this.LinePoint=[]; this.FullLine=null; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:false, IsCheckY:false}); if (!drawPoint || drawPoint.length!=2) return; var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.ClipFrame(); this.Canvas.strokeStyle=this.LineColor; this.SetLineWidth(); this.Canvas.beginPath(); this.Canvas.moveTo(drawPoint[0].X,drawPoint[0].Y); this.Canvas.lineTo(drawPoint[1].X,drawPoint[1].Y); var endPoint=this.CalculateExtendLineEndPoint(drawPoint); this.Canvas.lineTo(endPoint.X,endPoint.Y); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); this.FullLine={Start:drawPoint[0], End:endPoint}; } } // 画图工具-水平线 支持横屏 function ChartDrawPictureHorizontalLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureHorizontalLine'; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsDrawFirst=true; this.LineWidth=1; this.Super_SetOption=this.SetOption; //父类函数 this.Super_ExportStorageData=this.ExportStorageData; this.LabelConfig= { Left:{ IsShow:true, Margin:{ Left:5, Top:4, Bottom:2, Right:5 } }, Right:{ IsShow:true, Margin:{ Left:5, Top:4, Bottom:2, Right:5 } }, Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextColor:"rgb(255,255,255)" }; this.InsideLabelConfig= { Position:0, //0=左, 1=右 Font:`${14*GetDevicePixelRatio()}px 微软雅黑`, Margin:{ Left:5, Top:4, Bottom:2, Right:5 }, TextColor:"rgb(255,255,255)", BGAlpha:0.8, //背景色透明度 } this.LabelTitle; this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.LabelTitle) this.LabelTitle=option.LabelTitle; if (option.Label) { var item=option.Label; if (item.Left) { var subItem=item.Left; if (IFrameSplitOperator.IsBool(subItem.IsShow)) this.LabelConfig.Left.IsShow=subItem.IsShow; } if (item.Right) { var subItem=item.Right; if (IFrameSplitOperator.IsBool(subItem.IsShow)) this.LabelConfig.Right.IsShow=subItem.IsShow; } if (item.Font) this.LabelConfig.Font=item.Font; if (item.TextColor) this.LabelConfig.FoTextColornt=item.TextColor; } if (option.InsideLabel) { var item=option.InsideLabel; if (item.Font) this.InsideLabelConfig.Font=item.Font; if (item.TextColor) this.InsideLabelConfig.TextColor=item.TextColor; if (IFrameSplitOperator.IsNumber(item.Position)) this.InsideLabelConfig.Position=item.Position; if (IFrameSplitOperator.IsNumber(item.BGAlpha)) this.InsideLabelConfig.BGAlpha=item.BGAlpha; } } } this.ExportStorageData=function() { var storageData; if (this.Super_ExportStorageData) { storageData=this.Super_ExportStorageData(); if (this.LabelTitle) storageData.LabelTitle=this.LabelTitle; } return storageData; } /* this.GetXYCoordinate=function() { if (this.IsFrameMinSize()) return null; var drawPoint=this.CalculateDrawPoint(); return this.PointRange(drawPoint); } */ this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint || drawPoint.length!=1) return; if (!this.Frame) return; if (this.Value.length!=1) return; if (!this.IsYValueInFrame(this.Value[0].YValue)) return null; var isHScreen=this.Frame.IsHScreen; var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); if (isHScreen) { left=this.Frame.ChartBorder.GetTop(); right=this.Frame.ChartBorder.GetBottom(); } this.ClipFrame(); this.Canvas.strokeStyle=this.LineColor; this.SetLineWidth(); this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(drawPoint[0].X,left); this.Canvas.lineTo(drawPoint[0].X,right); } else { var yFixed=ToFixedPoint2(this.LineWidth,drawPoint[0].Y); this.Canvas.moveTo(left,yFixed); this.Canvas.lineTo(right,yFixed); } this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:new Point(), End:new Point()}; if (isHScreen) { line.Start.X=drawPoint[0].X; line.Start.Y=left; line.End.X=drawPoint[0].X; line.End.Y=right; } else { line.Start.X=left; line.Start.Y=drawPoint[0].Y; line.End.X=right; line.End.Y=drawPoint[0].Y; } this.LinePoint.push(line); //画点 this.DrawPoint(drawPoint); //显示价格 this.DrawInsideLabel(drawPoint[0]) this.Canvas.restore(); this.DrawValueLabel(drawPoint[0]); } this.DrawValueLabel=function(point) { if (!point) return; if (this.Frame.IsHScreen) return; //不支持横屏 var y=point.Y; var yValue=this.Frame.GetYData(y); var text=yValue.toFixed(2); var border=this.Frame.GetBorder(); var config=this.LabelConfig; this.Canvas.font=config.Font; var textHeight=this.Canvas.measureText("擎").width; var textWidth=this.Canvas.measureText(text).width; if (config.Left.IsShow && this.Frame.ChartBorder.Left>5) { var margin=config.Left.Margin; var rtBG={ Right:border.Left-1, Height:textHeight+margin.Top+margin.Bottom, Width:textWidth+margin.Left+margin.Right }; rtBG.Top=y-textHeight/2-margin.Top; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Left=rtBG.Right-rtBG.Width; this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.textAlign="left"; this.Canvas.textBaseline = "top"; var xText=rtBG.Left+margin.Left; var yText=rtBG.Top+margin.Top; this.Canvas.fillStyle=config.TextColor; this.Canvas.fillText(text,xText,yText); } if (config.Right.IsShow && this.Frame.ChartBorder.Right>5) { var margin=config.Right.Margin; var rtBG={ Left:border.Right+1, Height:textHeight+margin.Top+margin.Bottom, Width:textWidth+margin.Left+margin.Right }; rtBG.Top=y-textHeight/2-margin.Top; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.textAlign="left"; this.Canvas.textBaseline = "top"; var xText=rtBG.Left+margin.Left; var yText=rtBG.Top+margin.Top; this.Canvas.fillStyle=config.TextColor; this.Canvas.fillText(text,xText,yText); } } this.DrawInsideLabel=function(point) { if (!point) return; var isHScreen=this.Frame.IsHScreen; var config=this.InsideLabelConfig; if (config.Position!=0 && config.Position!=1) return; var margin=config.Margin; this.Canvas.fillStyle=this.LineColor; this.Canvas.font=config.Font; var textHeight=this.Canvas.measureText("擎").width; var border=this.Frame.GetBorder(); if (isHScreen) { var yValue=this.Frame.GetYData(point.X); var text=yValue.toFixed(2); if (this.LabelTitle) text=this.LabelTitle+text; var textWidth=this.Canvas.measureText(text).width; var rtBG=null; if (config.Position==0) //左 { var rtBG={ Top:border.Top+1, Width:textHeight+margin.Top+margin.Bottom, Height:textWidth+margin.Left+margin.Right, Left:point.X }; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; } else if (config.Position==1) //右 { var rtBG={ Bottom:border.Bottom-1, Width:textHeight+margin.Top+margin.Bottom, Height:textWidth+margin.Left+margin.Right, Left:point.X }; rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; } var bgColor=this.LineColor; if (config.BGAlpha<1) bgColor=IChartDrawPicture.ColorToRGBA(this.LineColor, config.BGAlpha); this.Canvas.fillStyle=bgColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); var xText=rtBG.Right-margin.Top; var yText=rtBG.Top+margin.Left; this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; this.Canvas.fillStyle=config.TextColor; this.Canvas.fillText(text,0,0); } else { var yValue=this.Frame.GetYData(point.Y); var text=yValue.toFixed(2); if (this.LabelTitle) text=this.LabelTitle+text; var textWidth=this.Canvas.measureText(text).width; var rtBG=null; if (config.Position==0) //左 { var rtBG={ Left:border.Left+1, Height:textHeight+margin.Top+margin.Bottom, Width:textWidth+margin.Left+margin.Right, Bottom:point.Y }; rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; } else if (config.Position==1) //右 { var rtBG={ Right:border.Right-1, Height:textHeight+margin.Top+margin.Bottom, Width:textWidth+margin.Left+margin.Right, Bottom:point.Y }; rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Left=rtBG.Right-rtBG.Width; } var bgColor=this.LineColor; if (config.BGAlpha<1) bgColor=IChartDrawPicture.ColorToRGBA(this.LineColor, config.BGAlpha); this.Canvas.fillStyle=bgColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); var xText=rtBG.Left+margin.Left; var yText=rtBG.Top+margin.Top; this.Canvas.textAlign="left"; this.Canvas.textBaseline = "top"; this.Canvas.fillStyle=config.TextColor; this.Canvas.fillText(text,xText,yText); } } } // 画图工具-水平射线线 支持横屏 function ChartDrawPictureHorizontalRay() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureHorizontalRay'; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsDrawFirst=true; this.LineWidth=1; this.Super_SetOption=this.SetOption; //父类函数 this.Super_ExportStorageData=this.ExportStorageData; this.LabelConfig= { Right:{ IsShow:true, Margin:{ Left:5, Top:4, Bottom:2, Right:5 } }, Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextColor:"rgb(255,255,255)" }; this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.LabelTitle) this.LabelTitle=option.LabelTitle; if (option.Label) { var item=option.Label; if (item.Right) { var subItem=item.Right; if (IFrameSplitOperator.IsBool(subItem.IsShow)) this.LabelConfig.Right.IsShow=subItem.IsShow; } if (item.Font) this.LabelConfig.Font=item.Font; if (item.TextColor) this.LabelConfig.FoTextColornt=item.TextColor; } } } this.ExportStorageData=function() { var storageData; if (this.Super_ExportStorageData) { storageData=this.Super_ExportStorageData(); } return storageData; } this.GetXYCoordinate=function() { if (this.IsFrameMinSize()) return null; var drawPoint=this.CalculateDrawPoint(); var data=this.PointRange(drawPoint); if (data) data.IsShowYCoordinate=false; return data; } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint || drawPoint.length!=1) return; if (!this.Frame) return; if (this.Value.length!=1) return; if (!this.IsYValueInFrame(this.Value[0].YValue)) return null; var isHScreen=this.Frame.IsHScreen; var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); if (isHScreen) { left=this.Frame.ChartBorder.GetTop(); right=this.Frame.ChartBorder.GetBottom(); } this.ClipFrame(); this.Canvas.strokeStyle=this.LineColor; this.SetLineWidth(); this.Canvas.beginPath(); if (isHScreen) { this.Canvas.moveTo(drawPoint[0].X,drawPoint[0].Y); this.Canvas.lineTo(drawPoint[0].X,right); } else { var yFixed=ToFixedPoint2(this.LineWidth,drawPoint[0].Y); this.Canvas.moveTo(drawPoint[0].X,yFixed); this.Canvas.lineTo(right,yFixed); } this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:new Point(), End:new Point()}; if (isHScreen) { line.Start.X=drawPoint[0].X; line.Start.Y=drawPoint[0].Y; line.End.X=drawPoint[0].X; line.End.Y=right; } else { line.Start.X=drawPoint[0].X; line.Start.Y=drawPoint[0].Y; line.End.X=right; line.End.Y=drawPoint[0].Y; } this.LinePoint.push(line); //画点 this.DrawPoint(drawPoint); this.Canvas.restore(); this.DrawValueLabel(drawPoint[0]); } this.DrawValueLabel=function(point) { if (!point) return; if (this.Frame.IsHScreen) return; //不支持横屏 var y=point.Y; var yValue=this.Frame.GetYData(y); var text=yValue.toFixed(2); var border=this.Frame.GetBorder(); var config=this.LabelConfig; this.Canvas.font=config.Font; var textHeight=this.Canvas.measureText("擎").width; var textWidth=this.Canvas.measureText(text).width; if (config.Right.IsShow && this.Frame.ChartBorder.Right>5) { var margin=config.Right.Margin; var rtBG={ Left:border.Right+1, Height:textHeight+margin.Top+margin.Bottom, Width:textWidth+margin.Left+margin.Right }; rtBG.Top=y-textHeight/2-margin.Top; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.textAlign="left"; this.Canvas.textBaseline = "top"; var xText=rtBG.Left+margin.Left; var yText=rtBG.Top+margin.Top; this.Canvas.fillStyle=config.TextColor; this.Canvas.fillText(text,xText,yText); } } } //水平线2 function ChartDrawHLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.Super_SetOption=this.SetOption; //父类函数 this.Super_ExportStorageData=this.ExportStorageData; //this.Label; //{Text:文本, Position: 0=左, 1=右 2=中间 } //this.Label={ Text:"xxxxxxx", Position:1}; this.LineWidth=1; this.Precision=2; //小数位数 this.ValueTextColor='rgb(250,250,250)'; this.IsShowCorssCursor=true; //画的时候是否显示十字光标 this.GetLabelCallback; //绘制标题回调函数 this.PointCount=1; this.ClassName='ChartDrawHLine'; this.Font=14*GetDevicePixelRatio() +"px 微软雅黑"; this.TextFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.RightSpaceWidth=50; this.ButtonPosition=0; //按钮位置, 0=价格后面, 1=价格上面 2=价格上面 左对齐 3=垂直排列 this.ButtonBGColor='rgb(190,190,190)'; this.ButtonSpace=3; this.TextMargin={ Left:0, Right:0, Top:0, Bottom:0, YOffset:4*GetDevicePixelRatio() }; this.AlwaysShowLab=false; //总是显示标签 this.Button= { CloseIcon: { Text:'\ue62b', Color:'rgb(255,255,255)', Family:"iconfont", Size:16, ID:JSCHART_BUTTON_ID.DRAW_PICTURE_DELETE, TooltipText:null, Margin:{ Left:2, Right:2 } }, SettingIcon: { Text:'\ue623',Color:'rgb(255,255,255)', Family:"iconfont", Size:16, ID:JSCHART_BUTTON_ID.DRAW_PICTURE_SETTING, TooltipText:null, Margin:{ Left:2, Right:2 } } //修改ID, Text , TooltipText 可以外部定制按钮 } this.CustomButton=[]; //自定义的按钮 { Text:'\ue62b', Color:'rgb(255,255,255)', Family:"iconfont", Size:16, ID:JSCHART_BUTTON_ID.DRAW_PICTURE_BUTTON_1, TooltipText:null, Data:null } this.AryShowButton=[]; //需要显示的按钮 { Data:, Width } this.AryButton=[]; this.ExtendData; //扩展数据 this.ShowPriceTextConfig= { IsShow:[false, false, true], //[0]=left内 [1]=right内 [2]=right外 Font: [ `${12*GetDevicePixelRatio()}px 微软雅黑`, `${12*GetDevicePixelRatio()}px 微软雅黑`, ], }; this.LableInfo; //{ Position:2=右侧外部 } //内部变量 this.ColseButtonSize=0; this.SettingButtonSize=0; this.ButtonBGWidth=0; this.VerticalButtonInfo={ Width:0, Height:0 }; //垂直按钮信息 this.IsPointIn=this.IsPointIn_XYValue_Line; this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.GetLabelCallback) { this.GetLabelCallback=option.GetLabelCallback; } if (IFrameSplitOperator.IsNumber(option.Precision)) this.Precision=option.Precision; if (option.Font) this.Font=option.Font; if (option.ValueTextColor) this.ValueTextColor=option.ValueTextColor; if (option.ButtonBGColor) this.ButtonBGColor=option.ButtonBGColor; if (IFrameSplitOperator.IsNumber(option.ButtonPosition)) this.ButtonPosition=option.ButtonPosition; if (IFrameSplitOperator.IsNumber(option.RightSpaceWidth)) this.RightSpaceWidth=option.RightSpaceWidth; if (IFrameSplitOperator.IsBool(option.AlwaysShowLab)) this.AlwaysShowLab=option.AlwaysShowLab; if (option.Button) { var item=option.Button; if (item.CloseIcon) { this.Button.CloseIcon=CloneData(item.CloseIcon); if (!this.Button.CloseIcon.ID) this.Button.CloseIcon.ID=JSCHART_BUTTON_ID.DRAW_PICTURE_DELETE; } else if (item.CloseIcon===null) { this.Button.CloseIcon=null; } if (item.SettingIcon) { this.Button.SettingIcon=CloneData(item.SettingIcon); if (!this.Button.SettingIcon.ID) this.Button.SettingIcon.ID=JSCHART_BUTTON_ID.DRAW_PICTURE_SETTING; } else if (item.SettingIcon===null) { this.Button.SettingIcon=null; } } if (option.ExtendData) this.ExtendData=option.ExtendData; if (IFrameSplitOperator.IsNonEmptyArray(option.IsShowPriceText)) { for(var i=0;i=rtButton.Left && moveonPoint.X=rtButton.Top && moveonPoint.Y<=rtButton.Bottom) { mouseStatus.MouseOnToolbar={ Rect:rtButton, Item:item, Frame:this.Frame, Point:{X:moveonPoint.X, Y:moveonPoint.Y} }; break; } } } } this.CalculateLabSize=function(labInfo) { this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; this.Canvas.font=this.TextFont; var lineHeight=this.Canvas.measureText("擎").width+2; var maxNameWidth=0, maxTextWidth=0; var lineCount=0; var lineSpace=0; if (IFrameSplitOperator.IsNumber(labInfo.LineSpace)) lineSpace=labInfo.LineSpace; var maxNameWidth=0, maxTextWidth=0; var lineCount=0; var maxWidth=0; for(var i=0;i0) yText+=lineSpace; var item=labelInfo.AryText[i]; if (item.Name) { this.Canvas.textAlign="left"; this.Canvas.fillStyle=item.NameColor; this.Canvas.fillText(item.Name,xText,yText); } if (item.Text) { this.Canvas.textAlign="right"; this.Canvas.fillStyle=item.TextColor; this.Canvas.fillText(item.Text,yRightText,yText); } yText+=labelSize.LineHeight; } } this.DrawRightLabel=function(y) { var rtDraw={ }; if (!this.LableInfo || !IFrameSplitOperator.IsNonEmptyArray(this.LableInfo.AryText) || this.LableInfo.Position!=2) { this.DrawValueText(y, rtDraw); return; } var priceSize=this.CalculateValueText(y); var labSize=this.CalculateLabSize(this.LableInfo); var border=this.Frame.GetBorder(); var yTop=y-priceSize.Height/2; var totalHeight=priceSize.Height+labSize.Height; var yBottom=yTop+totalHeight; var option={ }; if (yBottom>border.Bottom) //超过窗口底部, 标签位置不动 { yBottom=border.Bottom; yTop=yBottom-totalHeight; option.Top=yTop; } this.DrawValueText(y, rtDraw, option); var drawLeft=rtDraw.Right-labSize.Width; if (drawLeft1 实际数值就是长度 } if (item.Color) this.Canvas.strokeStyle=item.Color; else this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(left,yFixed); this.Canvas.lineTo(xRight,yFixed); this.Canvas.stroke(); if (yMaxyFixed) yMin=yFixed; } if (yMax!=yMin && this.LableInfo.VLine) { var item=this.LableInfo.VLine; var x=left+20*pixelRatio; if (IFrameSplitOperator.IsNumber(item.XOffset)) x=left+item.XOffset*pixelRatio; x=ToFixedPoint(x); if (item.Color) this.Canvas.strokeStyle=item.Color; else this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,yMax); this.Canvas.lineTo(x,yMin); this.Canvas.stroke(); } } this.DrawValueText=function(y, rtDraw, option) { var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); var top=this.Frame.ChartBorder.GetTopEx(); var bottom=this.Frame.ChartBorder.GetBottomEx(); var pixelTatio = GetDevicePixelRatio(); var labInfo=this.LabelInfo; if (labInfo && IFrameSplitOperator.IsNumber(labInfo.TopOffset)) top-=labInfo.TopOffset; if (labInfo && IFrameSplitOperator.IsNumber(labInfo.BottomOffset)) bottom+=labInfo.BottomOffset; var yValue=this.Frame.GetYData(y,false); var strValue=yValue.toFixed(this.Precision); if (labInfo &&labInfo.PriceSuffixText) strValue+=labInfo.PriceSuffixText; var bVisibleRange=true; if (ybottom) { y=bottom; bVisibleRange=false; } if (this.RightSpaceWidth>0) { if (!bVisibleRange) this.Canvas.setLineDash([2*pixelTatio,3*pixelTatio]); //虚线 this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(right,ToFixedPoint(y)); this.Canvas.lineTo(right+this.RightSpaceWidth,ToFixedPoint(y)); this.Canvas.stroke(); if (!bVisibleRange) this.Canvas.setLineDash([]); } this.Canvas.fillStyle=this.LineColor; this.Canvas.font=this.Font; var textWidth=this.Canvas.measureText(strValue).width; var lineHeight=this.GetFontHeight(); var rtBG={ Left:right+this.RightSpaceWidth, YCenter:y, Width:textWidth, Height:lineHeight }; rtBG.Height+=(this.TextMargin.Top+this.TextMargin.Bottom); rtBG.Width+=(this.TextMargin.Left+this.TextMargin.Right); rtBG.Right=rtBG.Left+rtBG.Width; rtBG.Top=rtBG.YCenter-rtBG.Height/2; rtBG.Bottom=rtBG.Top+rtBG.Height; if (option && IFrameSplitOperator.IsNumber(option.Top)) { rtBG.Top=option.Top; rtBG.Bottom=rtBG.Top+rtBG.Height; } var xText=rtBG.Left+this.TextMargin.Left; var yText=rtBG.Top+this.TextMargin.Top+this.TextMargin.YOffset; if (this.ButtonPosition==1) { this.Canvas.fillRect(ToFixedRect(rtBG.Left),ToFixedRect(rtBG.Top), ToFixedRect(rtBG.Width+this.ButtonBGWidth),ToFixedRect(rtBG.Height)); } else { this.Canvas.fillRect(ToFixedRect(rtBG.Left),ToFixedRect(rtBG.Top), ToFixedRect(rtBG.Width),ToFixedRect(rtBG.Height)); } this.Canvas.fillStyle=this.ValueTextColor this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; this.Canvas.fillText(strValue,xText,yText); rtDraw.Left=rtBG.Left; rtDraw.Top=rtBG.Top; rtDraw.Bottom=rtBG.Bottom; rtDraw.Right=rtBG.Right; this.DrawButton(rtBG.Top, rtBG.Right, lineHeight, rtDraw); } //计算右侧价格标签大小 this.CalculateValueText=function(y) { var yValue=this.Frame.GetYData(y,false); var strValue=yValue.toFixed(this.Precision); if (this.LableInfo &&this.LableInfo.PriceSuffixText) strValue+=this.LableInfo.PriceSuffixText; this.Canvas.font=this.Font; var textWidth=this.Canvas.measureText(strValue).width; var lineHeight=this.GetFontHeight(); var size={ Width:textWidth, Height:lineHeight }; size.Height+=(this.TextMargin.Top+this.TextMargin.Bottom); size.Width+=(this.TextMargin.Left+this.TextMargin.Right); return size; } this.DrawPriceText=function(text, ptStart, ptEnd, position) { if (position!=1 && position!=0) return; var font=this.ShowPriceTextConfig.Font[position]; this.Canvas.fillStyle=this.LineColor; this.Canvas.font=font; var textWidth=this.Canvas.measureText(text).width; var lineHeight=this.GetFontHeight(); var rtBG=null; if (position==1) { var rtBG={ Left:ptStart.X, Top:ptStart.Y-lineHeight/2, Width:textWidth+4, Height:lineHeight }; rtBG.Right=rtBG.Left+rtBG.Width; rtBG.Bottom=rtBG.Top+rtBG.Height; } else if (position==0) { var rtBG={ Right:ptEnd.X, Top:ptEnd.Y-lineHeight/2, Width:textWidth+4, Height:lineHeight }; rtBG.Left=rtBG.Right-rtBG.Width; rtBG.Bottom=rtBG.Top+rtBG.Height; } this.Canvas.fillRect(ToFixedRect(rtBG.Left),ToFixedRect(rtBG.Top), ToFixedRect(rtBG.Width+this.ButtonBGWidth),ToFixedRect(rtBG.Height)); this.Canvas.fillStyle=this.ValueTextColor this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillText(text,rtBG.Left+2,ptStart.Y); } this.CalculateButtonSize=function() { var pixelRatio=GetDevicePixelRatio(); if (!IFrameSplitOperator.IsNonEmptyArray(this.AryShowButton)) return; var totalWidth=0; for(var i=0;ichartWidth) //右边不够了 往左移动 { drawLeft=chartWidth-this.ButtonBGWidth; } if (rtDraw.Left>drawLeft) drawLeft=rtDraw.Left; } else if (this.ButtonPosition==2) { drawTop-=drawHeight; drawLeft=rtDraw.Left; } this.Canvas.fillStyle=this.LineColor; var left=drawLeft; var rtBG={ Left:drawLeft, Top:drawTop, Width:this.ButtonBGWidth, Height:drawHeight }; rtBG.Right=rtBG.Left+rtBG.Width; rtBG.Bottom=rtBG.Top+rtBG.Height; this.Canvas.fillStyle=this.ButtonBGColor; this.Canvas.fillRect(ToFixedRect(rtBG.Left),ToFixedRect(rtBG.Top), ToFixedRect(rtBG.Width),ToFixedRect(rtBG.Height)); var pixelRatio=GetDevicePixelRatio(); for(var i=0;i=0) return nIndex; var aryPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!aryPoint || aryPoint.length!=2) return -1; //是否在矩形边框上 var linePoint=[ {X:aryPoint[0].X,Y:aryPoint[0].Y},{X:aryPoint[1].X,Y:aryPoint[0].Y}]; if (this.IsPointInLine(linePoint,x,y,option)) return 100; linePoint=[ {X:aryPoint[1].X,Y:aryPoint[0].Y},{X:aryPoint[1].X,Y:aryPoint[1].Y}]; if (this.IsPointInLine2(linePoint,x,y,option)) return 100; linePoint=[ {X:aryPoint[1].X,Y:aryPoint[1].Y},{X:aryPoint[0].X,Y:aryPoint[1].Y}]; if (this.IsPointInLine(linePoint,x,y,option)) return 100; linePoint=[ {X:aryPoint[0].X,Y:aryPoint[1].Y},{X:aryPoint[0].X,Y:aryPoint[0].Y}]; if (this.IsPointInLine2(linePoint,x,y,option)) return 100; return -1; } //点是否在线段上 水平线段 this.IsPointInLine=function(aryPoint,x,y,option) { var radius=5; if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom; else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom; var pixel=GetDevicePixelRatio(); radius*=pixel; this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X,aryPoint[0].Y+radius); this.Canvas.lineTo(aryPoint[0].X,aryPoint[0].Y-radius); this.Canvas.lineTo(aryPoint[1].X,aryPoint[1].Y-radius); this.Canvas.lineTo(aryPoint[1].X,aryPoint[1].Y+radius); this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) return true; } //垂直线段 this.IsPointInLine2=function(aryPoint,x,y,option) { var radius=5; if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom; else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom; var pixel=GetDevicePixelRatio(); radius*=pixel; this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X-radius,aryPoint[0].Y); this.Canvas.lineTo(aryPoint[0].X+radius,aryPoint[0].Y); this.Canvas.lineTo(aryPoint[1].X+radius,aryPoint[1].Y); this.Canvas.lineTo(aryPoint[1].X-radius,aryPoint[1].Y); this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) return true; } } //画图工具-弧形 function ChartDrawPictureArc() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureArc'; this.Draw=function() { if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint || drawPoint.length!=2) return; this.ClipFrame(); //this.Canvas.beginPath(); //this.Canvas.rect(drawPoint[0].X,drawPoint[0].Y,drawPoint[1].X-drawPoint[0].X,drawPoint[1].Y-drawPoint[0].Y); this.SetLineWidth(); if (drawPoint[0].X < drawPoint[1].X && drawPoint[0].Y > drawPoint[1].Y) // 第一象限 { var a = drawPoint[1].X - drawPoint[0].X; var b = drawPoint[0].Y - drawPoint[1].Y; var step = (a > b) ? 1/a : 1 / b; var xcenter = drawPoint[0].X; var ycenter = drawPoint[1].Y; this.Canvas.beginPath(); this.Canvas.moveTo(drawPoint[0].X, drawPoint[0].Y); for (var i = 1.5*Math.PI; i < 2*Math.PI; i+=step) { this.Canvas.lineTo(xcenter+a*Math.cos(i), ycenter+b*Math.sin(i)*-1); } for (var j = 0; j <= 0.5*Math.PI; j += step) { this.Canvas.lineTo(xcenter+a*Math.cos(j), ycenter+b*Math.sin(j)*-1); } } else if (drawPoint[0].X > drawPoint[1].X && drawPoint[0].Y > drawPoint[1].Y) // 第二象限 { var a = drawPoint[0].X - drawPoint[1].X; var b = drawPoint[0].Y - drawPoint[1].Y; var step = (a > b) ? 1/a:1/b; var xcenter = drawPoint[1].X; var ycenter = drawPoint[0].Y; this.Canvas.beginPath(); this.Canvas.moveTo(drawPoint[0].X, drawPoint[0].Y); for (var i = 0; i <= Math.PI; i += step) { this.Canvas.lineTo(xcenter + a*Math.cos(i), ycenter + b*Math.sin(i)*-1); } } else if (drawPoint[0].X > drawPoint[1].X && drawPoint[0].Y < drawPoint[1].Y) // 第三象限 { var a = drawPoint[0].X - drawPoint[1].X; var b = drawPoint[1].Y - drawPoint[0].Y; var step = (a > b) ? 1/a:1/b; var xcenter = drawPoint[0].X; var ycenter = drawPoint[1].Y; this.Canvas.beginPath(); this.Canvas.moveTo(drawPoint[0].X, drawPoint[0].Y); for (var i = 0.5*Math.PI; i <= 1.5*Math.PI; i += step) { this.Canvas.lineTo(xcenter + a*Math.cos(i), ycenter + b*Math.sin(i)*-1); } } else if (drawPoint[0].X < drawPoint[1].X && drawPoint[0].Y < drawPoint[1].Y) // 第四象限 { var a = drawPoint[1].X - drawPoint[0].X; var b = drawPoint[1].Y - drawPoint[0].Y; var step = (a > b) ? 1/a : 1/b; var xcenter = drawPoint[1].X; var ycenter = drawPoint[0].Y; this.Canvas.beginPath(); this.Canvas.moveTo(drawPoint[0].X, drawPoint[0].Y); for (var i = Math.PI; i <= 2*Math.PI; i += step) { this.Canvas.lineTo(xcenter+a*Math.cos(i), ycenter + b*Math.sin(i)*-1); } } this.Canvas.strokeStyle=this.LineColor; this.Canvas.stroke(); this.RestoreLineWidth(); //this.Canvas.closePath(); this.Canvas.restore(); //画点 this.DrawPoint(drawPoint); } //0-10 鼠标对应的点索引 100=鼠标在正个图形上 -1 鼠标不在图形上 this.IsPointIn=function(x,y,option) { if (this.IsFrameMinSize()) return -1; if (!this.Frame || this.Status!=10) return -1; var data=this.Frame.Data; if (!data) return -1; //是否在点上 var nIndex=this.IsPointInXYValue(x,y,option); if (nIndex>=0) return nIndex; var aryPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!aryPoint || aryPoint.length!=2) return -1; //是否在弧线上 var ArcPoint=[ {X:aryPoint[0].X,Y:aryPoint[0].Y},{X:aryPoint[1].X,Y:aryPoint[1].Y}]; if (this.IsPointInArc(ArcPoint, x, y)) return 100; return -1; } this.IsPointInArc=function(aryPoint,x,y) { if (aryPoint.length != 2) return false; if (aryPoint[0].X < aryPoint[1].X && aryPoint[0].Y > aryPoint[1].Y) // 第一象限 { var a = aryPoint[1].X - aryPoint[0].X; var b = aryPoint[0].Y - aryPoint[1].Y; var step = (a > b) ? 1/a : 1 / b; var ainer = a * 0.8; var biner = b * 0.8; var stepiner = (ainer > biner) ? 1/ainer : 1/biner; var xcenter = aryPoint[0].X; var ycenter = aryPoint[1].Y; this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, aryPoint[0].Y); for (var i = 1.5*Math.PI; i < 2*Math.PI; i+=step) { this.Canvas.lineTo(xcenter+a*Math.cos(i), ycenter+b*Math.sin(i)*-1); } for (var j = 0; j <= 0.5*Math.PI; j += step) { this.Canvas.lineTo(xcenter+a*Math.cos(j), ycenter+b*Math.sin(j)*-1); } for (var k = 0.5*Math.PI; k >= 0; k -= stepiner) { this.Canvas.lineTo(xcenter+ainer*Math.cos(k), ycenter + biner*Math.sin(j)*-1); } for (var l = 2*Math.PI; l >= 1.5*Math.PI; l -= stepiner) { this.Canvas.lineTo(xcenter + ainer*Math.cos(l), ycenter + biner*Math.sin(l)*-1); } this.Canvas.closePath(); } else if (aryPoint[0].X > aryPoint[1].X && aryPoint[0].Y > aryPoint[1].Y) // 第二象限 { var a = aryPoint[0].X - aryPoint[1].X; var b = aryPoint[0].Y - aryPoint[1].Y; var step = (a > b) ? 1/a:1/b; var ainer = a * 0.8; var biner = b * 0.8; var stepiner = (ainer > biner) ? 1 / ainer : 1 / biner; var xcenter = aryPoint[1].X; var ycenter = aryPoint[0].Y; this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, aryPoint[0].Y); for (var i = 0; i <= Math.PI; i += step) { this.Canvas.lineTo(xcenter + a*Math.cos(i), ycenter + b*Math.sin(i)*-1); } for (var j = Math.PI; j >= 0; j -= stepiner) { this.Canvas.lineTo(xcenter + ainer * Math.cos(j), ycenter + biner*Math.sin(j)*-1); } this.Canvas.closePath(); } else if (aryPoint[0].X > aryPoint[1].X && aryPoint[0].Y < aryPoint[1].Y) // 第三象限 { var a = aryPoint[0].X - aryPoint[1].X; var b = aryPoint[1].Y - aryPoint[0].Y; var step = (a > b) ? 1/a:1/b; var ainer = a * 0.8; var biner = b * 0.8; var stepiner = (ainer > biner) ? 1/ainer : 1/biner; var xcenter = aryPoint[0].X; var ycenter = aryPoint[1].Y; this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, aryPoint[0].Y); for (var i = 0.5*Math.PI; i <= 1.5*Math.PI; i += step) { this.Canvas.lineTo(xcenter + a*Math.cos(i), ycenter + b*Math.sin(i)*-1); } for (var j = 1.5*Math.PI; j >= 0.5*Math.PI; j -= stepiner) { this.Canvas.lineTo(xcenter + ainer * Math.cos(j), ycenter + biner*Math.sin(j)*-1); } this.Canvas.closePath(); } else if (aryPoint[0].X < aryPoint[1].X && aryPoint[0].Y < aryPoint[1].Y) // 第四象限 { var a = aryPoint[1].X - aryPoint[0].X; var b = aryPoint[1].Y - aryPoint[0].Y; var step = (a > b) ? 1/a : 1/b; var ainer = a * 0.8; var biner = b * 0.8; var stepiner = (ainer > biner) ? 1/ainer : 1/biner; var xcenter = aryPoint[1].X; var ycenter = aryPoint[0].Y; this.Canvas.beginPath(); this.Canvas.moveTo(aryPoint[0].X, aryPoint[0].Y); for (var i = Math.PI; i <= 2*Math.PI; i += step) { this.Canvas.lineTo(xcenter+a*Math.cos(i), ycenter + b*Math.sin(i)*-1); } for (var j = 2*Math.PI; j >= Math.PI; j -= stepiner) { this.Canvas.lineTo(xcenter + ainer*Math.cos(j), ycenter + biner*Math.sin(j)*-1); } this.Canvas.closePath(); } if (this.Canvas.isPointInPath(x,y)) return true; else return false; } } //M头W底 支持横屏 function ChartDrawPictureWaveMW() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureWaveMW'; this.PointCount=5; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.IsHScreen=false; this.Draw=function() { this.LinePoint=[]; if (!this.Frame) return; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; this.IsHScreen=this.Frame.IsHScreen; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; //var points=drawPoint.slice(0); this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); this.ClipFrame(); this.CalculateLines(drawPoint); this.SetLineWidth(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End); } this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.CalculateLines=function(points) { if (!this.Frame) return; if (points.length<2) return; if (this.Status==2) { var line={Start:new Point(), End:new Point()}; line.Start.Y=points[0].Y; line.Start.X=points[0].X; line.End.Y=points[1].Y; line.End.X=points[1].X; this.LinePoint.push(line); var xMove=points[1].X-points[0].X; var yMove=points[1].Y-points[0].Y; line={Start:new Point(), End:new Point()}; if (this.IsHScreen) { line.Start.Y=points[1].Y; line.Start.X=points[1].X; line.End.Y=points[1].Y+yMove; line.End.X=points[0].X; } else { line.Start.Y=points[1].Y; line.Start.X=points[1].X; line.End.Y=points[0].Y; line.End.X=points[1].X+xMove; } this.LinePoint.push(line); var ptStart=line.End; var newPt=new Point(); newPt.X=ptStart.X; newPt.Y=ptStart.Y; this.Point[2]=newPt; line={Start:new Point(), End:new Point()}; if (this.IsHScreen) { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=ptStart.Y+yMove; line.End.X=points[1].X; } else { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=points[1].Y; line.End.X=ptStart.X+xMove; } this.LinePoint.push(line); var ptStart=line.End; var newPt=new Point(); newPt.X=ptStart.X; newPt.Y=ptStart.Y; this.Point[3]=newPt; line={Start:new Point(), End:new Point()}; if (this.IsHScreen) { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=ptStart.Y+yMove; line.End.X=points[0].X; } else { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=points[0].Y; line.End.X=ptStart.X+xMove; } this.LinePoint.push(line); var ptStart=line.End; var newPt=new Point(); newPt.X=ptStart.X; newPt.Y=ptStart.Y; this.Point[4]=newPt; this.PointCount=this.Point.length; } else if (points.length==5) { var line={Start:new Point(), End:new Point()}; line.Start.Y=points[0].Y; line.Start.X=points[0].X; line.End.Y=points[1].Y; line.End.X=points[1].X; this.LinePoint.push(line); var line={Start:new Point(), End:new Point()}; line.Start.Y=points[1].Y; line.Start.X=points[1].X; line.End.Y=points[2].Y; line.End.X=points[2].X; this.LinePoint.push(line); var line={Start:new Point(), End:new Point()}; line.Start.Y=points[2].Y; line.Start.X=points[2].X; line.End.Y=points[3].Y; line.End.X=points[3].X; this.LinePoint.push(line); var line={Start:new Point(), End:new Point()}; line.Start.Y=points[3].Y; line.Start.X=points[3].X; line.End.Y=points[4].Y; line.End.X=points[4].X; this.LinePoint.push(line); } } } //头肩 头肩顶(Head and shoulders top)以及头肩底(Head and shoulders bottom)两种形态 //支持横屏 function ChartDrawHeadShouldersBT() { this.newMethod=ChartDrawPictureWaveMW; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawHeadShouldersBT'; this.CalculateLines_Backup=this.CalculateLines; this.CalculateLines=function(points) { if (!this.Frame) return; if (points.length<2) return; if (this.Status==2) { var line={Start:new Point(), End:new Point()}; line.Start.Y=points[0].Y; line.Start.X=points[0].X; line.End.Y=points[1].Y; line.End.X=points[1].X; this.LinePoint.push(line); var xMove=points[1].X-points[0].X; var yMove=points[1].Y-points[0].Y; line={Start:new Point(), End:new Point()}; if (this.IsHScreen) { line.Start.Y=points[1].Y; line.Start.X=points[1].X; line.End.Y=points[1].Y+yMove; line.End.X=points[0].X-xMove; } else { line.Start.Y=points[1].Y; line.Start.X=points[1].X; line.End.Y=points[0].Y-yMove; line.End.X=points[1].X+xMove; } this.LinePoint.push(line); var ptStart=line.End; var newPt=new Point(); newPt.X=ptStart.X; newPt.Y=ptStart.Y; this.Point[2]=newPt; line={Start:new Point(), End:new Point()}; if (this.IsHScreen) { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=ptStart.Y+yMove; line.End.X=points[1].X; } else { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=points[1].Y; line.End.X=ptStart.X+xMove; } this.LinePoint.push(line); var ptStart=line.End; var newPt=new Point(); newPt.X=ptStart.X; newPt.Y=ptStart.Y; this.Point[3]=newPt; line={Start:new Point(), End:new Point()}; if (this.IsHScreen) { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=ptStart.Y+yMove; line.End.X=points[0].X; } else { line.Start.Y=ptStart.Y; line.Start.X=ptStart.X; line.End.Y=points[0].Y; line.End.X=ptStart.X+xMove; } this.LinePoint.push(line); var ptStart=line.End; var newPt=new Point(); newPt.X=ptStart.X; newPt.Y=ptStart.Y; this.Point[4]=newPt; this.PointCount=this.Point.length; } else { return this.CalculateLines_Backup(points); } } } //平行线 function ChartDrawPictureParallelLines() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureParallelLines'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.PointCount=3; this.LastPoint; //中心线 this.CenterLine={ LineDash:[2*GetDevicePixelRatio(),3*GetDevicePixelRatio()], Line:null, IsShow:false }; this.Super_SetOption=this.SetOption; //父类函数 this.Super_ExportStorageData=this.ExportStorageData; this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.CenterLine) { var item=option.CenterLine; if (IFrameSplitOperator.IsNonEmptyArray(item.LineDash)) this.CenterLine.LineDash=item.LineDash.slice(0); if (IFrameSplitOperator.IsBool(item.IsShow)) this.CenterLine.IsShow=item.IsShow; } } } this.ExportStorageData=function() { var storageData; if (this.Super_ExportStorageData) { storageData=this.Super_ExportStorageData(); if (this.CenterLine) { storageData.CenterLine={ IsShow:this.CenterLine.IsShow, LineDash:this.CenterLine.LineDash.slice(0) }; } } return storageData; } this.Draw=function() { this.LinePoint=[]; this.CenterLine.Line=null; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:false, IsCheckY:false}); //不检测x,y if (!drawPoint) return; this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); var points=drawPoint.slice(0); this.CalculateLines(points); this.ClipFrame(); this.DrawArea(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End); } if (this.CenterLine.IsShow && this.CenterLine.Line) { var item=this.CenterLine.Line; this.Canvas.setLineDash(this.CenterLine.LineDash); this.DrawLine(item.Start,item.End); this.Canvas.setLineDash([]); } this.DrawPoint(points); //画点 this.Canvas.restore(); } this.SetLastPoint=function(obj) { this.LastPoint={X:obj.X,Y:obj.Y}; } this.DrawArea=function() { if (this.LinePoint.length!=2) return; this.Canvas.fillStyle=this.AreaColor; this.Canvas.beginPath(); this.Canvas.moveTo(this.LinePoint[0].Start.X,this.LinePoint[0].Start.Y); this.Canvas.lineTo(this.LinePoint[0].End.X,this.LinePoint[0].End.Y); this.Canvas.lineTo(this.LinePoint[1].End.X,this.LinePoint[1].End.Y); this.Canvas.lineTo(this.LinePoint[1].Start.X,this.LinePoint[1].Start.Y); this.Canvas.closePath(); this.Canvas.fill(); } this.CalculateLines=function(points) { if (this.PointStatus==2 && this.LastPoint) { var pt=new Point(); pt.X=this.LastPoint.X; pt.Y=this.LastPoint.Y; points[2]=pt; } if (points.length==2) { var linePoint=this.CalculateExtendLinePoint(points[0],points[1]); this.LinePoint.push(linePoint); } else if (points.length==3) { var linePoint=this.CalculateExtendLinePoint(points[0],points[1]); this.LinePoint.push(linePoint); //计算平行线 var xMove=points[2].X-points[1].X; var yMove=points[2].Y-points[1].Y; var ptStart=new Point(); var ptEnd=new Point(); ptStart.X=points[0].X+xMove; ptStart.Y=points[0].Y+yMove; ptEnd.X=points[1].X+xMove; ptEnd.Y=points[1].Y+yMove; linePoint=this.CalculateExtendLinePoint(ptStart,ptEnd); this.LinePoint.push(linePoint); //中心线 var ptStart=new Point(); var ptEnd=new Point(); ptStart.X=points[0].X+xMove/2; ptStart.Y=points[0].Y+yMove/2; ptEnd.X=points[1].X+xMove/2; ptEnd.Y=points[1].Y+yMove/2; linePoint=this.CalculateExtendLinePoint(ptStart,ptEnd); this.CenterLine.Line=linePoint; } } } //FlatTop/Bottom 平滑顶/底 function ChartDrawFlatTop() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawFlatTop'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.PointCount=3; this.LastPoint; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); var points=drawPoint.slice(0); this.CalculateLines(points); this.ClipFrame(); for(var i=0;i=2) { var linePoint={Start:new Point(), End:new Point() }; linePoint.Start.X=drawPoint[0].X; linePoint.Start.Y=drawPoint[0].Y; linePoint.End.X=drawPoint[1].X; linePoint.End.Y=drawPoint[1].Y; this.LinePoint.push(linePoint); if (drawPoint.length==3 || this.Status==10) { var x=linePoint.End.X-linePoint.Start.X; var y=linePoint.End.Y-linePoint.Start.Y; var angle=Math.atan(Math.abs(x/y)); var yMove=this.ChannelWidth/Math.sin(angle); //JSConsole.Chart.Log('[ChartDrawPictureParallelChannel::CalculateDrawPoint]',xMove); linePoint={Start:new Point(), End:new Point() }; linePoint.Start.X=drawPoint[0].X; linePoint.Start.Y=drawPoint[0].Y-yMove; linePoint.End.X=drawPoint[1].X; linePoint.End.Y=drawPoint[1].Y-yMove; this.LinePoint.push(linePoint); var ptCenter=new Point(); ptCenter.X=linePoint.Start.X+(linePoint.End.X-linePoint.Start.X)/2; ptCenter.Y=linePoint.Start.Y+(linePoint.End.Y-linePoint.Start.Y)/2; drawPoint[2]=ptCenter; this.Point[2]=ptCenter; var xValue=parseInt(this.Frame.GetXData(ptCenter.X))+data.DataOffset; var yValue=this.Frame.GetYData(ptCenter.Y); this.Value[2]={XValue:xValue,YValue:yValue}; this.PointCount=this.Point.length; //完成以后是3个点 linePoint={Start:new Point(), End:new Point() }; linePoint.Start.X=drawPoint[0].X; linePoint.Start.Y=drawPoint[0].Y-yMove/2; linePoint.End.X=drawPoint[1].X; linePoint.End.Y=drawPoint[1].Y-yMove/2; this.CenterLine.Line=linePoint; } } return drawPoint; } this.DrawArea=function(pt,pt2,pt3,pt4) { this.Canvas.fillStyle=this.AreaColor; this.Canvas.beginPath(); this.Canvas.moveTo(pt.X,pt.Y); this.Canvas.lineTo(pt2.X,pt2.Y); this.Canvas.lineTo(pt3.X,pt3.Y); this.Canvas.lineTo(pt4.X,pt4.Y); this.Canvas.closePath(); this.Canvas.fill(); } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint) return; this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); this.ClipFrame(); if (this.LinePoint.length==2) { this.DrawArea(this.LinePoint[0].Start,this.LinePoint[0].End,this.LinePoint[1].End,this.LinePoint[1].Start); } for(var i=0;i=this.Point.length) continue; pt.X=this.Point[i].X; pt.Y=this.Point[i].Y; } this.Canvas.beginPath(); this.Canvas.arc(pt.X,pt.Y,5,0,360); if (this.Canvas.isPointInPath(x,y)) return i; } //是否在线段上 for(var i in this.LinePoint) { var item=this.LinePoint[i]; var ptStart=item.Start; var ptEnd=item.End; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y+5); this.Canvas.lineTo(ptStart.X,ptStart.Y-5); this.Canvas.lineTo(ptEnd.X,ptEnd.Y-5); this.Canvas.lineTo(ptEnd.X,ptEnd.Y+5); this.Canvas.closePath(); if (this.Canvas.isPointInPath(x,y)) return 100; } return -1; } } //文本 function ChartDrawPictureText() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureText'; this.Text='文本'; this.PointCount=1; this.FontOption={ Family:'微软雅黑', Size:20, Weight:null, Style:null }; //Weight(bold 粗体), Style(italic) //矢量图片 //this.Text="\ue606"; //this.FontOption={ Family:'iconfont', Size:20, Weight:null, Style:null }; //Weight(bold 粗体), Style(italic) this.TextRect=null; //文字区域 this.IsInitialized=false; //是否初始化了 this.SettingMenu; this.HQChart; this.SetOption=function(option) { if (!option) return; if (option.LineColor) this.LineColor=option.LineColor; if (option.Text) this.Text=option.Text; if (option.FontOption) this.FontOption=option.FontOption; } this.Draw=function(textFont) { this.TextRect=null; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint || drawPoint.length!=1) return; this.ClipFrame(); this.Canvas.fillStyle=this.LineColor; this.Canvas.textAlign="center"; this.Canvas.textBaseline="bottom"; this.Canvas.font=this.GetTextFont(); this.Canvas.fillText(this.Text,drawPoint[0].X,drawPoint[0].Y); var textWidth=this.Canvas.measureText(this.Text).width; var textHeight=this.FontOption.Size*GetDevicePixelRatio(); this.TextRect={}; this.TextRect.Left=drawPoint[0].X-textWidth/2; this.TextRect.Top=drawPoint[0].Y-textHeight; this.TextRect.Width=textWidth; this.TextRect.Height=textHeight //this.Canvas.strokeRect(this.TextRect.Left,this.TextRect.Top,this.TextRect.Width,this.TextRect.Height); this.Canvas.restore(); if (this.IsInitialized===false) { this.SetTextOption(); this.IsInitialized=true; } } //根据设置动态生成字体 this.GetTextFont=function() { const defaultFont=16*GetDevicePixelRatio() +"px 微软雅黑"; if (!this.FontOption || !this.FontOption.Family || this.FontOption.Size<=0) return defaultFont; var font=''; if (this.FontOption.Color) font+=this.FontOption.Color+' '; if (this.FontOption.Style) font+=this.FontOption.Style+' '; if (this.FontOption.Weight) font+=this.FontOption.Weight+' '; if (this.FontOption.Size>=0) font+=this.FontOption.Size*GetDevicePixelRatio()+'px '; font+=this.FontOption.Family; return font; } this.SetTextOption=function() { JSConsole.Chart.Log('[ChartDrawPictureText::SetTextOption]'); //创建div设置窗口 if (!this.SettingMenu) this.SettingMenu=new ChartPictureTextSettingMenu(this.Frame.ChartBorder.UIElement.parentNode); this.SettingMenu.ChartPicture=this; this.SettingMenu.HQChart=this.HQChart; this.SettingMenu.Position={Left:this.TextRect.Left+this.TextRect.Width,Top:this.TextRect.Top}; this.SettingMenu.DoModal(); } this.IsPointIn=function(x,y) { if (!this.Frame || this.Status!=10) return -1; var data=this.Frame.Data; if (!data) return -1; if (!this.TextRect) return -1; this.Canvas.beginPath(); this.Canvas.rect(this.TextRect.Left,this.TextRect.Top,this.TextRect.Width,this.TextRect.Height); if (this.Canvas.isPointInPath(x,y)) return 100; return -1; } } //iconfont 图片 function ChartDrawPictureIconFont() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureIconFont'; this.PointCount=1; //矢量图片 this.Text="\ue606"; this.FontOption={ Family:'iconfont', Size:24}; //Weight(bold 粗体), Style(italic) this.TextRect=null; //文字区域 this.SettingMenu; this.Angle=0; //旋转角度 this.SetOption=function(option) { if (!option) return; if (option.LineColor) this.LineColor=option.LineColor; if (option.FontOption && option.FontOption.Size>0) this.FontOption.Size=option.FontOption.Size; if (IFrameSplitOperator.IsNumber(option.Angle)) this.Angle=option.Angle; } this.Draw=function() { this.TextRect=null; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint || drawPoint.length!=1) return; var font=this.GetTextFont(); if (!font) return; this.ClipFrame(); var isHScreen=this.Frame.IsHScreen; var pixel=GetDevicePixelRatio(); this.Canvas.fillStyle=this.LineColor; this.Canvas.textAlign="center"; this.Canvas.textBaseline="middle"; this.Canvas.font=font; if (isHScreen) { this.Canvas.translate(drawPoint[0].X, drawPoint[0].Y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(this.Text,0,0); } else { if (this.Angle!=0) { this.Canvas.translate(drawPoint[0].X, drawPoint[0].Y); this.Canvas.rotate(this.Angle*(Math.PI / 180)); this.Canvas.fillText(this.Text,0,0); } else { this.Canvas.fillText(this.Text,drawPoint[0].X,drawPoint[0].Y); } } var textWidth=this.Canvas.measureText(this.Text).width; this.TextRect={}; this.TextRect.Left=drawPoint[0].X-textWidth/2; this.TextRect.Top=drawPoint[0].Y-this.FontOption.Size*pixel; this.TextRect.Width=textWidth; this.TextRect.Height=this.FontOption.Size*pixel; //this.Canvas.strokeRect(this.TextRect.Left,this.TextRect.Top,this.TextRect.Width,this.TextRect.Height); this.Canvas.restore(); } //根据设置动态生成字体 this.GetTextFont=function() { if (!this.FontOption || !this.FontOption.Family || this.FontOption.Size<=0) return null; var font=''; if (this.FontOption.Size>=0) font+=this.FontOption.Size*GetDevicePixelRatio()+'px '; font+=this.FontOption.Family; return font; } this.IsPointIn=function(x,y) { if (!this.Frame || this.Status!=10) return -1; var data=this.Frame.Data; if (!data) return -1; if (!this.TextRect) return -1; var offset=0; if (this.Option && this.Option.Zoom>=1) { offset=this.Option.Zoom*GetDevicePixelRatio(); } this.Canvas.beginPath(); this.Canvas.rect(this.TextRect.Left-offset,this.TextRect.Top-offset,this.TextRect.Width+offset*2,this.TextRect.Height+offset*2); if (this.Canvas.isPointInPath(x,y)) return 100; return -1; } } //江恩角度线(Gann Fan),亦又称作甘氏线的 function ChartDrawPictureGannFan() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureGannFan'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.LinePoint=[]; this.Font=16*GetDevicePixelRatio() +"px 微软雅黑"; this.LineDash=[5,10]; this.EnableDottedLine=false; //辅助线是否使用虚线 this.EnableArea=true; //是否绘制面积图 this.IsShowTitle=true; this.Super_SetOption=this.SetOption; //父类函数 this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.Font) this.Font=option.Font; if (Array.isArray(option.LineDash)) this.LineDash=option.LineDash; if (IFrameSplitOperator.IsBool(option.EnableDottedLine)) this.EnableDottedLine=option.EnableDottedLine; if (IFrameSplitOperator.IsBool(option.EnableArea)) this.EnableArea=option.EnableArea; if (IFrameSplitOperator.IsBool(option.IsShowTitle)) this.IsShowTitle=option.IsShowTitle; } } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; if (drawPoint.length!=2) return; this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); this.ClipFrame(); var quadrant=this.GetQuadrant(drawPoint[0],drawPoint[1]); this.SetLineWidth(); if (quadrant===1 || quadrant===2 || quadrant===3 || quadrant===4) { this.CalculateLines(drawPoint[0],drawPoint[1],quadrant); if (this.EnableArea) this.DrawArea(); for(var i=0; iptEnd.Y) return 1; else if (ptStart.X>ptEnd.X && ptStart.Y>ptEnd.Y) return 2; else if (ptStart.X < ptEnd.X && ptStart.Y< ptEnd.Y) return 4; else return 3; } //isDotline 是否是虚线 this.DrawLine=function(ptStart,ptEnd,isDottedline) { if (isDottedline) this.Canvas.setLineDash(this.LineDash); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); if (isDottedline) this.Canvas.setLineDash([]); } this.DrawTitle=function(pt,text) { this.Canvas.fillStyle=this.LineColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; this.Canvas.font=this.Font; this.Canvas.fillText(text,pt.X,pt.Y); } this.DrawArea=function() { var lineStart=null,lineEnd=null; for(var i in this.LinePoint) { var item=this.LinePoint[i]; if (item.Text=='1:8') lineStart=this.LinePoint[i]; else if (item.Text=='8:1') lineEnd=this.LinePoint[i]; } if (!lineStart || !lineEnd) return; this.Canvas.fillStyle=this.AreaColor; this.Canvas.beginPath(); this.Canvas.moveTo(lineStart.End.X,lineStart.End.Y); this.Canvas.lineTo(lineStart.Start.X,lineStart.Start.Y); this.Canvas.lineTo(lineEnd.End.X,lineEnd.End.Y); this.Canvas.closePath(); this.Canvas.fill(); } //计算线段 this.CalculateLines=function(ptStart,ptEnd,quadrant) { if (!this.Frame) return false; var top=this.Frame.ChartBorder.GetTopEx(); var right=this.Frame.ChartBorder.GetRight(); var bottom=this.Frame.ChartBorder.GetBottom(); const SPLIT_LINE_VALUE=[0.5, 1.0/3, 0.25, 0.125, 2.0/3]; const SPLIT_LINE_X_TITLE=["1:2","1:3","1:4","1:8","2:3"]; const SPLIT_LINE_Y_TITLE=["2:1","3:1","4:1","8:1","3:2"]; var ptLineStart=new Point(); var ptLineEnd=new Point(); ptLineStart.X=ptStart.X; ptLineStart.Y=ptStart.Y; ptLineEnd.X=ptEnd.X; ptLineEnd.Y=ptEnd.Y; var lineWidth=Math.abs(ptStart.X-ptEnd.X); var lineHeight=Math.abs(ptStart.Y-ptEnd.Y); if (quadrant===1) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.Start, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(),Text:SPLIT_LINE_X_TITLE[i]}; line.PtEnd.Y=ptEnd.Y; line.PtEnd.X=ptStart.X+lineWidth*SPLIT_LINE_VALUE[i]; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.Start; this.LinePoint.push(line); } if (lineHeight>5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y-lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.Start; this.LinePoint.push(line); } } } else if (quadrant==2) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.Start, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(),Text:SPLIT_LINE_X_TITLE[i]}; line.PtEnd.Y=ptEnd.Y; line.PtEnd.X=ptStart.X-lineWidth*SPLIT_LINE_VALUE[i]; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.Start; this.LinePoint.push(line); } if (lineHeight>5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y-lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.Start; this.LinePoint.push(line); } } } else if (quadrant==3) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.End, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(),Text:SPLIT_LINE_X_TITLE[i]}; line.PtEnd.Y=ptEnd.Y; line.PtEnd.X=ptStart.X-lineWidth*SPLIT_LINE_VALUE[i]; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.End; this.LinePoint.push(line); } if (lineHeight>5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y+lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.End; this.LinePoint.push(line); } } } else if (quadrant==4) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.End, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(),Text:SPLIT_LINE_X_TITLE[i]}; line.PtEnd.Y=ptEnd.Y; line.PtEnd.X=ptStart.X+lineWidth*SPLIT_LINE_VALUE[i]; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.End; this.LinePoint.push(line); } if (lineHeight>5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y+lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.End; this.LinePoint.push(line); } } } else { return false; } return true; } } //江恩角度线(Gann Fan) 通达信版本 function ChartDrawPictureGannFanV2() { this.newMethod=ChartDrawPictureGannFan; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureGannFanV2'; this.EnableDottedLine=true; //辅助线是否使用虚线 this.LineDash=[4,8]; this.EnableArea=false; this.Super_CalculateLines=this.CalculateLines; this.CalculateLines=function(ptStart,ptEnd,quadrant) { if (!this.Super_CalculateLines(ptStart,ptEnd,quadrant)) return false; var border=this.Frame.ChartBorder.GetBorder(); if (quadrant==1) { var line={ Start:ptStart, End:{ X:border.Right, Y:ptStart.Y}, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); var line={ Start:ptStart, End:{ X:ptStart.X, Y:border.TopEx }, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); } else if (quadrant==2) { var line={ Start:ptStart, End:{ X:ptStart.X, Y:border.TopEx }, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); var line={ Start:ptStart, End:{ X:border.Left, Y:ptStart.Y}, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); } else if (quadrant==3) { var line={ Start:ptStart, End:{ X:border.Left, Y:ptStart.Y}, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); var line={ Start:ptStart, End:{ X:ptStart.X, Y:border.BottomEx }, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); } else if (quadrant==4) { var line={ Start:ptStart, End:{ X:ptStart.X, Y:border.BottomEx }, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); var line={ Start:ptStart, End:{ X:border.Right, Y:ptStart.Y}, IsDottedLine:false, PtEnd:null, Text:null }; this.LinePoint.push(line); } } } //阻速线 (高 3等份) function ChartDrawPictureResistanceLine() { this.newMethod=ChartDrawPictureGannFan; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureResistanceLine'; //计算线段 this.CalculateLines=function(ptStart,ptEnd,quadrant) { if (!this.Frame) return false; var top=this.Frame.ChartBorder.GetTopEx(); var right=this.Frame.ChartBorder.GetRight(); var bottom=this.Frame.ChartBorder.GetBottom(); const SPLIT_LINE_VALUE=[1.0/3, 2.0/3]; const SPLIT_LINE_Y_TITLE=["3:1","3:2"]; var ptLineStart=new Point(); var ptLineEnd=new Point(); ptLineStart.X=ptStart.X; ptLineStart.Y=ptStart.Y; ptLineEnd.X=ptEnd.X; ptLineEnd.Y=ptEnd.Y; var lineWidth=Math.abs(ptStart.X-ptEnd.X); var lineHeight=Math.abs(ptStart.Y-ptEnd.Y); if (quadrant===1) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.Start, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y-lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.Start; this.LinePoint.push(line); } } } else if (quadrant==2) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.Start, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y-lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.Start; this.LinePoint.push(line); } } } else if (quadrant==3) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.End, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y+lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.End; this.LinePoint.push(line); } } } else if (quadrant==4) { var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); var line={Start:ptLineStart, End:extendLine.End, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); for(var i=0;i5) { line={Start:ptLineStart, End:null, IsDottedLine:this.EnableDottedLine,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; line.PtEnd.Y=ptStart.Y+lineHeight*SPLIT_LINE_VALUE[i]; line.PtEnd.X=ptEnd.X; var extendLine=this.CalculateExtendLinePoint(line.Start,line.PtEnd); line.End=extendLine.End; this.LinePoint.push(line); } } } else { return false; } return true; } this.DrawArea=function() { var lineStart=null,lineEnd=null; for(var i in this.LinePoint) { var item=this.LinePoint[i]; if (item.Text=='1:1') lineStart=this.LinePoint[i]; else if (item.Text=='3:1') lineEnd=this.LinePoint[i]; } if (!lineStart || !lineEnd) return; this.Canvas.fillStyle=this.AreaColor; this.Canvas.beginPath(); this.Canvas.moveTo(lineStart.End.X,lineStart.End.Y); this.Canvas.lineTo(lineStart.Start.X,lineStart.Start.Y); this.Canvas.lineTo(lineEnd.End.X,lineEnd.End.Y); this.Canvas.closePath(); this.Canvas.fill(); } } //阻速线2 (高 3等份)通达信版本 function ChartDrawPictureResistanceLineV2() { this.newMethod=ChartDrawPictureResistanceLine; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureResistanceLineV2'; this.EnableDottedLine=true; //辅助线是否使用虚线 this.LineDash=[4,8]; this.EnableArea=false; this.IsShowTitle=false; } //黄金分割线 function ChartDrawPictureGoldenSection() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureGoldenSection'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.Font=14*GetDevicePixelRatio() +"px 微软雅黑"; this.GetSectionData=function() { const GOLDEN_SECTION_DATA= [0,0.236,0.382,0.5,0.618,0.80,1,1.236,1.382,1.5,1.618,1.8,2]; return GOLDEN_SECTION_DATA; } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint) return; if (drawPoint.length!=2) return; this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); this.CalculateLines(drawPoint[0],drawPoint[1]); this.ClipFrame(); this.SetLineWidth(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End,item.IsDottedLine); } this.RestoreLineWidth(); for(var i in this.LinePoint) { var item =this.LinePoint[i]; if (item.Text) this.DrawTitle(item.Start,item.Text); } this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.CalculateHSCreenLines=function(ptStart,ptEnd) { var sectionData=this.GetSectionData(); var left=this.Frame.ChartBorder.GetTop(); var right=this.Frame.ChartBorder.GetBottom(); var lineHeight=ptStart.X-ptEnd.X; for(var i=0;i=0) return value; if (this.CircleData && this.CircleData.R>8) { var triangleX=this.CircleData.X-x; var triangleY=this.CircleData.Y-y; var r=Math.sqrt(triangleX*triangleX+triangleY*triangleY); //计算直径 if (rthis.CircleData.R-8) return 100; } return -1; } } //四边形 function ChartDrawPictureQuadrangle() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureQuadrangle'; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.PointCount=3; this.LastPoint; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.3); var points=drawPoint.slice(0); this.CalculateLines(points); this.ClipFrame(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End); } this.DrawArea(); this.DrawPoint(points); //画点 this.Canvas.restore(); } this.SetLastPoint=function(obj) { this.LastPoint={X:obj.X,Y:obj.Y}; } this.DrawArea=function() { if (this.LinePoint.length!=4) return; this.Canvas.fillStyle=this.AreaColor; this.Canvas.beginPath(); this.Canvas.moveTo(this.LinePoint[0].Start.X,this.LinePoint[0].Start.Y); this.Canvas.lineTo(this.LinePoint[0].End.X,this.LinePoint[0].End.Y); this.Canvas.lineTo(this.LinePoint[1].End.X,this.LinePoint[1].End.Y); this.Canvas.lineTo(this.LinePoint[2].End.X,this.LinePoint[2].End.Y); this.Canvas.closePath(); this.Canvas.fill(); } this.CalculateLines=function(points) { if (this.PointStatus==2 && this.LastPoint) { var pt=new Point(); pt.X=this.LastPoint.X; pt.Y=this.LastPoint.Y; points[2]=pt; } if (points.length==2) { var linePoint=this.CreateLineData(points[0],points[1]); this.LinePoint.push(linePoint); } else if (points.length==3) { var linePoint=this.CreateLineData(points[0],points[1]); this.LinePoint.push(linePoint); var linePoint=this.CreateLineData(points[1],points[2]); this.LinePoint.push(linePoint); //计算平行线 var xMove=points[2].X-points[1].X; var yMove=points[2].Y-points[1].Y; var pt4=new Point(); //第4个点的坐标 pt4.X=points[0].X+xMove; pt4.Y=points[0].Y+yMove; var linePoint=this.CreateLineData(points[2],pt4); this.LinePoint.push(linePoint); var linePoint=this.CreateLineData(pt4,points[0]); this.LinePoint.push(linePoint); } } } //斐波那契周期线 function ChartDrawPictureFibonacci() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPictureFibonacci'; this.PointCount=1; this.Font=14*GetDevicePixelRatio() +"px 微软雅黑"; this.IsPointIn=this.IsPointIn_XYValue_Line; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint) return; this.CalculateLines(); if (this.LinePoint.length<=0) return; this.ClipFrame(); this.SetLineWidth(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End); this.DrawTitle(item.Start,item.Title); } this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.DrawTitle=function(pt,text) { this.Canvas.fillStyle=this.LineColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; this.Canvas.font=this.Font; if (this.Frame.IsHScreen) { this.Canvas.save(); this.Canvas.translate(pt.X,pt.Y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,2,10); this.Canvas.restore(); } else { this.Canvas.fillText(text,pt.X+2,pt.Y+10); } } this.CalculateHSCreenLines=function() { var data=this.Frame.Data; if (!data) return; var xStart=null; if (this.Status==10) { if (this.Value.length!=1) return; xStart=this.Value[0].XValue; } else { if (this.Point.length!=1) return; xStart=parseInt(this.Frame.GetXData(this.Point[0].Y))+data.DataOffset; } var top=this.Frame.ChartBorder.GetRightEx(); var bottom=this.Frame.ChartBorder.GetLeftEx(); var showCount=this.Frame.XPointCount; const LINE_DATA=[1,2,3,5,8,13,21,34,55,89,144,233]; for(var i=0;i=showCount) continue; var x=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); var line={Start:new Point(), End:new Point(), Title:LINE_DATA[i]}; line.Start.X=top; line.Start.Y=x; line.End.X=bottom; line.End.Y=x; this.LinePoint.push(line); } } this.CalculateLines=function() { if (this.Status<2) return; if (!this.Frame) return; var data=this.Frame.Data; if (!data) return; if (this.Frame.IsHScreen) { this.CalculateHSCreenLines(); return; } var xStart=null; if (this.Status==10) { if (this.Value.length!=1) return; xStart=this.Value[0].XValue; } else { if (this.Point.length!=1) return; xStart=parseInt(this.Frame.GetXData(this.Point[0].X))+data.DataOffset; } var top=this.Frame.ChartBorder.GetTopEx(); var bottom=this.Frame.ChartBorder.GetBottom(); var showCount=this.Frame.XPointCount; const LINE_DATA=[1,2,3,5,8,13,21,34,55,89,144,233]; for(var i=0;i=showCount) continue; var x=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); var line={Start:new Point(), End:new Point(), Title:LINE_DATA[i]}; line.Start.Y=top; line.Start.X=x; line.End.Y=bottom; line.End.X=x; this.LinePoint.push(line); } } } //线性回归 function ChartDrawLinearRegression(option) { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawLinearRegression'; this.PointCount=2; this.IsPointIn=this.IsPointIn_XYValue_Line; this.ChartBorder; this.Lines=[]; //回归线 { XValue:, YValue: } this.IsShowMaxMinLine=false; //是否显示最高 最低价通道 this.IsShowExtendLine=false; //是否显示延长线 this.ExtendLineDash=[5,5]; //延长线虚线 this.MaxPoint; this.MinPoint; if (option) { if (option.IsShowMaxMinLine==true) this.IsShowMaxMinLine=true; if (option.IsShowExtendLine==true) this.IsShowExtendLine=true; } //导入 this.ImportStorageData=function(storageData) { if (storageData.IsShowMaxMinLine==true) this.IsShowMaxMinLine=true; if (storageData.IsShowExtendLine==true) this.IsShowExtendLine=true; if (storageData.Lines) this.Lines=storageData.Lines; if (storageData.MaxPoint && storageData.MinPoint) { this.MaxPoint=storageData.MaxPoint; this.MinPoint=storageData.MinPoint; } } //导出 this.Super_ExportStorageData=this.ExportStorageData; this.ExportStorageData=function() { var storageData; if (this.Super_ExportStorageData) { storageData=this.Super_ExportStorageData(); storageData.IsShowMaxMinLine=this.IsShowMaxMinLine; storageData.IsShowExtendLine=this.IsShowExtendLine; storageData.Lines=this.Lines; if (this.IsShowMaxMinLine) { storageData.MaxPoint=this.MaxPoint; storageData.MinPoint=this.MinPoint; } } return storageData; } this.PointToValue_Backup=this.PointToValue; this.PointToValue=function() { //拖拽完成 把点移动到线段头尾 this.Point[0]={X:this.Lines[0].X, Y:this.Lines[0].Y}; this.Point[1]={X:this.Lines[this.Lines.length-1].X, Y:this.Lines[this.Lines.length-1].Y}; this.PointToValue_Backup(); } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:true, IsCheckY:true} ); if (!drawPoint || drawPoint.length!=2) { if (this.Status==10) { this.ClipFrame(); this.ChartBorder=this.Frame.ChartBorder; this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.DrawLinearLines(); this.RestoreLineWidth(); this.Canvas.restore(); } return; } this.ClipFrame(); this.ChartBorder=this.Frame.ChartBorder; //0=开始画 1=完成第1个点 2=完成第2个点 3=完成第3个点 10=完成 20=移动) this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; if (this.Status==10) { this.DrawLinearLines(); } else { var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); var kPoint=this.PointToKLine([ptStart,ptEnd]); //JSConsole.Chart.Log('[ChartDrawLinearRegression::Draw] kPoint', kPoint); var linear=this.Calculate(kPoint); //JSConsole.Chart.Log('[ChartDrawLinearRegression::Draw] linear', linear); this.Lines=linear.Points; this.MaxPoint=linear.Max; this.MinPoint=linear.Min; this.DrawLinearLines(); this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,top); this.Canvas.lineTo(ptStart.X,bottom); this.Canvas.moveTo(ptEnd.X,top); this.Canvas.lineTo(ptEnd.X,bottom); this.Canvas.stroke(); } this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.Calculate=function(kPoint) { var startPoint=kPoint[0]; var endPoint=kPoint[1]; if (startPoint.XValue>endPoint.XValue) { startPoint=kPoint[1]; endPoint=kPoint[0]; } var num=(endPoint.XValue-startPoint.XValue)+1; var data=this.Frame.Data.Data; var i=endPoint.XValue; var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope; var i, j,x, k; for(j = 0, x=num; j < num && j <= i; ++j, --x) { Ex += x; Ey += data[i - j].Close; } Ex /= num; Ey /= num; for(j = 0, x=num; j < num && j <= i; ++j,--x) { Sxy += (x-Ex)*(data[i-j].Close-Ey); Sxx += (x-Ex)*(x-Ex); } Slope = Sxy / Sxx; //斜率 Const = Ey - Ex*Slope; //value=Slope * num + Const; //Y轴值 线性回归公式 var points=[]; var max=null, min=null; for(j = 0, k=num; j < num && j <= i; ++j,--k) { var xIndex=endPoint.XIndex-j; var xValue=endPoint.XValue-j; var x=this.Frame.GetXFromIndex(xIndex); var yValue=Slope * k + Const; var y=this.Frame.GetYFromData(yValue,false); var item={ X:x, Y:y, XValue:xValue, YValue:yValue }; points.push(item); if (max==null || max.Highdata[xValue].Low) { min={X:x,Y:y,XValue:xValue, YValue:yValue, Low:data[xValue].Low }; } } return { Points:points, Slope:Slope, Const:Const , Max:max, Min:min }; } this.DrawLinearLines=function() { if (!this.Frame) return null; var data=this.Frame.Data; if (!data) return null; var showCount=this.Frame.XPointCount; var dataOffset=data.DataOffset; var isHScreen=this.Frame.IsHScreen; var drawLines=[]; for(var i in this.Lines) { var item=this.Lines[i]; var dataIndex=item.XValue-dataOffset; if (dataIndex<0 || dataIndex>=showCount) continue; var pt={}; if (isHScreen) //横屏X,Y对调 { } else { pt.X=this.Frame.GetXFromIndex(dataIndex,false); pt.Y=this.Frame.GetYFromData(item.YValue,false); pt.YValue=item.YValue; } drawLines.push(pt); } if (drawLines.length>1) { for(var i in drawLines) { var item=drawLines[i]; if (i==0) { this.Canvas.beginPath(); this.Canvas.moveTo(item.X,item.Y); } else { this.Canvas.lineTo(item.X,item.Y); if (i==drawLines.length-1) this.Canvas.stroke(); } } this.DrawExtendLine(drawLines); } //最大 最小通道 if (this.IsShowMaxMinLine && drawLines.length>1 && this.MaxPoint && this.MinPoint) { var highOffset=this.MaxPoint.High-this.MaxPoint.YValue; for(var i in drawLines) { var item=drawLines[i]; item.Y=this.Frame.GetYFromData((item.YValue+highOffset),false); if (i==0) { this.Canvas.beginPath(); this.Canvas.moveTo(item.X,item.Y); } else { this.Canvas.lineTo(item.X,item.Y); if (i==drawLines.length-1) this.Canvas.stroke(); } } this.DrawExtendLine(drawLines); var lowOffset=this.MinPoint.Low-this.MinPoint.YValue; for(var i in drawLines) { var item=drawLines[i]; item.Y=this.Frame.GetYFromData((item.YValue+lowOffset),false); if (i==0) { this.Canvas.beginPath(); this.Canvas.moveTo(item.X,item.Y); } else { this.Canvas.lineTo(item.X,item.Y); if (i==drawLines.length-1) this.Canvas.stroke(); } } this.DrawExtendLine(drawLines); } } //画延长线 this.DrawExtendLine=function(lines) { if (!this.IsShowExtendLine) return; var ptStart=lines[0]; var ptEnd=lines[lines.length-1]; var aryPoint; if (ptEnd.X>ptStart.X) aryPoint=[ptStart, ptEnd]; else aryPoint=[ptEnd, ptStart]; var ptExtend=this.CalculateExtendLineEndPoint(aryPoint); this.Canvas.beginPath(); this.Canvas.moveTo(ptEnd.X,ptEnd.Y); this.Canvas.lineTo(ptExtend.X,ptExtend.Y); this.Canvas.setLineDash(this.ExtendLineDash); this.Canvas.stroke(); this.Canvas.setLineDash([]); } } //尺子 function ChartDrawRuler() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawRuler'; this.PointCount=2; this.Font=16*GetDevicePixelRatio() +"px 微软雅黑"; this.IsPointIn=this.IsPointIn_XYValue_Line; this.TitleColor=g_JSChartResource.ChartDrawRuler.TitleColor; this.IsHScreen=false; this.Draw=function() { this.LinePoint=[]; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.IsHScreen=this.Frame.IsHScreen; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; var kPoint=this.PointToKLine([ptStart,ptEnd]); //JSConsole.Chart.Log('[ChartDrawLinearRegression::ChartDrawRuler] kPoint', kPoint); var kDataInfo=this.Calculate(kPoint); //JSConsole.Chart.Log('[ChartDrawLinearRegression::ChartDrawRuler] kDataInfo', kDataInfo); var increase=IFrameSplitOperator.IsNumber(kDataInfo.Increase)? kDataInfo.Increase.toFixed(2)+'%': "--"; var risefall=IFrameSplitOperator.IsNumber(kDataInfo.Risefall)? kDataInfo.Risefall.toFixed(2): "--"; var title=`间距:${kDataInfo.Count} 涨跌:${risefall} 涨幅:${increase}`; //JSConsole.Chart.Log('[ChartDrawLinearRegression::ChartDrawRuler] title', title); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 //绘制信息 this.Canvas.textBaseline='bottom'; this.Canvas.textAlign='left'; this.Canvas.font=this.Font; if (this.TitleColor) { this.Canvas.fillStyle=this.TitleColor; } else if (IFrameSplitOperator.IsNumber(kDataInfo.Increase)) { if (kDataInfo.Increase>0) this.Canvas.fillStyle=g_JSChartResource.UpTextColor; else if (kDataInfo.Increase<0) this.Canvas.fillStyle=g_JSChartResource.DownTextColor; else this.Canvas.fillStyle=g_JSChartResource.UnchagneTextColor; } else { this.Canvas.fillStyle=g_JSChartResource.UnchagneTextColor; } var offset=3*GetDevicePixelRatio(); var xText=ptStart.X var yText=ptStart.Y if (this.IsHScreen) { this.Canvas.translate(xText+offset,yText+offset); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(title,0,0); } else { this.Canvas.fillText(title,xText+offset,yText-offset); } this.Canvas.restore(); } this.Calculate=function(kPoint) { var startPoint=kPoint[0]; var endPoint=kPoint[1]; if (startPoint.XValue>endPoint.XValue) { startPoint=kPoint[1]; endPoint=kPoint[0]; } var data=this.Frame.Data.Data; var open, high, low, yClose, close; var count=0; for(var i=startPoint.XValue;i<=endPoint.XValue;++i, ++count) { var item=data[i]; if (count==0) { yClose=item.YClose; open=item.Open; close=item.Close; low=item.Low; high=item.High; } else { close=item.Close; if (low>item.Low) low=item.Low; if (high=0 && indexright) return; var bottom=chartBorder.GetBottom(); var ptEnd={X:ptStart.X, Y:bottom}; var price=this.Frame.GetYData(ptStart.X, false); } else { var bottom=chartBorder.GetBottomEx(); var top=chartBorder.GetTopEx(); if (ptStart.Ybottom) return; var right=chartBorder.GetRight(); var ptEnd={X:right, Y:ptStart.Y}; var price=this.Frame.GetYData(ptStart.Y, false); } this.ClipFrame(); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.textBaseline='bottom'; this.Canvas.textAlign='left'; this.Canvas.fillStyle=this.LineColor; this.Canvas.font=this.Font; var offset=2*GetDevicePixelRatio(); var xText=ptStart.X; var yText=ptStart.Y; if (this.IsHScreen) { this.Canvas.translate(xText+offset,yText+offset); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(price.toFixed(2),0,0); } else { this.Canvas.fillText(price.toFixed(2),xText+offset,yText-offset); } this.Canvas.restore(); } } //画图工具-标价线2 支持横屏 支持价格文字在坐标内部显示 function ChartDrawPriceLineV2() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawPriceLineV2'; this.Font=12*GetDevicePixelRatio() +"px 微软雅黑"; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.LineWidth=1; this.IsDrawFirst=true; this.TextColor="rgb(255,255,255)"; this.Title; //标题 this.TextPosition=[null, 0]; //[0]=左侧(没有做) [1]=右侧 0=自动 1=内部 2=外部 this.Super_SetOption=this.SetOption; //父类函数 this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.TextColor) this.TextColor=option.TextColor; if (option.Title) this.Title=option.Title; if (IFrameSplitOperator.IsNonEmptyArray(option.TextPosition)) this.TextPosition=option.TextPosition.slice(); } } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:true } ); if (!drawPoint) return; if (drawPoint.length!=1) return; if (!this.IsYValueInFrame(this.Value[0].YValue)) return; this.IsHScreen=this.Frame.IsHScreen; var chartBorder=this.Frame.ChartBorder; var border=this.Frame.GetBorder(); if (this.IsHScreen) { var left=border.LeftEx; var right=border.RightEx; var bottom=border.Bottom; var top=border.Top; var ptStart={ X:drawPoint[0].X, Y:top }; if (ptStart.Xright) return; var ptEnd={X:drawPoint[0].X, Y:bottom }; var price=this.Frame.GetYData(ptStart.X, false); } else { var bottom=border.BottomEx; var top=border.TopTitle; var left=border.Left; var right=border.Right; var ptStart={ X:left, Y:drawPoint[0].Y }; if (ptStart.Ybottom) return; var ptEnd={ X:right, Y:drawPoint[0].Y }; var price=this.Frame.GetYData(ptStart.Y, false); } //this.ClipFrame(); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(ptStart.X),ToFixedPoint(ptStart.Y)); this.Canvas.lineTo(ToFixedPoint(ptEnd.X),ToFixedPoint(ptEnd.Y)); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); var pixelTatio = GetDevicePixelRatio(); this.Canvas.font=this.Font; var offset=2*pixelTatio; var xText=ptEnd.X; var yText=ptEnd.Y; this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; var textHeight=this.GetFontHeight(); var text=price.toFixed(2); var textWidth=this.Canvas.measureText(text).width+2*offset; var centerPoint=null; if (this.IsHScreen) { var position=this.TextPosition[1]; var bDrawInside=false; //在内部绘制 if (position==0) bDrawInside=chartBorder.Bottom<=10; else if (position==1) bDrawInside=true; else if (position==2) bDrawInside=false; if (bDrawInside) { yText=yText-textWidth; var rtBG={ Left:(xText-textHeight/2), Top:yText , Width:textHeight, Height: textWidth}; } else //框架内部显示 { var rtBG={ Left:(xText-textHeight/2), Top:yText , Width: textHeight, Height:textWidth }; } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.save(); this.Canvas.translate(xText,yText+1*pixelTatio); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,0,0); this.Canvas.restore(); if (this.Title) { var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio; if (bDrawInside) { var rtTitle={Left:rtBG.Left, Top:rtBG.Top-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth}; } else { var rtTitle={ Left:rtBG.Left, Top:bottom-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth }; } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtTitle.Left, rtTitle.Top, rtTitle.Width, rtTitle.Height); this.Canvas.save(); this.Canvas.translate(xText,rtTitle.Top+1*pixelTatio); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(this.Title,0,0); this.Canvas.restore(); } centerPoint={ X:ptStart.X, Y:ptStart.Y+(ptEnd.Y-ptStart.Y)/2 }; //中心点 } else { var position=this.TextPosition[1]; var bDrawInside=false; //在内部绘制 if (position==0) bDrawInside=chartBorder.Right<=10; else if (position==1) bDrawInside=true; else if (position==2) bDrawInside=false; if (bDrawInside) { var rtBG={ Left:xText-textWidth, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight}; } else //框架内部显示 { var rtBG={ Left:xText, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight}; if (rtBG.Left+rtBG.Width>border.ChartWidth) rtBG.Left=border.ChartWidth-rtBG.Width-2*pixelTatio; } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text, rtBG.Left+offset, yText); if (this.Title) { var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio; if (bDrawInside) { var rtTitle={Left:rtBG.Left-textWidth, Top:rtBG.Top, Width:textWidth, Height:textHeight} } else { var rtTitle={ Left:right-textWidth-1*pixelTatio, Top:rtBG.Top, Width:textWidth, Height:textHeight }; if (rtBG.Left!=right) rtTitle.Left=rtBG.Left-textWidth-1*pixelTatio; } this.Canvas.fillStyle=this.LineColor; this.Canvas.fillRect(rtTitle.Left, rtTitle.Top, rtTitle.Width, rtTitle.Height); this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(this.Title, rtTitle.Left+1*pixelTatio, yText); } centerPoint={ X:ptStart.X+(ptEnd.X-ptStart.X)/2, Y:ptStart.Y }; //中心点 } if (centerPoint) this.DrawPoint([centerPoint]); } this.DrawPrice=function() { } } //画图工具-竖线 支持横屏 function ChartDrawVerticalLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawVerticalLine'; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.GetXYCoordinate=this.GetXYCoordinate_default; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; if (!this.Frame || !this.Frame.Data) return; var data=this.Frame.Data; var drawPoint=this.CalculateDrawPoint( { IsCheckX:true, IsCheckY:true } ); if (!drawPoint) return; if (drawPoint.length!=1) return; this.IsHScreen=this.Frame.IsHScreen; var pt=drawPoint[0]; var chartBorder=this.Frame.ChartBorder; if (this.IsHScreen) { var xValue=Math.round(this.Frame.GetXData(pt.Y,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var yLine=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); yLine=ToFixedPoint2(this.LineWidth,yLine); var left=chartBorder.GetLeftEx(); var right=chartBorder.GetRightEx(); var ptStart={ X:left, Y:yLine }; var ptEnd={ X:right, Y:yLine }; } else { var xValue=Math.round(this.Frame.GetXData(pt.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var xLine=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); xLine=ToFixedPoint2(this.LineWidth,xLine); var top=chartBorder.GetTopEx(); var bottom=chartBorder.GetBottomEx(); var ptStart={ X:xLine, Y:top }; var ptEnd={ X:xLine, Y:bottom }; } this.ClipFrame(); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; this.LinePoint.push(line); if (this.Status==10) this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } } //画图工具-十字线 支持横屏 function ChartDrawCrosshair() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawCrosshair'; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.GetXYCoordinate=this.GetXYCoordinate_default; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; if (!this.Frame || !this.Frame.Data) return; var data=this.Frame.Data; var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:false } ); if (!drawPoint) return; if (drawPoint.length!=1) return; this.IsHScreen=this.Frame.IsHScreen; var pt=drawPoint[0]; var chartBorder=this.Frame.ChartBorder; var border=this.Frame.GetBorder(); if (this.IsHScreen) { var xValue=Math.round(this.Frame.GetXData(pt.Y,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var yLine=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); yLine=ToFixedPoint2(this.LineWidth,yLine); var xLine=ToFixedPoint2(this.LineWidth,pt.X); var left=border.LeftEx var right=border.RightEx var top=border.Top; var bottom=border.Bottom; var ptStart={ X:left, Y:yLine }; var ptEnd={ X:right, Y:yLine }; var ptStart2={ X:xLine, Y:top }; var ptEnd2={ X:xLine, Y:bottom }; } else { var xValue=Math.round(this.Frame.GetXData(pt.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var xLine=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); xLine=ToFixedPoint2(this.LineWidth,xLine); var yLine=ToFixedPoint2(this.LineWidth, pt.Y); var top=border.TopEx; var bottom=border.BottomEx; var left=border.Left; var right=border.Right; var ptStart={ X:xLine, Y:top }; var ptEnd={ X:xLine, Y:bottom }; var ptStart2={ X:left, Y:yLine }; var ptEnd2={ X:right, Y:yLine }; } this.ClipFrame(); this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,ptStart.Y); this.Canvas.lineTo(ptEnd.X,ptEnd.Y); this.Canvas.moveTo(ptStart2.X, ptStart2.Y); this.Canvas.lineTo(ptEnd2.X,ptEnd2.Y); this.Canvas.stroke(); this.RestoreLineWidth(); var line={Start:ptStart, End:ptEnd}; var line2={Start:ptStart2, End:ptEnd2}; this.LinePoint.push(line); this.LinePoint.push(line2); if (this.Status==10) this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } } //画图工具-监测线 function ChartDrawMonitorLine() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawMonitorLine'; this.PointCount=1; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.GetXYCoordinate=this.GetXYCoordinate_default; this.FormatLabelTextCallback=null; this.LineColor='rgb(255,215,0)' this.LabelConfig= { Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, BGColor:"rgb(30,144,255)", LineColor:"rgba(255,215,0,0.8)", LineDash:[3,5], Mergin:{ Left:5, Right:5, Top:5, Bottom:4 }, LineSpace:5, //行间距 TextAlign:1, //对齐方式 0=left 1=right } this.PointToValue_Backup=this.PointToValue; this.PointToValue=function() { if (!this.PointToValue_Backup()) return false; if (this.Frame.IsKLineFrame(false)) { if (this.Frame.Identify===0) { var dataIndex=this.Value[0].XValue; var data=this.Frame.Data; var kItem=data.Data[dataIndex]; this.Value[0].YValue=kItem.Close; //使用收盘价 } } return true; } this.SetOption=function(option) { if (option.LineColor) this.LineColor=option.LineColor; if (option.Label) { var item=option.Label; var dest=this.LabelConfig if (item.Font) dest.Font=item.Font; if (item.BGColor) dest.BGColor=item.BGColor; if (item.LineColor) dest.LineColor=item.LineColor; if (item.LineDash) dest.LineDash=item.LineDash; if (IFrameSplitOperator.IsNumber(item.LineSpace)) dest.LineSpace=item.LineSpace; if (IFrameSplitOperator.IsNumber(item.TextAlign)) dest.TextAlign=item.TextAlign; if (item.Mergin) CopyMarginConfig(dest.Mergin, item.Mergin); } if (option.FormatLabelTextCallback) this.FormatLabelTextCallback=option.FormatLabelTextCallback; } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; if (!this.Frame || !this.Frame.Data) return; var data=this.Frame.Data; if (!IFrameSplitOperator.IsNonEmptyArray(data.Data)) return; if (this.Point.length!=1) return; if (this.Value.length!=1) return; this.IsHScreen=this.Frame.IsHScreen; if (this.IsHScreen) return; if (this.Status==20) this.DrawMoveLine(); else if (this.Status==10) this.DrawMonitorLine(data); } this.DrawMoveLine=function() { var border=this.Frame.ChartBorder.GetBorder(); var pt=this.Point[0]; var x=ToFixedPoint(pt.X); this.ClipFrame(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,border.TopEx); this.Canvas.lineTo(x,border.BottomEx); this.Canvas.stroke(); this.Canvas.restore(); } this.DrawMonitorLine=function(data) { var isMinute=this.Frame.IsMinuteFrame(); var dataWidth=this.Frame.DataWidth; var distanceWidth=this.Frame.DistanceWidth; var xPointCount=this.Frame.XPointCount; if (this.IsHScreen) { //var border=this.Frame.ChartBorder.GetHScreenBorder(); //var chartright=border.BottomEx; //var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; } else { var border=this.Frame.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; } var ptData=this.Value[0]; this.ClipFrame(); var labelInfo=null; for(var i=data.DataOffset,j=0;ichartright) break; var x=left+(right-left)/2; } if (i==ptData.XValue) //起始 { this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,border.TopEx); this.Canvas.lineTo(x,border.BottomEx); this.Canvas.stroke(); var line={Start:{X:x, Y:border.TopEx}, End:{X:x, Y:border.BottomEx}}; this.LinePoint.push(line); } else if (i==data.Data.length-1) //结束 { if (this.LabelConfig.LineDash) this.Canvas.setLineDash(this.LabelConfig.LineDash); this.Canvas.strokeStyle=this.LabelConfig.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,border.TopEx); this.Canvas.lineTo(x,border.BottomEx); this.Canvas.stroke(); if (this.LabelConfig.LineDash) this.Canvas.setLineDash([]); labelInfo={ Left:right, Data:data, StartIndex:ptData.XValue, AryText:[] }; } } this.Canvas.restore(); if (labelInfo) this.DrawLabel(labelInfo); } this.DrawLabel=function(labelInfo) { if (!this.FormatLabelTextCallback) return; labelInfo.Config=this.LabelConfig; this.FormatLabelTextCallback(labelInfo); if (!IFrameSplitOperator.IsNonEmptyArray(labelInfo.AryText)) return; if (!IFrameSplitOperator.IsNumber(labelInfo.YValue)) return; /* labelInfo.YValue=7.15; labelInfo.AryText= [ { Name:"标题1:", Text:"6666", NameColor:"rgb(255,255,255)", TextColor:"rgb(30,10,30)" }, { Name:"标题2:", Text:"08.00", NameColor:"rgb(255,255,255)", TextColor:"rgb(30,10,30)" }, { Name:"标题3:", Text:"999.1", NameColor:"rgb(255,255,255)", TextColor:"rgb(30,10,30)" }, { Name:"标题4:", Text:"320" , NameColor:"rgb(255,255,255)", TextColor:"rgb(30,10,30)"}, { Name:"标题5:", Text:"77775.77", NameColor:"rgb(255,255,255)", TextColor:"rgb(30,10,30)" } ] */ this.CalculateLabelSize(labelInfo); var y=this.Frame.GetYFromData(labelInfo.YValue,false); var rtBG={ Left:labelInfo.Left+1, Top:y, Width:labelInfo.Width, Height:labelInfo.Height }; rtBG.Right=rtBG.Left+rtBG.Width; rtBG.Bottom=rtBG.Top+rtBG.Height; this.DrawDefaultLabel(labelInfo, rtBG); } } //画图工具-波浪尺 function ChartDrawWaveRuler() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawWaveRuler'; this.PointCount=3; this.Font=16*GetDevicePixelRatio() +"px 微软雅黑"; this.IsPointIn=this.IsPointIn_XYValue_Line; this.LastPoint; this.LinePoint; this.ScaleRuler=g_JSChartResource.ChartDrawWaveRuler.ScaleRuler; this.RulerWidth=g_JSChartResource.ChartDrawWaveRuler.RulerWidth;; //刻度尺长度 this.RulerLineWidth=g_JSChartResource.ChartDrawWaveRuler.RulerLineWidth; this.MaxScaleRuler=g_JSChartResource.ChartDrawWaveRuler.MaxScaleRuler; //尺子最大的高度比 this.Font=g_JSChartResource.ChartDrawWaveRuler.MaxScaleRuler; this.IsHScreen=false; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; this.IsHScreen=this.Frame.IsHScreen; this.CalculateLines(drawPoint); this.ClipFrame(); this.SetLineWidth(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End); } //绘制波浪信息 if (drawPoint.length==3) this.DrawWaveRuler(drawPoint); this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.SetLastPoint=function(obj) { this.LastPoint={X:obj.X,Y:obj.Y}; } this.CalculateLines=function(points) { if (this.PointStatus==2 && this.LastPoint) { var pt=new Point(); pt.X=this.LastPoint.X; pt.Y=this.LastPoint.Y; points[2]=pt; } if (points.length==2) { var linePoint= { Start:{X:points[0].X,Y:points[0].Y}, End:{X:points[1].X,Y:points[1].Y} }; this.LinePoint.push(linePoint); } else if (points.length==3) { var linePoint= { Start:{X:points[0].X,Y:points[0].Y}, End:{X:points[1].X,Y:points[1].Y} }; this.LinePoint.push(linePoint); linePoint= { Start:{X:points[1].X,Y:points[1].Y}, End:{X:points[2].X,Y:points[2].Y} }; this.LinePoint.push(linePoint); } } this.DrawWaveRuler=function(points) { var ptBottom=points[1]; var ptStart=points[0]; var ptEnd=points[2]; var lineWidth=this.RulerLineWidth*GetDevicePixelRatio(); this.Canvas.lineWidth=lineWidth; this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.fillStyle=this.LineColor; this.Canvas.font=this.Font; var rulerWidth=this.RulerWidth*GetDevicePixelRatio();//刻度线长度 if (this.IsHScreen) { var rulerHeight=ptStart.X-ptBottom.X; var ptExtendBottom={ X:ptEnd.X-this.MaxScaleRuler*rulerHeight, Y:ptEnd.Y}; this.DrawLine(ptEnd,ptExtendBottom); this.LinePoint.push({Start:ptEnd, End:ptExtendBottom}); var y=ptEnd.Y-rulerWidth/2, y2=ptEnd.Y+rulerWidth/2; } else { var rulerHeight=ptStart.Y-ptBottom.Y; var ptExtendBottom={ X:ToFixedPoint2(lineWidth,ptEnd.X), Y:ptEnd.Y-this.MaxScaleRuler*rulerHeight }; this.DrawLine({X:ToFixedPoint2(lineWidth,ptEnd.X), Y:ptEnd.Y},ptExtendBottom); this.LinePoint.push({Start:ptEnd, End:ptExtendBottom}); var x=ptEnd.X-rulerWidth/2, x2=ptEnd.X+rulerWidth/2; } var textOffset=4*GetDevicePixelRatio(); for(var i in this.ScaleRuler) { var item=this.ScaleRuler[i]; if (this.IsHScreen) { var x=ptEnd.X - item.Value*rulerHeight; var price=this.Frame.GetYData(x, false); this.DrawLine({X:x, Y:y}, {X:x, Y:y2}); var text=`${price.toFixed(2)} ${item.Text? item.Text: item.Value.toFixed(3)}`; this.Canvas.save(); this.Canvas.translate(x,ptEnd.Y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,textOffset,0); this.Canvas.restore(); } else { var y=ptEnd.Y - item.Value*rulerHeight; var price=this.Frame.GetYData(y, false); this.DrawLine({X:x, Y:ToFixedPoint2(lineWidth,y)}, {X:x2, Y:ToFixedPoint2(lineWidth,y)}); var text=`${price.toFixed(2)} ${item.Text? item.Text: item.Value.toFixed(3)}`; this.Canvas.fillText(text,x2+textOffset,y); } } } } //画图工具-波浪尺 2个点的 function ChartDrawWaveRuler2Point() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawWaveRuler2Point'; this.PointCount=2; this.Font=14*GetDevicePixelRatio() +"px 微软雅黑"; this.IsPointIn=this.IsPointIn_XYValue_Line; this.PointRate=[ 510, 517, 511.4]; this.LinePoint; this.CPoint; this.ScaleRuler=g_JSChartResource.ChartDrawWaveRuler2Point.ScaleRuler; this.RulerWidth=g_JSChartResource.ChartDrawWaveRuler2Point.RulerWidth;; //刻度尺长度 this.RulerLineWidth=g_JSChartResource.ChartDrawWaveRuler2Point.RulerLineWidth; this.MaxScaleRuler=g_JSChartResource.ChartDrawWaveRuler2Point.MaxScaleRuler; //尺子最大的高度比 this.Font=g_JSChartResource.ChartDrawWaveRuler2Point.MaxScaleRuler; this.IsHScreen=false; this.Super_SetOption=this.SetOption; //父类函数 this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.PointRate) this.PointRate=option.PointRate; } } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; this.IsHScreen=this.Frame.IsHScreen; this.CalculateLines(drawPoint); this.ClipFrame(); this.SetLineWidth(); for(var i in this.LinePoint) { var item=this.LinePoint[i]; this.DrawLine(item.Start,item.End); } var points=[drawPoint[0],drawPoint[1],this.CPoint]; this.DrawWaveRuler(points); this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.CalculateLines=function(points) { var firstLine= { Start:{ X:points[0].X,Y:points[0].Y }, End:{ X:points[1].X,Y:points[1].Y } }; this.LinePoint.push(firstLine); var a=points[0].Y; var b=points[1].Y; var width=this.PointRate[1]-this.PointRate[0]; var offset=this.PointRate[2]-this.PointRate[0]; var c=a-((a-b)*offset)/width; this.CPoint={ X:points[1].X, Y:c }; } this.DrawWaveRuler=function(points) { var ptBottom=points[1]; var ptStart=points[0]; var ptEnd=points[2]; var lineWidth=this.RulerLineWidth*GetDevicePixelRatio(); this.Canvas.lineWidth=lineWidth; this.Canvas.textBaseline='middle'; this.Canvas.textAlign='left'; this.Canvas.fillStyle=this.LineColor; this.Canvas.font=this.Font; var rulerWidth=this.RulerWidth*GetDevicePixelRatio();//刻度线长度 if (this.IsHScreen) { var rulerHeight=ptStart.X-ptBottom.X; var ptExtendBottom={ X:ptEnd.X-this.MaxScaleRuler*rulerHeight, Y:ptEnd.Y}; this.DrawLine(ptEnd,ptExtendBottom); this.LinePoint.push({Start:ptEnd, End:ptExtendBottom}); var y=ptEnd.Y-rulerWidth/2, y2=ptEnd.Y+rulerWidth/2; } else { var rulerHeight=ptStart.Y-ptBottom.Y; var ptExtendBottom={ X:ToFixedPoint2(lineWidth,ptEnd.X), Y:ptEnd.Y-this.MaxScaleRuler*rulerHeight }; this.DrawLine({X:ToFixedPoint2(lineWidth,ptEnd.X), Y:ptEnd.Y},ptExtendBottom); this.LinePoint.push({Start:ptEnd, End:ptExtendBottom}); var x=ptEnd.X, x2=ptEnd.X+rulerWidth; } var textOffset=4*GetDevicePixelRatio(); for(var i in this.ScaleRuler) { var item=this.ScaleRuler[i]; if (this.IsHScreen) { var x=ptEnd.X - item.Value*rulerHeight; var price=this.Frame.GetYData(x, false); this.DrawLine({X:x, Y:y}, {X:x, Y:y2}); var text=`${price.toFixed(2)} ${item.Text? item.Text: item.Value.toFixed(3)}`; this.Canvas.save(); this.Canvas.translate(x,ptEnd.Y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,textOffset,0); this.Canvas.restore(); } else { var y=ptEnd.Y - item.Value*rulerHeight; var price=this.Frame.GetYData(y, false); this.DrawLine({X:x, Y:ToFixedPoint2(lineWidth,y)}, {X:x2, Y:ToFixedPoint2(lineWidth,y)}); var text=`${price.toFixed(2)} ${item.Text? item.Text: item.Value.toFixed(3)}`; this.Canvas.fillText(text,x2+textOffset,y); } } } } //画图工具-箱型线 支持横屏 function ChartDrawBox() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawBox'; this.PointCount=2; this.Font=16*GetDevicePixelRatio() +"px 微软雅黑"; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.AvPriceLineDash=[5*GetDevicePixelRatio(),5*GetDevicePixelRatio()]; this.KLineBorder; this.PointToValue_Backup=this.PointToValue; this.PointToValue=function() { //拖拽完成 把点移动到线段头尾 this.Point[0]={X:this.KLineBorder.Left, Y:this.KLineBorder.Top}; this.Point[1]={X:this.KLineBorder.Right, Y:this.KLineBorder.Bottom}; this.PointToValue_Backup(); } this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.IsHScreen=this.Frame.IsHScreen; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; var kPoint=this.PointToKLine([ptStart,ptEnd]); JSConsole.Chart.Log('[ChartDrawBox::Draw] kPoint', kPoint); var kDataInfo=this.Calculate(kPoint); JSConsole.Chart.Log('[ChartDrawBox::Draw] kDataInfo', kDataInfo); var klineBorder=this.GetKLineBorder(drawPoint, kDataInfo); this.KLineBorder=klineBorder; this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; this.Canvas.strokeRect(ToFixedRect(klineBorder.Left), ToFixedRect(klineBorder.Top), ToFixedRect(klineBorder.Right-klineBorder.Left), ToFixedRect(klineBorder.Bottom-klineBorder.Top)); //均价 var avPriceText; if (kDataInfo.Amount>0 && kDataInfo.Vol>0) { var price=kDataInfo.Amount/kDataInfo.Vol; avPriceText=`均价${price.toFixed(2)}`; this.Canvas.beginPath(); if (this.IsHScreen) { var x=this.Frame.GetYFromData(price,false); this.Canvas.moveTo(ToFixedPoint2(this.Canvas.lineWidth,x),klineBorder.Top); this.Canvas.lineTo(ToFixedPoint2(this.Canvas.lineWidth,x),klineBorder.Bottom); } else { var y=this.Frame.GetYFromData(price,false); this.Canvas.moveTo(klineBorder.Left,ToFixedPoint2(this.Canvas.lineWidth,y)); this.Canvas.lineTo(klineBorder.Right,ToFixedPoint2(this.Canvas.lineWidth,y)); } this.Canvas.setLineDash(this.AvPriceLineDash); this.Canvas.stroke(); this.Canvas.setLineDash([]); } this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 //绘制信息 this.Canvas.textBaseline='top'; this.Canvas.textAlign='left'; this.Canvas.font=this.Font; this.Canvas.fillStyle=this.LineColor; var textOffset=2*GetDevicePixelRatio(); var text=`K线数${kDataInfo.Count}`; if (this.IsHScreen) this.DrawText(text,klineBorder.Right,klineBorder.Top, textOffset, textOffset); else this.DrawText(text,klineBorder.Left,klineBorder.Top, textOffset, textOffset); if (avPriceText) { if (this.IsHScreen) this.DrawText(avPriceText,x,klineBorder.Top, textOffset, textOffset); //均价 else this.DrawText(avPriceText,klineBorder.Left,y, textOffset, textOffset); //均价 } var yClose=IFrameSplitOperator.IsNumber(kDataInfo.YClose)? kDataInfo.YClose:kDataInfo.Open; var value=(kDataInfo.Close-yClose)/yClose*100; text=`${value.toFixed(2)}%`; if (this.IsHScreen) this.DrawText(text,klineBorder.Right,klineBorder.Bottom, textOffset, textOffset); else this.DrawText(text,klineBorder.Right,klineBorder.Top, textOffset, textOffset); value=kDataInfo.Close-yClose; text=`${value.toFixed(2)}`; this.Canvas.textBaseline='bottom'; if (this.IsHScreen) this.DrawText(text,klineBorder.Left,klineBorder.Bottom, textOffset, 0); else this.DrawText(text,klineBorder.Right,klineBorder.Bottom, textOffset, 0); this.Canvas.restore(); } this.Calculate=function(kPoint) { var startPoint=kPoint[0]; var endPoint=kPoint[1]; if (startPoint.XValue>endPoint.XValue) { startPoint=kPoint[1]; endPoint=kPoint[0]; } var data=this.Frame.Data.Data; var open, high, low, yClose, close, vol=0, amount=0; var count=0; for(var i=startPoint.XValue;i<=endPoint.XValue;++i, ++count) { var item=data[i]; if (count==0) { yClose=item.YClose; open=item.Open; close=item.Close; low=item.Low; high=item.High; } else { close=item.Close; if (low>item.Low) low=item.Low; if (high=data.Data.length) xValue=data.Data.length-1; var yStart=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); xValue=Math.round(this.Frame.GetXData(ptEnd.Y,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var yEnd=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); var xHigh=this.Frame.GetYFromData(kInfo.High,false); var xLow=this.Frame.GetYFromData(kInfo.Low,false); var result= { Left:xLow, Top:yStart, Right:xHigh, Bottom:yEnd }; this.LinePoint.push({Start:{X:xLow, Y:yStart}, End:{X:yEnd, Y:yStart}}); this.LinePoint.push({Start:{X:xLow, Y:yEnd}, End:{X:yEnd, Y:yEnd}}); this.LinePoint.push({Start:{X:xLow, Y:yStart}, End:{X:xLow, Y:yEnd}}); this.LinePoint.push({Start:{X:xHigh, Y:yStart}, End:{X:xHigh, Y:yEnd}}); return result; } else { var xValue=Math.round(this.Frame.GetXData(ptStart.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var xStart=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); xValue=Math.round(this.Frame.GetXData(ptEnd.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var xEnd=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); var yHigh=this.Frame.GetYFromData(kInfo.High,false); var yLow=this.Frame.GetYFromData(kInfo.Low,false); var result= { Left:xStart, Top:yHigh, Right:xEnd, Bottom:yLow }; this.LinePoint.push({Start:{X:xStart, Y:yHigh}, End:{X:xEnd, Y:yHigh}}); this.LinePoint.push({Start:{X:xStart, Y:yLow}, End:{X:xEnd, Y:yLow}}); this.LinePoint.push({Start:{X:xStart, Y:yHigh}, End:{X:xStart, Y:yLow}}); this.LinePoint.push({Start:{X:xEnd, Y:yHigh}, End:{X:xEnd, Y:yLow}}); return result; } } this.DrawText=function(text, x, y, xOffset, yOffset) { if (this.IsHScreen) { this.Canvas.save(); this.Canvas.translate(x,y); this.Canvas.rotate(90 * Math.PI / 180); this.Canvas.fillText(text,xOffset,yOffset); this.Canvas.restore(); } else { this.Canvas.fillText(text,x+xOffset,y+yOffset); } } } function ChartDrawTwoPointDemo() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawTwoPointDemo'; this.PointCount=2; this.Font=16*GetDevicePixelRatio() +"px 微软雅黑"; this.IsPointIn=this.IsPointIn_XYValue_Line; this.IsHScreen=false; this.PointInfo=[]; //保存点及点对应K线的信息 this.PointToValue_Backup=this.PointToValue; this.PointToValue=function() { this.OnFinish(); this.PointToValue_Backup(); } //移动或创建完成 this.OnFinish=function() { for(var i in this.PointInfo) { var item=this.PointInfo[i]; if (!item || !item.Point || !IFrameSplitOperator.IsNumber(item.Point.Y2)) continue; this.Point[i].Y=this.PointInfo[i].Point.Y2; //点Y轴坐标调整 } } this.Draw=function() { this.LinePoint=[]; this.PointInfo=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; this.IsHScreen=this.Frame.IsHScreen; //this.CalculateLines(drawPoint); this.ClipFrame(); this.SetLineWidth(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1] this.CalculatePointInfo(drawPoint); if (this.Status==10) //绘制完成 { this.DrawEx(); } else //绘制中只画连线 { for(var i=1;i0;--i) { var price=endInfo.KItem.YClose*(0.03*i)+endInfo.KItem.High; //%2涨幅一档画线 var y=this.Frame.GetYFromData(price,false); y=this.ToFixedPoint(y); //线段 this.DrawLine({X:ptEnd.X, Y:y}, {X:ptEnd.X+100, Y:y}); //文字 this.Canvas.fillText(price.toFixed(2), ptEnd.X-5, y); } this.Canvas.setLineDash([]); } //防止竖线或横线模糊调整坐标 this.ToFixedPoint=function(value,width) { if (!IFrameSplitOperator.IsNumber(width)) width=this.LineWidth; return ToFixedPoint2(width, value) } } function ChartDrawThreePointDemo() { this.newMethod=ChartDrawTwoPointDemo; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawThreePointDemo'; this.PointCount=3; this.SetLastPoint=function(obj) { this.LastPoint={X:obj.X,Y:obj.Y}; } //计算需要调整的Y轴坐标 this.CalculateYPoint=function() { var y; for(var i in this.PointInfo) { var item=this.PointInfo[i]; if (i==0 || i==2) y=this.Frame.GetYFromData(item.KItem.Low,false); else y=this.Frame.GetYFromData(item.KItem.High,false); item.Point.Y2=y; } } this.DrawEx=function() { //起始点 结束点信息 var startInfo=this.PointInfo[0]; var secondInfo=this.PointInfo[1]; var endInfo=this.PointInfo[2]; //K线边框信息 var chartBorder=this.Frame.ChartBorder; var frameRight=chartBorder.GetRight(); //右边 var frameLeft=chartBorder.GetLeft(); //左边 var ptStart={ X:startInfo.Point.X, Y:startInfo.Point.Y2 }; var ptSecond={ X:secondInfo.Point.X, Y:secondInfo.Point.Y2}; var ptEnd={ X:endInfo.Point.X, Y:endInfo.Point.Y2 }; this.DrawLine(ptStart,ptSecond); this.DrawLine(ptSecond,ptEnd); this.LinePoint.push({Start:ptStart, End:ptSecond}); this.LinePoint.push({Start:ptSecond, End:ptEnd}); this.Canvas.setLineDash([5,5]); //this.Canvas.lineWidth=2; var topPrice=endInfo.KItem.YClose*0.09+endInfo.KItem.High; //结束点最高价+涨幅6% 画竖线 var y=this.Frame.GetYFromData(topPrice,false); this.DrawLine({X:this.ToFixedPoint(ptEnd.X), Y:ptEnd.Y}, {X:this.ToFixedPoint(ptEnd.X), Y:y}); this.Canvas.textAlign="right"; this.Canvas.textBaseline = 'center'; this.Canvas.fillStyle='rgb(33,45,100)'; for(var i=3;i>0;--i) { var price=endInfo.KItem.YClose*(0.03*i)+endInfo.KItem.High; //%2涨幅一档画线 var y=this.Frame.GetYFromData(price,false); y=this.ToFixedPoint(y); //线段 this.DrawLine({X:ptEnd.X, Y:y}, {X:ptEnd.X+100, Y:y}); //文字 this.Canvas.fillText(price.toFixed(2), ptEnd.X-5, y); } this.Canvas.setLineDash([]); } } //画图工具-水平线段 function ChartDrawHLineSegment() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawHLineSegment'; this.PointCount=2; this.IsPointIn=this.IsPointIn_XYValue_Line; this.ChartBorder; this.PointToValue_Backup=this.PointToValue; this.PointToValue=function() { //拖拽完成 把点移动到线段头尾 if (this.Frame.IsHScreen) { this.Point[1].X=this.Point[0].X; } else { this.Point[1].Y=this.Point[0].Y; } this.PointToValue_Backup(); } this.GetXYCoordinate=function() { if (this.IsFrameMinSize()) return null; var drawPoint=this.CalculateDrawPoint({ IsCheckX:false, IsCheckY:true }); return this.PointRange(drawPoint); } this.Draw=function() { if (!this.Frame) return; this.IsHScreen=this.Frame.IsHScreen; this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:true} ); if (!drawPoint || drawPoint.length!=2) return; this.ClipFrame(); this.ChartBorder=this.Frame.ChartBorder; this.SetLineWidth(); this.Canvas.strokeStyle=this.LineColor; var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; if (this.Status==10) //0=开始画 1=完成第1个点 2=完成第2个点 3=完成第3个点 10=完成 20=移动) { this.DrawLine(ptStart,ptEnd,false); } else { //var kPoint=this.PointToKLine([ptStart,ptEnd]); this.DrawVerticalLine(ptStart,ptEnd); } this.RestoreLineWidth(); var line={ Start:ptStart, End:ptEnd }; this.LinePoint.push(line); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.DrawVerticalLine=function(ptStart, ptEnd) { var data=this.Frame.Data; if (this.IsHScreen) { var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var xValue=Math.round(this.Frame.GetXData(ptStart.Y,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var yStart=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); xValue=Math.round(this.Frame.GetXData(ptEnd.Y,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var yEnd=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); this.Canvas.beginPath(); this.Canvas.moveTo(left,yStart); this.Canvas.lineTo(right,yStart); this.Canvas.moveTo(left,yEnd); this.Canvas.lineTo(right,yEnd); this.Canvas.stroke(); this.Canvas.beginPath(); this.Canvas.moveTo(ptStart.X,yStart); this.Canvas.lineTo(ptStart.X,yEnd); this.Canvas.stroke(); } else { var top=this.ChartBorder.GetTopEx(); var bottom=this.ChartBorder.GetBottomEx(); var xValue=Math.round(this.Frame.GetXData(ptStart.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var xStart=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); xValue=Math.round(this.Frame.GetXData(ptEnd.X,false))+data.DataOffset; if (xValue<0) xValue=0; else if (xValue>=data.Data.length) xValue=data.Data.length-1; var xEnd=this.Frame.GetXFromIndex(xValue-data.DataOffset,false); this.Canvas.beginPath(); this.Canvas.moveTo(xStart,top); this.Canvas.lineTo(xStart,bottom); this.Canvas.moveTo(xEnd,top); this.Canvas.lineTo(xEnd,bottom); this.Canvas.stroke(); this.Canvas.beginPath(); this.Canvas.moveTo(xStart,ptStart.Y); this.Canvas.lineTo(xEnd,ptStart.Y); this.Canvas.stroke(); } } } //画图工具-volume profile fixed range function ChartDrawVolProfile() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDrawVolProfile'; this.PointCount=2; this.IsPointIn=this.IsPointIn_XYValue_Line; this.ChartBorder; this.GetXYCoordinate=this.GetXYCoordinate_default; this.IsShowText=true; //是否显示成交量数据 this.VolType=0; //0=up|down bar 1=total bar this.BarPosition=0; //柱子方向 0=左边 1=右边 this.VolFont; this.VAVol=60; //Value area volume this.BarWidthRate=0.3; this.Data; this.MaxVol; this.MaxVolPrice; this.DataStatus=0; //0=请求总 1=完成 this.BGColor=g_JSChartResource.ChartDrawVolProfile.BGColor; this.BorderColor=g_JSChartResource.ChartDrawVolProfile.BorderColor; this.VolLineColor=g_JSChartResource.ChartDrawVolProfile.VolLineColor; this.TextConfig= { Color:g_JSChartResource.ChartDrawVolProfile.Text.Color, Family:g_JSChartResource.ChartDrawVolProfile.Text.Family, FontMaxSize:g_JSChartResource.ChartDrawVolProfile.Text.FontMaxSize, FontMinSize:g_JSChartResource.ChartDrawVolProfile.Text.FontMinSize, Color:g_JSChartResource.ChartDrawVolProfile.Text.Color, } this.BarColor= [ g_JSChartResource.ChartDrawVolProfile.UpVolColor, g_JSChartResource.ChartDrawVolProfile.DownVolColor, g_JSChartResource.ChartDrawVolProfile.AreaUpColor, g_JSChartResource.ChartDrawVolProfile.AreaDonwColor ] this.Super_SetOption=this.SetOption; //父类函数 this.SetOption=function(option) { if (this.Super_SetOption) this.Super_SetOption(option); if (option) { if (option.BGColor) this.BGColor=option.BGColor; if (option.BorderColor) this.BGColor=option.BorderColor; if (option.VolLineColor) this.BGColor=option.VolLineColor; if (option.UpVolColor) this.BarColor[0]=option.UpVolColor; if (option.DownVolColor) this.BarColor[1]=option.DownVolColor; if (option.AreaUpColor) this.BarColor[2]=option.AreaUpColor; if (option.AreaDonwColor) this.BarColor[3]=option.AreaDonwColor; if (IFrameSplitOperator.IsNumber(option.BarWidthRate)) this.BarWidthRate=option.BarWidthRate; if (IFrameSplitOperator.IsBool(option.IsShowText)) this.IsShowText=option.IsShowText; if (IFrameSplitOperator.IsNumber(option.VolType)) this.VolType=option.VolType; if (IFrameSplitOperator.IsNumber(option.BarPosition)) this.BarPosition=option.BarPosition; if (IFrameSplitOperator.IsNumber(option.VAVol)) this.VAVol=option.VAVol; } } this.OnFinish=function() { this.RequestVolumeProfileData(); } this.OnMoveFinish=function() { this.RequestVolumeProfileData(); } this.IsDrawMain=function() //选中绘制在动态绘图上, 没有选中绘制在背景上 { if (!this.GetActiveDrawPicture) return true; var active=this.GetActiveDrawPicture(); if (active.Select.Guid==this.Guid) return false; return true; } this.RequestVolumeProfileData=function() { //请求数据 var start=this.Value[0], end=this.Value[1]; if (start.XValue>end.XValue) { start=this.Value[1]; end=this.Value[0]; } var option={ Start:{ Date:start.DateTime.Date, DataIndex:start.XValue }, End:{ Date:end.DateTime.Date, DataIndex:end.XValue }, Chart:this }; if (IFrameSplitOperator.IsNumber(start.DateTime.Time)) option.Start.Time=start.DateTime.Time; if (IFrameSplitOperator.IsNumber(end.DateTime.Time)) option.End.Time=end.DateTime.Time; option.ValueAreaVol=this.VAVol; this.DataStatus=0 if (this.HQChart && this.HQChart.RequestVolumeProfileData) { this.HQChart.RequestVolumeProfileData(option); } } this.OnRecvVolumeProfileData=function(data) { if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) return; var maxVol=0,vol=0; var maxVolPrice=null; for(var i=0, j=0;iend.XValue) { start=this.Value[1]; end=this.Value[0]; } var dataOffset=this.GetKDataOffset(); var cellHeight=this.GetPriceYOffset(this.Data.PriceOffset); var left=this.Frame.GetXFromIndex(start.XValue-dataOffset,false); var right=this.Frame.GetXFromIndex(end.XValue-dataOffset,false); var top=this.Frame.GetYFromData(this.Data.MaxPrice)-cellHeight/2; var bottom=this.Frame.GetYFromData(this.Data.MinPrice)+cellHeight/2; var width=right-left; var height=bottom-top; var maxBarWidth=width*this.BarWidthRate; this.Canvas.fillStyle=this.BGColor; //JSConsole.Chart.Log('[ChartDrawVolProfile::DrawVolBar] BGColor ', this.BGColor); this.Canvas.fillRect(left,top,width,height); //背景 if (this.MaxVolPrice>=this.Frame.HorizontalMin&& this.MaxVolPrice<=this.Frame.HorizontalMax) { var lineWidth=2; var yLine=ToFixedPoint2(lineWidth,this.Frame.GetYFromData(this.MaxVolPrice,false)); this.Canvas.lineWidth=lineWidth; this.Canvas.strokeStyle=this.VolLineColor; this.Canvas.beginPath(); this.Canvas.moveTo(left,yLine); this.Canvas.lineTo(right,yLine); this.Canvas.stroke(); var linePoint= { Start:{X:left,Y:yLine}, End:{X:right,Y:yLine} }; this.LinePoint.push(linePoint); } if (this.IsShowText) { this.VolFont=this.GetDynamicVolTextFont(cellHeight, maxBarWidth); if (this.VolFont) this.Canvas.font=this.VolFont; } //this.Canvas.lineWidth=1; for(var i=0;ithis.Frame.HorizontalMax) continue; this.DrawVolBarItem(item, left, right, maxBarWidth, cellHeight); } } this.DrawVolBarItem=function(item, left, right, maxBarWidth, cellHeight) { var barLeft=left; var barRight=right; var barTop=this.Frame.GetYFromData(item.Price)-cellHeight/2; var barHeight=cellHeight-1; if (barHeight<1) barHeight=1; if (this.VolType==1) { if (!item.TotalVol) return; if (!IFrameSplitOperator.IsNumber(item.TotalVol.Value)) return; var barWidth=item.TotalVol.Value*maxBarWidth/this.MaxVol; var color; if (IFrameSplitOperator.IsNumber(item.TotalVol.ColorID)) color=this.BarColor[item.TotalVol.ColorID]; else if (item.TotalVol.Color) color=item.TotalVol.Color; this.Canvas.fillStyle=color; if (this.BarPosition==1) { this.Canvas.fillRect(barRight,ToFixedRect(barTop),-barWidth,ToFixedRect(barHeight)); } else { this.Canvas.fillRect(barLeft,ToFixedRect(barTop),barWidth,ToFixedRect(barHeight)); } if (this.IsShowText && this.VolFont) { var text=IFrameSplitOperator.FormatVolString(item.TotalVol.Value, this.HQChart.LanguageID); this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle=this.TextConfig.Color; if (this.BarPosition==1) { this.Canvas.textAlign = 'right'; this.Canvas.fillText(text,right-5,barTop+cellHeight/2); } else { this.Canvas.textAlign = 'left'; this.Canvas.fillText(text,left+5,barTop+cellHeight/2); } } } else { var text=""; for(var i=0;i0) text+="x"; text+=volText; } if (this.IsShowText && this.VolFont) { this.Canvas.textBaseline = 'middle'; this.Canvas.fillStyle=this.TextConfig.Color; if (this.BarPosition==1) { this.Canvas.textAlign = 'right'; this.Canvas.fillText(text,right-5,barTop+cellHeight/2); } else { this.Canvas.textAlign = 'left'; this.Canvas.fillText(text,left+5,barTop+cellHeight/2); } } } } this.GetKDataOffset=function() { var kData=this.HQChart.ChartPaint[0].Data; return kData.DataOffset; } this.GetPriceYOffset=function(value) { var frame=this.Frame var y=frame.ChartBorder.GetHeightEx()*(value)/(frame.HorizontalMax-frame.HorizontalMin); return y; } this.GetDynamicVolTextFont=function(cellHeight, width, fontOption) { var fontSize=parseInt(cellHeight)-2; if (cellHeight<5) fontSize=parseInt(cellHeight); //高度太小了就不要上下间距了 if (fontSize>this.TextConfig.FontMaxSize) fontSize=this.TextConfig.FontMaxSize; else if (fontSize<=0) fontSize=1; if (fontSize0) height+=this.LineSpace; if (item.Text) { var value=this.GetMultiLineText(item.Text, width); if (value && IFrameSplitOperator.IsNonEmptyArray(value.AryText)) { for(var j=0; j0) height+=this.LineSpace; var textItem=value.AryText[j]; aryText.push(textItem); height+=lineHeight; } } } else { aryText.push({Text:""}); height+=lineHeight; } } } else { height=lineHeight; } var rtBG={ Width:width+this.NoteMargin.Left+this.NoteMargin.Right, Height:height+this.NoteMargin.Top+this.NoteMargin.Bottom, ArrowType:0 }; if (isHScreen) { rtBG.Left=this.PtTop.X-rtBG.Width/2-this.PtCenter.X; rtBG.Top=this.PtTop.Y-rtBG.Height-this.ArrowSize-this.PtCenter.Y; rtBG.Right=rtBG.Left+rtBG.Width; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Arrow={ X:this.PtTop.X-this.PtCenter.X, Y:this.PtTop.Y-this.PtCenter.Y}; //Type 0=向下箭头 1=向上箭头 if (this.PtCenter.X+height+this.FontOption.Size*pixel/2+2+this.ArrowSize>border.RightEx) { rtBG.Top=this.PtButtom.Y+this.ArrowSize+this.PointRadius*pixel-this.PtCenter.Y; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Arrow.X=this.PtButtom.X-this.PtCenter.X; rtBG.Arrow.Y=this.PtButtom.Y-this.PtCenter.Y; rtBG.ArrowType=1; } } else { rtBG.Left=this.PtTop.X-rtBG.Width/2; rtBG.Top=this.PtTop.Y-rtBG.Height-this.ArrowSize; rtBG.Right=rtBG.Left+rtBG.Width; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Arrow={ X:this.PtTop.X, Y:this.PtTop.Y}; //Type 0=向下箭头 1=向上箭头 if (rtBG.Leftborder.Right) { rtBG.Right=border.Right; rtBG.Left=rtBG.Right-rtBG.Width; } if (rtBG.Top=0) font+=this.FontOption.Size*GetDevicePixelRatio()+'px '; font+=this.FontOption.Family; return font; } this.IsPointIn=function(x,y) { if (!this.Frame || this.Status!=10) return -1; var data=this.Frame.Data; if (!data) return -1; if (!this.TextRect) return -1; var offset=0; if (this.Option && this.Option.Zoom>=1) { offset=this.Option.Zoom*GetDevicePixelRatio(); } var rect={ Left:this.TextRect.Left-offset, Top:this.TextRect.Top-offset, Width:this.TextRect.Width+offset*2, Height:this.TextRect.Height+offset*2 }; rect.Right=rect.Left+rect.Width; rect.Bottom=rect.Top+rect.Height; if (x>rect.Left && xrect.Top && y0) height+=this.LineSpace; if (this.TextMaxWidth>50 && item.Text) //限制宽度 { var value=this.GetMultiLineText(item.Text, this.TextMaxWidth); if (value && IFrameSplitOperator.IsNonEmptyArray(value.AryText)) { for(var j=0; j0) height+=this.LineSpace; var textItem=value.AryText[j]; aryText.push(textItem); height+=lineHeight; } } } else { if (item.Text) { var textWidth=this.Canvas.measureText(item.Text).width+2; if (maxTextWidth50) maxTextWidth=this.TextMaxWidth; var rtBG= { Left:ptBottom.X, Bottom:ptBottom.Y, Height:height+this.TextMargin.Top+this.TextMargin.Bottom, Width:maxTextWidth+this.TextMargin.Left+this.TextMargin.Right }; rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; this.DrawBG(rtBG); this.Canvas.fillStyle=this.TextColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="top"; var xText=rtBG.Left+this.TextMargin.Left; var yText=rtBG.Top+this.TextMargin.Top; for(var i=0;irect.Left && xrect.Top && yrect.Left && xrect.Top && y=0 && angle<=45) || (angle>=315 && angle<=360)) { var left=ptPrice.X; var bottom=ptPrice.Y; var rtBG={ Left:left, Bottom:bottom, Width:textWidth+this.TextMargin.Left+this.TextMargin.Right, Height:textHeight+this.TextMargin.Top+this.TextMargin.Bottom }; rtBG.Bottom=bottom+(rtBG.Height/2); rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; } else if (angle>45 && angle<=135) { var left=ptPrice.X; var bottom=ptPrice.Y; var rtBG={ Left:left, Bottom:bottom, Width:textWidth+this.TextMargin.Left+this.TextMargin.Right, Height:textHeight+this.TextMargin.Top+this.TextMargin.Bottom }; rtBG.Left=left-(rtBG.Width/2); rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=rtBG.Left+rtBG.Width; } else if (angle>=135 && angle<=225) { var left=ptPrice.X; var bottom=ptPrice.Y; var rtBG={ Width:textWidth+this.TextMargin.Left+this.TextMargin.Right, Height:textHeight+this.TextMargin.Top+this.TextMargin.Bottom }; rtBG.Bottom=bottom+(rtBG.Height/2); rtBG.Top=rtBG.Bottom-rtBG.Height; rtBG.Right=left; rtBG.Left=rtBG.Right-rtBG.Width; } else if (angle>=225 && angle<=315) { var left=ptPrice.X; var top=ptPrice.Y; var rtBG={ Width:textWidth+this.TextMargin.Left+this.TextMargin.Right, Height:textHeight+this.TextMargin.Top+this.TextMargin.Bottom }; rtBG.Top=top; rtBG.Bottom=rtBG.Top+rtBG.Height; rtBG.Left=left-(rtBG.Width/2); rtBG.Right=rtBG.Left-rtBG.Width; } else return; this.DrawBG(rtBG); this.Canvas.textAlign="left"; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.TextColor; var xText=rtBG.Left+this.TextMargin.Left; var yText=rtBG.Top+rtBG.Height/2; var yOffset=0; this.Canvas.fillText(text,xText,yText+yOffset); //绘制一个点 if (this.BGColor) { this.Canvas.beginPath(); this.Canvas.arc(ptStart.X,ptStart.Y,2*pixelRatio,0,360,false); this.Canvas.fillStyle=this.BGColor; this.Canvas.fill(); } this.TextRect=rtBG; } this.DrawBG=function(rtBG) { if (!rtBG) return; var pixelRatio=GetDevicePixelRatio(); var roundRadius=this.BorderRoundRadius*pixelRatio; var path=new Path2D(); path.roundRect(ToFixedPoint(rtBG.Left), ToFixedPoint(rtBG.Top), ToFixedRect(rtBG.Width), ToFixedRect(rtBG.Height), [roundRadius]); if (this.BGColor) { this.Canvas.fillStyle=this.BGColor; this.Canvas.fill(path); } if (this.BorderColor) { this.Canvas.strokeStyle=this.BorderColor; this.Canvas.stroke(path); } } this.IsPointIn=function(x,y) { if (!this.Frame || this.Status!=10) return -1; if (!this.TextRect) return -1; var rect=this.TextRect; if (x>rect.Left && xrect.Top && y=0) { option.Magnet= { Enable:true, PointIndex:pointIndex, Distance:this.Option.Magnet.Distance, Type:this.Option.Magnet.Type } } } this.AdjustPoint(aryPoint,option) } this.CalculateAllPoint=function(ptStart, pt2, ptEnd) { var drawPoint=[]; drawPoint.push({ X:ptStart.X, Y:ptStart.Y }); drawPoint.push({ X:pt2.X, Y:pt2.Y }); this.MagnetXY(drawPoint); drawPoint.push({ X:ptEnd.X, Y:ptEnd.Y }); var radius=this.CalculateHypotenuse(drawPoint[0], drawPoint[1]); //求半径 var a=drawPoint[0].X-drawPoint[2].X; var b=drawPoint[0].Y-drawPoint[2].Y; var c=Math.sqrt(a*a+b*b); var a2=a*radius/c; var b2=b*radius/c; drawPoint[2].X=drawPoint[0].X-a2; drawPoint[2].Y=drawPoint[0].Y-b2; return drawPoint; } //数值转成坐标 this.ValueToPoint_V2=function(aryValue) { if (!IFrameSplitOperator.IsNonEmptyArray(aryValue)) return null; if (!this.Frame) return null; var data=this.Frame.Data; if (!data) return null; var isHScreen=this.Frame.IsHScreen; var aryPoint=[]; for(var i=0; i=showCount) ++invaildX; var pt=new Point(); if (isHScreen) //横屏X,Y对调 { pt.Y=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false); pt.X=this.Frame.GetYFromData(item.YValue,false); } else { pt.X=this.Frame.GetXFromIndex(item.XValue-data.DataOffset,false); pt.Y=this.Frame.GetYFromData(item.YValue,false); } drawPoint.push(pt); } } else if (this.Status==20) { drawPoint=this.CalculateAllPoint(this.Point[0], this.Point[1], this.Point[2]); } return drawPoint; } this.Draw=function() { this.LinePoint=[]; this.TextAngle=null; this.Radius=null; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:false, IsCheckY:false}); if (!IFrameSplitOperator.IsNonEmptyArray(drawPoint)) return; var points=drawPoint.slice(0); this.CalculateLines(points); this.ClipFrame(); this.DrawArea(points); this.DrawLines(this.LinePoint); this.DrawPoint(points); //画点 this.DrawTitle(points); this.Canvas.restore(); } this.DrawArea=function(aryPoint) { if (aryPoint.length!=3) return; if (!this.AreaConfig || !IFrameSplitOperator.IsNonEmptyArray(this.AreaConfig.AryData)) return; var ptCenter=aryPoint[0]; var radius=this.CalculateHypotenuse(ptCenter, aryPoint[1]); //求半径 var startAngle=this.CalculateAngle(ptCenter.X,ptCenter.Y,aryPoint[1].X,aryPoint[1].Y); var endAngle=this.CalculateAngle(ptCenter.X,ptCenter.Y,aryPoint[2].X,aryPoint[2].Y); var sectorAngle=startAngle-endAngle; if (sectorAngle<0) sectorAngle+=360; if (sectorAngle>180) { var temp=startAngle; startAngle=endAngle; endAngle=temp; } var centerAngle=startAngle-(startAngle-endAngle)/2; if (startAngle-endAngle<0) centerAngle-=180; var preValue=null; for(var i=0;i=0) return value; value=this.IsPointInLine(x,y,option); if (value>=0) return 100; return -1; } this.IsPointInDots=function(x, y, aryPoint, option) { if (!IFrameSplitOperator.IsNonEmptyArray(aryPoint)) return -1; if (!this.Frame) return -1; var data=this.Frame.Data; if (!data) return -1; if (!this.Value) return -1; var radius=5; if (option && IFrameSplitOperator.IsNumber(option.Zoom)) radius+=option.Zoom; else if (this.Option && IFrameSplitOperator.IsNumber(this.Option.Zoom)) radius+=this.Option.Zoom; var isHScreen=this.Frame.IsHScreen; radius*=GetDevicePixelRatio(); for(var i=0;i{ return right.Value-left.Value; }) return aryArea; } this.DrawBlock=function(ptStart, ptEnd) { var yTop=Math.min(ptStart.Y, ptEnd.Y); var yBottom=Math.max(ptStart.Y, ptEnd.Y); var xLeft=Math.min(ptStart.X, ptEnd.X); var xRight=Math.max(ptStart.X, ptEnd.X); var height=yBottom-yTop; //var baseValue=Math.min(this.Value[0].YValue, this.Value[1].YValue); //var diffValue=Math.abs(this.Value[0].YValue-this.Value[1].YValue); //差值 if (this.ExtendLine.Right) xRight=this.Frame.ChartBorder.GetRight(); if (this.ExtendLine.Left) xLeft=this.Frame.ChartBorder.GetLeft(); var aryArea=this.GetArrayAreaConfig(); var yPre=null; //上一个点 var clrArea=null; this.Canvas.font=this.Font; if (this.ExtendLine.Left) this.Canvas.textAlign="left"; else this.Canvas.textAlign="right"; this.Canvas.textBaseline="bottom"; for(var i=0;iptEnd.Y) return 1; else if (ptStart.X>ptEnd.X && ptStart.Y>ptEnd.Y) return 2; else if (ptStart.X=ptRightTop.X && pt.XptLeftTop.X) { this.Canvas.lineTo(ptLeftTop.X,ptLeftTop.Y); } } else if (quadrant==3) { if (ptPre.X<=ptLeftBottom.X && pt.X>ptLeftBottom.X) { this.Canvas.lineTo(ptLeftBottom.X,ptLeftBottom.Y); } } else if (quadrant==4) { if (ptPre.X>=ptRightBottom.X && pt.X=ptRightTop.X) { this.Canvas.lineTo(ptRightTop.X,ptRightTop.Y); } } else if (quadrant==2) { if (ptPre.X>ptLeftTop.X && pt.X<=ptLeftTop.X) { this.Canvas.lineTo(ptLeftTop.X,ptLeftTop.Y); } } else if (quadrant==3) { if (ptPre.X>ptLeftBottom.X && pt.X<=ptLeftBottom.X) { this.Canvas.lineTo(ptLeftBottom.X,ptLeftBottom.Y); } } else if (quadrant==4) { if (ptPre.X=ptRightBottom.X) { this.Canvas.lineTo(ptRightBottom.X,ptRightBottom.Y); } } this.Canvas.lineTo(pt.X,pt.Y); this.Canvas.closePath(); this.Canvas.fillStyle=clrArea; this.Canvas.fill(); } this.Canvas.strokeStyle=item.Color; this.Canvas.beginPath(); this.Canvas.moveTo(center.X,center.Y); this.Canvas.lineTo(pt.X,pt.Y); this.Canvas.stroke(); this.LinePoint.push({Start:center, End:pt}); if (item.Value!=1) { this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,center.Y); this.Canvas.lineTo(x,ptStart.Y); this.Canvas.stroke(); } ptPre=pt; clrArea=IChartDrawPicture.ColorToRGBA(item.Color, this.AreaConfig.Opacity); //文字 var text=`${item.Value}`; this.Canvas.fillStyle=item.Color; this.Canvas.fillText(text,x,center.Y+textOffset); } } this.GetArrayAreaConfig=function(aryData) { var aryArea=[]; for(var i=0;i{ return right.Value-left.Value; }) return aryArea; } } function ChartPriceRange() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartPriceRange'; this.PointCount=2; this.Font=12*GetDevicePixelRatio() +"px 微软雅黑"; this.TextColor=this.LineColor; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.PointToValue_Default=this.PointToValue; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.LineWidth=1; this.EnableBGColor=true; this.BGColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.15); this.ExtendLine={ Left:false, Right: false }; //延长线 this.Label={ TextColor:"rgb(0,0,0)", BGColor:"rgb(211,211,211)", EnableBGColor:true, LeftMargin:5, RightMargin:5 }; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var bCheckXY=true; if (this.ExtendLine.Left || this.ExtendLine.Right) bCheckXY=false; var drawPoint=this.CalculateDrawPoint( {IsCheckX:bCheckXY, IsCheckY:bCheckXY} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.SetLineWidth(); this.DrawRange(ptStart,ptEnd); this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.DrawRange=function(ptStart, ptEnd) { var yTop=Math.min(ptStart.Y, ptEnd.Y); var yBottom=Math.max(ptStart.Y, ptEnd.Y); var xLeft=Math.min(ptStart.X, ptEnd.X); var xRight=Math.max(ptStart.X, ptEnd.X); var height=yBottom-yTop; var xCenter=ptStart.X+(ptEnd.X-ptStart.X)/2; if (this.ExtendLine.Right) xRight=this.Frame.ChartBorder.GetRight(); if (this.ExtendLine.Left) xLeft=this.Frame.ChartBorder.GetLeft(); if (this.EnableBGColor) { var rtBG={ Left:xLeft, Top:yTop, Right:xRight, Bottom:yBottom }; rtBG.Width=rtBG.Right-rtBG.Left; rtBG.Height=rtBG.Bottom-rtBG.Top; this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); } this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(xLeft,ToFixedPoint(yTop)); this.Canvas.lineTo(xRight,ToFixedPoint(yTop)); this.Canvas.moveTo(xLeft,ToFixedPoint(yBottom)); this.Canvas.lineTo(xRight,ToFixedPoint(yBottom)); this.Canvas.moveTo(ToFixedPoint(xCenter),ToFixedPoint(yTop)); this.Canvas.lineTo(ToFixedPoint(xCenter),ToFixedPoint(yBottom)); this.Canvas.stroke(); this.LinePoint.push({ Start:{X:xLeft, Y:yTop}, End:{X:xRight, Y:yTop} }); this.LinePoint.push({ Start:{X:xLeft, Y:yBottom}, End:{X:xRight, Y:yBottom} }); this.LinePoint.push({ Start:{X:xCenter, Y:yTop}, End:{X:xCenter, Y:yBottom} }); this.DrawArrow({X:ToFixedPoint(xCenter), Y:ptStart.Y}, {X:ToFixedPoint(xCenter), Y:ptEnd.Y}); var bottom=this.Frame.ChartBorder.GetBottomEx(); var top=this.Frame.ChartBorder.GetTopEx(); //文字输出 var startValue=this.Frame.GetYData(ptStart.Y,false); var endValue=this.Frame.GetYData(ptEnd.Y,false); var diffValue=endValue-startValue; var rate=(diffValue/startValue)*100; var text=`${diffValue.toFixed(2)} (${rate.toFixed(2)}%)`; this.Canvas.font=this.Font; var textHeight=this.GetFontHeight(); var textWidth=this.Canvas.measureText(text).width+4+(this.Label.LeftMargin+this.Label.RightMargin); var rtTextBG={ Left:xCenter-textWidth/2, Width:textWidth, Height:textHeight+2 }; if (diffValue>0) rtTextBG.Top=ptEnd.Y-rtTextBG.Height-4; else rtTextBG.Top=ptEnd.Y+4; rtTextBG.Bottom=rtTextBG.Top+rtTextBG.Height; if (diffValue>0) { if (rtTextBG.Top<=top) { rtTextBG.Top=top; rtTextBG.Bottom=rtTextBG.Top+rtTextBG.Height; } } else { if (rtTextBG.Bottom>=bottom) { rtTextBG.Bottom=bottom; rtTextBG.Top=rtTextBG.Bottom-rtTextBG.Height; } } if (this.Label.EnableBGColor) { var path=new Path2D(); path.roundRect(ToFixedPoint(rtTextBG.Left), ToFixedPoint(rtTextBG.Top), ToFixedRect(rtTextBG.Width), ToFixedRect(rtTextBG.Height), [3]); this.Canvas.fillStyle=this.Label.BGColor; this.Canvas.fill(path); } this.Canvas.fillStyle=this.Label.TextColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; this.Canvas.fillText(text,rtTextBG.Left+2+this.Label.LeftMargin,rtTextBG.Bottom-2); } } function ChartDateRange() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDateRange'; this.PointCount=2; this.Font=12*GetDevicePixelRatio() +"px 微软雅黑"; this.TextColor=this.LineColor; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.PointToValue_Default=this.PointToValue; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.LineWidth=1; this.EnableBGColor=true; this.BGColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.15); this.ExtendLine={ Top:false, Bottom: false }; //延长线 this.Label={ TextColor:"rgb(0,0,0)", BGColor:"rgb(211,211,211)", EnableBGColor:true, LeftMargin:5, RightMargin:5 }; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var bCheckXY=true; var drawPoint=this.CalculateDrawPoint( {IsCheckX:bCheckXY, IsCheckY:bCheckXY} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.SetLineWidth(); this.DrawRange(ptStart,ptEnd); this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.DrawRange=function(ptStart, ptEnd) { var yTop=Math.min(ptStart.Y, ptEnd.Y); var yBottom=Math.max(ptStart.Y, ptEnd.Y); var xLeft=Math.min(ptStart.X, ptEnd.X); var xRight=Math.max(ptStart.X, ptEnd.X); var height=yBottom-yTop; var width=xRight-xLeft; var yCenter=ptStart.Y+(ptEnd.Y-ptStart.Y)/2; var xCenter=ptStart.X+(ptEnd.X-ptStart.X)/2; if (this.ExtendLine.Top) yTop=this.Frame.ChartBorder.GetTopEx(); if (this.ExtendLine.Bottom) yBottom=this.Frame.ChartBorder.GetBottomEx(); if (this.EnableBGColor) { var rtBG={ Left:xLeft, Top:yTop, Right:xRight, Bottom:yBottom }; rtBG.Width=rtBG.Right-rtBG.Left; rtBG.Height=rtBG.Bottom-rtBG.Top; this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); } this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xLeft),yTop); this.Canvas.lineTo(ToFixedPoint(xLeft),yBottom); this.Canvas.moveTo(ToFixedPoint(xRight),yTop); this.Canvas.lineTo(ToFixedPoint(xRight),yBottom); this.Canvas.moveTo(ToFixedPoint(xLeft),ToFixedPoint(yCenter)); this.Canvas.lineTo(ToFixedPoint(xRight),ToFixedPoint(yCenter)); this.Canvas.stroke(); this.LinePoint.push({ Start:{X:xLeft, Y:yTop}, End:{X:xLeft, Y:yBottom} }); this.LinePoint.push({ Start:{X:xRight, Y:yTop}, End:{X:xRight, Y:yBottom} }); this.LinePoint.push({ Start:{X:xLeft, Y:yCenter}, End:{X:xRight, Y:yCenter} }); this.DrawArrow({X:ptStart.X, Y:ToFixedPoint(yCenter)}, {X:ptEnd.X, Y:ToFixedPoint(yCenter)}); //文字输出 var bottom=this.Frame.ChartBorder.GetBottomEx(); var top=this.Frame.ChartBorder.GetTopEx(); var startIndex=this.Frame.GetXData(ptStart.X,false); var endIndex=this.Frame.GetXData(ptEnd.X,false); var startValue=this.Frame.GetYData(ptStart.Y,false); var endValue=this.Frame.GetYData(ptEnd.Y,false); var diffValue=endValue-startValue; var barCount=endIndex-startIndex+1; var text=`${barCount} bars`; this.Canvas.font=this.Font; var textHeight=this.GetFontHeight(); var textWidth=this.Canvas.measureText(text).width+4+(this.Label.LeftMargin+this.Label.RightMargin); var rtTextBG={ Left:xCenter-textWidth/2, Top:ptEnd.Y+4, Width:textWidth, Height:textHeight+2 }; if (diffValue>0) rtTextBG.Top=ptEnd.Y-rtTextBG.Height-4; else rtTextBG.Top=ptEnd.Y+4; rtTextBG.Bottom=rtTextBG.Top+rtTextBG.Height; if (diffValue>0) { if (rtTextBG.Top<=top) { rtTextBG.Top=top; rtTextBG.Bottom=rtTextBG.Top+rtTextBG.Height; } } else { if (rtTextBG.Bottom>=bottom) { rtTextBG.Bottom=bottom; rtTextBG.Top=rtTextBG.Bottom-rtTextBG.Height; } } if (this.Label.EnableBGColor) { var path=new Path2D(); path.roundRect(ToFixedPoint(rtTextBG.Left), ToFixedPoint(rtTextBG.Top), ToFixedRect(rtTextBG.Width), ToFixedRect(rtTextBG.Height), [3]); this.Canvas.fillStyle=this.Label.BGColor; this.Canvas.fill(path); } this.Canvas.fillStyle=this.Label.TextColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; this.Canvas.fillText(text,rtTextBG.Left+2+this.Label.LeftMargin,rtTextBG.Bottom-2); } } function ChartDatePriceRange() { this.newMethod=IChartDrawPicture; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartDatePriceRange'; this.PointCount=2; this.Font=12*GetDevicePixelRatio() +"px 微软雅黑"; this.TextColor=this.LineColor; this.IsPointIn=this.IsPointIn_XYValue_Line; this.GetXYCoordinate=this.GetXYCoordinate_default; this.PointToValue_Default=this.PointToValue; this.OnlyMoveXIndex=true; this.IsSupportMagnet=true; this.LineWidth=1; this.EnableBGColor=true; this.BGColor=IChartDrawPicture.ColorToRGBA(this.LineColor,0.15); this.ExtendLine={ Top:false, Bottom: false }; //延长线 this.Label={ TextColor:"rgb(0,0,0)", BGColor:"rgb(211,211,211)", EnableBGColor:true, LeftMargin:5, RightMargin:5 }; this.Draw=function() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; if (!this.IsShow) return; var bCheckXY=true; var drawPoint=this.CalculateDrawPoint( {IsCheckX:bCheckXY, IsCheckY:bCheckXY} ); if (!drawPoint) return; if (drawPoint.length!=2) return; this.ClipFrame(); var ptStart=drawPoint[0]; var ptEnd=drawPoint[1]; this.SetLineWidth(); this.DrawRange(ptStart,ptEnd); this.RestoreLineWidth(); this.DrawPoint(drawPoint); //画点 this.Canvas.restore(); } this.DrawRange=function(ptStart, ptEnd) { var yTop=Math.min(ptStart.Y, ptEnd.Y); var yBottom=Math.max(ptStart.Y, ptEnd.Y); var xLeft=Math.min(ptStart.X, ptEnd.X); var xRight=Math.max(ptStart.X, ptEnd.X); var height=yBottom-yTop; var width=xRight-xLeft; var yCenter=ptStart.Y+(ptEnd.Y-ptStart.Y)/2; var xCenter=ptStart.X+(ptEnd.X-ptStart.X)/2; if (this.ExtendLine.Top) yTop=this.Frame.ChartBorder.GetTopEx(); if (this.ExtendLine.Bottom) yBottom=this.Frame.ChartBorder.GetBottomEx(); if (this.EnableBGColor) { var rtBG={ Left:xLeft, Top:yTop, Right:xRight, Bottom:yBottom }; rtBG.Width=rtBG.Right-rtBG.Left; rtBG.Height=rtBG.Bottom-rtBG.Top; this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); } this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); this.Canvas.moveTo(ToFixedPoint(xLeft),yTop); this.Canvas.lineTo(ToFixedPoint(xLeft),yBottom); this.Canvas.moveTo(ToFixedPoint(xRight),yTop); this.Canvas.lineTo(ToFixedPoint(xRight),yBottom); this.Canvas.moveTo(ToFixedPoint(xLeft),ToFixedPoint(yCenter)); this.Canvas.lineTo(ToFixedPoint(xRight),ToFixedPoint(yCenter)); this.Canvas.moveTo(ToFixedPoint(xCenter),ToFixedPoint(yTop)); this.Canvas.lineTo(ToFixedPoint(xCenter),ToFixedPoint(yBottom)); this.Canvas.stroke(); this.LinePoint.push({ Start:{X:xLeft, Y:yTop}, End:{X:xLeft, Y:yBottom} }); this.LinePoint.push({ Start:{X:xRight, Y:yTop}, End:{X:xRight, Y:yBottom} }); this.LinePoint.push({ Start:{X:xLeft, Y:yCenter}, End:{X:xRight, Y:yCenter} }); this.DrawArrow({X:ptStart.X, Y:ToFixedPoint(yCenter)}, {X:ptEnd.X, Y:ToFixedPoint(yCenter)}); this.DrawArrow({X:ToFixedPoint(xCenter), Y:ptStart.Y}, {X:ToFixedPoint(xCenter), Y:ptEnd.Y}); //文字输出 var bottom=this.Frame.ChartBorder.GetBottomEx(); var top=this.Frame.ChartBorder.GetTopEx(); var startIndex=this.Frame.GetXData(ptStart.X,false); var endIndex=this.Frame.GetXData(ptEnd.X,false); var barCount=endIndex-startIndex+1; var startValue=this.Frame.GetYData(ptStart.Y,false); var endValue=this.Frame.GetYData(ptEnd.Y,false); var diffValue=endValue-startValue; var rate=(diffValue/startValue)*100; var aryText= [ `${diffValue.toFixed(2)} (${rate.toFixed(2)}%)`, `${barCount} bars` ]; this.Canvas.font=this.Font; var textHeight=this.GetFontHeight(); var textWidth=0; for(var i=0;i0) rtTextBG.Top=ptEnd.Y-rtTextBG.Height-4; else rtTextBG.Top=ptEnd.Y+4; rtTextBG.Bottom=rtTextBG.Top+rtTextBG.Height; if (diffValue>0) { if (rtTextBG.Top<=top) { rtTextBG.Top=top; rtTextBG.Bottom=rtTextBG.Top+rtTextBG.Height; } } else { if (rtTextBG.Bottom>=bottom) { rtTextBG.Bottom=bottom; rtTextBG.Top=rtTextBG.Bottom-rtTextBG.Height; } } if (this.Label.EnableBGColor) { var path=new Path2D(); path.roundRect(ToFixedPoint(rtTextBG.Left), ToFixedPoint(rtTextBG.Top), ToFixedRect(rtTextBG.Width), ToFixedRect(rtTextBG.Height), [3]); this.Canvas.fillStyle=this.Label.BGColor; this.Canvas.fill(path); } this.Canvas.fillStyle=this.Label.TextColor; this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; var yText=rtTextBG.Bottom-2; for(var i=0;iptEnd.X) { ptStart=labelInfo.PtEnd; ptEnd=labelInfo.PtStart; } var config=labelInfo.Config; var xCenter=labelInfo.PtStart.X+(labelInfo.PtEnd.X-labelInfo.PtStart.X)/2; var yCenter=labelInfo.PtStart.Y+(labelInfo.PtEnd.Y-labelInfo.PtStart.Y)/2; if (ptStart.Yitem[0] && interval<=item[1]) { var result={}; result.FixInterval=item[2]; result.Increase=item[3]; return result; } } return null; } } function PriceSplitData() { this.newMethod=SplitData; //派生 this.newMethod(); delete this.newMethod; this.Data=[ [0.000001, 0.000002, 0.000001, 0.0000001], [0.000002, 0.000004, 0.000002, 0.0000002], [0.000004, 0.000005, 0.000004, 0.0000001], [0.000005, 0.00001, 0.000005, 0.0000005], [0.00001, 0.00002, 0.00001, 0.000001], [0.00002, 0.00004, 0.00002, 0.000002], [0.00004, 0.00005, 0.00004, 0.000001], [0.00005, 0.0001, 0.00005, 0.000005], [0.0001, 0.0002, 0.0001, 0.00001], [0.0002, 0.0004, 0.0002, 0.00002], [0.0004, 0.0005, 0.0004, 0.00001], [0.0005, 0.001, 0.0005, 0.00005], [0.001, 0.002, 0.001, 0.0001], [0.002, 0.004, 0.002, 0.0001], [0.004, 0.005, 0.004, 0.0001], [0.005, 0.01, 0.005, 0.0005], [0.01, 0.02, 0.01, 0.001], [0.02, 0.04, 0.02, 0.001], [0.04, 0.05, 0.04, 0.001], [0.05, 0.1, 0.05, 0.001], [0.1, 0.2, 0.1, 0.01], [0.2, 0.4, 0.2, 0.01], [0.4, 0.5, 0.2, 0.01], [0.5, 0.8, 0.2, 0.01], [0.8, 1, 0.5, 0.01], [1, 2, 0.5, 0.05], [2, 4, 0.5, 0.05], [4, 5, 0.5, 0.05], [5, 10, 0.5, 0.05], [10, 12, 10, 2], [20, 40, 20, 5], [40, 50, 40, 2], [50, 100, 50, 10], [100, 200, 100, 10], [200, 400, 200, 20], [400, 500, 400, 10], [500, 1000, 500, 50], [1000, 2000, 1000, 50], [2000, 4000, 2000, 50], [4000, 5000, 4000, 50], [5000, 10000, 5000, 100], [10000, 20000, 10000, 1000], [20000, 40000, 20000, 2000], [40000, 50000, 40000, 1000], [50000, 100000, 50000, 5000], [100000, 200000, 100000, 10000], [200000, 400000, 200000, 20000], [400000, 500000, 400000, 10000], [500000, 1000000, 500000, 50000], [1000000, 2000000, 1000000, 100000], [2000000, 4000000, 2000000, 200000], [4000000, 5000000, 4000000, 100000], [5000000, 10000000, 5000000, 500000], [10000000, 20000000, 10000000, 1000000], [20000000, 40000000, 20000000, 2000000], [40000000, 50000000, 40000000, 1000000], [50000000, 100000000, 50000000, 5000000], [100000000, 200000000, 100000000, 10000000], [200000000, 400000000, 200000000, 20000000], [400000000, 500000000, 400000000, 10000000], [500000000, 1000000000, 500000000, 50000000], [1000000000, 2000000000, 1000000000, 100000000], [2000000000, 4000000000, 2000000000, 200000000], [4000000000, 5000000000, 4000000000, 100000000], [5000000000, 10000000000, 5000000000, 500000000] ]; } ///////////////////////////////////////////////////////////////////////////// // 全局配置颜色 // // function JSChartResource() { this.IsDOMFrameTitle=false; //外部DOM指标标题栏 this.IsDOMFrameToolbar=false; //全局K线窗口按钮配置 this.KLineToolbar= { ModifyIndex:true, //修改参数 ChangeIndex:true, //切换指标 CloseIndex:true, //关闭窗口 OverlayIndex:false, //叠加指标 MaxMinWindow:true, //最大最小化窗口 TitleWindow:true, //标题模式 ExportData:false, //数据导出 IsShowOverlayToolbar:true, //是否显示叠加坐标工具栏按钮 IsShowOverlayFrame:true, //是否显示右侧叠加坐标 } //全局分时图窗口按钮配置 this.MinuteToolbar= { ModifyIndex:true, //修改参数 ChangeIndex:true, //切换指标 CloseIndex:true, //关闭窗口 OverlayIndex:true, //叠加指标 MaxMinWindow:true, //最大最小化窗口 TitleWindow:true, //标题模式 ExportData:false, //数据导出 } this.TooltipBGColor="rgb(255, 255, 255)"; //背景色 this.TooltipAlpha=0.92; //透明度 this.PopMinuteChart= { BGColor:"rgba(250,250,250,0.95)", BorderColor:"rgb(0,0,0)", } this.SelectRectBGColor="rgba(1,130,212,0.06)"; //背景色 // this.SelectRectAlpha=0.06; //透明度 this.UpBarColor="rgb(238,21,21)"; //上涨柱子颜色 this.DownBarColor="rgb(25,158,0)"; //下跌柱子颜色 this.UnchagneBarColor="rgb(0,0,0)"; //平盘柱子颜色 this.EmptyBarBGColor="rgb(255,255,255)"; //空心柱子背景色 this.HighLowBarColor='rgb(41,98,255)'; //high low bar 颜色 this.HighLowText={ FontName:"arial", MaxSize:30, MinSize:4, Color:"rgb(41,98,255)", MaxText:"9999.9" }; this.SplashScreen= { BGColor:"rgba(112,128,144,0.5)", Title:"下载数据中......", TextColor:"rgb(43,54,69)", Font:14*GetDevicePixelRatio() +'px 微软雅黑' } this.HLCArea= { HighLineColor:'rgb(242,54,69)', LowLineColor:"rgb(8,153,129)", CloseLineColor:"rgb(224,227,227)", LineWidth:2*GetDevicePixelRatio(), UpAreaColor:"rgba(253,214,218, 0.5)", DownAreaColor:"rgba(205,235,230, 0.5)", }; this.Minute={}; this.Minute.VolBarColor=null; //分时图成交量柱子颜色 默认不用, 设置了柱子就不是红绿了 this.Minute.VolTitleColor="rgb(105,105,105)"; this.Minute.PriceColor="rgb(50,171,205)"; //分时图价格线颜色 this.Minute.PriceLineWidth=1*GetDevicePixelRatio(); //价格线宽度 this.Minute.AreaPriceColor='rgba(50,171,205,0.1)'; //价格的面积图 this.Minute.AvPriceColor="rgb(238,127,9)"; //分时图均价线颜色 this.Minute.PositionColor='rgb(218,165,32)'; //持仓量线段颜色 this.Minute.FrameSplitTextColor=null; //刻度文字颜色 (缺省使用 this.FrameSplitTextColor) this.Minute.Before= { BGColor:'rgba(240,240,240,0.7)', //分钟 集合竞价背景 LineColor:"rgb(50,171,205)", //集合竞价线段颜色 VolColor:["rgb(192,192,0)"], //成交量其他的颜色 colorID=3 开始 AvPriceColor:'rgb(190,190,190)', //均线 Point:{ Color:"rgb(65,105,225)", Radius:2*GetDevicePixelRatio() }, CloseIcon: { Family:'iconfont', Text:"\ue60c", Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Size:12*GetDevicePixelRatio() } //关闭按钮 }; this.Minute.After= { BGColor:'rgba(240,240,240,0.7)', //分钟 集合竞价背景 LineColor:"rgb(50,171,205)", //集合竞价线段颜色 VolColor:["rgb(192,192,0)"], //成交量其他的颜色 colorID=3 开始 AvPriceColor:'rgb(190,190,190)', //均线 Point:{ Color:"rgb(65,105,225)", Radius:2*GetDevicePixelRatio() }, }; this.Minute.NightDay= { NightBGColor:"rgba(0,0,0,0.2)", Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, Day: { Color:"rgb(0,0,0)", BGColor:"rgb(179,179,179)", BorderColor:"rgb(179,179,179)", Margin:{ Left:5, Top:2, Bottom:2, Right:5 } }, Night: { Color:"rgb(0,0,0)", BGColor:"rgb(179,179,179)", BorderColor:"rgb(179,179,179)", Margin:{ Left:5, Top:2, Bottom:2, Right:5 } }, } this.DefaultTextColor="rgb(43,54,69)"; //图形中默认的字体颜色 this.DefaultTextFont=14*GetDevicePixelRatio() +'px 微软雅黑'; //图形中默认的字体 this.TitleFont=13*GetDevicePixelRatio() +'px 微软雅黑'; //指标显示,tooltip显示字体 this.IndexTitleBGColor='rgb(250,250,250)'; //指标名字背景色 this.IndexTitleBorderColor='rgb(180,180,180)'; //指标名字边框颜色 this.IndexTitleBorderMoveOnColor='rgb(0,0,0)'; //指标名字边框颜色(鼠标在上面) this.IndexTitleBorderStyle=1, //0=直角边框 1=圆角边框 this.IndexTitleColor="rgb(43,54,69)"; //指标名字颜色 this.IndexTitleSelectedColor="rgb(65,105,225)"; this.OverlayIndexTitleBGColor='rgba(255,255,255,0.7)'; this.IndexTitleMerginLeft=1; //指标输出左边间距 this.IndexTitle= { UpDownArrow: //数值涨跌箭头 { UpColor:"rgb(238,21,21)", //上涨 DownColor:"rgb(25,158,0)", //下跌 UnchangeColor:"rgb(0,0,0)" //不变 }, ArrowType:0, EnableIndexArrow:true, //指标数值是否带上涨下跌箭头 NameArrow:{ Color:"rgb(43,54,69)", Space:2, Symbol:'▼' }, } this.Title={ TradeIndexColor:'rgb(105,105,105)', //交易指标颜色 ColorIndexColor:'rgb(112,128,144)', //五彩K线颜色 VolColor:"rgb(43,54,69)", //标题成交量 AmountColor:"rgb(43,54,69)", //成交金额 DateTimeColor:"rgb(43,54,69)", //时间,日期 SettingColor:"rgb(43,54,69)", //周期,复权 NameColor:"rgb(43,54,69)" , //股票名称 TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(43,54,69)" //持仓 }; this.UpTextColor="rgb(238,21,21)"; //上涨文字颜色 this.DownTextColor="rgb(25,158,0)"; //下跌文字颜色 this.UnchagneTextColor="rgb(0,0,0)"; //平盘文字颜色 this.CloseLineColor='rgb(0,191,255)'; //收盘价线颜色 this.CloseLineAreaColor=['rgba(0,191,255,0.8)','rgba(0,191,255,0.2)']; //收盘价面积图颜色 this.CloseLineWidth=2; //收盘价面积|收盘价|叠加的收盘价线段宽度 this.FrameBorderPen="rgb(225,236,242)"; //边框颜色 this.MultiDayBorderPen='rgb(225,236,242)'; //多日分时图集合竞价分割线 this.FrameSplitPen="rgb(225,236,242)"; //刻度分割线 this.FrameDotSplitPen='rgb(105,105,105)'; //分割虚线 this.FrameYLineDash= null; //[5*GetDevicePixelRatio(), 5*GetDevicePixelRatio()]; //Y轴线段虚线点间距,填null 就是实线 this.FrameXLineDash= null; //[5*GetDevicePixelRatio(), 5*GetDevicePixelRatio()]; //X轴线段虚线点间距,填null 就是实线 this.FrameSplitTextColor="rgb(117,125,129)"; //刻度文字颜色 this.FrameSplitTextFont=14*GetDevicePixelRatio() +"px 微软雅黑"; //坐标刻度文字字体 this.FrameTitleBGColor="rgb(246,251,253)"; //标题栏背景色 this.SelFrameBorderColor='rgb(130, 130, 130)'; this.Frame={ XBottomOffset:2*GetDevicePixelRatio(), //X轴文字向下偏移 YTopOffset:2*GetDevicePixelRatio(), //Y轴顶部文字向下偏移 YTextPadding:[2,2], EnableRemoveZero:true, //移除小数点后面的0 StringFormat:0 }; this.ToolbarButtonStyle=0; this.FrameLogo= { TextColor:'rgb(178,34,34)', Font:"bold "+ 16*GetDevicePixelRatio() +"px 微软雅黑", Text:"", //不要修改声明, 任何修改声明产生的任何法律责任由修改者自行独立承担,与HQChart插件作者无关。 BGColor:"rgba(230,230,230, 0.5)", }; //百分比坐标文字颜色 this.Frame.PercentageText= { PriceColor:'rgb(117,125,129)', PercentageColor:"rgb(117,125,129)", SplitColor:"rgb(117,125,129)", Font:14*GetDevicePixelRatio() +"px 微软雅黑" }; //对数坐标 this.FrameLogarithmic= { OpenPriceFont: "bold "+14*GetDevicePixelRatio() +"px 微软雅黑", //开盘价刻度文字字体 MinInterval: 45*GetDevicePixelRatio() //刻度最小间距 }; //等比坐标 this.FrameSplitIncrease= { Increase:0.1 //涨幅 }; //等分坐标 this.FrameSplitAverage= { Count:4 //分割个数 }; //黄金分割坐标 this.FrameGoldenSection= { Golden:[0, 0.191, 0.382, 0.5, 0.618, 0.809, 1] }; //Y轴最新价格刻度颜色 this.FrameLatestPrice = { TextColor:'rgb(255,255,255)', //最新价格文字颜色 UpBarColor:"rgb(238,21,21)", //上涨 DownBarColor:"rgb(25,158,0)", //下跌 UnchagneBarColor:"rgb(0,0,0)", //平盘 BGAlpha:0.6, EmptyBGColor:"rgb(255,255,255)", //空心背景色 OverlayTextColor:"rgb(255,255,255)", //叠加股票的文字颜色 }; this.FrameMargin=4; //左右一共的边距 this.FrameLeftMargin=2; this.FrameRightMargin=2; this.DragSubFrameBorder= { TopBorderHeight:6*GetDevicePixelRatio(), //拖拽边框高度 MinFrameHeight:50*GetDevicePixelRatio() //指标窗口最小高度 }, //叠加指标框架 this.OverlayFrame={ BolderPen:'rgb(190,190,190)', //指标边框线 TitleColor:'rgb(105,105,105)', //指标名字颜色 TitleFont:11*GetDevicePixelRatio() +'px arial', //指标名字字体 }; this.CorssCursorBGColor="rgb(43,54,69)"; //十字光标背景 this.CorssCursorTextColor="rgb(255,255,255)"; //十字光文字颜色 this.CorssCursorTextFont=14*GetDevicePixelRatio() +"px 微软雅黑"; this.CorssCursorHPenColor="rgb(130,130,130)"; //十字光标线段颜色(水平) this.CorssCursorVPenColor="rgb(130,130,130)"; //十字光标线段颜色(垂直) this.CorssCursorXRangeBGColor="rgba(100,149,237,0.3)"; //十字光标X轴访问背景色 this.CorssCursor= { RightButton : { BGColor:'rgb(43,54,69)', PenColor:'rgb(255,255,255)', Icon: { Text:'\ue6a3', Color:'rgb(255,255,255)', Family:"iconfont", Size:18 } }, RightMargin: { Left:2, Right:2, Top:5, Bottom:3 } }; this.LockBGColor = "rgb(220, 220, 220)"; //指标锁区域颜色 this.LockTextColor = "rgb(210, 34, 34)"; //指标锁提示信息文字颜色 this.Domain="http://127.0.0.1:8080"; //API域名 this.CacheDomain="http://127.0.0.1:8087"; //缓存域名 this.PyIndexDomain='http://127.0.0.1:8088'; //py指标计算域名 //K线配置 this.KLine= { MaxMin: {Font:12*GetDevicePixelRatio() +'px 微软雅黑',Color:'rgb(43,54,69)', RightArrow:"→", LeftArrow:"←", HighYOffset:0, LowYOffset:0}, //K线最大最小值显示 Info: //信息地雷 { Investor: { ApiUrl:'/API/NewsInteract', //互动易 IconFont: { Family:'iconfont', Text:'\ue631' , HScreenText:'\ue684', Color:'#1c65db'} //SVG 文本 }, Announcement: //公告 { ApiUrl:'/API/ReportList', IconFont: { Family:'iconfont', Text:'\ue633', HScreenText:'\ue685', Color:'#f5a521' }, //SVG 文本 IconFont2: { Family:'iconfont', Text:'\ue634', HScreenText:'\ue686', Color:'#ed7520' }, //SVG 文本 //季报 }, Pforecast: //业绩预告 { ApiUrl:'/API/StockHistoryDay', IconFont: { Family:'iconfont', Text:'\ue62e', HScreenText:'\ue687', Color:'#986cad' } //SVG 文本 }, Research: //调研 { ApiUrl:'/API/InvestorRelationsList', IconFont: { Family:'iconfont', Text:'\ue632', HScreenText:'\ue688', Color:'#19b1b7' } //SVG 文本 }, BlockTrading: //大宗交易 { ApiUrl:'/API/StockHistoryDay', IconFont: { Family:'iconfont', Text:'\ue630', HScreenText:'\ue689', Color:'#f39f7c' } //SVG 文本 }, TradeDetail: //龙虎榜 { ApiUrl:'/API/StockHistoryDay', IconFont: { Family:'iconfont', Text:'\ue62f', HScreenText:'\ue68a' ,Color:'#b22626' } //SVG 文本 }, //扩展图标库 IconLibrary: { Family:'iconfont', Icon: [ { Text:'\ue630', HScreenText:'\ue689', Color:'#f39f7c' }, { Text:'\ue632', HScreenText:'\ue688', Color:'#19b1b7' }, { Text:'\ue62f', HScreenText:'\ue68a' ,Color:'#b22626' }, { Text:'\ue634', HScreenText:'\ue686', Color:'#ed7520' } ] }, }, NumIcon: { Color:'rgb(251,80,80)',Family:'iconfont', Text:[ '\ue649', '\ue63b','\ue640','\ue63d','\ue63f','\ue645','\ue641','\ue647','\ue648','\ue646','\ue636', '\ue635','\ue637','\ue638','\ue639','\ue63a','\ue63c','\ue63e','\ue642','\ue644','\ue643' ] }, TradeIcon: //交易指标 图标 { Family:'iconfont', Buy: { Color:'rgb(255,15,4)', Text:'\ue683', HScreenText:'\ue682'}, Sell: { Color:'rgb(64,122,22)', Text:'\ue681',HScreenText:'\ue680'}, } }; this.VirtualKLine= { Color:'rgb(100,100,100)', LineDash:[2,2] }; this.PriceGapStyple= { Line:{ Color:"rgb(186,186,186)" }, Text:{ Color:"rgb(105,105,105)", Font:`${12*GetDevicePixelRatio()}px 微软雅黑`} }; //订单流配置 this.OrderFlow= { UpColor:{BG:'rgb(223,191,180)', Border:"rgb(196,84,86)" }, //阳线 DownColor:{ BG:"rgb(176,212,184)", Border:'rgb(66,94,74)' }, //阴线 UnchagneColor: {BG:"rgb(216,221,177)", Border:"rgb(209,172,129)"}, //平盘 Text:{ Color: "rgb(92,96,89)" , Family:'Arial', FontMaxSize:18, MaxValue:"8888" }, //文字(风格 2,3共用) Line:{ UpDownColor: "rgb(0,0,0)", MiddleColor:"rgb(211,211,211)" }, //最大, 最低,中间 竖线 AlwaysShowOrderText:true, //总是显示订单流文字 POCGBColor:"rgba(178,34,34,0.8)", AskBarColor:'rgb(14,209,69)', BidBarColor:'rgb(236,28,36)' }; this.OrderFlow_Style2= { BarWidth:10, UpColor:'rgb(241,55,63)', DownColor:"rgb(75,105,150)", UnchagneColor:"rgb(79,79,79)" }; this.OrderFlow_Style3= { BarWidth:20, UpColor:'rgb(241,55,63)', DownColor:"rgb(75,105,150)", UnchagneColor:"rgb(79,79,79)" }; this.OrderFlow_Style4= { KBarWidth:5, UpColor:'rgb(241,55,63)', DownColor:"rgb(75,105,150)", UnchagneColor:"rgb(79,79,79)", VolBarSpace:1, LeftMargin:1, RightMargin:1 }; this.OrderFlow_Style5= { AskBarColor:"rgb(176,22,22)", //左 BidBarColor:"rgb(98,126,176)", //右 LeftMargin:3, RightMargin:2, }; this.Index={}; //指标线段颜色 this.Index.LineColor= [ "rgb(255,174,0)", "rgb(25,199,255)", "rgb(175,95,162)", "rgb(236,105,65)", "rgb(68,114,196)", "rgb(229,0,79)", "rgb(0,128,255)", "rgb(252,96,154)", "rgb(42,230,215)", "rgb(24,71,178)", ]; this.OverlaySymbol={ Random:0 }; //Random 颜色的随机数 this.OverlaySymbol.Color= //叠加股票颜色 [ "rgb(38,198,218)", "rgb(103,58,183)", "rgb(0,191,165)", "rgb(130,177,255)", ]; //历史数据api this.Index.StockHistoryDayApiUrl="http://127.0.0.1:8080/API/StockHistoryDay"; //市场多空 this.Index.MarketLongShortApiUrl="http://127.0.0.1:8080/API/FactorTiming"; //市场关注度 this.Index.MarketAttentionApiUrl="http://127.0.0.1:8080/API/MarketAttention"; //行业,指数热度 this.Index.MarketHeatApiUrl="http://127.0.0.1:8080/API/MarketHeat"; //自定义指数热度 this.Index.CustomIndexHeatApiUrl="http://127.0.0.1:8080/API/QuadrantCalculate"; //指标不支持信息 this.Index.NotSupport={Font:`${14*GetDevicePixelRatio()}px 微软雅黑`, TextColor:"rgb(52,52,52)"}; //按钮 this.Buttons= { CloseOverlayIndex: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue60c", Size:12*GetDevicePixelRatio(), MerginLeft:3 }, CloseWindow: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue60c", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, ChangeIndex: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue656", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, OverlayIndex: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue655", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, ModifyIndexParam: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue604", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, //最大化, 最小化 MaxMinWindow: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue6a5", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, //指标标题窗口模式 TitleWindow: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue6a6", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, //指标标题窗口模式 ExportData: { Color:"rgb(0,0,0)", MoveOnColor:'rgb(30,144,255)', Family:"iconfont", Text:"\ue6a9", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, Tooltip: { Font:13*GetDevicePixelRatio() +"px 微软雅黑", Color:'rgb(71,71,71)', ColorBG:'rgb(255,255,255)', ColorBorder:'rgb(0,0,0)', BorderRadius:2, Mergin:{ Left:4, Right:4, Top:2, Bottom:3 }, } } //画图工具 this.DrawPicture= { LineColor: [ "rgb(41,98,255)" ], PointColor: [ "rgb(41,98,255)", //选中颜色 "rgb(89,135,255)", //moveon颜色 "rgb(255,255,255)" //空心点背景色 ], XYCoordinate: { BGColor:'rgba(203,216,255,0.5)', //区间段背景色 TextBGColor:"rgb(52,101,255)", //文字背景色 TextColor:"rgb(255,255,255)", //文字颜色 Font:14*GetDevicePixelRatio() +"px 微软雅黑" //文字字体 }, PointType:2, // 0=圆点 1=方框 2=空心圆 IsShowPoint:false //是否始终显示点 }; this.ChartOX= { Family:'iconfont', Up:{Color:'rgb(178,34,34)', Text:"\ue697" }, Down:{Color:"rgb(0,206,209)", Text:"\ue68c" }, SquareLineColor:'rgb(119,136,153)' }; this.KLineTrain = { Font:'bold 14px arial', LastDataIcon: {Color:'rgb(0,0,205)',Text:'⬇'}, BuyIcon: {Color:'rgb(0,205,102 )',Text:'B'}, SellIcon: {Color:'rgb(255,127,36 )',Text:'S'}, IconFont: { Family:'iconfont', Buy:{ Text:'\ue64a', HScreenText:'\ue68a' ,Color:'rgb(255,140,0)' }, Sell:{ Text:'\ue64b', HScreenText:'\ue68a' ,Color:'rgb(6,79,18)' }, Last:{ Text:'\ue681', HScreenText:'\ue68a' ,Color:'rgb(55,0,255)' }, } }; this.ChartKLineTable= { TextFont:{ Family:'Arial' , FontMaxSize:25 }, ItemMergin:{ Left:5, Right:5, Top:4, Bottom:2 }, }; //手机端tooltip this.TooltipPaint = { BGColor:'rgba(250,250,250,0.8)', //背景色 BorderColor:'rgb(120,120,120)', //边框颜色 TitleColor:'rgb(79, 79, 79)', //标题颜色 TitleFont:13*GetDevicePixelRatio() +'px 微软雅黑', //字体 DateTimeColor:'rgb(105 105 105)', VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(79, 79, 79)", //成交金额 }; this.PCTooltipPaint = { BGColor:'rgba(250,250,250)', //背景色 BorderColor:'rgb(120,120,120)', //边框颜色 TitleColor:'rgb(60,60,60)', //标题颜色 TitleFont:12*GetDevicePixelRatio() +'px 微软雅黑', //字体 DateTimeColor:'rgb(60,60,60)', VolColor:"rgb(60,60,60)", //标题成交量 AmountColor:"rgb(60,60,60)", //成交金额 PositionColor:"rgb(60,60,60)", //持仓量 }; this.PCTooltip= { LineHeight:25 //单行高度 }; this.DialogTooltip= { BGColor:'rgb(250,250,250)', //背景色 BorderColor:'rgb(20,20,20)', //边框颜色 TitleColor:'rgb(250,250,250)', //标题颜色 TitleBGColor:"rgb(200, 66, 69)", //标题背景颜色 VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(79, 79, 79)", //成交金额 DateTimeColor:'rgb(60,60,60)', TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(255,0,255)", //持仓 TextColor:"rgb(0,0,0)", //数值名称 ValueColor:"rgb(0,0,0)", //数值 }; this.FloatTooltip= { BGColor:'rgb(250,250,250)', //背景色 BorderColor:'rgb(20,20,20)', //边框颜色 VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(79, 79, 79)", //成交金额 DateTimeColor:'rgb(60,60,60)', TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(255,0,255)", //持仓 TextColor:"rgb(0,0,0)", //数值名称 ValueColor:"rgb(0,0,0)", //数值 }; //区间统计 this.DialogSelectRect= { BGColor:'rgb(250,250,250)', //背景色 BorderColor:'rgb(20,20,20)', //边框颜色 TitleColor:'rgb(0,0,0)', //对话框标题颜色 TextColor:"rgb(0,0,0)", //数值名称 ValueColor:"rgb(0,0,0)", //数值 VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(79, 79, 79)", //成交金额 TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(255,0,255)" //持仓 }; //键盘精灵 this.DialogPopKeyboard= { BGColor:'rgb(250,250,250)', //背景色 BorderColor:'rgb(20,20,20)', //边框颜色 TitleColor:'rgb(0,0,0)', //对话框标题颜色 TitleBGColor:"rgb(200, 66, 69)", //标题背景颜色 Input: { BGColor:"rgb(250,250,250)", TextColor:"rgb(0,0,0)", } }; //指标搜索 this.DialogSearchIndex= { BGColor:'rgb(250,250,250)', //背景色 BorderColor:'rgb(20,20,20)', //边框颜色 TitleColor:'rgb(250,250,250)', //标题颜色 TitleBGColor:"rgb(200, 66, 69)", //标题背景颜色 IndexNameColor:"rgb(0,0,0)", //数值名称 GroupNameColor:"rgb(0,0,0)", InputTextColor:"rgb(0,0,0)" }; //弹幕 this.Barrage= { Font:16*GetDevicePixelRatio() +'px 微软雅黑', //字体 Height:20, Color:'RGB(109,109,109)' } //走势图 信息地雷 this.MinuteInfo={ TextColor: 'rgb(84,143,255)', Font: 14*GetDevicePixelRatio() +'px 微软雅黑', PointColor:'rgb(38,113,254)', LineColor:'rgb(120,167,255)', TextBGColor:'rgba(255,255,255,0.8)', PointRadius:4*GetDevicePixelRatio(), //圆点半径 } //画图工具-尺子 this.ChartDrawRuler= { TitleColor:null, //K线信息标题颜色, (可选,不填使用涨跌颜色) } //画图工具-波浪尺 this.ChartDrawWaveRuler= { RulerWidth:10, //刻度尺长度 RulerLineWidth:1, //刻度线粗细 MaxScaleRuler:2, //尺子最大的高度比 Font:14*GetDevicePixelRatio() +"px 微软雅黑", ScaleRuler: [ {Value:0, Text:"0.0%"}, { Value:0.382, Text:"38.2%" }, { Value:0.618, Text:"61.8%" } ,{ Value:1, Text:"100%"}, { Value:1.618, Text:"161.8%" }, { Value:2.0, Text:"200%" } ] } this.ChartDrawWaveRuler2Point= { RulerWidth:20, //刻度尺长度 RulerLineWidth:1, //刻度线粗细 MaxScaleRuler:2, //尺子最大的高度比 Font:14*GetDevicePixelRatio() +"px 微软雅黑", ScaleRuler: [ {Value:0, Text:"base"}, { Value:0.618, Text:"61.8%" } ,{ Value:1, Text:"100%"}, { Value:1.618, Text:"161.8%" } ] } this.ChartDrawVolProfile= { BGColor:"rgba(244,250,254,0.8)", BorderColor:"rgba(255,255,255)", VolLineColor:"rgb(232,5,9)", UpVolColor:"rgba(103,179,238, 0.24)", DownVolColor:"rgba(237,208,105,0.24)", AreaUpColor:"rgb(103,179,238,0.7)", AreaDonwColor:"rgba(237,208,105,0.7)", Text:{ Color: "rgb(0,0,0)" , Family:'Arial', FontMaxSize:18, FontMinSize:6 }, //文字 } this.ChartVolProfileVisibleRange= { VolLineColor:"rgb(232,5,9)", VolLineFont:14*GetDevicePixelRatio() +"px 微软雅黑", VolLineTextColor:'rgb(255,255,255)', UpVolColor:"rgba(103,179,238, 0.24)", DownVolColor:"rgba(237,208,105,0.24)", AreaUpColor:"rgb(103,179,238,0.7)", AreaDonwColor:"rgba(237,208,105,0.7)", Text:{ Color: "rgb(0,0,0)" , Family:'Arial', FontMaxSize:18, FontMinSize:6 }, //文字 VAHLineColor:'rgb(0,0,255)', VAHTextColor:"rgb(255,255,255)", VALLineColor:"rgb(0,0,255)", VALTextColor:"rgb(255,255,255)", VAFont:14*GetDevicePixelRatio() +"px 微软雅黑", } this.ChartDrawNote= { Text:"\ue6aa", FontOption:{ Family:'iconfont', Size:32 }, NoteFontOption:{ Family:'微软雅黑', Size:12, Weight:null, Style:null }, //Weight(bold 粗体), Style(italic) NoteWidth:200, NoteMargin:{ Left:5, Top:5, Bottom:5, Right:5 }, NoteBGColor:'rgba(104,114,255,0.7)', NoteTextColor:"rgb(240,240,240)", NoteBorderColor:"rgb(220,220,220)", LineSpace:3, //行间距 ArrowSize:10 } this.ChartDrawAnchoredText= { TextMargin:{ Left:5, Top:5, Bottom:5, Right:5 }, BGColor:'rgba(104,114,255,0.7)', BorderColor:"rgb(220,220,220)", TextColor:'rgb(0,0,0)', FontOption:{ Family:'微软雅黑', Size:12, Weight:null, Style:null }, //Weight(bold 粗体), Style(italic) LineSpace:2, //行间距 TextMaxWidth:-1 } this.ChartDrawPriceLabel= { TextMargin:{ Left:10, Top:5, Bottom:5, Right:10 }, BGColor:'rgba(104,114,255,0.7)', BorderColor:"rgb(220,220,220)", TextColor:'rgb(0,0,0)', FontOption:{ Family:'微软雅黑', Size:14, Weight:null, Style:null }, //Weight(bold 粗体), Style(italic) } this.ChartDrawPriceNote= { TextMargin:{ Left:10, Top:5, Bottom:5, Right:10 }, BGColor:'rgba(104,114,255,0.7)', BorderColor:"rgb(220,220,220)", TextColor:'rgb(0,0,0)', FontOption:{ Family:'微软雅黑', Size:14, Weight:null, Style:null }, //Weight(bold 粗体), Style(italic) } //多图标指标ChartMultiSVGIcon -> MULTI_SVGICON //单图标指标ChartSingleText -> DRAWICON this.DRAWICON= { Icon: { MaxSize:24, //图标最大 MinSize:12, //图标最小 YOffset:0, Zoom: { Type:1, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value; Value:1 } }, Text: { MaxSize:50, //字体最大 MinSize:12, //字体最小 YOffset:0, Zoom: { Type:1, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value; Value:1 }, FontName:'Arial' //字体 } } this.DRAWTEXT= { MaxSize:30, //字体最大 MinSize:20, //字体最小 YOffset:0, Zoom: { Type:1, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value; Value:1 }, FontName:'微软雅黑' //字体 } this.DRAWNUMBER= { MaxSize:30, //字体最大 MinSize:20, //字体最小 YOffset:0, Zoom: { Type:1, //0=放大(K线宽度*Value) 1=放大(K线+间距)*Value 2=(K线+间距)+2*Value; Value:1 }, FontName:'微软雅黑' //字体 } this.DRAWABOVE= { YOffset:0 //y坐标向上偏移 } this.DRAWTEXT_FIX={ Font:14*GetDevicePixelRatio() +'px 微软雅黑' } this.DRAWNUMBER_FIX={ Font:14*GetDevicePixelRatio() +'px 微软雅黑' } //虚线配置 this.DOTLINE= { LineDash:[3,5] //虚线配置 } this.DRAWSL= { PixelWidth:15 //1个像素点宽度 } this.CIRCLEDOT= { Radius:1.3*GetDevicePixelRatio() } this.TIPICON= { Family:'iconfont', TextFont:`${GetDevicePixelRatio()}px 微软雅黑`, Size:10*GetDevicePixelRatio(), Color:"rgb(255,165,0)" } this.POINTDOT= { Radius:2*GetDevicePixelRatio() } this.DepthMapPaint= { LineColor:"rgba(255,185,15)", AreaColor:["rgba(255,185,15,0.8)","rgba(255,185,15,0.4)"], TextColor:"rgba(255,255,255)", TextBGColor:'rgb(43,54,69)' } this.KLineYAxisBGPaint= { Font:12*GetDevicePixelRatio() +'px 微软雅黑', LineColor:"rgb(117,125,129)", DiffValutTextColor:"rgb(117,125,129)", DiffValueBGColor:"rgb(251,140,1)" } //筹码分布图 this.StockChip= { InfoColor:'rgb(0,0,0)', //文字颜色 DayInfoColor:'rgb(255,255,255)', //周期颜色内文字颜色 DefaultButton: { Color:"rgb(128,128,128)", MoveOnColor:'rgb(30,144,255)', SelectedColor:"rgb(255,0,0)", Family:"iconfont", Text:"\ue621", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, LongButton: { Color:"rgb(128,128,128)", MoveOnColor:'rgb(30,144,255)', SelectedColor:"rgb(255,128,0)", Family:"iconfont", Text:"\ue617", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, RecentButton: { Color:"rgb(128,128,128)", MoveOnColor:'rgb(30,144,255)', SelectedColor:"rgb(0,0,204)", Family:"iconfont", Text:"\ue617", Size:13*GetDevicePixelRatio(), MerginLeft:4 }, } //深度图 this.DepthChart= { BidColor: { Line:"rgb(82,176,123)", Area:"rgba(82,176,123,0.8)"}, //卖 AskColor: { Line:"rgb(207,76,89)", Area:"rgba(207,76,89, 0.8)"}, //买 LineWidth:4 } this.DepthCorss= { BidColor: { Line:"rgb(82,176,123)" }, //卖 AskColor: { Line:"rgb(207,76,89)" }, //买 LineWidth:2, //线段宽度 LineDash:[3,3], Tooltip: { BGColor:'rgba(236,240,245, 0.8)', TextColor:"rgb(130,140,151)", Border:{ Top:5, Left:20, Right:20, Bottom:5, ItemSpace:5 }, Font:14*GetDevicePixelRatio() +"px 微软雅黑", } } //区间选择 this.RectSelect= { LineColor:"rgb(64,64,64)", //竖线 LineWidth:1*GetDevicePixelRatio(), LineDotted:[3,3], AreaColor:"rgba(234,234,234,0.5)", //面积 SubAreaColor:"rgba(105,105,105,0.5)", RangeTextColor:"rgb(248,248,255)", RangeTextFont:14*GetDevicePixelRatio() +"px 微软雅黑", RangeTextBGColor:'rgb(43,54,69)', RangeTextSubColor:"rgb(255,255,255)", RangeTextSubFont:12*GetDevicePixelRatio() +"px 微软雅黑", RangeTextSubBGColor:'rgb(54,54,54)', Mark:{ Family:'iconfont', Text:'\ue695' , Color:'rgb(250,0,0)', Size:15*GetDevicePixelRatio(), Position:{ Index:0, Top:"TopEx" } } } //选中图形 this.SelectedChart= { LineWidth:1, LineColor:'rgb(55,100,100)', Radius:4, MinSpace:200, //点和点间最小间距 BGColor:"rgb(255,255,255)" } //鼠标区间选中 this.RectDrag= { LineColor:"rgb(0,0,0)", //竖线 LineWidth:1*GetDevicePixelRatio(), BGColor:"rgba(128,128,128,0.2)", //面积 } this.DragMovePaint= { TextColor:"rgb(0,0,0)", Font:14*GetDevicePixelRatio() +"px 微软雅黑" } this.SessionBreaksPaint= { BGColor:[null, "rgb(245,246,246)"], SplitLine:{ Color:'rgb(73,133,231)', Width:1*GetDevicePixelRatio(), Dash:[5*GetDevicePixelRatio(),5*GetDevicePixelRatio()] } } //成交明细 this.DealList= { BorderColor:'rgb(192,192,192)', //边框线 Header: { Color:"RGB(60,60,60)", Mergin:{ Left:5, Right:5, Top:4, Bottom:2 }, Font:{ Size:12, Name:"微软雅黑" } }, Row: { Mergin:{ Top:2, Bottom:2 }, Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:3, Right:3, Bottom:2 } }, FieldColor: { Vol:"rgb(90,90,90)", //成交量 Time:"rgb(60,60,60)", //时间 Deal:"rgb(90,90,90)", //成交笔数 Index:"rgb(60,60,60)", //序号 BarTitle:'rgb(60,60,60)', //柱子文字 Text:"rgb(60,60,60)", //默认文本 Bar: [ "rgb(255,0,0)", "rgb(34,139,34)", "rgb(119,136,153)","rgb(75,0,130)", "rgb(65,105,225)","rgb(255,215,0)", 'rgb(255,0,255)', "rgb(128,128,0)" ] //柱子颜色 }, UpTextColor:"rgb(238,21,21)", //上涨文字颜色 DownTextColor:"rgb(25,158,0)", //下跌文字颜色 UnchagneTextColor:"rgb(0,0,0)" //平盘文字颜色 }, //报价列表 this.Report= { BorderColor:'rgb(192,192,192)', //边框线 SelectedColor:"rgb(180,240,240)", //选中行 Header: { Color:"rgb(60,60,60)", //表头文字颜色 SortColor:"rgb(255,0,0)", //排序箭头颜色 Mergin:{ Left:5, Right:5, Top:4, Bottom:4 }, //表头四周间距 Font:{ Size:12, Name:"微软雅黑" }, //表头字体 }, //排序图标 SortIcon: { Size:12, Family:"iconfont", Arrow:[null, "\ue6b2", "\ue6b1"], Color:[null, "rgb(255,0,0)", "rgb(255,0,0)"], Margin:{ Left:0, Bottom:6 } }, Item: { Mergin:{ Top:2, Bottom:4,Left:5, Right:5 }, //单元格四周间距 Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:3, Right:3, Bottom:2 },//单元格字体 NameFont:{ Size:14, Name:"微软雅黑" }, SymbolFont:{ Size:12, Name:"微软雅黑" }, }, //固定行 FixedItem: { Font:{ Size:15, Name:"微软雅黑"}, }, LimitBorder: { Color:"rgb(180,180,180)", Mergin:{ Top:1, Bottom:1,Left:0, Right:0 }, }, NameSymbolV2: { Name:{ Size:14, Name:"微软雅黑", Color: "rgb(60,60,60)"}, Symbol:{ Size:10, Name:"微软雅黑", Color: "rgb(105 105 105)"}, }, //涨停 跌停背景色 LimitColor: { UpColor:"rgb(255,0,0)", DownColor:"rgb(0,128,0)", TextColor:"rgb(250,250,250)", }, FieldColor: { Index:"rgb(60,60,60)", //序号 Symbol:"rgb(60,60,60)", Name:"rgb(60,60,60)", Vol:"rgb(90,90,90)", //成交量 Amount:"rgb(90,90,90)", //成交金额 Text:"rgb(60,60,60)", //默认文本 }, UpTextColor:"rgb(238,21,21)", //上涨文字颜色 DownTextColor:"rgb(25,158,0)", //下跌文字颜色 UnchagneTextColor:"rgb(90,90,90)", //平盘文字颜色 CloseLine: { CloseColor:"rgb(30,144,255)", YCloseColor:"rgba(105,105,105,0.5)", //昨收线 AreaColor:'rgba(0,191,255,0.2)', }, KLine: { UpColor:"rgb(255,0,0)", DownColor:"rgb(0,128,0)", UnchagneColor:'rgb(90,90,90)', DataWidth:16, DistanceWidth:3 }, Tab: { Font:{ Size:12, Name:"微软雅黑" }, ScrollBarWidth:100, ButtonColor:"rgb(252,252,252)", BarColor:"rgb(180,180,180)", BorderColor:'rgb(180,180,180)', Mergin:{ Left:5, Right:5, Top:4, Bottom:2 }, TabTitleColor:'rgb(60,60,60)', TabSelectedTitleColor:'rgb(255,255,255)', TabSelectedBGColor:"rgb(234,85,4)", TabMoveOnTitleColor:"rgb(234,85,4)", TabBGColor:"rgb(220,220,220)" }, PageInfo: { Font:{ Size:15, Name:"微软雅黑"}, TextColor:"rgb(0,0,0)", BGColor:"rgba(180,180,180,0.5)", Mergin:{ Left:5, Right:5, Top:4, Bottom:2 }, }, DragRow: { Color:"rgba(190,190,190,0.8)", TextColor:'rgba(0,0, 0, 0.8)', MoveRowColor:'rgb(240,128,128)', SrcRowColor:'rgb(180,240,240)', }, VScrollbar: { ScrollBarHeight:60, ButtonColor:"rgba(252,252,252,0.8)", BarColor:"rgba(168,168,168,0.9)", BorderColor:'rgba(180,180,180,0.9)', BGColor:"rgba(234,239,248,0.9)", BarWidth:{ Size:12 } }, CheckBox: { Family:"iconfont", Size:15, Checked:{ Color:"rgb(69,147,238)", Symbol:"\ue6b3", DisableColor:"rgb(230,230,230)", MouseOnColor:"rgb(69,147,238)" }, Unchecked:{ Color:"rgb(120,120,120)", Symbol:"\ue6b4", DisableColor:"rgb(230,230,230)", MouseOnColor:"rgb(69,147,238)" }, Margin:{ Left:5, Right:5, Bottom:2, Top:4 }, }, Link: { Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextColor:"rgb(30,144,255)", Disable:{ TextColor:"rgb(211,211,211)" }, MouseOn:{ TextColor:"rgb(30,144,255)" }, }, ProgressBar: { BGColor:"rgb(229,231,238)", BarColor:"rgb(26,125,255)", Margin:{ Left:2, Right:2, Bottom:2, Top:2 }, BarMargin:{ Left:2, Right:2, Bottom:2, Top:2 }, TextColor:"rgb(0,0,0)", Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextMargin:{ Left:40, Right:2, Bottom:2, Top:2}, Disable:{ BGColor:"rgb(229,231,238)", BarColor:"rgb(131,131,131)", TextColor:"rgb(159,161,159)"} }, Button: { BGColor:"rgb(61,134,180)", TextColor:"rgb(255,255,255)", BorderColor:"rgb(200,200,200)", Disable:{ BGColor:"rgb(105,105,105)", TextColor:"rgb(169,169,169)"}, MouseOn:{ BGColor:"rgb(57,125,169)", TextColor:"rgb(230,230,230)" }, Margin:{ Left:5, Right:5, Bottom:2, Top:2 }, TextMargin:{ Bottom:2 }, Font:`${12*GetDevicePixelRatio()}px 微软雅黑` } }, //报价列表 this.TReport= { BorderColor:'rgb(192,192,192)', //边框线 SelectedColor:"rgb(3,89,245)", //选中行 Header: { Color:"rgb(60,60,60)", //表头文字颜色 SortColor:"rgb(255,0,0)", //排序箭头颜色 Mergin:{ Left:5, Right:5, Top:4, Bottom:2}, //表头四周间距 Font:{ Size:14, Name:"微软雅黑" } //表头字体 }, Item: { Mergin:{ Top:2, Bottom:0,Left:5, Right:5 }, //单元格四周间距 Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:3, Right:3, Bottom:2 },//单元格字体 NameFont:{ Size:14, Name:"微软雅黑" }, SymbolFont:{ Size:12, Name:"微软雅黑" } }, //固定行 FixedItem: { Font:{ Size:15, Name:"微软雅黑"}, }, CenterItem: { TextColor:"rgb(60,60,83)", BaseTextColor:"rgb(60,60,83)", BGColor:"rgb(180,180,180)" }, FieldColor: { Index:"rgb(60,60,60)", //序号 Symbol:"rgb(60,60,60)", Name:"rgb(60,60,60)", Vol:"rgb(90,90,90)", //成交量 Position:"rgb(90,90,90)", //持仓量 Amount:"rgb(90,90,90)", //成交金额 Text:"rgb(60,60,60)", //默认文本 }, UpTextColor:"rgb(238,21,21)", //上涨文字颜色 DownTextColor:"rgb(25,158,0)", //下跌文字颜色 UnchangeTextColor:"rgb(90,90,90)", //平盘文字颜色 UpBGColor:"rgb(255,220,220)", DownBGColor:"rgb(190,220,190)", MarkBorder: { MaxPositionColor:"rgb(192,192,192)" }, }, //键盘精灵 this.Keyboard= { BorderColor:'rgb(192,192,192)', //边框线 SelectedColor:"rgb(180,240,240)", //选中行 TextColor:"rgb(0,0,0)", Item: { Mergin:{ Top:2, Bottom:0,Left:1, Right:1 }, //单元格四周间距 Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:0, Right:0, Bottom:2 },//单元格字体 NameFont:{ Size:14, Name:"微软雅黑" }, SymbolFont:{ Size:12, Name:"微软雅黑" } }, VScrollbar: { ScrollBarHeight:50, ButtonColor:"rgba(252,252,252,0.8)", BarColor:"rgba(168,168,168,0.9)", BorderColor:'rgba(180,180,180,0.9)', BGColor:"rgba(234,239,248,0.9)", BarWidth:{ Size:8 } }, }, //滚动条 this.ScrollBar= { BorderColor:'rgb(192,192,192)', XSplitTextFont:`${12*GetDevicePixelRatio()}px 微软雅黑`, XSplitTextColor:"rgb(0,0,0)", XSplitLineColor:"rgba(0,0,0,0.8)", BGChart: { Color:"rgb(135,206,250)", LineWidth:1, AreaColor:"rgba(135,206,250,0.5)", }, Slider: { DateFont:`${14*GetDevicePixelRatio()}px 微软雅黑`, DateColor:'rgb(0,0,0)', BarColor:"rgb(207,207,207)", BarAreaColor:"rgba(232,232,232,0.65)", BarWidth:10, BarPadding:15, //上下留白 MinCenterWidth:15 } }, this.FrameButtomToolbar= { BGColor:"rgb(235,235,235)", BorderColor:"rgb(204,204,204)", Button: { Font:{ Family:"微软雅黑", Size:12*GetDevicePixelRatio() }, TitleColor: { Selected:"rgb(255,255,255)", Default:"rgb(125,125,125)", MoveOn:"rgb(234,85,4)" }, BGColor: { Selected:"rgb(234,85,4)", Default:"rgb(235,235,235)", MoveOn:"rgb(242,242,242)" }, BorderColor:"rgb(204,204,204)", Mergin: { Left:5*GetDevicePixelRatio(), Right:5*GetDevicePixelRatio(), Top:4*GetDevicePixelRatio(), Bottom:2*GetDevicePixelRatio() }, SVG:{ Family:"iconfont", Size:12*GetDevicePixelRatio(), MerginLeft:4*GetDevicePixelRatio() } } } //自定义风格 this.SetStyle=function(style) { var T_SetButtonStyle=function(item, dest) { if (!item) return; if (item.Color) dest.Color=item.Color; if (item.MoveOnColor) dest.MoveOnColor=item.MoveOnColor; if (item.SelectedColor) dest.SelectedColor=item.SelectedColor; if (item.Family) dest.Family=item.Family; if (item.Text) dest.Text=item.Text; if (IFrameSplitOperator.IsNumber(item.Size)) dest.Size=item.Size; if (IFrameSplitOperator.IsNumber(item.MerginLeft)) dest.MerginLeft=item.MerginLeft; } if (style.TooltipBGColor) this.TooltipBGColor = style.TooltipBGColor; if (style.TooltipAlpha) this.TooltipAlpha = style.TooltipAlpha; if (style.SelectRectBGColor) this.SelectRectBGColor = style.SelectRectBGColor; if (style.UpBarColor) this.UpBarColor = style.UpBarColor; if (style.DownBarColor) this.DownBarColor = style.DownBarColor; if (style.UnchagneBarColor) this.UnchagneBarColor = style.UnchagneBarColor; if (style.EmptyBarBGColor) this.EmptyBarBGColor=style.EmptyBarBGColor; if (style.HighLowBarColor) this.HighLowBarColor=style.HighLowBarColor; if (style.HighLowText) { var dest=this.HighLowText; var item=style.HighLowText; if (item.FontName) dest.FontName=item.FontName; if (item.Color) dest.Color=item.Color; if (item.MaxText) dest.MaxText=item.MaxText; if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) dest.MaxSize=item.MaxSize; if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) dest.MinSize=item.MinSize; } if (style.SplashScreen) { var item=style.SplashScreen; if (item.BGColor) this.SplashScreen.BGColor=item.BGColor; if (item.Title) this.SplashScreen.Title=item.Title; if (item.TextColor) this.SplashScreen.TextColor=item.TextColor; if (item.Font) this.SplashScreen.Font=item.Font; } if (style.HLCArea) { var item=style.HLCArea; if (item.HighLineColor) this.HLCArea.HighLineColor=item.HighLineColor; if (item.LowLineColor) this.HLCArea.LowLineColor=item.LowLineColor; if (item.CloseLineColor) this.HLCArea.CloseLineColor=item.CloseLineColor; if (item.UpAreaColor) this.HLCArea.UpAreaColor=item.UpAreaColor; if (item.DownAreaColor) this.HLCArea.DownAreaColor=item.DownAreaColor; if (IFrameSplitOperator.IsNumber(item.LineWidth)) this.HLCArea.LineWidth=item.LineWidth; } if (style.Minute) { if (style.Minute.VolBarColor) this.Minute.VolBarColor = style.Minute.VolBarColor; if (style.Minute.VolTitleColor) this.Minute.VolTitleColor = style.Minute.VolTitleColor; if (style.Minute.PriceColor) this.Minute.PriceColor = style.Minute.PriceColor; if (IFrameSplitOperator.IsNumber(style.Minute.PriceLineWidth)) this.Minute.PriceLineWidth=style.Minute.PriceLineWidth; if (style.Minute.AvPriceColor) this.Minute.AvPriceColor = style.Minute.AvPriceColor; if (style.Minute.AreaPriceColor) this.Minute.AreaPriceColor = style.Minute.AreaPriceColor; if (style.Minute.PositionColor) this.Minute.PositionColor = style.Minute.PositionColor; if (style.Minute.FrameSplitTextColor) this.Minute.FrameSplitTextColor = style.Minute.FrameSplitTextColor; if (style.Minute.Before) { var item=style.Minute.Before; if (item.BGColor) this.Minute.Before.BGColor=item.BGColor; if (item.LineColor) this.Minute.Before.LineColor=item.LineColor; if (item.VolColor) this.Minute.Before.VolColor=item.VolColor; if (item.AvPriceColor) this.Minute.Before.AvPriceColor=item.AvPriceColor; if (item.CloseIcon) T_SetButtonStyle(item.CloseIcon, this.Minute.Before.CloseIcon); if (item.Point) { if (item.Point.Color) this.Minute.Before.Point.Color=item.Point.Color; if (item.Point.Radius) this.Minute.Before.Point.Radius=item.Point.Radius; } } if (style.Minute.After) { var item=style.Minute.After; if (item.BGColor) this.Minute.After.BGColor=item.BGColor; if (item.LineColor) this.Minute.After.LineColor=item.LineColor; if (item.VolColor) this.Minute.After.VolColor=item.VolColor; if (item.AvPriceColor) this.Minute.After.AvPriceColor=item.AvPriceColor; if (item.Point) { if (item.Point.Color) this.Minute.After.Point.Color=item.Point.Color; if (item.Point.Radius) this.Minute.After.Point.Radius=item.Point.Radius; } } if (style.Minute.NightDay) { var item=style.Minute.NightDay; if (item.NightBGColor) this.Minute.NightDay.NightBGColor=item.NightBGColor; if (item.Font) this.Minute.NightDay.Font=item.Font; if (item.Day) { var subItem=item.Day; if (subItem.Color) this.Minute.NightDay.Day.Color=subItem.Color; if (subItem.BGColor) this.Minute.NightDay.Day.BGColor=subItem.BGColor; if (subItem.BorderColor) this.Minute.NightDay.Day.BorderColor=subItem.BorderColor; CopyMarginConfig(this.Minute.NightDay.Day.Margin,subItem.Margin); } if (item.Night) { var subItem=item.Night; if (subItem.Color) this.Minute.NightDay.Night.Color=subItem.Color; if (subItem.BGColor) this.Minute.NightDay.Night.BGColor=subItem.BGColor; if (subItem.BorderColor) this.Minute.NightDay.Night.BorderColor=subItem.BorderColor; CopyMarginConfig(this.Minute.NightDay.Night.Margin,subItem.Margin); } } } if (style.PopMinuteChart) { var item=style.PopMinuteChart; if (item.BGColor) this.PopMinuteChart.BGColor=item.BGColor; if (item.BorderColor) this.PopMinuteChart.BorderColor=item.BorderColor; } if (style.DefaultTextColor) this.DefaultTextColor = style.DefaultTextColor; if (style.DefaultTextFont) this.DefaultTextFont = style.DefaultTextFont; if (style.TitleFont) this.TitleFont = style.TitleFont; if (style.IndexTitleBGColor) this.IndexTitleBGColor=style.IndexTitleBGColor; if (style.IndexTitleBorderColor) this.IndexTitleBorderColor=style.IndexTitleBorderColor; if (style.IndexTitleBorderMoveOnColor) this.IndexTitleBorderMoveOnColor=style.IndexTitleBorderMoveOnColor; if (IFrameSplitOperator.IsNumber(style.IndexTitleBorderStyle)) this.IndexTitleBorderStyle=style.IndexTitleBorderStyle; if (style.IndexTitleColor) this.IndexTitleColor=style.IndexTitleColor; if (style.IndexTitleSelectedColor) this.IndexTitleSelectedColor=style.IndexTitleSelectedColor; if (style.OverlayIndexTitleBGColor) this.OverlayIndexTitleBGColor=style.OverlayIndexTitleBGColor; if (style.UpTextColor) this.UpTextColor = style.UpTextColor; if (style.DownTextColor) this.DownTextColor = style.DownTextColor; if (style.UnchagneTextColor) this.UnchagneTextColor = style.UnchagneTextColor; if (style.CloseLineColor) this.CloseLineColor = style.CloseLineColor; if (style.CloseLineAreaColor) this.CloseLineAreaColor = style.CloseLineAreaColor; if (style.CloseLineWidth) this.CloseLineWidth=style.CloseLineWidth; if (style.FrameBorderPen) this.FrameBorderPen = style.FrameBorderPen; if (style.MultiDayBorderPen) this.MultiDayBorderPen = style.MultiDayBorderPen; if (style.FrameSplitPen) this.FrameSplitPen = style.FrameSplitPen; if (style.FrameDotSplitPen) this.FrameDotSplitPen = style.FrameDotSplitPen; if (style.FrameSplitTextColor) this.FrameSplitTextColor = style.FrameSplitTextColor; if (style.FrameSplitTextFont) this.FrameSplitTextFont = style.FrameSplitTextFont; if (style.FrameTitleBGColor) this.FrameTitleBGColor = style.FrameTitleBGColor; if (style.SelFrameBorderColor) this.SelFrameBorderColor=style.SelFrameBorderColor; if (IFrameSplitOperator.IsNumber(style.IndexTitleMerginLeft)) this.IndexTitleMerginLeft = style.IndexTitleMerginLeft; if (style.IndexTitle) { var item=style.IndexTitle; if (item.UpDownArrow) { var subItem=item.UpDownArrow; if (subItem.UpColor) this.IndexTitle.UpDownArrow.UpColor = subItem.UpColor; if (subItem.DownColor) this.IndexTitle.UpDownArrow.DownColor = subItem.DownColor; if (subItem.UnchangeColor) this.IndexTitle.UpDownArrow.UnchangeColor = subItem.UnchangeColor; } if (IFrameSplitOperator.IsNumber(item.ArrowType)) this.IndexTitle.ArrowType=item.ArrowType; if (IFrameSplitOperator.IsBool(item.EnableIndexArrow)) this.IndexTitle.EnableIndexArrow=item.EnableIndexArrow; if (item.NameArrow) { var subItem=item.NameArrow; if (subItem.Color) this.IndexTitle.NameArrow.Color = subItem.Color; if (subItem.Symbol) this.IndexTitle.NameArrow.Symbol = subItem.Symbol; if (IFrameSplitOperator.IsNumber(subItem.Space)) this.IndexTitle.NameArrow.Space = subItem.Space; } } if (style.Frame) { if (style.Frame.XBottomOffset) this.Frame.XBottomOffset=style.Frame.XBottomOffset; if (style.Frame.YTopOffset) this.Frame.YTopOffset=style.Frame.YTopOffset; if (style.Frame.PercentageText) { var item=style.Frame.PercentageText; if (item.PriceColor) this.Frame.PercentageText.PriceColor=item.PriceColor; if (item.PercentageColor) this.Frame.PercentageText.PercentageColor=item.PercentageColor; if (item.SplitColor) this.Frame.PercentageText.SplitColor=item.SplitColor; if (item.Font) this.Frame.PercentageText.Font=item.Font; } } if (IFrameSplitOperator.IsNumber(style.ToolbarButtonStyle)) this.ToolbarButtonStyle=style.ToolbarButtonStyle; if (IFrameSplitOperator.IsBool(style.IsDOMFrameTitle)) this.IsDOMFrameTitle=style.IsDOMFrameTitle; if (style.FrameLatestPrice) { var item=style.FrameLatestPrice; if (style.FrameLatestPrice.TextColor) this.FrameLatestPrice.TextColor = style.FrameLatestPrice.TextColor; if (style.FrameLatestPrice.UpBarColor) this.FrameLatestPrice.UpBarColor = style.FrameLatestPrice.UpBarColor; if (style.FrameLatestPrice.DownBarColor) this.FrameLatestPrice.DownBarColor = style.FrameLatestPrice.DownBarColor; if (style.FrameLatestPrice.UnchagneBarColor) this.FrameLatestPrice.UnchagneBarColor = style.FrameLatestPrice.UnchagneBarColor; if (style.FrameLatestPrice.BGAlpha) this.FrameLatestPrice.BGAlpha = style.FrameLatestPrice.BGAlpha; if (style.FrameLatestPrice.OverlayTextColor) this.FrameLatestPrice.OverlayTextColor = style.FrameLatestPrice.OverlayTextColor; if (item.EmptyBGColor) this.FrameLatestPrice.EmptyBGColor = item.EmptyBGColor; } if (style.OverlayFrame) { var item=style.OverlayFrame; if (style.OverlayFrame.BolderPen) this.OverlayFrame.BolderPen = style.OverlayFrame.BolderPen; if (style.OverlayFrame.TitleColor) this.OverlayFrame.TitleColor = style.OverlayFrame.TitleColor; if (style.OverlayFrame.TitleFont) this.OverlayFrame.TitleFont = style.OverlayFrame.TitleFont; } if (style.CorssCursorBGColor) this.CorssCursorBGColor = style.CorssCursorBGColor; if (style.CorssCursorTextColor) this.CorssCursorTextColor = style.CorssCursorTextColor; if (style.CorssCursorTextFont) this.CorssCursorTextFont = style.CorssCursorTextFont; if (style.CorssCursorVPenColor) this.CorssCursorVPenColor = style.CorssCursorVPenColor; if (style.CorssCursorHPenColor) this.CorssCursorHPenColor = style.CorssCursorHPenColor; if (style.CorssCursorBorderColor) this.CorssCursorBorderColor=style.CorssCursorBorderColor; if (style.CorssCursorXRangeBGColor) this.CorssCursorXRangeBGColor=style.CorssCursorXRangeBGColor; if (style.CorssCursor && style.CorssCursor.RightButton) { var item=style.CorssCursor.RightButton; if (item.BGColor) this.CorssCursor.RightButton.BGColor=item.BGColor; if (item.PenColor) this.CorssCursor.RightButton.PenColor=item.PenColor; if (item.Icon) this.CorssCursor.RightButton.Icon=item.Icon; } if (style.KLine) this.KLine = style.KLine; if (style.VirtualKLine) { var item=style.VirtualKLine; if (item.Color) this.VirtualKLine.Color=item.Color; if (item.LineDash) this.VirtualKLine.LineDash=item.LineDash; } if (style.PriceGapStyple) { var item=style.PriceGapStyple; if (item.Line && item.Line.Color) this.PriceGapStyple.Line.Color=item.Line.Color; if (item.Text) { if (item.Text.Color) this.PriceGapStyple.Text.Color=item.Text.Color; if (item.Text.Font) this.PriceGapStyple.Text.Font=item.Text.Font; } } if (style.Index) { if (style.Index.LineColor) this.Index.LineColor = style.Index.LineColor; if (style.Index.NotSupport) this.Index.NotSupport = style.Index.NotSupport; } if (style.ColorArray) this.ColorArray = style.ColorArray; if (style.DrawPicture) { var item=style.DrawPicture; if (item.LineColor) this.DrawPicture.LineColor = item.LineColor; if (item.PointColor) this.DrawPicture.PointColor = item.PointColor; if (item.XYCoordinate) this.DrawPicture.XYCoordinate=item.XYCoordinate; if (IFrameSplitOperator.IsNumber(item.PointType)) this.DrawPicture.PointType=item.PointType; if (IFrameSplitOperator.IsBool(item.IsShowPoint)) this.DrawPicture.IsShowPoint=item.IsShowPoint; } if (style.TooltipPaint) { if (style.TooltipPaint.BGColor) this.TooltipPaint.BGColor=style.TooltipPaint.BGColor; if (style.TooltipPaint.BorderColor) this.TooltipPaint.BorderColor=style.TooltipPaint.BorderColor; if (style.TooltipPaint.TitleColor) this.TooltipPaint.TitleColor=style.TooltipPaint.TitleColor; if (style.TooltipPaint.TitleFont) this.TooltipPaint.TitleFont=style.TooltipPaint.TitleFont; if (style.TooltipPaint.DateTimeColor) this.TooltipPaint.DateTimeColor=style.TooltipPaint.DateTimeColor; if (style.TooltipPaint.VolColor) this.TooltipPaint.VolColor=style.TooltipPaint.VolColor; if (style.TooltipPaint.AmountColor) this.TooltipPaint.AmountColor=style.TooltipPaint.AmountColor; } if (style.PCTooltipPaint) { var item=style.PCTooltipPaint; if (item.BGColor) this.PCTooltipPaint.BGColor=item.BGColor; if (item.BorderColor) this.PCTooltipPaint.BorderColor=item.BorderColor; if (item.TitleColor) this.PCTooltipPaint.TitleColor=item.TitleColor; if (item.TitleFont) this.PCTooltipPaint.TitleFont=item.TitleFont; if (item.DateTimeColor) this.PCTooltipPaint.DateTimeColor=item.DateTimeColor; if (item.VolColor) this.PCTooltipPaint.VolColor=item.VolColor; if (item.AmountColor) this.PCTooltipPaint.AmountColor=item.AmountColor; if (item.PositionColor) this.PCTooltipPaint.PositionColor=item.PositionColor; } if (style.DialogTooltip) { var item=style.DialogTooltip; if (item.BGColor) this.DialogTooltip.BGColor=item.BGColor; if (item.BorderColor) this.DialogTooltip.BorderColor=item.BorderColor; if (item.TitleColor) this.DialogTooltip.TitleColor=item.TitleColor; if (item.TitleBGColor) this.DialogTooltip.TitleBGColor=item.TitleBGColor; if (item.DateTimeColor) this.DialogTooltip.DateTimeColor=item.DateTimeColor; if (item.VolColor) this.DialogTooltip.VolColor=item.VolColor; if (item.AmountColor) this.DialogTooltip.AmountColor=item.AmountColor; if (item.TurnoverRateColor) this.DialogTooltip.TurnoverRateColor=item.TurnoverRateColor; if (item.PositionColor) this.DialogTooltip.PositionColor=item.PositionColor; if (item.TextColor) this.DialogTooltip.TextColor=item.TextColor; if (item.ValueColor) this.DialogTooltip.ValueColor=item.ValueColor; } if (style.FloatTooltip) { var item=style.FloatTooltip; if (item.BGColor) this.FloatTooltip.BGColor=item.BGColor; if (item.BorderColor) this.FloatTooltip.BorderColor=item.BorderColor; if (item.DateTimeColor) this.FloatTooltip.DateTimeColor=item.DateTimeColor; if (item.VolColor) this.FloatTooltip.VolColor=item.VolColor; if (item.AmountColor) this.FloatTooltip.AmountColor=item.AmountColor; if (item.TurnoverRateColor) this.FloatTooltip.TurnoverRateColor=item.TurnoverRateColor; if (item.PositionColor) this.FloatTooltip.PositionColor=item.PositionColor; if (item.TextColor) this.FloatTooltip.TextColor=item.TextColor; if (item.ValueColor) this.FloatTooltip.ValueColor=item.ValueColor; } if (style.DialogSelectRect) { var item=style.DialogSelectRect; if (item.BGColor) this.DialogSelectRect.BGColor=item.BGColor; if (item.BorderColor) this.DialogSelectRect.BorderColor=item.BorderColor; if (item.TitleColor) this.DialogSelectRect.TitleColor=item.TitleColor; if (item.TextColor) this.DialogSelectRect.TextColor=item.TextColor; if (item.ValueColor) this.DialogSelectRect.ValueColor=item.ValueColor; if (item.VolColor) this.DialogSelectRect.VolColor=item.VolColor; if (item.AmountColor) this.DialogSelectRect.AmountColor=item.AmountColor; if (item.TurnoverRateColor) this.DialogSelectRect.TurnoverRateColor=item.TurnoverRateColor; if (item.PositionColor) this.DialogSelectRect.PositionColor=item.PositionColor; } if (style.DialogPopKeyboard) { var item=style.DialogPopKeyboard; if (item.BGColor) this.DialogPopKeyboard.BGColor=item.BGColor; if (item.BorderColor) this.DialogPopKeyboard.BorderColor=item.BorderColor; if (item.TitleColor) this.DialogPopKeyboard.TitleColor=item.TitleColor; if (item.TitleBGColor) this.DialogTooltip.TitleBGColor=item.TitleBGColor; if (item.Input) { var subItem=item.Input; if (subItem.BGColor) this.DialogPopKeyboard.Input.BGColor=subItem.BGColor; if (subItem.TextColor) this.DialogPopKeyboard.Input.TextColor=subItem.TextColor; } } if (style.DialogSearchIndex) { var item=style.DialogSearchIndex; if (item.BGColor) this.DialogSearchIndex.BGColor=item.BGColor; if (item.BorderColor) this.DialogSearchIndex.BorderColor=item.BorderColor; if (item.TitleColor) this.DialogSearchIndex.TitleColor=item.TitleColor; if (item.TitleBGColor) this.DialogSearchIndex.TitleBGColor=item.TitleBGColor; if (item.IndexNameColor) this.DialogSearchIndex.IndexNameColor=item.IndexNameColor; if (item.GroupNameColor) this.DialogSearchIndex.GroupNameColor=item.GroupNameColor; if (item.InputTextColor) this.DialogSearchIndex.InputTextColor=item.InputTextColor; } if (style.MinuteInfo) { var item=style.MinuteInfo; if (style.MinuteInfo.TextColor) this.MinuteInfo.TextColor=style.MinuteInfo.TextColor; if (style.MinuteInfo.Font) this.MinuteInfo.Font=style.MinuteInfo.Font; if (style.MinuteInfo.PointColor) this.MinuteInfo.PointColor=style.MinuteInfo.PointColor; if (style.MinuteInfo.LineColor) this.MinuteInfo.LineColor=style.MinuteInfo.LineColor; if (style.MinuteInfo.TextBGColor) this.MinuteInfo.TextBGColor=style.MinuteInfo.TextBGColor; if (IFrameSplitOperator.IsNumber(item.PointRadius)) this.MinuteInfo.PointRadius=item.PointRadius; } if (style.Title) { if (style.Title.TradeIndexColor) this.Title.TradeIndexColor=style.Title.TradeIndexColor; if (style.Title.ColorIndexColor) this.Title.ColorIndexColor=style.Title.ColorIndexColor; if (style.Title.VolColor) this.Title.VolColor=style.Title.VolColor; if (style.Title.AmountColor) this.Title.AmountColor=style.Title.AmountColor; if (style.Title.DateTimeColor) this.Title.DateTimeColor=style.Title.DateTimeColor; if (style.Title.NameColor) this.Title.NameColor=style.Title.NameColor; if (style.Title.SettingColor) this.Title.SettingColor=style.Title.SettingColor; if (style.Title.TurnoverRateColor) this.Title.TurnoverRateColor=style.Title.TurnoverRateColor; if (style.Title.PositionColor) this.Title.PositionColor=style.Title.PositionColor; } if (style.DRAWICON) { if (style.DRAWICON.Icon) { var item=style.DRAWICON.Icon; if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) this.DRAWICON.Icon.MaxSize=item.MaxSize; if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) this.DRAWICON.Icon.MinSize=item.MinSize; if (item.Zoom) this.DRAWICON.Icon.Zoom=item.Zoom; if (IFrameSplitOperator.IsNumber(item.YOffset)) this.DRAWICON.Icon.YOffset=item.YOffset; } if (style.DRAWICON.Text) { var item=style.DRAWICON.Text; if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) this.DRAWICON.Text.MaxSize=item.MaxSize; if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) this.DRAWICON.Text.MinSize=item.MinSize; if (item.Zoom) this.DRAWICON.Text.Zoom=item.Zoom; if (item.FontName) this.DRAWICON.Text.FontName=item.FontName; if (IFrameSplitOperator.IsNumber(item.YOffset)) this.DRAWICON.Text.YOffset=item.YOffset; } } if (style.DRAWTEXT) { var item=style.DRAWTEXT; if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) this.DRAWICON.MaxSize=item.MaxSize; if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) this.DRAWICON.MinSize=item.MinSize; if (item.Zoom) this.DRAWTEXT.Zoom=item.Zoom; if (item.FontName) this.DRAWTEXT.FontName=item.FontName; if (IFrameSplitOperator.IsNumber(item.YOffset)) this.DRAWTEXT.YOffset=item.YOffset; } if (style.DRAWTEXT_FIX) { var item=style.DRAWTEXT_FIX; if (item.Font) this.DRAWTEXT_FIX.Font=item.Font; } if (style.DRAWNUMBER_FIX) { var item=style.DRAWNUMBER_FIX; if (item.Font) this.DRAWNUMBER_FIX.Font=item.Font; } if (style.DRAWNUMBER) { var item=style.DRAWNUMBER; if (IFrameSplitOperator.IsPlusNumber(item.MaxSize)) this.DRAWNUMBER.MaxSize=item.MaxSize; if (IFrameSplitOperator.IsPlusNumber(item.MinSize)) this.DRAWNUMBER.MinSize=item.MinSize; if (item.Zoom) this.DRAWNUMBER.Zoom=item.Zoom; if (item.FontName) this.DRAWNUMBER.FontName=item.FontName; if (IFrameSplitOperator.IsNumber(item.YOffset)) this.DRAWNUMBER.YOffset=item.YOffset; } if (style.DRAWABOVE) { var item=style.DRAWABOVE; if (IFrameSplitOperator.IsNumber(item.YOffset)) this.DRAWABOVE.YOffset=item.YOffset; } if (style.DOTLINE) this.DOTLINE=style.DOTLINE; if (style.DRAWSL) this.DOTLINE=style.DRAWSL; if (style.DragSubFrameBorder) this.DragSubFrameBorder=style.DragSubFrameBorder; if (style.DepthMapPaint) { var item=style.DepthMapPaint; if (item.LineColor) this.DepthMapPaint.LineColor=item.LineColor; if (item.AreaColor) this.DepthMapPaint.AreaColor=item.AreaColor; if (item.TextColor) this.DepthMapPaint.TextColor=item.TextColor; if (item.TextBGColor) this.DepthMapPaint.TextBGColor=item.TextBGColor; } if (style.KLineYAxisBGPaint) { var item=style.KLineYAxisBGPaint; if (item.Font) this.KLineYAxisBGPaint.Font=item.Font; if (item.LineColor) this.KLineYAxisBGPaint.LineColor=item.LineColor; if (item.DiffValutTextColor) this.KLineYAxisBGPaint.DiffValutTextColor=item.DiffValutTextColor; if (item.DiffValueBGColor) this.KLineYAxisBGPaint.DiffValueBGColor=item.DiffValueBGColor; } if (style.StockChip) { var item=style.StockChip; if (item.InfoColor) this.StockChip.InfoColor=item.InfoColor; if (item.DayInfoColor) this.StockChip.DayInfoColor=item.DayInfoColor; if (item.DefaultButton) T_SetButtonStyle(item.DefaultButton, this.StockChip.DefaultButton); if (item.LongButton) T_SetButtonStyle(item.LongButton, this.StockChip.LongButton); if (item.RecentButton) T_SetButtonStyle(item.RecentButton, this.StockChip.RecentButton); } if (style.DepthChart) { var item=style.DepthChart; if (item.BidColor) { if (item.BidColor.Line) this.DepthChart.BidColor.Line=item.BidColor.Line; if (item.BidColor.Area) this.DepthChart.BidColor.Area=item.BidColor.Area; } if (item.AskColor) { if (item.AskColor.Line) this.DepthChart.AskColor.Line=item.AskColor.Line; if (item.AskColor.Area) this.DepthChart.AskColor.Area=item.AskColor.Area; } if (item.LineWidth) this.DepthChart.LineWidth=item.LineWidth; } if (style.DepthCorss) { var item=style.DepthCorss; if (item.BidColor) { if (item.BidColor.Line) this.DepthCorss.BidColor.Line=item.BidColor.Line; } if (item.AskColor) { if (item.AskColor.Line) this.DepthCorss.AskColor.Line=item.AskColor.Line; } if (item.LineWidth) this.DepthCorss.LineWidth=item.LineWidth; if (item.LineDash) this.DepthCorss.LineDash=item.LineDash; if (item.Tooltip) { var tooltip=item.Tooltip; if (tooltip.BGColor) this.DepthCorss.Tooltip.BGColor=tooltip.BGColor; if (tooltip.TextColor) this.DepthCorss.Tooltip.TextColor=tooltip.TextColor; if (tooltip.Font) this.DepthCorss.Tooltip.Font=tooltip.Font; if (tooltip.LineHeight) this.DepthCorss.Tooltip.LineHeight=tooltip.LineHeight; var border=tooltip.Border; if (IFrameSplitOperator.IsNumber(border.Top)) this.DepthCorss.Tooltip.Border.Top=border.Top; if (IFrameSplitOperator.IsNumber(border.Bottom)) this.DepthCorss.Tooltip.Border.Bottom=border.Bottom; if (IFrameSplitOperator.IsNumber(border.Left)) this.DepthCorss.Tooltip.Border.Left=border.Left; if (IFrameSplitOperator.IsNumber(border.Right)) this.DepthCorss.Tooltip.Border.Right=border.Right; if (IFrameSplitOperator.IsNumber(border.ItemSpace)) this.DepthCorss.Tooltip.Border.ItemSpace=border.ItemSpace; } } if (style.CIRCLEDOT) { var item=style.CIRCLEDOT; if (IFrameSplitOperator.IsNumber(item.Radius)) this.CIRCLEDOT.Radius=item.Radius; } if (style.POINTDOT) { var item=style.POINTDOT; if (IFrameSplitOperator.IsNumber(item.Radius)) this.POINTDOT.Radius=item.Radius; } if (style.RectSelect) { var item=style.RectSelect; if (item.LineColor) this.RectSelect.LineColor=item.LineColor; if (item.LineWidth>0) this.RectSelect.LineWidth=item.LineWidth; if (item.LineDotted) this.RectSelect.LineDotted=item.LineDotted; if (item.AreaColor) this.RectSelect.AreaColor=item.AreaColor; if (item.SubAreaColor) this.RectSelect.SubAreaColor=item.SubAreaColor; if (item.RangeTextColor) this.RectSelect.RangeTextColor=item.RangeTextColor; if (item.RangeTextFont) this.RectSelect.RangeTextFont=item.RangeTextFont; if (item.RangeTextBGColor) this.RectSelect.RangeTextBGColor=item.RangeTextBGColor; if (item.RangeTextSubColor) this.RectSelect.RangeTextSubColor=item.RangeTextSubColor; if (item.RangeTextSubFont) this.RectSelect.RangeTextSubFont=item.RangeTextSubFont; if (item.RangeTextSubBGColor) this.RectSelect.RangeTextSubBGColor=item.RangeTextSubBGColor; if (item.Mark) { var subItem=item.Mark; if (subItem.Family) this.RectSelect.Mark.Family=subItem.Family; if (subItem.Text) this.RectSelect.Mark.Text=subItem.Text; if (subItem.Color) this.RectSelect.Mark.Color=subItem.Color; if (IFrameSplitOperator.IsNumber(subItem.Size)) this.RectSelect.Mark.Size=subItem.Size; if (subItem.Position) { if (subItem.Position.Top) this.RectSelect.Mark.Position.Top=subItem.Position.Top; if (IFrameSplitOperator.IsNumber(subItem.Position.Index)) this.RectSelect.Mark.Position.Index=subItem.Position.Index; } } } if (style.RectDrag) { var item=style.RectDrag; var dest=this.RectDrag; if (item.LineColor) dest.LineColor=item.LineColor; if (IFrameSplitOperator.IsPlusNumber(item.LineWidth)) dest.LineWidth=item.LineWidth; if (item.BGColor) dest.BGColor=item.BGColor; } if (style.OrderFlow) { item=style.OrderFlow; if (item.UpColor) this.OrderFlow.UpColor=item.UpColor; if (item.DownColor) this.OrderFlow.DownColor=item.DownColor; if (item.UnchagneColor) this.OrderFlow.UnchagneColor=item.UnchagneColor; if (item.Text) this.OrderFlow.Text=item.Text; if (item.Line) this.OrderFlow.Line=item.Line; } if (style.OrderFlow_Style2) { item=style.OrderFlow_Style2; if (item.UpColor) this.OrderFlow_Style2.UpColor=item.UpColor; if (item.DownColor) this.OrderFlow_Style2.DownColor=item.DownColor; if (item.UnchagneColor) this.OrderFlow_Style2.UnchagneColor=item.UnchagneColor; if (IFrameSplitOperator.IsNumber(item.BarWidth)) this.OrderFlow_Style2.BarWidth=item.BarWidth; } if (style.ChartOX) { var item=style.ChartOX; if (item.Family) this.ChartOX.Family=item.Family; if (item.Up) this.ChartOX.Up=item.Up; if (item.Down) this.ChartOX.Down=item.Down; if (item.SquareLineColor) this.ChartOX.SquareLineColor=item.SquareLineColor; } if (style.DealList) { var item=style.DealList; if (item.BorderColor) this.DealList.BorderColor=item.BorderColor; if (item.UpTextColor) this.DealList.UpTextColor=item.UpTextColor; if (item.DownTextColor) this.DealList.DownTextColor=item.DownTextColor; if (item.UnchagneTextColor) this.DealList.UnchagneTextColor=item.UnchagneTextColor; if (item.CloseLineColor) this.DealList.CloseLineColor=item.CloseLineColor; if (item.Header) { var header=item.Header; if (header.Color) this.DealList.Header.Color=header.Color; if (header.Mergin) { var mergin=header.Mergin; if (IFrameSplitOperator.IsNumber(mergin.Left)) this.DealList.Header.Mergin.Left=mergin.Left; if (IFrameSplitOperator.IsNumber(mergin.Right)) this.DealList.Header.Mergin.Left=mergin.Right; if (IFrameSplitOperator.IsNumber(mergin.Top)) this.DealList.Header.Mergin.Top=mergin.Top; if (IFrameSplitOperator.IsNumber(mergin.Bottom)) this.DealList.Header.Mergin.Bottom=mergin.Bottom; } if (header.Font) { var font=header.Font; if (font.Name) this.DealList.Header.Font.Name=font.Name; if (IFrameSplitOperator.IsNumber(font.Size)) this.DealList.Header.Font.Size=font.Size; } } if (item.Row) { var row=item.Row; if (row.Mergin) { var mergin=row.Mergin; if (IFrameSplitOperator.IsNumber(mergin.Top)) this.DealList.Row.Mergin.Top=mergin.Top; if (IFrameSplitOperator.IsNumber(mergin.Bottom)) this.DealList.Row.Mergin.Bottom=mergin.Bottom; } if (row.Font) { var font=row.Font; if (font.Name) this.DealList.Row.Font.Name=font.Name; if (IFrameSplitOperator.IsNumber(font.Size)) this.DealList.Row.Font.Size=font.Size; } if (row.BarMergin) { var mergin=row.BarMergin; if (IFrameSplitOperator.IsNumber(mergin.Left)) this.DealList.Row.BarMergin.Left=mergin.Left; if (IFrameSplitOperator.IsNumber(mergin.Top)) this.DealList.Row.BarMergin.Top=mergin.Top; if (IFrameSplitOperator.IsNumber(mergin.Right)) this.DealList.Row.BarMergin.Right=mergin.Right; if (IFrameSplitOperator.IsNumber(mergin.Bottom)) this.DealList.Row.BarMergin.Bottom=mergin.Bottom; } } if (item.FieldColor) { var filed=item.FieldColor; if (filed.Vol) this.DealList.FieldColor.Vol=filed.Vol; if (filed.Time) this.DealList.FieldColor.Time=filed.Time; if (filed.Deal) this.DealList.FieldColor.Deal=filed.Deal; if (filed.Index) this.DealList.FieldColor.Index=filed.Index; if (filed.BarTitle) this.DealList.FieldColor.BarTitle=filed.BarTitle; if (filed.Text) this.DealList.FieldColor.Text=filed.Text; if (IFrameSplitOperator.IsNonEmptyArray(filed.Bar)) { for(var i=0;i= brickSize && Math.abs(movementFromOpen)>=brickSize) { var vol=0; if (movementFromClose>0 || movementFromOpen>0) { var yClose=this.LastData.Close; var open=Math.max(this.LastData.Close,this.LastData.Open); var close=open+brickSize; var high=close; var low=open; vol=kItem.Vol; } else { var yClose=this.LastData.Close; var open=Math.min(this.LastData.Close,this.LastData.Open); var close=open-brickSize; var high=open; var low=close; vol=kItem.Vol; } var item=new HistoryData(); item.Date=kItem.Date; item.Time=kItem.Time; item.YClose=yClose; item.Open=open; item.High=high; item.Low=low; item.Close=close; item.Vol=this.LastData.Vol+vol; bindData.Data.push(item); this.LastData.YClose=item.YClose; this.LastData.Open = item.Open; this.LastData.High = item.High; this.LastData.Low = item.Low; this.LastData.Close = item.Close; this.LastData.Date=item.Date; this.LastData.Time=item.Time; this.LastData.Vol=0; } else { this.LastData.Vol+=kItem.Vol; //量需要累加 ++i; } } return bindData; } this.RecvHistoryData=function(sourceData, option) //历史日线数据 { this.Symbol=option.Symbol; this.SourceData=sourceData; this.FloatPrecision=GetfloatPrecision(this.Symbol); if (this.BrickSizeType==1) this.CalculateATR(); return this.CalculateByClose(sourceData); } this.Clear=function() { this.SourceData=null; this.LastData=null; this.Symbol=null; } //获取配置信息 this.GetTitle=function() { if (this.BrickSizeType==1) { var text=`Renko [ATR(${this.ATR.Count}), ${this.ATR.BrickSize}]`; } else { var text=`Renko [Traditional, ${this.BrickSize}]`; } return text; } //通过ATR计算砖块大小 //真实范围 = MAX(最高价 (1) – 最低价 (1);最高价 (1) – 收盘价 (2);收盘价 (2) – 最低价 (1)) this.CalculateATR=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) return; var kData=this.SourceData.Data; var count=kData.length; var aryData=[]; for(var i=count-1, j=0; i>=0 && jkagiItem.Close) { kagiItem.Direction=1; kagiItem.Close=kItem.Close; kagiItem.EndItem=kItem; kagiItem.High=kItem.Close; break; } else if (kItem.Close=kagiItem.High) { kagiItem.Close=kItem.Close; kagiItem.High=kItem.Close; kagiItem.EndItem=kItem; changeItem=null; } else { if (!changeItem) { changeItem=HistoryData.Copy(kItem); changeItem.High=changeItem.Low=kItem.Close; } else { changeItem.Close=kItem.Close; if (changeItem.Low>kItem.Close) changeItem.Low=kItem.Close; } if (Math.abs(changeItem.Low-kagiItem.High)>brickSize) //达到变盘点 { bindData.Data.push(kagiItem); var newItem=HistoryData.Copy(kItem); newItem.High=kagiItem.High; newItem.Low=kItem.Close; newItem.Direction=2; //1 上 2=下 newItem.StartItem=kItem; kagiItem=newItem; changeItem=null; } } } else if (kagiItem.Direction==2) //下 { if (kItem.Close<=kagiItem.Low) { kagiItem.Close=kItem.Close; kagiItem.Low=kItem.Close; kagiItem.EndItem=kItem; } else { if (!changeItem) { changeItem=HistoryData.Copy(kItem); changeItem.High=changeItem.Low=kItem.Close; } else { changeItem.Close=kItem.Close; if (changeItem.HighbrickSize) //达到变盘点 { bindData.Data.push(kagiItem); var newItem=HistoryData.Copy(kItem); newItem.High=kItem.Close; newItem.Low=kagiItem.Low; newItem.Direction=1; //1 上 2=下 newItem.StartItem=kItem; kagiItem=newItem; changeItem=null; } } } } return bindData; } //获取配置信息 this.GetTitle=function() { if (this.BrickSizeType==1) { var text=`Kagi [ATR(${this.ATR.Count}), ${this.ATR.BrickSize}]`; } else { var text=`Kagi [Traditional]`; } return text; } } ////////////////////////////////////////////////////////////////// // HeikinAshi // function HeikinAshiCalculate() { this.SourceData; this.Symbol; this.FloatPrecision=2; //品种小数位数 this.ClassName="HeikinAshiCalculate"; this.Clear=function() { this.SourceData=null; this.LastData=null; this.Symbol=null; } this.RecvHistoryData=function(sourceData, option) //历史日线数据 { this.Symbol=option.Symbol; this.SourceData=sourceData; this.FloatPrecision=GetfloatPrecision(this.Symbol); return this.Calculate(sourceData); } this.GetTitle=function() { return "Heikin Ashi"; } this.Calculate=function(sourceData) { var bindData=new ChartData(); bindData.Data=[] bindData.Right=sourceData.Right; bindData.Period=sourceData.Period; bindData.DataType=sourceData.DataType; bindData.Symbol=sourceData.symbol; if (!IFrameSplitOperator.IsNonEmptyArray(sourceData.Data)) return bindData; var lastKItem=null; var yClose=null; for(var i=0;ikItem.Low) preItem.Low=kItem.Low; } preItem.Date=kItem.Date; preItem.Time=kItem.Time; preItem.Vol+=kItem.Vol; preItem.Amount+=kItem.Amount; } for(var i=index;ipreItem.High) //阳线 { var item=new HistoryData(); item.YClose=preItem.Low; if (preItem) item.Open=preItem.High; else item.Open=preItem.High; item.Close=kItem.Close; item.Low=Math.min(item.Open,item.Close); item.High=Math.max(item.Open,item.Close); item.Date=kItem.Date; item.Time=kItem.Time; item.Vol=kItem.Vol; item.Amount=kItem.Amount; item.Direction=1; //阳线 bindData.Data.push(item); //if (preItem && preItem.Direction==1) preItem.Close=preItem.High; //else if (preItem && preItem.Direction==2) preItem.Close=preItem.Low; preItem=item; } else if (kItem.ClosekItem.Low) preItem.Low=kItem.Low; } preItem.Vol+=kItem.Vol; preItem.Amount+=kItem.Amount; } } } return bindData; } } ///////////////////////////////////////////////////////////////////////////////////////////// // K线图 控件 // this.ChartPaint[0] K线画法 这个不要修改 // // function KLineChartContainer(uielement,OffscreenElement, cacheElement) { var _self =this; this.newMethod=JSChartContainer; //派生 this.newMethod(uielement,OffscreenElement,cacheElement); 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.IsApiPeriod=false; //使用API计算周期 this.Right=0; //复权 0 不复权 1 前复权 2 后复权 this.RightFormula=0 //复权公式 0=简单复权, 1=复权因子复权 this.SourceData; //原始的历史数据 this.MaxRequestDataCount=3000; //数据个数 this.MaxRequestMinuteDayCount=5; //分钟数据请求的天数 this.PageSize=200; //每页数据个数 this.KLineDrawType=0; this.ScriptErrorCallback; //脚本执行错误回调 this.FlowCapitalReady=false; //流通股本是否下载完成 this.EnableFlowCapital={}; //强制现在流通股 { BIT:数据货币true/false, } this.EnableZoomUpDown=null; //是否手势/键盘/鼠标允许缩放{ Touch:true/false, Mouse:true/false, Keyboard:true/false, Wheel:true/false } this.ChartDrawStorage=new ChartDrawStorage(); this.ChartDrawStorageCache=null; //首次需要创建的画图工具数据 this.RightSpaceCount=0; //右侧空白个数 this.SourceDataLimit=new Map(); //每个周期缓存数据最大个数 key=周期 value=最大个数 this.CtrlMoveStep=5; //Ctrl+(Left/Right) 移动数据个数 this.CustomShow=null; //首先显示的K线的起始日期 { Date:日期, Time:时间, PageSize:, Callback:} this.ZoomType=0; //缩放模式 0=最右边固定缩放, 1=十字光标两边缩放 this.IsZoomLockRight=false; this.KLineSize=null; //{ DataWidth:, } //this.EnableYDrag={ Left:false, Right:true }; this.Page= { Day:{ Enable:false, Index:0, Finish:false }, //日线 Minute:{ Enable:false, Index:0, Finish:false } //分钟 }; //分页下载 Enable:是否分页下载 Index:已下载到第几页 Finish:是否所有分页完成 this.DragDownload= { Day:{ Enable:false, IsEnd:false, Status:0 }, //日线数据拖拽下载 Status: 0空闲 1 下载中 Minute: { Enable:false, IsEnd:false, Status:0 }, //分钟/秒数据拖拽下载 Tick: { Enable:false, IsEnd:false, Status:0 } //分笔 }; this.ZoomDownload= { Day:{ Enable:false, IsEnd:false, Status:0 }, //日线数据缩放下载 Status: 0空闲 1 下载中 Minute: { Enable:false, IsEnd:false, Status:0 }, //分钟/秒数据缩放下载 Tick: { Enable:false, IsEnd:false, Status:0 } //分笔 } //自动更新设置 this.IsAutoUpdate=false; //是否自动更新行情数据 this.AutoUpdateFrequency=30000; //30秒更新一次数据 this.AutoUpdateTimer; //自动更新定时器 //this.KLineApiUrl="http://opensource.zealink.com/API/KLine2"; //历史K线api地址 this.KLineApiUrl=g_JSChartResource.Domain+"/API/KLine2"; //历史K线api地址 this.MinuteKLineApiUrl=g_JSChartResource.Domain+'/API/KLine3'; //历史分钟数据 this.DragMinuteKLineApiUrl=g_JSChartResource.Domain+'/API/KLine4'; //拖动1分钟K数据下载 this.DragKLineApiUrl=g_JSChartResource.Domain+'/API/KLine5'; //拖动日K数据下载 this.ZoomMinuteKLineApiUrl=g_JSChartResource.Domain+'/API/KLine4'; //拖动1分钟K数据下载 this.ZoomKLineApiUrl=g_JSChartResource.Domain+'/API/KLine5'; //拖动日K数据下载 this.RealtimeApiUrl=g_JSChartResource.Domain+"/API/Stock"; //实时行情api地址 this.KLineMatchUrl=g_JSChartResource.Domain+"/API/KLineMatch"; //形态匹配 this.StockHistoryDayApiUrl= g_JSChartResource.Domain+'/API/StockHistoryDay'; //股票历史数据 this.TickApiUrl=g_JSChartResource.Domain+'/API/StockDetail'; //当天分笔数据 this.PopMinuteChart=null; //双击历史K线 弹出分钟走势图 this.BeforeBindMainData=null; //function(funcName) 在BindMainData() 调用前回调用 this.AfterBindMainData=null; //function(funcName) 在BindMainData() 调用前后调用 this.KLineCalculate=null; //K线定制指标计算 this.KLineCalcOption=new Map(); //K线定制指标配置 this.ScrollBar=null; //横向滚动条 this.IsAutoSyncDataOffset=true; //增量更新时,是否移动当前屏数据 this.GetKLineCalulate=function() { var kLineDrawType=this.GetKLineDrawType(); var className; if (kLineDrawType==10) className="RenkoCalculate"; else if (kLineDrawType==11) className="HeikinAshiCalculate"; else if (kLineDrawType==12) className="LineBreakCalcuate"; else if (kLineDrawType==16) className="KagiCalculate"; else return null; if (!this.KLineCalculate || this.KLineCalculate.ClassName!=className) { this.KLineCalculate=g_KLineCustomCalulate.Create(className); if (this.KLineCalculate.SetOption && this.KLineCalcOption.has(className)) { var option=this.KLineCalcOption.get(className); this.KLineCalculate.SetOption(option); } } return this.KLineCalculate; } this.SetKLineCalcOption=function(className, option) { this.KLineCalcOption.set(className, option); if (this.KLineCalculate && this.KLineCalculate.ClassName==className && this.KLineCalculate.SetOption) { this.KLineCalculate.SetOption(option); } } this.ClearKLineCaluate=function() { if (!this.KLineCalculate) return; if (!this.KLineCalculate.Clear) return; this.KLineCalculate.Clear(); } this.ResetDragDownload=function() { this.DragDownload.Day.Status=0; this.DragDownload.Day.IsEnd=false; this.DragDownload.Minute.Status=0; this.DragDownload.Minute.IsEnd=false; this.DragDownload.Tick.Status=0; this.DragDownload.Tick.IsEnd=false; } this.ResetZoomDownload=function() { this.ZoomDownload.Day.Status=0; this.ZoomDownload.Day.IsEnd=false; this.ZoomDownload.Minute.Status=0; this.ZoomDownload.Minute.IsEnd=false; this.ZoomDownload.Tick.Status=0; this.ZoomDownload.Tick.IsEnd=false; } this.ResetPage=function() //重置分页下载 { this.Page.Day.Finish=false; this.Page.Day.Index=0; this.Page.Minute.Finish=false; this.Page.Minute.Index=0; } 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) { var data=null; if (this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; if (data) data.DataOffset=obj.DataOffset; } this.UpdataDataoffset(); //更新数据偏移 this.UpdatePointByCursorIndex(1); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); //刷新画图 this.SendManualKLineUpdateEvent(bindData); } //获取k线数据 this.GetKDataInfo=function() { if (!this.ChartPaint[0]) return null; var chartKLine=this.ChartPaint[0]; var obj={}; if (chartKLine.Data && chartKLine.Data.Data) obj.Data=chartKLine.Data.CloneData("HistoryData"); obj.ShowRange=chartKLine.ShowRange; obj.Period=this.Period; obj.RightSpaceCount=this.RightSpaceCount; return obj; } this.ChartOperator=function(obj) //图形控制函数 {ID:JSCHART_OPERATOR_ID, ...参数 } { var id=obj.ID; if (id===JSCHART_OPERATOR_ID.OP_SCROLL_LEFT || id===JSCHART_OPERATOR_ID.OP_SCROLL_RIGHT ) //左右移动 { Step:移动数据个数 } { var isLeft=(id===JSCHART_OPERATOR_ID.OP_SCROLL_LEFT ? true:false); var step=1; if (obj.Step>0) step=obj.Step; var oneStepWidth=this.GetMoveOneStepWidth(); if(this.DataMove(step*oneStepWidth,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.ResetFrameXSplit(); 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_LEFT_ZOOM_IN || id==JSCHART_OPERATOR_ID.OP_LEFT_ZOOM_OUT) //{ Step:增加/减少数量 } 左边增加/减少显示个数 { var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 var dataCount=hisData.Data.length; var showCount=this.Frame.SubFrame[0].Frame.XPointCount; //获取一屏显示的数据个数 var dataOffset=hisData.DataOffset; if (id==JSCHART_OPERATOR_ID.OP_LEFT_ZOOM_IN) //增加 { if (IFrameSplitOperator.IsNumber(obj.Step)) { if (showCount>=dataCount) return; var step=obj.Step; if (step>dataOffset) step=dataOffset; if (showCount+step>dataCount) step=dataCount-showCount; if (step<=0) return; showCount+=step; hisData.DataOffset-=step; } } else if (id==JSCHART_OPERATOR_ID.OP_LEFT_ZOOM_OUT) //减少 { var pageSize = this.GetMaxMinPageSize(); var minShowCount=pageSize.Min; if (IFrameSplitOperator.IsNumber(obj.Step)) { if (showCount=dataCount) return; var endPos=dataOffset+showCount; var rightCount=dataCount-endPos; if (rightCount<=0) return; var step=obj.Step; if (step>rightCount) step=rightCount; if (step<=0) return; showCount+=step; } } else if (id==JSCHART_OPERATOR_ID.OP_RIGHT_ZOOM_OUT) //减少 { var pageSize = this.GetMaxMinPageSize(); var minShowCount=pageSize.Min; if (IFrameSplitOperator.IsNumber(obj.Step)) { if (showCountshowCount) step=showCount; if (showCount-step=firstPoint.DataIndex && drawKRange.Start>=secondPoint.DataIndex) || (drawKRange.End<=firstPoint.DataIndex && drawKRange.End<=secondPoint.DataIndex) ) { var offset=firstPoint.DataIndex;; var dataCount=hisData.Data.length; var showCount=this.ChartPaint[0].ShowRange.ShowCount; //显示个数 if (offset+showCount>dataCount) offset=dataCount-showCount; if (offset<0) offset=0; hisData.DataOffset=offset; bMoveKLine=true; } } if (bMoveKLine) { this.ChartOperator_Temp_Update(); } else { this.Draw(); } return true; } else if (id==JSCHART_OPERATOR_ID.OP_SET_SUB_SELECTRECT) // {Start:{ Date:, Time:}, End:{ Date:, Time } { if (!this.ChartPaint[0]) return false; if (!this.ChartPaint[0].Data) return false; var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!IFrameSplitOperator.IsNonEmptyArray(hisData.Data)) return false; var paint=this.GetRectSelectPaint(); if (!paint) return false; if (!ChartData.IsDayPeriod(this.Period,true)) return false; //TODO:暂时只支持日线的 var firstPoint, secondPoint, subFirstPoint, subSecondPoint; for(var i=0;i0) //调整一屏显示的个数 { 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(); } else if (id==JSCHART_OPERATOR_ID.OP_GOTO_BY_DATAINDEX) //{PageSize:可选, DataIndex:起始位置数据索引} { if (!IFrameSplitOperator.IsNumber(obj.DataIndex)) return; var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 if (obj.DataIndex<0 || obj.DataIndex>=hisData.Data.length) { JSConsole.Chart.Log(`[KLineChartContainer::ChartOperator] OP_GOTO_BY_DATAINDEX obj.DataIndex=${obj.DataIndex} error.}`); return; } var oldXPointCount=this.Frame.SubFrame[0].Frame.XPointCount; var xPointCount=oldXPointCount; if (obj.PageSize>0) xPointCount=obj.PageSize; //调整一屏显示的个数 if (xPointCount!=oldXPointCount) this.Frame.SetXShowCount(xPointCount); //设置X轴显示数据个数 hisData.DataOffset=obj.DataIndex; this.CursorIndex=0; this.LastPoint.X=null; this.LastPoint.Y=null; this.ChartOperator_Temp_Update(); } else if (id==JSCHART_OPERATOR_ID.OP_CORSSCURSOR_GOTO) //移动十字光标{ Date:, Time } { if (!IFrameSplitOperator.IsNumber(obj.Date)) return; var bTime=IFrameSplitOperator.IsNumber(obj.Time); var pageInfo=this.GetChartStatus(); if (!pageInfo) return; var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 var start=hisData.DataOffset; var findIndex=-1, findItem=null, dataIndex=-1; for(var i=start, j=0; i=dateTime.Date) return i; } } return null; } if (ChartData.IsMinutePeriod(period,true) || ChartData.IsMilliSecondPeriod(period)) { var findTime=null; if (IFrameSplitOperator.IsNumber(dateTime.Time)) findTime=dateTime.Time; for(var i=0;i=dateTime.Date) return i; } else { if (item.Date>dateTime.Date || (item.Date==dateTime.Date && item.Time>=findTime)) return i; } } } return null; } return null; } this.OnWheel=function(e) { JSConsole.Chart.Log('[KLineChartContainer::OnWheel]',e); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); var wheelValue=e.wheelDelta; if (!IFrameSplitOperator.IsObjectExist(e.wheelDelta)) wheelValue=e.deltaY* -0.01; var enableZoomUpDown=true; //是否允许缩放 if (this.EnableZoomUpDown && this.EnableZoomUpDown.Wheel===false) enableZoomUpDown=false; if (this.SourceData && this.SourceData.Data) { if (isInClient && wheelValue<0 && enableZoomUpDown) //缩小 { var cursorIndex={ ZoomType:this.ZoomType, IsLockRight:this.IsZoomLockRight }; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (e.ctrlKey) cursorIndex.ZoomType=1; //ctrl+滚轴 十字中心缩放 if (this.Frame.ZoomDown(cursorIndex, { ZoomDownloadDataCallback:(requestData)=>{ this.ZoomDownloadData(requestData) } } )) { this.CursorIndex=cursorIndex.Index; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.ResetFrameXSplit(); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) { } else { this.Draw(); } this.OnKLinePageChange("wheel"); } } else if (isInClient && wheelValue>0 && enableZoomUpDown) //放大 { var cursorIndex={ ZoomType:this.ZoomType, IsLockRight:this.IsZoomLockRight }; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (e.ctrlKey) cursorIndex.ZoomType=1; //ctrl+滚轴 十字中心缩放 if (this.Frame.ZoomUp(cursorIndex)) { JSConsole.Chart.Log("[KLineChartContainer::OnWheel] cursorIndex ",cursorIndex) this.CursorIndex=cursorIndex.Index; this.UpdatePointByCursorIndex(); this.UpdataDataoffset(); this.UpdateFrameMaxMin(); this.ResetFrameXSplit(); this.Draw(); this.OnKLinePageChange("wheel"); } } } if (!isInClient) { if (!this.OnWheel_ZoomUpDownFrameY(e,x,y)) return; } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } //通过滚轴缩放Y轴 this.OnWheel_ZoomUpDownFrameY=function(e, x, y) { if (!this.EnableYDrag.Wheel) return false; var dragY=this.TryYDrag(x,y); if (!dragY) return false; if ((dragY.Left && !dragY.IsOverlay) || dragY.Right) { } else { return false; } var wheelValue=e.wheelDelta; if (!IFrameSplitOperator.IsObjectExist(e.wheelDelta)) wheelValue=e.deltaY* -0.01; var yMove=this.EnableYDrag.WheelYMove; if (wheelValue>0) yMove*=-1; dragY.Position=0; //只能两边缩放 if (!this.Frame.OnZoomUpDownFrameY(dragY, yMove)) return false; this.Frame.SetSizeChage(true); this.Draw(); return true; } //创建 //windowCount 窗口个数 this.Create=function(windowCount, option) { 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.StringFormatY.ExtendChartPaint=this.ExtendChartPaint; this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.OnChangeStatusCallback=(data, obj)=>{ this.OnChangeCorssCursorStatus(data,obj); } //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; 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.GetExtendChartRightWidth=()=> { return this.GetExtendChartRightWidth() } this.Frame.GetExtendChartByClassName=(name)=> { return this.GetExtendChartByClassName(name); } this.Frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartCorssCursor.Frame=this.Frame; //十字光标绑定框架 this.ChartSplashPaint.Frame = this.Frame; this.CreateChildWindow(windowCount); this.CreateMainKLine(); this.CreateExtendChart("RectSelectPaint", option? option.SelectRect:null); //区间统计 if (this.EnableIndexChartDrag) this.CreateExtendChart("DragMovePaint"); this.CreateDragSelectRect(option? option.DragSelectRect:null); //子窗口动态标题 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); } titlePaint.SelectedChart=this.SelectedChart; this.TitlePaint.push(titlePaint); } this.ChartCorssCursor.StringFormatX.Frame=this.Frame.SubFrame[0].Frame; this.ChartCorssCursor.StringFormatY.Frame=this.Frame; var bRegisterKeydown=true; var bRegisterWheel=true; if (option && option.Listener) { var item=option.Listener; if (item.KeyDown===false) { bRegisterKeydown=false; JSConsole.Chart.Log('[KLineChartContainer::Create] not register keydown event.'); } if (item.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[KLineChartContainer::Create] not register wheel event.'); } } if (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 this.InitalPopMinuteChart(option); } this.InitalPopMinuteChart=function(option) { if (!option || !option.KLine) return false; var item=option.KLine; if (item.KLineDoubleClick===true) { this.PopMinuteChart=new JSPopMinuteChart(); this.PopMinuteChart.Inital(this); return true; } return false; } this.DestroyPopMinuteChart=function() { if (!this.PopMinuteChart) return; this.PopMinuteChart.Destroy(); this.PopMinuteChart=null; } this.ShowMinuteChartDialog=function(data, x,y) { if (!this.PopMinuteChart) return; if (!data.Tooltip || !data.Chart) return; var pixelRatio=GetDevicePixelRatio(); var rtClient=this.UIElement.getBoundingClientRect(); var rtScroll=GetScrollPosition(); x+=(rtClient.left+rtScroll.Left); y+=(rtClient.top+rtScroll.Top); var date=data.Tooltip.Data.Date; var symbol=data.Chart.Symbol; this.PopMinuteChart.Show({ Date:date, Symbol:symbol, Data:data.Tooltip.Data }, x/pixelRatio,y/pixelRatio); } this.OnCustomKeyDown=function(keyID, e) //自定义键盘事件 { if (keyID==37 && e.ctrlKey) //Ctrl+Left { this.MoveCorssCursorLeft(this.CtrlMoveStep); return true; } else if (keyID==39 && e.ctrlKey) //Ctrl+Right { this.MoveCorssCursorRight(this.CtrlMoveStep); return true; } else { return false; } } this.MoveCorssCursorLeft=function(step) { var data=null; if (this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; if (!data) return; if (data.DataOffset<=0 && this.CursorIndex<=0) //数据到头了 { if (this.DragDownloadData) this.DragDownloadData(); return; } if (this.CursorIndex-step<0) //当前屏到头了 { data.DataOffset-=step; if (data.DataOffset<0) { data.DataOffset=0; this.CursorIndex=0; } this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.Draw(); this.ShowTooltipByKeyDown(); this.OnKLinePageChange("keydown"); return; } this.CursorIndex-=step; this.UpdatePointByCursorIndex(); this.DrawDynamicInfo(); this.ShowTooltipByKeyDown(); } this.MoveCorssCursorRight=function(step) { var data=null; if (this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; if (!data) return; var xPointcount=0; //当前屏显示个数 if (this.Frame.XPointCount) xPointcount=this.Frame.XPointCount; else xPointcount=this.Frame.SubFrame[0].Frame.XPointCount; if (this.CursorIndex+data.DataOffset+1>=data.Data.length) return; //最右边了 var bMoveEnd=false; //最后一个 if (this.CursorIndex+step+data.DataOffset+1>data.Data.length) //数据不够步长 { step=data.Data.length-1-data.DataOffset-this.CursorIndex; bMoveEnd=true; } if (this.CursorIndex+step>=xPointcount) //当前屏最右边了 { var lMoveStep=(this.CursorIndex+step)-(xPointcount-1); data.DataOffset+=lMoveStep; if (bMoveEnd) this.CursorIndex=xPointcount-1; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.Draw(); this.ShowTooltipByKeyDown(); this.OnKLinePageChange("keydown"); return; } this.CursorIndex+=step; this.UpdatePointByCursorIndex(); this.DrawDynamicInfo(); this.ShowTooltipByKeyDown(); } //获取K线图实例 this.GetKLineChart=function() { if (!this.ChartPaint[0]) return null; return this.ChartPaint[0]; } //创建子窗口 this.CreateChildWindow=function(windowCount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME); for(var i=0;i{ return this.GetExtraCanvas(name); }; frame.ChartBorder=border; frame.Identify=i; //窗口序号 frame.RightSpaceCount=this.RightSpaceCount; //右边 frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; frame.GlobalOption=this.GlobalOption; if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.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'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.GetKLineChartCallback=()=> { return this.GetKLineChart(); } frame.YSplitOperator.HQChart=this; var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 border.BottomSpace=15*pixelTatio; //主图上下留空间 border.TopSpace=15*pixelTatio; frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } } 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.GetKLineChartCallback=()=> { return this.GetKLineChart(); } frame.YSplitOperator.HQChart=this; //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.LanguageID=this.LanguageID; 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 frameClassName="KLineFrame"; if (this.ClassName=="KLineChartHScreenContainer") frameClassName="KLineHScreenFrame"; var frame=g_ChartFrameFactory.Create(frameClassName, { ID:id }); frame.Canvas=this.Canvas; frame.GetExtraCanvas=(name)=>{ return this.GetExtraCanvas(name); }; frame.ChartBorder=border; frame.Identify=id; //窗口序号 frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; frame.GlobalOption=this.GlobalOption; if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.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.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; frame.YSplitOperator.GetKLineChartCallback=()=> { return this.GetKLineChart(); }; frame.YSplitOperator.HQChart=this; frame.XSplitOperator.Symbol=this.Symbol; frame.XSplitOperator.Period=this.Period; //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=g_ChartPaintFactory.Create("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.Identify="Main-KLine"; 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].OverlayChartPaint=this.OverlayChartPaint; //绑定叠加 this.TitlePaint[0].LanguageID=this.LanguageID; this.TitlePaint[0].HQChart=this; this.TitlePaint[0].GetEventCallback=(id)=>{ return this.GetEventCallback(id); }; } //绑定主图K线数据 this.BindMainData=function(hisData, showCount, chartOperator) { var isShowAll=false; //全部显示 if (chartOperator && chartOperator.IsShowAll===true) isShowAll=true; this.ChartPaint[0].Data=hisData; this.ChartPaint[0].Symbol=this.Symbol; if (this.KLineSize) { if (!IFrameSplitOperator.IsNumber(this.KLineSize.DataWidth)) { 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=0;i=hisData.Data.length) this.CursorIndex=hisData.Data.length-1-dataOffset; if (this.CursorIndex<0) this.CursorIndex=0; //不一定对啊 } this.ChartPaint[0].Period=this.Period; this.ChartCorssCursor.StringFormatY.Symbol=this.Symbol; if (this.CustomShow) //定制显示 1次有效 { this.SetCustomShow(this.CustomShow,hisData); this.CustomShow=null; } } this.ShowAllKLine=function() { var chart=this.ChartPaint[0]; if (!chart) return false; var kData=chart.Data; if (!kData || !IFrameSplitOperator.IsNonEmptyArray(kData.Data)) return false; var xCount=kData.Data.length+this.RightSpaceCount; for(var i=0;i0 && 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) //更新Y轴K线数据 { 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 in this.OverlayChartPaint) //主图股票数据绑定到叠加股票上 { var item=this.OverlayChartPaint[i]; item.MainData=this.ChartPaint[0].Data; } this.ChartCorssCursor.StringFormatY.Symbol=this.Symbol; } this.SetCustomShow=function(customShow,hisData) { if (customShow.Callback) //预留给外部回调,可以定制移动 { customShow.Callback(chart, hisData) return; } var index=this.ChartOperator_GetIndex_ByDateTime(hisData,customShow, this.Period, 0); if (index===null) { JSConsole.Chart.Log("[KLineChartContainer::SetCustomShow] Can't find index by customShow=",customShow); return; } if (IFrameSplitOperator.IsPlusNumber(customShow.PageSize)) //调整一屏显示个数 否则使用默认的 { var showCount=customShow.PageSize; for(var i=0;i=kData.Data.length) index=kData.Data.length-1; var item = kData.Data[index]; JSConsole.Chart.Log("[KLineChartContainer::OnMarkRectSelect] item", item); if (!this.SetRectSelectData(item, index)) return; var pointCount=paint.GetPointCount(); var pixelTatio = GetDevicePixelRatio(); if (pointCount==1) //第1个位置 { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYDOWN_SELECT_RECT_FIRST); if (event && event.Callback) { var data= { X:corssCursor.LastPoint.X/pixelTatio, Y:corssCursor.LastPoint.Y/pixelTatio, Item:item, Index:index, RectSelectPaint:paint, //区间选择背景 e:e, }; event.Callback(event,data,this); } } else if (pointCount==2) { var selectData=paint.GetSelectRectData(); var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYDOWN_SELECT_RECT); var isShowMenu=true; if (event && event.Callback) { var data= { X:corssCursor.LastPoint.X/pixelTatio, Y:corssCursor.LastPoint.Y/pixelTatio, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint, //区间选择背景 IsShowMenu:true, e:e, }; event.Callback(event,data,this); isShowMenu=data.IsShowMenu; } if (isShowMenu) { var data= { Chart:this, X:corssCursor.LastPoint.X/pixelTatio, Y:corssCursor.LastPoint.Y/pixelTatio, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; e.data=data this.PopupSelectRectMenuV2(data, e); } } this.Draw(); } //创建指定窗口指标 this.CreateWindowIndex=function(windowIndex) { this.WindowIndex[windowIndex].Create(this,windowIndex); } this.BindIndexData=function(windowIndex, hisData, option) { if (!this.WindowIndex[windowIndex]) return; var item=this.WindowIndex[windowIndex]; if (typeof(item.RequestData)=="function") //数据需要另外下载的. { item.RequestData(this,windowIndex,hisData, option); return; } if (typeof(item.ExecuteScript)=='function') { if (option && option.CheckRunCount) if (item.IsExcessRunCount()) return; item.ExecuteScript(this,windowIndex,hisData); return; } item.BindData(this,windowIndex,hisData); } //叠加指标 option={ CheckRunCount:执行次数检测 ,SyncExecute:同步|异步检测 } this.BindOverlayIndexData=function(overlayItem, windowIndex, hisData, option) { if (!overlayItem.Script) return; if (typeof(overlayItem.Script.RequestData)=='function') { overlayItem.Script.RequestData(this,windowIndex,hisData); return; } if (typeof(overlayItem.Script.ExecuteScript)=='function') { if (option) { if (option.CheckRunCount) //检测执行次数 { if (overlayItem.Script.IsExcessRunCount()) return; } if (IFrameSplitOperator.IsBool(option.SyncExecute)) //异步|同步 { if (overlayItem.Script.IsSync!=option.SyncExecute) return; } } overlayItem.Script.ExecuteScript(this,windowIndex,hisData); return; } overlayItem.Script.BindData(this,windowIndex,hisData); } //执行指示(专家指示 五彩K线) this.BindInstructionIndexData=function(hisData) { if (this.ColorIndex && typeof(this.ColorIndex.ExecuteScript)=='function') //五彩K线 { this.ColorIndex.ExecuteScript(this,0,hisData); } if (this.TradeIndex && typeof(this.TradeIndex.ExecuteScript)=='function') //交易指标 { this.TradeIndex.ExecuteScript(this,0,hisData); } } //获取子窗口的所有画法 this.GetChartPaint=function(windowIndex) { var paint=new Array(); for(var i in this.ChartPaint) { if (i==0) continue; //第1个K线数据除外 var item=this.ChartPaint[i]; if (item.ChartFrame==this.Frame.SubFrame[windowIndex].Frame) paint.push(item); } return paint; } this.AutoUpdateEvent=function(bStart, explain) //自定更新事件, 是给websocket使用 { var eventID=bStart ? JSCHART_EVENT_ID.RECV_START_AUTOUPDATE:JSCHART_EVENT_ID.RECV_STOP_AUTOUPDATE; if (!this.mapEvent.has(eventID)) return; var self=this; var event=this.mapEvent.get(eventID); var data={ Stock:{ Symbol:this.Symbol, Name:this.Name, Right:this.Right, Period:this.Period }, Explain: explain }; if (bStart) { data.Callback=function(data) //数据到达更新回调 { if (ChartData.IsDayPeriod(self.Period,true)) self.RecvRealtimeData(data); else if (ChartData.IsMinutePeriod(self.Period,true)) self.RecvMinuteRealtimeData(data); else if (ChartData.IsSecondPeriod(self.Period)) self.RecvMinuteRealtimeData(data); else if (ChartData.IsMilliSecondPeriod(self.Period)) self.RecvMinuteRealtimeData(data); } } event.Callback(event,data,this); } this.SendKLineUpdateEvent=function(bindData) { var event=this.GetEventCallback(JSCHART_EVENT_ID.RECV_KLINE_UPDATE_DATA); if (event && event.Callback) { var data={ HistoryData:bindData, Stock:{Symbol:this.Symbol, Name:this.Name } } event.Callback(event,data,this); return true; } return false; } this.SendManualKLineUpdateEvent=function(bindData) { var event=this.GetEventCallback(JSCHART_EVENT_ID.RECV_KLINE_MANUAL_UPDATE_DATA); if (event && event.Callback) { var data={ HistoryData:bindData, Stock:{Symbol:this.Symbol, Name:this.Name } } event.Callback(event,data,this); return true; } return false; } this.GetKLineDrawType=function() { return this.KLineDrawType; } this.RequestHistoryData=function() { var self=this; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.EnableSplash(true); this.FlowCapitalReady=false; this.ResetPage(); //重置分页 this.ResetDragDownload(); this.ResetZoomDownload(); this.Draw(); if (this.NetworkFilter) { var kLineDrawType=this.GetKLineDrawType(); var obj= { Name:'KLineChartContainer::RequestHistoryData', //类名:: Explain:'日K数据', Request:{ Url:self.KLineApiUrl, Type:'POST' , Data: { symbol:self.Symbol, count:self.MaxRequestDataCount, field: ["name","symbol","yclose","open","price","high","low","vol"], period:this.Period, right:this.Right, klineDrawType:kLineDrawType } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvHistoryData(data); var page=self.Page.Day; if (page.Enable==true && page.Finish==false) { self.RequestHistoryPageData(); } else { self.AutoUpdateEvent(true,'KLineChartContainer::RequestHistoryData'); self.AutoUpdate(); } }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: this.KLineApiUrl, data: { "field": ["name","symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestDataCount }, type:"post", dataType: "json", async:true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvHistoryData(data); var page=self.Page.Day; if (page.Enable==true && page.Finish==false) { self.RequestHistoryPageData(); } else { self.AutoUpdateEvent(true,'KLineChartContainer::RequestHistoryData'); self.AutoUpdate(); } } }); } this.BindAllOverlayIndexData=function(hisData, option) { if (!this.Frame || !this.Frame.SubFrame) return; //叠加指标 for(var i=0;i0 && !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; } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:"RecvHistoryData" }); bindData=newBindData; this.FlowCapitalReady=true; } //绑定数据 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; //周期 } var page=this.Page.Day; if (page.Enable==false || (page.Enable==true && page.Finish==true)) //分页下载 这些数据迁移到分页下载完以后下载 { this.ReqeustKLineInfoData({ FunctionName:"RecvHistoryData" }); //请求信息地雷 this.RequestFlowCapitalData(); //请求流通股本数据 (主数据下载完再下载) this.RequestOverlayHistoryData(); //请求叠加数据 (主数据下载完再下载) this.CreateChartDrawPictureByStorage(); //创建画图工具 } if (page.Enable) page.Index=1; //第一页下载完成 this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; i0 && bindData.Period<=3) //复权(日线数据才复权) { 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.UpdateMainData(bindData,lastDataCount); this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; i0 && !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; } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:"RecvMinuteHistoryData" }); bindData=newBindData; this.FlowCapitalReady=true; } //绑定数据 this.Symbol=data.symbol; this.Name=data.name; var chartOperator=null; //额外的图形控制 if (data && data.ChartOperator) { var item=data.ChartOperator; chartOperator={ }; if (item.IsShowAll===true) chartOperator.IsShowAll=true; //全部显示 } this.BindMainData(bindData,this.PageSize,chartOperator); 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线数据 firstSubFrame.YSplitOperator.Period=this.Period; //周期 } for(var i in this.OverlayChartPaint) //分钟数据不支持叠加 清空 { var item=this.OverlayChartPaint[i]; item.Data=null; //item.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID; } var page=this.Page.Minute; if (page.Enable==false || (page.Enable==true && page.Finish==true) ) { this.ReqeustKLineInfoData({ FunctionName:"RecvMinuteHistoryData" }); //请求信息地雷 this.RequestFlowCapitalData(); //请求流通股本数据 (主数据下载完再下载) this.RequestOverlayHistoryMinuteData(); //请求叠加数据 (主数据下载完再下载) this.CreateChartDrawPictureByStorage(); //创建画图工具 } if (page.Enable) ++page.Index; this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; i0 && ChartData.IsDayPeriod(bindData.Period,false)) //复权(日线数据才复权) { 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.UpdateMainData(bindData,lastDataCount); this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; i0) newItem.YClose=this.SourceData.Data[this.SourceData.Data.length-1].YClose; this.SourceData.Data.push(newItem); } else { var bFind=false; var aryKData=this.SourceData.Data; for(var i=aryKData.length-1;i>=0; --i) { var kItem=aryKData[i]; if (kItem.Date==realtimeData.Date) { HistoryData.CopyTo(kItem,realtimeData); bFind=true; break; } } if (!bFind) 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) && MARKET_SUFFIX_NAME.IsSHSZStockA(this.Symbol) && !this.IsApiPeriod) //复权(A股日线数据才复权) { 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; } } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:"RecvRealtimeData" }); bindData=newBindData; this.FlowCapitalReady=true; } this.UpdateMainData(bindData,lastDataCount);//更新主图数据 this.UpdateOverlayRealtimeData(data); //更新叠加股票数据 this.BindInstructionIndexData(bindData); //执行指示脚本 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.RequestMinuteRealtimeData=function() { var self=this; var arySymbol=[self.Symbol]; for(var i in this.OverlayChartPaint) //叠加的股票更新 { var item=this.OverlayChartPaint[i]; if (!item.Symbol) continue; if (!item.MainData) continue; //等待主图股票数据未下载完 if (item.Status!=OVERLAY_STATUS_ID.STATUS_FINISHED_ID) continue; arySymbol.push(item.Symbol); } if (this.NetworkFilter) { var kLineDrawType=this.GetKLineDrawType(); var dateRange=null; var hisData=this.ChartOperator_Temp_GetHistroyData(); if (hisData) dateRange=hisData.GetDateRange(); var obj= { Name:'KLineChartContainer::RequestMinuteRealtimeData', //类名:: Explain:'当天1分钟K线数据', Request: { Url:self.RealtimeApiUrl, Data: { symbol: arySymbol, field:["name","symbol","price","yclose","minutecount","minute","date","time"], period:this.Period, right:this.Right, klineDrawType:kLineDrawType, dateRange:dateRange }, Type:'POST' }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvMinuteRealtimeData(data); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: this.RealtimeApiUrl, data: { "field": ["name","symbol","price","yclose","minutecount","minute","date","time"], "symbol": arySymbol, "start": -1 }, type:"post", dataType: "json", async:true, success: function (data) { self.RecvMinuteRealtimeData(data); self.AutoUpdate(); } }); } this.SetSourceDatatLimit=function(aryLimit) { this.SourceDataLimit=new Map(); for(var i in aryLimit) { var item=aryLimit[i]; this.SourceDataLimit.set(item.Period, item.MaxCount); //每个周期缓存数据最大个数 key=周期 value=最大个数 JSConsole.Chart.Log(`[KLineChartContainer::SetSourceDatatLimit] Period=${item.Period}, MaxCount=${item.MaxCount}`); } } this.ReduceSourceData=function() { if (!this.SourceDataLimit) return; if (!this.SourceDataLimit.has(this.Period)) return; var limitCount=this.SourceDataLimit.get(this.Period); 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; if (limitCount<50) return; var dataOffset=frameHisdata.DataOffset; var removeCount=0; while(this.SourceData.Data.length>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.RecvMinuteRealtimeDataV2=function(data) //新版本的 { if (this.IsOnTouch==true) return; //正在操作中不更新数据 if (this.EnableVerifyRecvData && data.symbol!=this.Symbol) { JSConsole.Chart.Warn(`[KLineChartContainer::RecvMinuteRealtimeDataV2] recv data symbol not match. HQChart[${this.Symbol}] , Recv[${data.symbol}]`); return; } var aryMinuteData=KLineChartContainer.JsonDataToMinuteHistoryData(data); if (!aryMinuteData || aryMinuteData.length<=0) return; if (this.IsApiPeriod) this.ReduceSourceData(); //减少数据 var lastDataCount=this.GetHistoryDataCount(); //保存下上一次的数据个数 if (!this.SourceData) return; if (!this.SourceData.MergeMinuteData(aryMinuteData)) return; JSConsole.Chart.Log(`[KLineChartContainer::RecvMinuteRealtimeDataV2] update kline by 1 minute data [${lastDataCount}->${this.SourceData.Data.length}], IsAutoSyncDataOffset=${this.IsAutoSyncDataOffset}`); if (this.IsAutoSyncDataOffset===false) lastDataCount=null; //维持当前的屏位置 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 && !this.IsApiPeriod && 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)) && !this.IsApiPeriod) //周期数据 (0= 日线,4=1分钟线 不需要处理) { var periodData=bindData.GetPeriodData(bindData.Period); bindData.Data=periodData; } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:"RecvMinuteRealtimeDataV2" }); bindData=newBindData; this.FlowCapitalReady=true; } //绑定数据 this.UpdateMainData(bindData,lastDataCount); this.UpdateOverlayMinuteRealtimeData(data); //更新叠加股票数据 this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; i${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 && !this.IsApiPeriod && 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)) && !this.IsApiPeriod) //周期数据 (0= 日线,4=1分钟线 不需要处理) { var periodData=bindData.GetPeriodData(bindData.Period); bindData.Data=periodData; } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:"RecvMinuteRealtimeData" }); bindData=newBindData; this.FlowCapitalReady=true; } //绑定数据 this.UpdateMainData(bindData,lastDataCount); this.UpdateOverlayMinuteRealtimeData(data); //更新叠加股票数据 this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; iresult.MaxRequestDataCount) result.MaxRequestDataCount=lCount; } else if (ChartData.IsMinutePeriod(this.Period,true)) { var date; var lCount=0; for(var i in this.SourceData.Data) { var item=this.SourceData.Data[i]; if (item.Date!=date) ++lCount; date=item.Date; } if (lCount>result.MaxRequestMinuteDayCount) result.MaxRequestMinuteDayCount=lCount; } return result; } //分笔数据 this.RequestTickData=function() { var self=this; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); self.ChartSplashPaint.EnableSplash(true); self.Draw(); //下载缓存文件 var cacheUrl=g_JSChartResource.CacheDomain+'/cache/dealday/today/'+self.Symbol+'.json' if (this.NetworkFilter) { var obj= { Name:'KLineChartContainer::RequestTickData', //类名:: Explain:'当天分笔数据', Request:{ Url:cacheUrl, Data:{ symbol: self.Symbol }, Type:'GET' }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvTickData(data); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: cacheUrl, data:{"symbol":self.Symbol}, type:"get", dataType: "json", async:true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvTickData(data); self.AutoUpdate(1); }, error: function(http,e) { self.ChartSplashPaint.EnableSplash(false); self.AutoUpdate(); //self.RecvError(http,e,param);; } }); } this.RecvTickData=function(data) { if (data.ver==2.0) var aryDayData=KLineChartContainer.JsonDataToTickDataV2(data); else var aryDayData=KLineChartContainer.JsonDataToTickData(data); //原始数据 var sourceData=new ChartData(); sourceData.Data=aryDayData; sourceData.DataType=2; //0=日线数据 1=分钟数据 2=分笔数据 this.SourceData=sourceData; if (this.BeforeBindMainData) this.BeforeBindMainData("RecvTickData"); //显示的数据 var bindData=new ChartData(); bindData.Data=aryDayData; bindData.Right=this.Right; bindData.Period=this.Period; bindData.DataType=2; //绑定数据 this.Symbol=data.symbol; this.Name=data.name; this.BindMainData(bindData,this.PageSize); if (this.AfterBindMainData) this.AfterBindMainData("RecvTickData"); this.BindInstructionIndexData(bindData); //执行指示脚本 var firstSubFrame; for(var i=0; i0) lastTime=source[source.length-1].Time; var newCount=0; for(var i in aryDayData) { var item=aryDayData[i]; if (item.Time<=lastTime) continue; source.push(item); ++newCount; } if (newCount<=0 && redraw==false) return; //显示的数据 var bindData=new ChartData(); bindData.Data=source; bindData.Right=this.Right; bindData.Period=this.Period; bindData.DataType=2; //绑定数据 this.Symbol=data.symbol; this.Name=data.name; this.UpdateMainData(bindData,lastDataCount); this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; iCUSTOM_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) || (period>CUSTOM_MILLISECOND_PERIOD_START && period<=CUSTOM_MILLISECOND_PERIOD_END) ) { if (this.SourceData.DataType!=1) isDataTypeChange=true; else if (ChartData.IsSecondPeriod(period)) isDataTypeChange=true; else if (ChartData.IsMilliSecondPeriod(period)) isDataTypeChange=true; } else { switch(period) { case 0: //日线 case 1: //周 case 2: //月 case 3: //年 case 9: //季线 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; case 10: //分笔线 if (this.SourceData.DataType!=2) isDataTypeChange=true; break; } } } this.Period=period; if (right!=null) this.Right=right; this.ReloadChartDrawPicture(); //切换周期了 清空画图工具 this.ClearRectSelect(true); this.Frame.ClearUpDonwFrameYData(); this.ClearCustomKLine(); this.ClearKLineCaluate(); var kLineDrawType=this.GetKLineDrawType(); if (kLineDrawType==10 || kLineDrawType==11 || kLineDrawType==12 || kLineDrawType==16) isDataTypeChange=true; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CHANGE_KLINE_PERIOD); if (event && event.Callback) { var sendData= { IsApiPeriod:this.IsApiPeriod, Old:oldData, Now:{ Period:this.Period, Right:this.Right, KLineDrawType:this.KLineDrawType, Symbol:this.Symbol }, IsDataTypeChange:isDataTypeChange, //数据类型是否改变 true 重新请求数据 } event.Callback(event, sendData, this); isDataTypeChange=sendData.IsDataTypeChange; } if (isDataTypeChange==false && !this.IsApiPeriod) { this.ClearIndexRunCount(); this.Update( {UpdateCursorIndexType:2} ); //更新的时候 取消显示十字光标 return; } this.ClearIndexPaint(); if (ChartData.IsDayPeriod(this.Period,true)) { this.CancelAutoUpdate(); //先停止定时器 this.AutoUpdateEvent(false,'KLineChartContainer::ChangePeriod'); //切换周期先停止更新 this.ResetScrollBar(); this.ResetOverlaySymbolStatus(); this.ClearIndexRunCount(); this.Frame.ClearYCoordinateMaxMin(); this.RequestHistoryData(); //请求日线数据 //this.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(this.Period,true) || ChartData.IsSecondPeriod(this.Period) || ChartData.IsMilliSecondPeriod(this.Period)) { this.CancelAutoUpdate(); //先停止定时器 this.AutoUpdateEvent(false,'KLineChartContainer::ChangePeriod'); //切换周期先停止更新 this.ResetScrollBar(); this.ResetOverlaySymbolStatus(); this.ClearIndexRunCount(); this.Frame.ClearYCoordinateMaxMin(); this.RequestHistoryMinuteData(); //请求分钟数据 } else if (ChartData.IsTickPeriod(this.Period)) { this.CancelAutoUpdate(); //先停止定时器 this.AutoUpdateEvent(false,'KLineChartContainer::ChangePeriod'); this.ResetScrollBar(); this.ClearIndexRunCount(); this.Frame.ClearYCoordinateMaxMin(); this.RequestTickData(); //请求分笔数据 } } //复权切换 this.ChangeRight=function(right) { if (!MARKET_SUFFIX_NAME.IsEnableRight(this.Period,this.Symbol, this.RightFormula)) return; var upperSymbol=this.Symbol.toUpperCase(); if (MARKET_SUFFIX_NAME.IsBIT(upperSymbol)) return; if (right<0 || right>2) return; if (this.Right==right) return; var oldData={ Period:this.Period, Right:this.Right, KLineDrawType:this.KLineDrawType, Symbol:this.Symbol }; this.Right=right; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CHANGE_KLINE_RIGHT); if (event && event.Callback) { var sendData= { IsApiPeriod:this.IsApiPeriod, Old:oldData, Now:{ Period:this.Period, Right:this.Right, KLineDrawType:this.KLineDrawType, Symbol:this.Symbol }, } event.Callback(event, sendData, this); } if (!this.IsApiPeriod) { this.Update(); return; } else //API周期数据 重新请求数据 { if (ChartData.IsDayPeriod(this.Period,true)) { this.CancelAutoUpdate(); //先停止定时器 this.AutoUpdateEvent(false,'KLineChartContainer::ChangeRight'); //切换复权先停止更新 this.ClearIndexPaint(); this.ResetOverlaySymbolStatus(); this.ResetScrollBar(); this.RequestHistoryData(); //请求日线数据 } else if (ChartData.IsMinutePeriod(this.Period,true) || ChartData.IsSecondPeriod(this.Period) || ChartData.IsMilliSecondPeriod(this.Period)) { this.CancelAutoUpdate(); //先停止定时器 this.AutoUpdateEvent(false,'KLineChartContainer::ChangeRight'); //切换复权先停止更新 this.ClearIndexPaint(); this.ResetOverlaySymbolStatus(); this.ResetScrollBar(); 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;i0) 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.IsLocked=false; //解除上锁 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(option); this.CreateWindowIndex(windowIndex); var bindData=this.ChartPaint[0].Data; this.BindIndexData(windowIndex,bindData); this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } this.ChangePyScriptIndex=function(windowIndex,indexData) { this.DeleteIndexPaint(windowIndex); this.WindowIndex[windowIndex]=new PyScriptIndex(indexData.Name,indexData.Script,indexData.Args,indexData); //脚本执行 var bindData=this.ChartPaint[0].Data; this.BindIndexData(windowIndex,bindData); //执行脚本 this.UpdataDataoffset(); //更新数据偏移 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 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]; var overlayFrame=new OverlayIndexItem(); if (obj.Identify) overlayFrame.Identify=obj.Identify; //由外部指定id //var frame= this.ClassName==='KLineChartHScreenContainer' ? new OverlayKLineHScreenFrame() : new OverlayKLineFrame(); var frame=this.CreateOverlayFrame(); frame.Canvas=this.Canvas; frame.MainFrame=subFrame.Frame; frame.ChartBorder=subFrame.Frame.ChartBorder; frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; if (obj.ShowRightText===true) frame.IsShow=true; else if (obj.ShowRightText===false) frame.IsShow=false; if (IFrameSplitOperator.IsBool(obj.ShowToolbar)) frame.IsShowToolbar=obj.ShowToolbar; //废弃 if (IFrameSplitOperator.IsBool(obj.IsShareY)) frame.IsShareY=obj.IsShareY; if (IFrameSplitOperator.IsNumber(obj.IsShowMainFrame)) frame.IsShowMainFrame=obj.IsShowMainFrame; //if (IFrameSplitOperator.IsBool(obj.IsShowIndexTitle)) frame.IsShowIndexTitle=obj.IsShowIndexTitle; if (IFrameSplitOperator.IsBool(obj.IsCalculateYMaxMin)) frame.IsCalculateYMaxMin=obj.IsCalculateYMaxMin; //是否计算Y最大最小值 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.GetKLineChartCallback=()=> { return this.GetKLineChart(); } frame.YSplitOperator.OverlayIndex=overlayFrame; frame.YSplitOperator.HQChart=this; frame.YSplitOperator.OverlayIdentify=overlayFrame.Identify; if (obj.Frame) { var item=obj.Frame; if (item.Custom) frame.YSplitOperator.Custom=item.Custom; if (IFrameSplitOperator.IsBool(item.IsYDrawMainFrame)) frame.IsYDrawMainFrame=item.IsYDrawMainFrame; //自定义刻度绘制在主图上 if (IFrameSplitOperator.IsBool(item.IsShowToolbar)) frame.IsShowToolbar=item.IsShowToolbar; //是否显示工具栏 } 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; } var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_OVERLAY_FRAME); if (event && event.Callback) { var sendData={ OverlayFrame:overlayFrame, WindowIndex:windowIndex, SubFrame:subFrame }; event.Callback(event, sendData, this); } subFrame.OverlayIndex.push(overlayFrame); return overlayFrame; } this.DeleteOverlayWindowsIndex=function(identify) //删除叠加指标 { if (!this.DeleteOverlayIndex(identify, null)) return; this.UpdateFrameMaxMin(); //重新计算坐标范围 this.Frame.ResetXYSplit(true); this.Draw(); } this.ChangeKLineDrawType=function(drawType, isDraw, option) { if (this.KLineDrawType==drawType && !option) return; var oldKLineType=this.KLineDrawType; this.KLineDrawType=drawType; var setKLineType=new Set([5,7,8,10,11,12,17]); if (setKLineType.has(oldKLineType) || setKLineType.has(drawType)) { var chart=this.ChartPaint[0]; if (chart) chart.DrawType=this.KLineDrawType; this.CancelAutoUpdate(); //先停止定时器 this.AutoUpdateEvent(false,'KLineChartContainer::ChangeKLineDrawType'); if (ChartData.IsDayPeriod(this.Period,true)) { this.ResetOverlaySymbolStatus(); this.RequestHistoryData(); //请求日线数据 } else if (ChartData.IsMinutePeriod(this.Period,true) || ChartData.IsSecondPeriod(this.Period) || ChartData.IsMilliSecondPeriod(this.Period)) { this.ResetOverlaySymbolStatus(); this.RequestHistoryMinuteData(); //请求分钟数据 } return; } for(var i=0; i=0 && obj.Type<=5) frame.YSplitOperator.CoordinateType=obj.Type; if (obj.IsReverse===true) frame.CoordinateType=1; else if (obj.IsReverse==false) frame.CoordinateType=0; } //请求缓存的最大最小值 frame.YMaxMin.Max=null; frame.YMaxMin.Min=null; this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); } //设置指标窗口个数 this.ChangeIndexWindowCount=function(count,option) { if (count<=0) return; if (this.Frame.SubFrame.length==count) return; this.Frame.RestoreIndexWindows(); var currentLength=this.Frame.SubFrame.length; if (currentLength>count) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); for(var i=currentLength-1;i>=count;--i) { this.DeleteIndexPaint(i); this.DeleteChartPaintExtend({WindowIndex:i}); this.Frame.SubFrame[i].Frame.ClearToolbar(); 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); //最后一个显示X轴坐标 for(var i=0;i { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; this.TitlePaint[i+1]=titlePaint; } //最后一个显示X轴坐标 for(var i=0;i0) indexName=option.Windows; //外部设置增加窗口的默认指标 let scriptData = new JSIndexScript(); for(var i=currentLength;icount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); for(var i=currentLength-1;i>=count;--i) { this.Frame.SubFrame[i].Frame.ClearToolbar(); 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[i]; var titleIndex=windowIndex+1; this.TitlePaint[titleIndex].Data=[]; this.TitlePaint[titleIndex].Title=null; var frame=this.Frame.SubFrame[i]; 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[windowIndex]=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 systemScript = new JSIndexScript(); 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(frame, item, frameItem); } //最后一个显示X轴坐标 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; this.Frame.RestoreIndexWindows(); var delFrame=this.Frame.SubFrame[id].Frame; this.DeleteIndexPaint(id); this.DeleteChartPaintExtend({WindowIndex:id}); this.Frame.SubFrame[id].Frame.ClearToolbar(); 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 in this.ChartDrawPicture) { var item=this.ChartDrawPicture[i]; if (item.Frame==delFrame) continue; aryDrawPicture.push(item); } this.ChartDrawPicture=aryDrawPicture; } this.Frame.SetSizeChage(true); this.UpdateFrameMaxMin(); this.ResetFrameXYSplit(); this.Draw(); } this.CreateExtendChart=function(name, option) //创建扩展图形 { var chart; switch(name) { case '筹码分布': chart=new StockChip(); chart.Canvas=this.Canvas; chart.ChartBorder=this.Frame.ChartBorder; chart.ChartFrame=this.Frame; chart.HQChart=this; chart.Left=this.Frame.ChartBorder.Right; //左边间距使用当前框架间距 chart.SetOption(option); this.ExtendChartPaint.push(chart); this.Frame.ChartBorder.Right+=chart.Width; //创建筹码需要增加右边的间距 return chart; case 'KLineTooltip': if (option.Create && typeof(option.Create)=='function') chart=option.Create(); else chart=new KLineTooltipPaint(); 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; case "深度图": chart=new DepthMapPaint(); 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; case "K线Y轴背景图": chart=new KLineYAxisBGPaint(); 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; case '背景图': chart=new BackgroundPaint(); 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; case "FrameSplitPaint": //框架分割 chart=new FrameSplitPaint(); 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; 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.OnTouchFinished=function() { if (this.DragMode==JSCHART_DRAG_ID.CLICK_TOUCH_MODE_ID) { if (this.TouchStatus.CorssCursorShow==true && this.TouchDrawCount>0) return; this.TouchStatus.CorssCursorShow=false; this.DrawDynamicInfo(); return; } if (this.EnableClickModel===true) { if (this.ClickModel.IsShowCorssCursor==true && this.TouchDrawCount>0) return; this.ClickModel.IsShowCorssCursor=false; this.DrawDynamicInfo(); return; } if (this.CorssCursorTouchEnd===true) //手势离开十字光标消失 { if (this.TouchDrawCount>0) this.DrawDynamicInfo(); return; } for(var i in this.ExtendChartPaint) { var item=this.ExtendChartPaint[i]; if (item.ClassName==='KLineTooltipPaint') { this.DrawDynamicInfo(); } } } //锁|解锁指标 { Index:指标名字,IsLocked:是否要锁上,Callback:回调 } this.LockIndex=function(lockData) { if (!lockData) return; if (!lockData.IndexName) return; for(let i in this.WindowIndex) { let item=this.WindowIndex[i]; if (!item) conintue; if (item.Name==lockData.IndexName) { item.SetLock(lockData); this.Update(); break; } } } this.TryClickLock=function(x,y) { for(var i=0;i0 && 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; for(var i=0; i0 && 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) && !this.IsApiPeriod) //周期数据 { var periodData=bindData.GetPeriodData(bindData.Period); bindData.Data=periodData; } item.Data=bindData; } } this.ReqeustKLineInfoData( {FunctionName:"Update"} ); this.CreateChartDrawPictureByStorage(); //创建画图工具 //刷新画图 this.UpdataDataoffset(); //更新数据偏移 if (option && option.UpdateCursorIndexType>0) this.UpdatePointByCursorIndex(option.UpdateCursorIndexType); else this.UpdatePointByCursorIndex(); //更新十字光标位子 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Frame.SetSizeChage(true); this.Draw(); //叠加指标 for(var i=0;i=this.WindowIndex.length) break; //暂时不支持 动态增加/减少 var item=windows[i]; if (!item) continue; 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 systemScript = new JSIndexScript(); var indexInfo = systemScript.Get(indexID); if (indexInfo) { JSIndexScript.ModifyAttribute(indexInfo,item); indexInfo.ID=indexID; this.WindowIndex[i]=new ScriptIndex(indexInfo.Name,indexInfo.Script,indexInfo.Args,indexInfo); //脚本执行 } } } } if (option.CustomShow && IFrameSplitOperator.IsPlusNumber(option.CustomShow.Date)) { var item=option.CustomShow; this.CustomShow={ Date:item.Date }; if (IFrameSplitOperator.IsNumber(item.Time)) this.CustomShow.Time=item.Time; if (IFrameSplitOperator.IsPlusNumber(item.PageSize)) this.CustomShow.PageSize=item.PageSize; } } this.ReloadChartDrawPicture(); this.Frame.ClearUpDonwFrameYData(); if (ChartData.IsDayPeriod(this.Period,true)) { this.ClearStockCache(); this.RequestHistoryData(); //请求日线数据 //this.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(this.Period,true) || ChartData.IsSecondPeriod(this.Period) || ChartData.IsMilliSecondPeriod(this.Period)) { this.ClearStockCache(); this.RequestHistoryMinuteData(); //请求分钟数据 } else if (ChartData.IsTickPeriod(this.Period)) { this.ClearStockCache(); this.RequestTickData(); } } 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; } //信息地雷信息 if (!IFrameSplitOperator.IsNonEmptyArray(this.ChartInfo)) 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; } 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 self = this; var dataCount=this.GetRequestDataCount(); var firstDate=this.SourceData.Data[0].Date; var firstTime=this.SourceData.Data[0].Time; for(var i=0; i0) { indexData.Value=financeData.a; //流通股本(股) aryData.push(indexData); } } if (this.IsApiPeriod) { var klineData=this.ChartPaint[0].Data; var aryFixedData=null; if (ChartData.IsMinutePeriod(this.Period,true)) //分钟数据 { aryFixedData=klineData.GetMinuteFittingFinanceData(aryData); } else if (ChartData.IsDayPeriod(this.Period,true)) //日线数据 { aryFixedData=klineData.GetFittingFinanceData(aryData); } if (aryFixedData && klineData.Data && aryFixedData.length==klineData.Data.length) { for(var i in klineData.Data) { var item=klineData.Data[i]; if (aryFixedData[i] && IFrameSplitOperator.IsNumber(aryFixedData[i].Value)) item.FlowCapital=aryFixedData[i].Value; } } } else { if (ChartData.IsMinutePeriod(this.Period,true)) //分钟数据 { var aryFixedData=this.SourceData.GetMinuteFittingFinanceData(aryData); for(var i=0; i0 && this.RightFormula>=1) //复权 { var rightData=newBindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); newBindData.Data=rightData; } if (ChartData.IsMinutePeriod(bindData.Period,false)) //周期数据 { var periodData=newBindData.GetPeriodData(bindData.Period); newBindData.Data=periodData; } bindData.Data=newBindData.Data; } else { var aryFixedData=this.SourceData.GetFittingFinanceData(aryData); for(let i in this.SourceData.Data) { var item=this.SourceData.Data[i]; if (aryFixedData[i] && IFrameSplitOperator.IsNumber(aryFixedData[i].Value)) item.FlowCapital=aryFixedData[i].Value; } var bindData=this.ChartPaint[0].Data; var newBindData=new ChartData(); newBindData.Data=this.SourceData.Data; if (bindData.Right>0) //复权 { var rightData=newBindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); newBindData.Data=rightData; } if (ChartData.IsDayPeriod(bindData.Period,false)) //周期数据 { var periodData=newBindData.GetPeriodData(bindData.Period); newBindData.Data=periodData; } bindData.Data=newBindData.Data; } } this.FlowCapitalReady=true; var bDraw=false; for(var i in this.ExtendChartPaint) { var item=this.ExtendChartPaint[i]; if (item.ClassName=='StockChip') { bDraw=true; break; } } if (bDraw) this.Draw(); } //创建画图工具 this.CreateChartDrawPicture=function(name, option, callback) { var drawPicture=null; var item=IChartDrawPicture.GetDrawPictureByName(name); if (item) { drawPicture=item.Create(); if (drawPicture.ClassName=='ChartDrawPictureText' || drawPicture.ClassName=="ChartDrawVolProfile") drawPicture.HQChart=this; } if (!drawPicture) //iconfont图标 { if (IChartDrawPicture.MapIonFont.has(name)) { var iconItem=IChartDrawPicture.MapIonFont.get(name); drawPicture=new ChartDrawPictureIconFont(); drawPicture.FontOption.Family=iconItem.Family drawPicture.Text=iconItem.Text; if (iconItem.Color) drawPicture.LineColor=iconItem.Color; } } if (!drawPicture) return false; drawPicture.Canvas=this.Canvas; drawPicture.Status=0; drawPicture.Symbol=this.Symbol; drawPicture.Period=this.Period; drawPicture.Right=this.Right; drawPicture.Option=this.ChartDrawOption; if (callback) drawPicture.FinishedCallback=callback; //完成通知上层回调 if (option) drawPicture.SetOption(option); var self=this; drawPicture.Update=function() //更新回调函数 { self.DrawDynamicInfo(); }; drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); } this.CurrentChartDrawPicture=drawPicture; //JSConsole.Chart.Log("[KLineChartContainer::CreateChartDrawPicture] ", name,this.CurrentChartDrawPicture); return true; } this.AddChartDrawPicture=function(obj) { if (!obj) return null; if (obj.FrameID<0 || obj.FrameID>=this.Frame.SubFrame.length) return null; var self=this; var item=IChartDrawPicture.GetDrawPictureByClassName(obj.ClassName); if (!item) return null; var drawPicture=item.Create(); drawPicture.Canvas=this.Canvas; drawPicture.Status=10; drawPicture.Frame=this.Frame.SubFrame[obj.FrameID].Frame; //绑定框架坐标 drawPicture.Symbol=this.Symbol; drawPicture.Period=this.Period; drawPicture.Right=this.Right; drawPicture.Option=this.ChartDrawOption; if (obj.Value) drawPicture.Value=obj.Value; if (obj.Guid) drawPicture.Guid=obj.Guid; if (drawPicture.ImportStorageData) drawPicture.ImportStorageData(obj); drawPicture.SetOption(obj); if (obj.EnableUpdateXValue) drawPicture.UpdateXValue(); drawPicture.ValueToPoint(); drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); } if (drawPicture.ClassName==='ChartDrawPictureText') drawPicture.IsInitialized=true; this.ChartDrawPicture.push(drawPicture); this.DrawDynamicInfo(); return drawPicture; } this.PasteChartDrawPicture=function(data, frameID, option) { if (!data || !data.ClassName) return null; if (frameID<0 || frameID>=this.Frame.SubFrame.length) return null; var item=IChartDrawPicture.GetDrawPictureByClassName(data.ClassName); if (!item) return null; var drawPicture=item.Create(); if (!drawPicture) return null; var self=this; drawPicture.Canvas=this.Canvas; drawPicture.Status=10; drawPicture.Frame=this.Frame.SubFrame[frameID].Frame; //绑定框架坐标 drawPicture.Symbol=this.Symbol; drawPicture.Period=this.Period; drawPicture.Right=this.Right; drawPicture.Option=this.ChartDrawOption; drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); } if (drawPicture.SetOption) drawPicture.SetOption(data); this.RandomDrawPictureValue(drawPicture, data); drawPicture.PointToValue(); if (drawPicture.ClassName==='ChartDrawPictureText') drawPicture.IsInitialized=true; this.ChartDrawPicture.push(drawPicture); //存盘 if (this.ChartDrawStorage) this.ChartDrawStorage.SaveDrawData(drawPicture); this.DrawDynamicInfo(); return drawPicture; } //随机生成画图的点 this.RandomDrawPictureValue=function(chart, data) { if (!IFrameSplitOperator.IsNonEmptyArray(data.Value)) return; var kData=this.GetKLineChart(); if (!kData || !kData.Data || !IFrameSplitOperator.IsNumber(kData.Data.DataOffset) || kData.Data.DataOffset<0) return null; if (!IFrameSplitOperator.IsNonEmptyArray(kData.Data.Data)) return null; var aryKData=kData.Data.Data; var startIndex=kData.Data.DataOffset; var endIndex=kData.Data.DataOffset+kData.ChartFrame.XPointCount-1; if (endIndex>=aryKData.length) endIndex=aryKData.length-1; var frameHeight=chart.Frame.ChartBorder.GetHeight(); var max=chart.Frame.HorizontalMax; var min=chart.Frame.HorizontalMin; var y=chart.Frame.ChartBorder.GetBottomEx()-(frameHeight)*data.YFristScale; const range={Max:5, Min:2}; const xRandomOffset=Math.floor(Math.random() * (range.Max - range.Min + 1)) + range.Min; var xValue=data.Value[0].XIndex+xRandomOffset; var firstPoint=null; chart.Value=[]; for(var i=0; i{ this.OnClickRightMenu(data); } var x=data.X, y=data.Y; this.PopupMenuByRClick(menuData, x, y); } //重新加载画图工具(切换股票|周期) this.ReloadChartDrawPicture=function() { this.ChartDrawPicture=[]; if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false; this.SelectChartDrawPicture=null; this.CurrentChartDrawPicture=null; if (this.ChartDrawStorage) { this.ChartDrawStorageCache=this.ChartDrawStorage.GetDrawData( {Symbol:this.Symbol, Period:this.Period} ); var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_LOAD_DRAWPICTURE); if (event && event.Callback) { var sendData={ Symbol:this.Symbol, Period:this.Period, DrawStorage:this.ChartDrawStorage, ChartDrawStorageCache:this.ChartDrawStorageCache }; event.Callback(event,sendData,this); } } } this.CreateChartDrawPictureByStorage=function() //把缓存(this.ChartDrawStorageCache) 画图工具创建出来 { if (!IFrameSplitOperator.IsNonEmptyArray(this.ChartDrawStorageCache)) return; 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;i0) { var firstKItem=hisData.Data[0]; var aryInfo=[]; for(var i=0, j=0; i=firstKItem.Date || (item.Date==firstKItem.Date && item.Time>=firstKItem.Time)) //在K线范围内的才显示 aryInfo.push(item); } } aryInfo.sort(function(a,b) { if (a.Date==b.Date) return a.Time-b.Time; return a.Date-b.Date }); //排序 for(var i=0;i0) //复权 { 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; } } if (typeof(this.WindowIndex[index].ExecuteScript)=='function') { var hisData=this.ChartPaint[0].Data; this.WindowIndex[index].ExecuteScript(this,index,hisData); } else if (typeof(this.WindowIndex[index].RequestData)=="function") //数据需要另外下载的. { var hisData=this.ChartPaint[0].Data; this.WindowIndex[index].RequestData(this, index, hisData, null); } else { this.WindowIndex[index].BindData(this,index,bindData); } this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } this.GetOverlayIndexByIdentify=function(identify) { for(var i=0; i=0) { this.CancelZoomUpDownFrameY(dragY); } } var selectedChart; //图形选中 if (this.SelectedChart.EnableSelected) { selectedChart=this.PtInChart(x,y); } var dbClickInfo={ SelectedChart:selectedChart }; this.DBClickEvent(dbClickInfo, e); if (!selectedChart && this.EnableZoomIndexWindow) //双击放大缩小 { var frameId=this.Frame.PtInFrame(x,y); JSConsole.Chart.Log("[KLineChartContainer::OnDoubleClick] frameId",frameId); if (frameId>=this.Frame.ZoomStartWindowIndex) { if (this.ZoomIndexWindow(frameId, {X:x, Y:y})) { this.Frame.SetSizeChage(true); this.Draw(); return true; } } } var tooltip=new TooltipData(); if (!this.PtInChartPaintTooltip(x,y,tooltip)) { if (!this.PtInOverlayIndexTooltip(x, y,tooltip)) return; } if (!tooltip.Data) return; var event=null; if (this.mapEvent.has(JSCHART_EVENT_ID.DBCLICK_KLINE)) event=this.mapEvent.get(JSCHART_EVENT_ID.DBCLICK_KLINE); if (event) { if (this.ClickChartTimer!=null) //清空单击定时器 { clearTimeout(this.ClickChartTimer); this.ClickChartTimer=null; } var data={ Tooltip:tooltip, Stock:{Symbol:this.Symbol, Name:this.Name }, X:e.clientX, Y:e.clientY, PreventDefault:false }; event.Callback(event,data,this); if (data.PreventDefault) return; } //内置弹分时图 if (this.PopMinuteChart && tooltip.Type===0) this.ShowMinuteChartDialog({ Chart:this,Tooltip:tooltip, e:e }, x,y); } this.CancelAutoUpdate=function() //关闭停止更新 { if (typeof (this.AutoUpdateTimer) == 'number') { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = undefined; } } //数据自动更新 this.AutoUpdate=function(waitTime) //waitTime 更新时间 { this.CancelAutoUpdate(); if (!this.IsAutoUpdate) return; if (!this.Symbol) return; var self = this; var marketStatus=MARKET_SUFFIX_NAME.GetMarketStatus(this.Symbol); if (marketStatus==0 || marketStatus==3) //闭市,盘后 { //等待开盘 this.AutoUpdateTimer=setTimeout(function() { self.AutoUpdate(); },20000); return; } var frequency=this.AutoUpdateFrequency; if (marketStatus==1) //盘前 { this.AutoUpdateTimer=setTimeout(function() { self.AutoUpdate(); },frequency); } else if (marketStatus==2) //盘中 { this.AutoUpdateTimer=setTimeout(function() { if (ChartData.IsDayPeriod(self.Period,true)) { self.RequestRealtimeData(); //更新最新行情 //self.ReqeustKLineInfoData(); } else if (ChartData.IsMinutePeriod(self.Period,true) || ChartData.IsSecondPeriod(self.Period) || ChartData.IsMilliSecondPeriod(self.Period)) { self.RequestMinuteRealtimeData(); //请求分钟数据 } else if (ChartData.IsTickPeriod(self.Period)) { self.RequestTickRealtimeData(); //请求最新分笔 } },frequency); } } this.GetMaxMinPageSize = function () { let pageSize={}; let width = this.Frame.ChartBorder.GetWidth(); let barWidth = (ZOOM_SEED[ZOOM_SEED.length - 1][0] + ZOOM_SEED[ZOOM_SEED.length - 1][1]); pageSize.Max=parseInt(width / barWidth) - 2; barWidth= (ZOOM_SEED[0][0] + ZOOM_SEED[0][1]); pageSize.Min=parseInt(width / barWidth) - 2; JSConsole.Chart.Log(`[KLineChartContainer::GetMaxMinPageSize] Max=${pageSize.Max} Min=${pageSize.Min}`); return pageSize; } //获取图形控件的状态 this.GetChartStatus=function() { var subFrame=this.Frame.SubFrame[0].Frame; if (!subFrame) return null; var hisData=subFrame.Data; if (!hisData) return null; var status={ KLine:{ }, Zoom:{} }; status.KLine.Count=hisData.Data.length; status.KLine.Offset=hisData.DataOffset; status.KLine.PageSize=subFrame.XPointCount; status.Zoom.Index=subFrame.ZoomIndex; status.Zoom.Max=ZOOM_SEED.length; return status; } //数据拖拽下载 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(); } else if(ChartData.IsTickPeriod(this.Period)) { JSConsole.Chart.Log(`[KLineChartContainer.DragDownloadData] Tick:[Enable=${this.DragDownload.Tick.Enable}, IsEnd=${this.DragDownload.Tick.IsEnd}, Status=${this.DragDownload.Tick.Status}]`); if (!this.DragDownload.Tick.Enable) return; if (this.DragDownload.Tick.IsEnd) return; //全部下载完了 if (this.DragDownload.Tick.Status!=0) return; this.RequestDragTickData(); } } //数据缩放下载 this.ZoomDownloadData=function(requestData) { 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.ZoomDownloadData] Minute:[Enable=${this.ZoomDownload.Minute.Enable}, IsEnd=${this.ZoomDownload.Minute.IsEnd}, Status=${this.DragDownload.Minute.Status}, Period=${this.Period}]`); if (!this.ZoomDownload.Minute.Enable) return; if (this.ZoomDownload.Minute.IsEnd) return; //全部下载完了 if (this.ZoomDownload.Minute.Status!=0) return; this.RequestZoomMinuteData(requestData); } else if (ChartData.IsDayPeriod(this.Period,true)) { JSConsole.Chart.Log(`[KLineChartContainer.ZoomDownloadData] Day:[Enable=${this.ZoomDownload.Minute.Enable}, IsEnd=${this.ZoomDownload.Minute.IsEnd}, Status=${this.DragDownload.Minute.Status}]`); if (!this.ZoomDownload.Day.Enable) return; if (this.ZoomDownload.Day.IsEnd) return; //全部下载完了 if (this.ZoomDownload.Day.Status!=0) return; this.RequestZoomDayData(requestData); } else if(ChartData.IsTickPeriod(this.Period)) { JSConsole.Chart.Log(`[KLineChartContainer.ZoomDownloadData] Tick:[Enable=${this.ZoomDownload.Tick.Enable}, IsEnd=${this.ZoomDownload.Tick.IsEnd}, Status=${this.DragDownload.Tick.Status}]`); if (!this.ZoomDownload.Tick.Enable) return; if (this.ZoomDownload.Tick.IsEnd) return; //全部下载完了 if (this.ZoomDownload.Tick.Status!=0) return; this.RequestZoomTickData(requestData); } } //TODO: this.RequestDragTickData=function() { JSConsole.Chart.Log(`[KLineChartContainer.RequestDragTickData] not finished.`); } //请求拖动或缩放的分钟历史数据 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;i0 && 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; } } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:option.RecvFuncName }); bindData=newBindData; this.FlowCapitalReady=true; } //绑定数据 this.UpdateMainData(bindData,lastDataCount); if (option) //缩放需要调整当前屏的位置 { if (option.ZoomData) { var zoomData=option.ZoomData; var showCount=zoomData.PageSize-zoomData.RightSpaceCount; //一屏显示的数据个数 bindData.DataOffset= bindData.Data.length-showCount; if (bindData.DataOffset<0) bindData.DataOffset=0; } else if (IFrameSplitOperator.IsNumber(option.DataOffset)) { bindData.DataOffset+=option.DataOffset; if (bindData.DataOffset<0) bindData.DataOffset=0; } } this.UpdateOverlayDragMinuteData(data); this.BindInstructionIndexData(bindData); //执行指示脚本 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; i0) //复权 { 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; } } var kLineCalculate=this.GetKLineCalulate(); if (kLineCalculate) //额外的K线图形计算 { var newBindData=kLineCalculate.RecvHistoryData(bindData, { Symbol:this.Symbol, Function:option.RecvFuncName }); bindData=newBindData; this.FlowCapitalReady=true; } //绑定数据 this.UpdateMainData(bindData,lastDataCount); if (option) //缩放需要调整当前屏的位置 { if (option.ZoomData) { var zoomData=option.ZoomData; var showCount=zoomData.PageSize-zoomData.RightSpaceCount; //一屏显示的数据个数 bindData.DataOffset= bindData.Data.length-showCount; if (bindData.DataOffset<0) bindData.DataOffset=0; } else if (IFrameSplitOperator.IsNumber(option.DataOffset)) { bindData.DataOffset+=option.DataOffset; if (bindData.DataOffset<0) bindData.DataOffset=0; } } this.UpdateOverlayDragDayData(data); this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; icount) count=requestData.Count; var zoomData={ PageSize:requestData.PageSize, DataCount:requestData.DataCount, RightSpaceCount:requestData.RightSpaceCount }; var option= { FuncName:'KLineChartContainer::RequestZoomDayData', FuncExplain:"缩放日K数据下载", RecvFuncName:"RecvZoomDayData", Download:this.ZoomDownload.Day, Url:this.ZoomKLineApiUrl, XShowCount:this.Frame.GetXShowCount(), Count:count, ZoomData:zoomData }; this.RequestPreviousDayData(option); } this.RequestDragDayData=function() { var option= { FuncName:'KLineChartContainer::RequestDragDayData', FuncExplain:"拖拽日K数据下载", RecvFuncName:"RecvDragDayData", Download:this.DragDownload.Day, Url:this.DragKLineApiUrl, Count:this.MaxRequestDataCount, XShowCount:this.Frame.GetXShowCount(), }; this.RequestPreviousDayData(option); } this.MergeOverlaySymbolDayData=function(item, aryOverlayData) { if (!item.Symbol) return false; if (!IFrameSplitOperator.IsNonEmptyArray(aryOverlayData)) return false; var findData=null; 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; //this.Frame.CalculateChartBorder(); var obj=this.Frame.OnSize(); this.Frame.SetSizeChage(true); if (obj.Changed) { this.UpdataDataoffset(); this.UpdatePointByCursorIndex(2); this.UpdateFrameMaxMin(); } this.Draw(); } this.ClickFrameButton=function(button, e) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_FRAME_TOOLBAR); if (event && event.Callback) { var data={ Info:button, PreventDefault:false }; //PreventDefault 是否阻止内置的点击处理 event.Callback(event,data,this); if (data.PreventDefault) return; } if (button.ID==JSCHART_BUTTON_ID.CLOSE_OVERLAY_INDEX) { var id=button.IndexID; if (id) this.DeleteOverlayWindowsIndex(id); } else if (button.ID==JSCHART_BUTTON_ID.MODIFY_OVERLAY_INDEX_PARAM) { var id=button.IndexID; var frame=button.Frame; e.data={ Chart:this, Identify:id, IsOverlay:true }; if (frame.ModifyIndexEvent) frame.ModifyIndexEvent(e); } else if (button.ID==JSCHART_BUTTON_ID.CLOSE_INDEX_WINDOW) { var frame=button.Frame; this.RemoveIndexWindow(frame.Identify); } else if (button.ID==JSCHART_BUTTON_ID.CHANGE_INDEX) { var frame=button.Frame; var sendData={ e:e, WindowIndex:frame.Identify, OpType:1 }; this.ShowChangeIndexDialog(sendData); /* e.data={ Chart:this, Identify:frame.Identify, IsOverlay:false }; if (frame.ChangeIndexEvent) frame.ChangeIndexEvent(e); */ } else if (button.ID==JSCHART_BUTTON_ID.MODIFY_INDEX_PARAM) { var frame=button.Frame; e.data={ Chart:this, Identify:frame.Identify, IsOverlay:false }; if (frame.ModifyIndexEvent) frame.ModifyIndexEvent(e); } else if (button.ID==JSCHART_BUTTON_ID.OVERLAY_INDEX) { var frame=button.Frame; var sendData={ e:e, WindowIndex:frame.Identify, OpType:2 }; this.ShowAddOverlayIndexDialog(sendData); /* e.data={ Chart:this, Identify:frame.Identify, IsOverlay:true }; if (frame.ChangeIndexEvent) frame.ChangeIndexEvent(e); */ } else if (button.ID==JSCHART_BUTTON_ID.MAX_MIN_WINDOW) { var id=button.IndexID; var frame=button.Frame; var frameId=button.FrameID; if (frameId>=this.Frame.ZoomStartWindowIndex) { if (this.ZoomIndexWindow(frameId, null)) { this.Frame.SetSizeChage(true); this.Draw(); } } } else if (button.ID==JSCHART_BUTTON_ID.TITLE_WINDOW) //标题模式 { var id=button.IndexID; var frame=button.Frame; var frameId=button.FrameID; if (this.ShowIndexTitleOnly(frameId)) { this.Frame.SetSizeChage(true); this.Draw(); } } else if (button.ID==JSCHART_BUTTON_ID.EXPORT_DATA) //数据导出 { var data=this.ExportData({Type:"CSV"}); if (!data) return; var date=Date.now(); var fileName = `hqchart_${this.Symbol}_${date}.csv`; var alink = document.createElement("a"); var csvDataBlob = new Blob([data], { type: "text/csv" }); alink.href = URL.createObjectURL(csvDataBlob); document.body.appendChild(alink); alink.setAttribute("download", fileName); alink.click(); document.body.removeChild(alink); } } this.ClickTitleButton=function(button, e) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_TITLE_BUTTON); if (event && event.Callback) { var data={ Info:button, PreventDefault:false, e:e }; //PreventDefault 是否阻止内置的点击处理 event.Callback(event,data,this); if (data.PreventDefault) return; } } this.ClickExtendChartButton=function(button, e) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_EXTENDCHART_BUTTON); if (event && event.Callback) { var data={ Info:button, PreventDefault:false, e:e }; //PreventDefault 是否阻止内置的点击处理 event.Callback(event,data,this); if (data.PreventDefault) return; } //筹码按钮 if (button.ID==JSCHART_BUTTON_ID.CHIP_DEFULT) { button.Chart.ShowType=0; this.Draw(); } else if (button.ID==JSCHART_BUTTON_ID.CHIP_LONG) { button.Chart.ShowType=1; this.Draw(); } else if (button.ID==JSCHART_BUTTON_ID.CHIP_RECENT) { button.Chart.ShowType=2; this.Draw(); } } //成交量分布图数据请求 this.RequestVolumeProfileData=function(option) { var self=this; var chart=option.Chart; if (this.NetworkFilter) { var obj= { Name:'KLineChartContainer::RequestVolumeProfileData', //类名::函数 Explain:'成交量分布图下载', Request:{ Period:this.Period, Right:this.Right, Start:option.Start, End:option.End, Symbol:this.Symbol, ValueAreaVol:option.ValueAreaVol }, Self:this, VolProfile:chart, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvVolumeProfileData(data, chart); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } } this.RecvVolumeProfileData=function(data, chart) { chart.OnRecvVolumeProfileData(data); this.Draw(); } this.ExportMainData=function(data, option) { var aryData=data.ExportKLineData(option); //导出K线 return aryData; } this.UpdateScrollBar=function() { if (!this.ScrollBar) return; var data=this.GetChartStatus(); if (!data) return; var kData=this.ChartPaint[0].Data; var start=data.KLine.Offset; var end=start+data.KLine.PageSize-1; //if (end>=kData.Data.length) end=kData.Data.length-1; var obj={ Start:start, End:end, Data:kData, Draw:true, RightSpaceCount:this.RightSpaceCount }; if (this.Frame && this.Frame.ChartBorder) { var border=this.Frame.ChartBorder; obj.Border={ Left:border.Left, Right:border.Right }; } this.ScrollBar.UpdateSlider(obj); } this.ResetScrollBar=function() { if (!this.ScrollBar) return; this.ScrollBar.Reset({Draw:true}); } 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(); } this.DrawTooltipDialog=function() { if (!this.DialogTooltip) return; this.UpdateTooltipDialog(); } this.UpdateTooltipDialog=function() { if (!this.DialogTooltip) return false; if (!this.ChartCorssCursor) return false; var dataType=0; var kItem=null; if (this.ChartCorssCursor.ClientPos>=0) { var hisData=this.ChartOperator_Temp_GetHistroyData();; if (!hisData) return false; //数据还没有到达 if (!IFrameSplitOperator.IsNonEmptyArray(hisData.Data)) return false; var dataIndex=hisData.DataOffset+this.ChartCorssCursor.CursorIndex; if (dataIndex>=hisData.Data.length) dataIndex=hisData.Data.length-1; var kItem=hisData.Data[dataIndex]; } else //取最后一个数据 { var hisData=this.ChartOperator_Temp_GetHistroyData();; if (!hisData) return false; //数据还没有到达 if (!IFrameSplitOperator.IsNonEmptyArray(hisData.Data)) return false; var kItem=hisData.Data[hisData.Data.length-1]; var dataID={ Symbol:this.Symbol, Date:kItem.Date }; if (IFrameSplitOperator.IsNumber(kItem.Time)) dataID.Time=kItem.Time; if (!this.DialogTooltip.IsEqualDataID(dataID)) return false; dataType=1; } var sendData= { DataType:dataType, //0=全部更新 1=更新实时K线 ClientPos:this.ChartCorssCursor.ClientPos, //位置 IsShowCorss:this.ChartCorssCursor.IsShowCorss, //是否显示十字线 KItem:kItem, Symbol:this.Symbol, Name:this.Name, LastValue:this.ChartCorssCursor.LastValue, }; this.DialogTooltip.Update(sendData); return true; } this.DrawSelectRectDialog=function(e) { if (!this.DialogSelectRect) return; this.UpdateSelectRectDialog(e); } this.UpdateSelectRectDialog=function(e) { if (!this.DialogSelectRect) return false; var data=e.data; //区间统计数据 var x,y; if (data && IFrameSplitOperator.IsNumber(data.X) && IFrameSplitOperator.IsNumber(data.Y)) { var pixelRatio=GetDevicePixelRatio(); var rtClient=this.UIElement.getBoundingClientRect(); var rtScroll=GetScrollPosition(); x=data.X y=data.Y; x+=(rtClient.left+rtScroll.Left); y+=(rtClient.top+rtScroll.Top); } var sendData= { Symbol:this.Symbol, Name:this.Name, SelectData:data.SelectData, X:x, Y:y, e:e } this.DialogSelectRect.Update(sendData); } this.UpdateHQFloatTooltip=function(kData) { if (!this.FloatTooltip) return; if (!this.FloatTooltip.IsShow()) return; if (!kData || !IFrameSplitOperator.IsNonEmptyArray(kData.Data)) return; var lastItem=kData.Data[kData.Data.length-1]; if (!lastItem) return; var dataID={ Symbol:kData.Symbol, Date:lastItem.Date, Time:lastItem.Time }; if (!this.FloatTooltip.IsEqualHQID(dataID)) return; var sendData= { Data:lastItem, Symbol:this.Symbol, Name:this.Name, DataType:2, }; this.FloatTooltip.Update(sendData); } } //API 返回数据 转化为array[] KLineChartContainer.JsonDataToHistoryData=function(data) { var aryDayData=[]; if (!data.data) return aryDayData; var upperSymbol=null; if (data.symbol) upperSymbol=data.symbol.toUpperCase(); var isFutures=false; //是否是期货 if (upperSymbol) isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); var list = data.data; 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 bVirtual=13; //虚拟数据 var bNonTrade=14; //非交易日 var flowCapital=15; //流通股本 var orderFlow=JSCHART_DATA_FIELD_ID.KLINE_ORDERFLOW; var colorData=JSCHART_DATA_FIELD_ID.KLINE_COLOR_DATA; var heatMapIndex=JSCHART_DATA_FIELD_ID.KLINE_HEATMAP; 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[flowCapital])) item.FlowCapital=jsData[flowCapital]; //流通股本 if (IFrameSplitOperator.IsNumber(jsData[bfactor])) item.BFactor=jsData[bfactor]; //前复权因子 if (IFrameSplitOperator.IsNumber(jsData[afactor])) item.AFactor=jsData[afactor]; //后复权因子 if (IFrameSplitOperator.IsBool(jsData[bVirtual])) item.IsVirtual=jsData[bVirtual]; //虚拟数据 if (IFrameSplitOperator.IsBool(jsData[bNonTrade])) item.IsNonTrade=jsData[bNonTrade]; //虚拟数据 if (!IFrameSplitOperator.IsNumber(item.Open) && !(item.IsVirtual===true)) continue; if (jsData[orderFlow]) item.OrderFlow=jsData[orderFlow]; if (jsData[colorData]) item.ColorData=jsData[colorData]; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; if (jsData[heatMapIndex]) item.HeatMap=jsData[heatMapIndex]; aryDayData.push(item); } return aryDayData; } KLineChartContainer.JsonDataToRealtimeData=function(data, symbol) { if (!data.stock) return null; var stock; for(var i in data.stock) //查找对应的股票数据 { var stockItem=data.stock[i]; if (stockItem && stockItem.symbol==symbol) { stock=stockItem; break; } } if (!stock) return null; var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var item=new HistoryData(); item.Date=stock.date; item.Open=stock.open; item.YClose=stock.yclose; item.High=stock.high; item.Low=stock.low; item.Vol=stock.vol; //股 item.Amount=stock.amount; item.Close=stock.price; if (IFrameSplitOperator.IsNumber(stock.position)) item.Position=stock.position; //持仓量 if (IFrameSplitOperator.IsNumber(stock.yclearing)) item.YFClose=stock.yclearing; //前结算价 if (IFrameSplitOperator.IsNumber(stock.clearing)) item.FClose=stock.clearing; //结算价 if (IFrameSplitOperator.IsNumber(stock.bfactor)) item.BFactor=stock.bfactor; //前复权因子 if (IFrameSplitOperator.IsNumber(stock.afactor)) item.AFactor=stock.afactor; //后复权因子 if (stock.colordata) item.ColorData=stock.colordata; //自定义颜色 if (stock.extendData) item.ExtendData=stock.extendData; if (stock.heatmapData) item.HeatMap=stock.heatmapData; if (IFrameSplitOperator.IsBool(stock.isvirtual)) item.IsVirtual=stock.isvirtual; //虚拟数据 if (IFrameSplitOperator.IsBool(stock.isnontrade)) item.IsNonTrade=stock.isnontrade; //虚拟数据 return item; } KLineChartContainer.JsonDataToMinuteRealtimeData=function(data,symbol) { if (!data.stock) return null; var stock; for(var i in data.stock) //查找对应的股票数据 { var stockItem=data.stock[i]; if (stockItem && stockItem.symbol==symbol) { stock=stockItem; break; } } if (!stock) return null; var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); var aryMinuteData=new Array(); var preClose=stock.yclose; //前一个数据价格 var date=stock.date; if (isFutures && stock.yclearing)preClose=stock.yclearing; //期货使用昨结算价 for(var i in stock.minute) { var jsData=stock.minute[i]; var item = new HistoryData(); item.Close=jsData.price; item.Open=jsData.open; item.High=jsData.high; item.Low=jsData.low; item.Vol=jsData.vol; //股 item.Amount=jsData.amount; if (jsData.date>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; } //分钟K线叠加数据增量更新v2版本 KLineChartContainer.JsonDataToMinuteRealtimeDataV2=function(data,symbol) { if (!data || !data.overlay || !symbol) return null; var overlayData=null; for(var i=0;i 0) { minData.Open = minData.YClose; minData.High = minData.YClose; minData.Low = minData.YClose; minData.Close = minData.YClose; } } else // 用前一个有效数据填充 { for(var j = i-1; j >= 0; --j) { var minData2 = aryDayData[j]; if (minData2 == null) coninue; if (minData2.Open > 0 && minData2.High > 0 && minData2.Low > 0 && minData2.Close > 0) { if (minData.YClose <= 0) minData.YClose = minData2.Close; minData.Open = minData2.Open; minData.High = minData2.High; minData.Low = minData2.Low; minData.Close = minData2.Close; break; } } } } } */ return aryDayData; } KLineChartContainer.JsonDataToTickData=function(data) { var aryDayData=[]; if (!data.detail) return aryDayData; var date=data.date; var yClose=data.yclose; for(var i in data.detail) { var item = new HistoryData(); var tick=data.detail[i]; if (!tick) continue; item.Date = date; item.Time=tick[0]; item.Low=item.High=item.Close=item.Open = tick[1]; item.YClose = yClose; //当前数据的前收盘 item.Vol = tick[2]; //原始单位股 item.Amount = tick[3]; item.Flag=tick[4]; if (!IFrameSplitOperator.IsNumber(item.Open)) continue; //停牌的数据剔除 //yClose=item.Close; aryDayData.push(item); } return aryDayData; } KLineChartContainer.JsonDataToTickDataV2=function(data) { var aryDayData=[]; if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return aryDayData; for(var i=0;i=this.Frame.ZoomStartWindowIndex) { if (this.ZoomIndexWindow(frameId, null)) { this.Frame.SetSizeChage(true); this.Draw(); } } } else if (button.ID==JSCHART_BUTTON_ID.TITLE_WINDOW) //标题模式 { var id=button.IndexID; var frame=button.Frame; var frameId=button.FrameID; if (this.ShowIndexTitleOnly(frameId)) { this.Frame.SetSizeChage(true); this.Draw(); } } else if (button.ID==JSCHART_BUTTON_ID.EXPORT_DATA) //数据导出 { var data=this.ExportData({Type:"CSV"}); if (!data) return; var date=Date.now(); var fileName = `hqchart_${this.Symbol}_${date}.csv`; var alink = document.createElement("a"); var csvDataBlob = new Blob([data], { type: "text/csv" }); alink.href = URL.createObjectURL(csvDataBlob); document.body.appendChild(alink); alink.setAttribute("download", fileName); alink.click(); document.body.removeChild(alink); } } //图形控制 { ID:, ....参数 } this.ChartOperator=function(obj) { var id=obj.ID; if (id===JSCHART_OPERATOR_ID.OP_SCROLL_LEFT || id===JSCHART_OPERATOR_ID.OP_SCROLL_RIGHT ) //左右移动 { Step:移动天数 } { if (this.DayCount==1) return false; if (!this.PageInfo.Enable) return false; if (!this.DayData) return false; //数据还没有下载好 var isLeft=(id===JSCHART_OPERATOR_ID.OP_SCROLL_LEFT ? true:false); var step=1; if (obj.Step>0) step=obj.Step; if (!this.DayOffset) return false; if (isLeft) { var offset=this.DayOffset.Offset; offset+=step; if (offset+this.DayOffset.ShowDayCount>this.DayOffset.DayCount) offset=this.DayOffset.DayCount-this.DayOffset.ShowDayCount; if (offset==this.DayOffset.Offset) return false; this.DayOffset.Offset=offset; } else { var offset=this.DayOffset.Offset; offset-=step; if (offset<0) offset=0; if (offset==this.DayOffset.Offset) return false; this.DayOffset.Offset=offset; } this.UpdateHistoryMinuteUI(null); this.SendPageChangedEvent(); return true; } else if (id==JSCHART_OPERATOR_ID.OP_SCROLL_GOTO) { if (this.DayCount==1) return false; if (!this.PageInfo.Enable) return false; if (!this.DayData) return false; //数据还没有下载好 if (IFrameSplitOperator.IsNumber(obj.ShowDayCount)) { this.PageInfo.ShowDayCount=obj.ShowDayCount; this.DayOffset.ShowDayCount=obj.ShowDayCount; } if (IFrameSplitOperator.IsNumber(obj.Offset)) { var offset=obj.Offset; if (this.DayOffset.ShowDayCount>0 && offset+this.DayOffset.ShowDayCount>=this.DayOffset.DayCount) offset=this.DayOffset.DayCount-this.DayOffset.ShowDayCount; if (offset==this.DayOffset.Offset) return false; this.DayOffset.Offset=offset; } this.UpdateHistoryMinuteUI(null); this.SendPageChangedEvent(); return true; } else if (id==JSCHART_OPERATOR_ID.OP_CORSSCURSOR_GOTO) //{ Type:1 如果不存在 就隐藏十字光标} { if (!this.SourceData) return false; if (!this.Frame || !this.Frame.SubFrame[0] || !this.Frame.SubFrame[0].Frame) return false; var frame=this.Frame.SubFrame[0].Frame; if (!IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) return false; if (IFrameSplitOperator.IsNumber(obj.Time) && IFrameSplitOperator.IsNumber(obj.Date)) { var findIndex=-1, value=null, lastPrice=null; for(var i=0;i0)) { var timeData = g_MinuteTimeStringData.GetTimeData(this.Symbol); for(var i=0;i=rect.Left && x<=rect.Right && y>=rect.Top && y<=rect.Bottom) return true; return false; } //左右拖拽 this.OnDragMode_One=function(moveData, e) { var drag=this.MouseDrag; var moveSetp=moveData.X; var yMoveSetp=moveData.Y; if (this.RectSelectDrag && this.RectSelectDrag.Index>=0) //区间选择 { if (moveSetp<5) return; var obj={ X:e.clientX, Y:e.clientY, PointIndex:this.RectSelectDrag.Index, Name:"MoveRectSelectLine" }; if (this.MoveRectSelectPoint(obj)) { drag.LastMove.X=e.clientX; this.Draw(); } } else { if (moveSetp<5 && yMoveSetp<5) return; if (!this.EnableSelectRect) return; //this.UIElement.style.cursor="default"; this.SetCursor({Cursor:"default"}); var ptStart=this.PointAbsoluteToRelative(drag.Click.X, drag.Click.Y); var ptEnd=this.PointAbsoluteToRelative(e.clientX, e.clientY); this.ShowDragSelectRect(ptStart, ptEnd); drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; } } this.OnMinuteSelectRectMouseUp=function(e) { var drag=this.MouseDrag; drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; var selectData=new SelectRectData(); var pixelTatio = GetDevicePixelRatio(); //区间起始位置 结束位子 selectData.XStart=(drag.Click.X-uielement.getBoundingClientRect().left)*pixelTatio; selectData.YStart=(drag.Click.Y-uielement.getBoundingClientRect().top)*pixelTatio; selectData.XEnd=(drag.LastMove.X-uielement.getBoundingClientRect().left)*pixelTatio; selectData.YEnd=(drag.LastMove.Y-uielement.getBoundingClientRect().top)*pixelTatio; selectData.JSChartContainer=this; selectData.Stock={Symbol:this.Symbol, Name:this.Name}; if (this.EnableSelectRect && !this.BorderDrag && this.GetSelectRectData(selectData)) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SELECT_RECT); var paint=this.GetRectSelectPaint(); var isShowDialog=true; //是否显示内置区间选择框 if (event && event.Callback) { var data= { X:drag.LastMove.X-uielement.getBoundingClientRect().left, Y:drag.LastMove.Y-uielement.getBoundingClientRect().top, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint, //区间选择背景 e:e }; event.Callback(event,data,this); isShowDialog=false; //外部调用了区间选择事件,不弹框 } if (isShowDialog && this.DialogSelectRect) { e.data= { Chart:this, X:drag.LastMove.X-uielement.getBoundingClientRect().left, Y:drag.LastMove.Y-uielement.getBoundingClientRect().top, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; this.HideSelectRect(); this.UpdateSelectRect(selectData.Start,selectData.End); this.DrawSelectRectDialog(e); } else { this.HideSelectRect(); this.UpdateSelectRect(selectData.Start,selectData.End); } } else { this.TryClickPaintEvent(JSCHART_EVENT_ID.ON_CLICKUP_CHART_PAINT,this.ClickDownPoint,e); this.ClickEvent(e); } } this.OnDragSelectRectMouseUp=function(e) { var paint=this.GetRectSelectPaint(); if (!paint) return; var selectData=paint.GetSelectRectData(); if (!selectData) return; var pixelTatio = GetDevicePixelRatio(); var corssCursor=this.ChartCorssCursor; //十字光标 var x=corssCursor.LastPoint.X/pixelTatio; var y=corssCursor.LastPoint.Y/pixelTatio; var isShowDialog=true; //是否显示内置区间选择框 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAG_SELECT_RECT_MOUSEUP); if (event) { var data= { X:x, Y:y, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint, //区间选择背景 IsShowDialog:false }; event.Callback(event,data,this); isShowDialog=data.IsShowDialog; } if (isShowDialog) { var data = { Chart:this, X:x, Y:y, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; e.data=data; this.UpdateSelectRectDialog(e); } } this.UpdateSelectRect=function(start,end) { if (!this.SourceData || !this.SourceData.Data) return; var paint=this.GetRectSelectPaint(); if (!paint) return; var data=this.SourceData; if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) return; var count=data.Data.length; var startItem=data.Data[start]; if (end>=count) end=count-1; var endItem=data.Data[end]; if (!startItem || !endItem) return; JSConsole.Chart.Log('[MinuteChartContainer::UpdateSelectRect]',startItem,endItem); paint.SetPoint(startItem, { Index:0 }); paint.SetPoint(endItem, { Index:1 }); this.Draw(); } this.MoveRectSelectPoint=function(obj) { var paint=this.GetRectSelectPaint(); if (!paint) return false; if (!this.SourceData || !this.SourceData.Data) return false; var kData=this.SourceData; if (!this.Frame.SubFrame[0]) return false; var subFrame=this.Frame.SubFrame[0].Frame; if (!subFrame) false; var pixelTatio = GetDevicePixelRatio(); var x=(obj.X-uielement.getBoundingClientRect().left)*pixelTatio; var index=subFrame.GetXData(x); index=parseInt(index.toFixed(0)); var dataIndex=index+kData.DataOffset; if (dataIndex>=kData.Data.length) dataIndex=kData.Data.length-1; var item = kData.Data[dataIndex]; JSConsole.Chart.Log("[MinuteChartContainer::MoveRectSelectPoint] point, item", obj.PointIndex, item); if (!paint.SetPoint(item,{ Index: obj.PointIndex })) return false; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAG_SELECT_RECT); if (event) { var selectData=paint.GetSelectRectData(); var data={ X:obj.X, Y:obj.Y, SelectData:selectData, RectSelectPaint:paint }; event.Callback(event,data,this); } if (this.IsShowSelectRectDialog()) //区间统计 { var selectData=paint.GetSelectRectData(); var data={ X:obj.X, Y:obj.Y, SelectData:selectData, RectSelectPaint:paint }; var e={ data:data }; this.DrawSelectRectDialog(e); } return true; } this.GetLastCursorIndex=function(obj) { if (obj.DataType==1) { for(var i=obj.Data.length-1;i>=0;--i) { var item=obj.Data[i]; if (!item || !item.DayItem || !item.DayItem.Data) continue; obj.IndexData.DayIndex=0; obj.IndexData.DataIndex=item.DayItem.Data.length-1; obj.IndexData.Type=item.Type; return; } } else if (obj.DataType==2) { for(var i=obj.Data.length-1;i>=0;--i) { var dayItem=obj.Data[i]; for(var j=dayItem.length-1;j>=0;--j) { var item=dayItem[j]; if (!item || !item.DayItem || !item.DayItem.Data) continue; obj.IndexData.DayIndex=i; obj.IndexData.DataIndex=item.DayItem.Data.length-1; obj.IndexData.Type=item.Type; return; } } } } this.GetFirstCursorIndex=function(obj) { if (obj.DataType==1) { for(var i=0;i=100 && clientPos<=199) { this.CorssCursorIndex.DayIndex=clientPos-100; this.CorssCursorIndex.Type=10; var value=frame.GetXData(option.Point.X); var index=parseInt(value.toFixed(0)); this.CorssCursorIndex.DataIndex=index%frame.MinuteCount; } else if (clientPos>=200 && clientPos<=299) { this.CorssCursorIndex.DayIndex=clientPos-200; this.CorssCursorIndex.Type=20; var aryData=this.MultiDayBeforeOpenData; if (this.DayOffset) { var offset=0, showDayCount=this.MultiDayBeforeOpenData.length; if (IFrameSplitOperator.IsNumber(this.DayOffset.Offset)) offset=this.DayOffset.Offset; if (IFrameSplitOperator.IsNumber(this.DayOffset.ShowDayCount)) showDayCount=this.DayOffset.ShowDayCount; aryData=this.MultiDayBeforeOpenData.slice(offset,offset+showDayCount); } frame.GetLeftExtendXValidData(option.Point.X,{ Data: aryData, IndexData: this.CorssCursorIndex }); } else if (clientPos>=300 && clientPos<=399) { this.CorssCursorIndex.DayIndex=clientPos-300; this.CorssCursorIndex.Type=30; var aryData=this.MultiDayAfterCloseData; if (this.DayOffset && this.MultiDayAfterCloseData) { var offset=0, showDayCount=this.MultiDayAfterCloseData.length; if (IFrameSplitOperator.IsNumber(this.DayOffset.Offset)) offset=this.DayOffset.Offset; if (IFrameSplitOperator.IsNumber(this.DayOffset.ShowDayCount)) showDayCount=this.DayOffset.ShowDayCount; aryData=this.MultiDayAfterCloseData.slice(offset,offset+showDayCount); } frame.GetRightExtendXValidData(option.Point.X,{ Data: aryData, IndexData: this.CorssCursorIndex }); } this.LastPoint.X=this.CorssCursorIndex.Point.X; option.Point.X=this.CorssCursorIndex.Point.X; } } // 100-199=多日分时主图 200-299=盘前 300-399=盘后 1=主图 2=盘前 3=盘后 this.PtInClient_V2=function(x,y) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { var border=this.Frame.ChartBorder.GetHScreenBorder(); this.Canvas.rect(border.Left,border.TopEx,border.Right-border.Left,border.BottomEx-border.TopEx); } else { var border=this.Frame.ChartBorder.GetBorder(); if (border.DayBorder) //多日分时+多日集合竞价 { for(var i=0;i10) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { this.Canvas.rect(border.Left,border.Top,border.Right-border.Left,border.TopEx-border.Top); } else { this.Canvas.rect(border.Left,border.Top,border.LeftEx-border.Left,border.Bottom-border.Top); } if (this.Canvas.isPointInPath(x,y)) return 2; } if (this.Frame.ChartBorder.RightExtendWidth>10) { this.Canvas.beginPath(); if (this.Frame.IsHScreen===true) { this.Canvas.rect(border.Left,border.BottomEx,border.Right-border.Left,border.Bottom-border.BottomEx); } else { this.Canvas.rect(border.RightEx,border.Top,border.Right-border.RightEx,border.Bottom-border.Top); } if (this.Canvas.isPointInPath(x,y)) return 3; } return -1; } //手势 this.OnTouchStart=function(e) { if(this.DragMode==0) return; if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; this.IsPress=false; this.IsOnTouch=true; this.TouchDrawCount=0; this.PhonePinch=null; this.StopDragTimer(); if (this.EnableScrollUpDown==false) e.preventDefault(); //上下拖动图形不能阻止事件 if (this.IsPhoneDragging(e)) { var drag= { Click:{}, LastMove:{} };//LastMove=最后移动的位置 var touches=this.GetToucheData(e,this.IsForceLandscape); var pt=this.PointAbsoluteToRelative(touches[0].clientX, touches[0].clientY, true); if (this.TryClickLock || this.TryClickIndexTitle) //指标枷锁区域 , 指标标题点击 { var x = pt.X; var y = pt.Y; if (this.TryClickLock && this.TryClickLock(x, y)) return; if (this.TryClickIndexTitle && this.TryClickIndexTitle(x,y)) return; } if (this.ClickFrameButton) { var button=this.Frame.PtInButtons(pt.X,pt.Y); if (button) { this.ClickFrameButton(button, e); return; } } drag.Click.X=touches[0].clientX; drag.Click.Y=touches[0].clientY; drag.LastMove.X=touches[0].clientX; drag.LastMove.Y=touches[0].clientY; var self=this; var T_ShowCorssCursor=function() //临时函数(Temp_) T_开头 { if (self.ChartCorssCursor.IsShow === true) //移动十字光标 { var pt=self.PointAbsoluteToRelative(drag.Click.X, drag.Click.Y, true); var x = pt.X; var y = pt.Y self.OnMouseMove(x, y, e); } } if (this.ChartDrawOption.IsLockScreen) { this.MouseDrag=drag; 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}); } if (e.cancelable) e.preventDefault(); return; } else { var drawPictrueData={}; var pixelTatio = GetDevicePixelRatio(); //鼠标移动坐标是原始坐标 需要乘以放大倍速 drawPictrueData.X=(touches[0].clientX-uielement.getBoundingClientRect().left); drawPictrueData.Y=(touches[0].clientY-uielement.getBoundingClientRect().top); 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); } if (e.cancelable) e.preventDefault(); return; } } } else { if (this.EnableScrollUpDown==true) { this.DragTimer=setTimeout(function() { self.IsPress=true; if (drag.Click.X==drag.LastMove.X && drag.Click.Y==drag.LastMove.Y) { var mouseDrag=self.MouseDrag; self.MouseDrag=null; T_ShowCorssCursor(); self.PreventTouchEvent(e) } }, 800); } this.MouseDrag=drag; this.PhoneTouchInfo={ Start:{X:touches[0].clientX, Y:touches[0].clientY }, End:{ X:touches[0].clientX, Y:touches[0].clientY } }; this.SelectChartDrawPicture=null; var bStartTimer=true; //长按计时开始 if (this.EnableClickModel) { if (this.ClickModel.IsShowCorssCursor==true) bStartTimer=false; else bStartTimer= true; } if (bStartTimer) { this.StopDragTimer(); this.DragTimer = setTimeout(()=>{ this.IsPress=true; if (drag.Click.X == drag.LastMove.X && drag.Click.Y == drag.LastMove.Y) //手指没有移动,出现十字光标 { this.MouseDrag = null; //移动十字光标 var x = drag.Click.X; var y = drag.Click.Y; if (this.EnableClickModel===true) this.ClickModel.IsShowCorssCursor=true; self.MoveCorssCursor(drag.Click,e);//移动十字光标 } }, this.PressTime); } else if (!this.EnableClickModel) { if (this.EnableScrollUpDown==false) T_ShowCorssCursor(); //移动十字光标 else if (this.IsClickShowCorssCursor) T_ShowCorssCursor(); } } if (this.EnableZoomIndexWindow) { this.PhoneDBClick.AddTouchStart(touches[0].clientX, touches[0].clientY, Date.now()); JSConsole.Chart.Log("[MinuteChartContainer::OnTouchStart] PhoneDBClick ", this.PhoneDBClick); } 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,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.SelectChartDrawPicture=null; } } this.OnTouchMove=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var touches=this.GetToucheData(e,this.IsForceLandscape); if (this.IsPhoneDragging(e)) { var drag=this.MouseDrag; if (drag==null) { var pixelTatio = GetDevicePixelRatio(); var x = touches[0].clientX-uielement.getBoundingClientRect().left*pixelTatio; var y = touches[0].clientY-uielement.getBoundingClientRect().top*pixelTatio; this.OnMouseMove(x,y,e); } 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 (this.EnableClickModel && this.ClickModel.IsShowCorssCursor===false) { //点击模式 十字光标隐藏 不做任何操作 } else { //上下滚动 if ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true ) { this.StopDragTimer(); return; } this.PreventTouchEvent(e); this.MouseDrag=null; var pixelTatio = GetDevicePixelRatio(); var x = touches[0].clientX-uielement.getBoundingClientRect().left*pixelTatio; var y = touches[0].clientY-uielement.getBoundingClientRect().top*pixelTatio; this.OnMouseMove(x,y,e); } } if (this.PhoneTouchInfo) { this.PhoneTouchInfo.End.X=touches[0].clientX; this.PhoneTouchInfo.End.Y=touches[0].clientY; } } else if (this.IsPhonePinching(e)) { this.PreventTouchEvent(e); var phonePinch=this.PhonePinch; if (!phonePinch) 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(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.StopDragTimer(); return; } } } phonePinch.Last={"X":touches[0].pageX,"Y":touches[0].pageY,"X2":touches[1].pageX,"Y2":touches[1].pageY}; } if (this.EnableScrollUpDown==false) { e.preventDefault(); } else { if (drag==null) { this.PreventTouchEvent(e); //十字光标出来了,阻止消息 } else { this.StopDragTimer(); //上下推动图片,停止定时器,消息传递下去 } } } this.OnTouchEnd=function(e) { JSConsole.Chart.Log('[MinuteChartContainer::OnTouchEnd]',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.StopDragTimer(); this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchEnd"}, e); this.OnTouchFinished(); this.TouchDrawCount=0; } //键盘左右移动十字光标 this.OnKeyDown=function(e) { this.StopDisplayLatest(); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; //回调事件 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYDOWN); if (event && event.Callback) { var sendData={ e:e, PreventDefault:false }; event.Callback(event, sendData, this); if (sendData.PreventDefault) return; } var keyID = e.keyCode ? e.keyCode :e.which; var draw=false; if (this.ChartCorssCursor && this.ChartCorssCursor.OnKeyDown) //十字光标 隐藏显示 { var sendData={ e:e, KeyID:keyID, Draw:false, PreventDefault:false }; this.ChartCorssCursor.OnKeyDown(sendData); draw=sendData.Draw; } switch(keyID) { case 37: //left if (this.EnableNewIndex) { this.MoveCorssCursorIndex({IsMoveLeft:true}); } else { if (!IFrameSplitOperator.IsNumber(this.CursorIndex)) { var xPointcount=0; if (this.Frame.XPointCount) xPointcount=this.Frame.XPointCount; else xPointcount=this.Frame.SubFrame[0].Frame.XPointCount; this.CursorIndex=xPointcount-1; } this.CursorIndex=parseInt(this.CursorIndex); if (this.CursorIndex<=0.99999) { if (!this.DataMoveLeft()) break; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.Draw(); } else { --this.CursorIndex; this.UpdatePointByCursorIndex(); this.DrawDynamicInfo(); } } break; case 39: //right if (this.EnableNewIndex) { this.MoveCorssCursorIndex({IsMoveLeft:false}); } else { var xPointcount=0; if (this.Frame.XPointCount) xPointcount=this.Frame.XPointCount; else xPointcount=this.Frame.SubFrame[0].Frame.XPointCount; if (!IFrameSplitOperator.IsNumber(this.CursorIndex)) this.CursorIndex=0; this.CursorIndex=parseInt(this.CursorIndex); if (this.CursorIndex+1>=xPointcount) { if (!this.DataMoveRight()) break; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.Draw(); } else { //判断是否在最后一个数据上 var data=null; if (this.Frame.Data) data=this.Frame.Data; else data=this.Frame.SubFrame[0].Frame.Data; if (!data) break; if (this.CursorIndex+data.DataOffset+1>=data.Data.length) break; ++this.CursorIndex; this.UpdatePointByCursorIndex(); this.DrawDynamicInfo(); } } break; case 46: //del if (this.SelectChartDrawPicture) { var drawPicture=this.SelectChartDrawPicture; JSConsole.Chart.Log(drawPicture,"drawPicturedrawPicturedrawPicture") this.SelectChartDrawPicture=null; this.ClearChartDrawPicture(drawPicture); //删除选中的画图工具 } else if (this.SelectedChart && this.SelectedChart.Selected.Identify) { var selectedInfo=this.GetSelectedChartInfo(this.SelectedChart.Selected); if (selectedInfo) { if (selectedInfo.Type==JSCHART_DRAGCHART_TYPE_ID.OVERLAY_INDEX) this.DeleteOverlayWindowsIndex(selectedInfo.IndexID); else if (selectedInfo.Type==JSCHART_DRAGCHART_TYPE_ID.OVERLAY_MINUTE) this.DeleteOverlaySymbol(selectedInfo.Symbol); } } break; case 32: //space this.OnMarkRectSelect(e); break; case 33: //page up if (this.PageInfo.Enable) { var option={ID:JSCHART_OPERATOR_ID.OP_SCROLL_LEFT, Step:this.PageInfo.ShowDayCount }; this.ChartOperator(option); } break; case 34: //page down if (this.PageInfo.Enable) { var option={ID:JSCHART_OPERATOR_ID.OP_SCROLL_RIGHT, Step:this.PageInfo.ShowDayCount }; this.ChartOperator(option); } break; case 27: if (this.CurrentChartDrawPicture) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status!=20) //画布移动的时候不能取消 this.CurrentChartDrawPicture=null; } break; default: return; } if (draw) this.DrawDynamicInfo(); //不让滚动条滚动 if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnMarkRectSelect=function(e) { var corssCursor=this.ChartCorssCursor; //十字光标 if (!corssCursor || corssCursor.Status==0) return; if (!IFrameSplitOperator.IsNumber(corssCursor.CursorIndex)) return; if (!this.SourceData || !this.SourceData.Data) return; var paint=this.GetRectSelectPaint(); if (!paint) return; var cursorIndex=corssCursor.CursorIndex; JSConsole.Chart.Log("[MinuteChartContainer::OnMarkRectSelect] dataIndex", cursorIndex); var kData=this.SourceData; cursorIndex=parseInt(cursorIndex.toFixed(0)); var index=cursorIndex+kData.DataOffset; if (index>=kData.Data.length) index=kData.Data.length-1; var item = kData.Data[index]; JSConsole.Chart.Log("[MinuteChartContainer::OnMarkRectSelect] item", item); if (!this.SetRectSelectData(item)) return; var pointCount=paint.GetPointCount(); var pixelTatio = GetDevicePixelRatio(); if (pointCount==1) //第1个位置 { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYDOWN_SELECT_RECT_FIRST); if (event && event.Callback) { var data= { X:corssCursor.LastPoint.X/pixelTatio, Y:corssCursor.LastPoint.Y/pixelTatio, Item:item, Index:index, RectSelectPaint:paint, //区间选择背景 e:e, }; event.Callback(event,data,this); } } else if (pointCount==2) //第2个位置 { var selectData=paint.GetSelectRectData(); var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYDOWN_SELECT_RECT); if (event && event.Callback) { var data= { X:corssCursor.LastPoint.X/pixelTatio, Y:corssCursor.LastPoint.Y/pixelTatio, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint, //区间选择背景 e:e, }; event.Callback(event,data,this); } if (this.DialogSelectRect) { e.data= { Chart:this, X:corssCursor.LastPoint.X/pixelTatio, Y:corssCursor.LastPoint.Y/pixelTatio, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; this.DrawSelectRectDialog(e); } } this.Draw(); } //注册鼠标右键事件 this.OnRightMenu=function(x,y,e) { var pixelTatio = GetDevicePixelRatio(); //x,y 需要乘以放大倍速 var frameId=this.Frame.PtInFrame(x*pixelTatio,y*pixelTatio); this.PopupRightMenuV2({X:e.offsetX, Y:e.offsetY, FrameID:frameId}, e); var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CONTEXT_MENU); if (event) { var data={ X:x, Y:y, Event:e, FrameID:frameId }; event.Callback(event,data,this); } } //右键菜单数据 this.GetRightMenuData=function(frameID) { var windowCount=this.Frame.SubFrame.length; //窗口个数 var aryOverlaySymbol=[]; //叠加的股票列表 for(var i=0; i=this.Frame.ZoomStartWindowIndex) { if (this.ZoomIndexWindow(frameId, {X:x, Y:y})) { this.Frame.SetSizeChage(true); this.Draw(); } } } } this.GetDataItem=function(pointInfo) { if (!pointInfo) return null; if (!IFrameSplitOperator.IsNumber(pointInfo.Index)) return null; if (!this.SourceData || !this.SourceData.Data) return null; var data=this.SourceData; var clientPos=pointInfo.ClientPos; if (clientPos==2 || clientPos==3 || (clientPos>=200&& clientPos<=299) || (clientPos>=300&& clientPos<=399)) { if (!this.ChartCorssCursor || !this.ChartCorssCursor.CallAcutionXOperator) return null; var isHScreen=this.Frame.IsHScreen===true; var callAcutionXOper=this.ChartCorssCursor.CallAcutionXOperator; callAcutionXOper.Value=isHScreen?pointInfo.Point.Y:pointInfo.Point.X; callAcutionXOper.Point={X:pointInfo.Point.X, Y:pointInfo.Point.Y}; callAcutionXOper.ClientPos=clientPos; if (clientPos==2) { if (!this.BeforeOpenData) return null; } else if (clientPos==3) { if (!this.AfterCloseData) return null; } else if (clientPos>=200 && clientPos<=299) { if (!this.MultiDayBeforeOpenData || !IFrameSplitOperator.IsNonEmptyArray(this.MultiDayBeforeOpenData) ) return; } else if (clientPos>=300 && tclientPos<=399) { if (!this.MultiDayAfterCloseData || !IFrameSplitOperator.IsNonEmptyArray(this.MultiDayAfterCloseData) ) return; } if (callAcutionXOper.Operator()) { var item=callAcutionXOper.Item; return {Type:clientPos, Item:item, Index:callAcutionXOper.DataIndex }; } return null; } var index=parseInt(pointInfo.Index.toFixed(0)); var dataIndex=index+data.DataOffset; if (dataIndex>=data.Data.length) return null; var item=data.Data[dataIndex]; return {Type:clientPos, Item:item, Index:dataIndex }; } this.UpdatePointByCursorIndex=function() { this.LastPoint.X=this.Frame.GetXFromIndex(this.CursorIndex); var index=this.CursorIndex; index=parseInt(index.toFixed(0)); var data=this.Frame.SourceData; if (data.DataOffset+index>=data.Data.length) { return; } var item=data.Data[data.DataOffset+index]; var close=null; if (item.Before) close=item.Before.Close; else close=item.Close this.LastPoint.Y=this.Frame.GetYFromData(close); } //创建 //windowCount 窗口个数 this.Create=function(windowCount,option) { this.UIElement.JSChartContainer=this; //创建十字光标 this.ChartCorssCursor=new ChartCorssCursor(); this.ChartCorssCursor.PtInClient=(x,y)=>{ return this.PtInClient(x,y); } this.ChartCorssCursor.Canvas=this.Canvas; this.ChartCorssCursor.StringFormatX=g_DivTooltipDataForamt.Create("CorssCursor_Minute_XStringFormat"); 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.StringFormatY.ShareAfterVol=this.ShareAfterVol; this.ChartCorssCursor.CallAcutionXOperator=new CallAcutionXOperator(); this.ChartCorssCursor.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; 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.TitleHeight=0; this.Frame.ChartBorder.Left=50; this.Frame.ChartBorder.Bottom=20; this.Frame.Canvas=this.Canvas; this.Frame.GetExtendChartRightWidth=()=> { return this.GetExtendChartRightWidth() } 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(); this.CreateExtendChart("RectSelectPaint", option? option.SelectRect:null); //区间统计 if (this.EnableIndexChartDrag) this.CreateExtendChart("DragMovePaint"); this.CreateDragSelectRect(option? option.DragSelectRect:null); //子窗口动态标题 for(var i=0;i { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint.push(titlePaint); } this.ChartCorssCursor.StringFormatX.Frame=this.Frame.SubFrame[0].Frame; this.ChartCorssCursor.StringFormatY.Frame=this.Frame; if (this.ChartCorssCursor.CallAcutionXOperator) this.ChartCorssCursor.CallAcutionXOperator.Frame=this.Frame.SubFrame[0].Frame; var bRegisterKeydown=true; var bRegisterWheel=true; if (option && option.Listener) { var item=option.Listener; if (item.KeyDown===false) { bRegisterKeydown=false; JSConsole.Chart.Log('[MinuteChartContainer::Create] not register keydown event.'); } if (item.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[MinuteChartContainer::Create] not register wheel event.'); } } if (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e);} , true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 } //创建子窗口 this.CreateChildWindow=function(windowCount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_FRAME); for(var i=0;i { return this.GetEventCallback(id); } if (i>=2) { if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.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]; if (i==0) { frame.YSplitOperator=new FrameSplitMinutePriceY(); frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('price'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.DayOffset=this.DayOffset; frame.YSplitOperator.GlobalOption=this.GlobalOption; frame.YSplitOperator.HQChart=this; } else { frame.YSplitOperator=new FrameSplitY(); frame.YSplitOperator.LanguageID=this.LanguageID; frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (i==1) frame.YSplitOperator.ShareAfterVol=this.ShareAfterVol; } frame.YSplitOperator.Frame=frame; frame.YSplitOperator.ChartBorder=border; frame.XSplitOperator=new FrameSplitMinuteX(); frame.XSplitOperator.Frame=frame; frame.XSplitOperator.ChartBorder=border; frame.XSplitOperator.DayOffset=this.DayOffset; 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, mainFrame) { var border=new ChartBorder(); border.UIElement=this.UIElement; if (mainFrame && mainFrame.ChartBorder && mainFrame.ChartBorder.MultiDayMinute) { var item=mainFrame.ChartBorder.MultiDayMinute; border.MultiDayMinute.Count=item.Count; border.MultiDayMinute.Left=item.Left; border.MultiDayMinute.Right=item.Right; } var frame=null; if (this.ClassName=="MinuteChartHScreenContainer") frame=new MinuteHScreenFrame(); else frame=new MinuteFrame(); frame.Canvas=this.Canvas; frame.ChartBorder=border; frame.Identify=id; //窗口序号 frame.XPointCount=243; frame.GlobalOption=this.GlobalOption; frame.HQChart=this; frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (id>=2) { if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.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.DayOffset=this.DayOffset; frame.XSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.XSplitOperator.Symbol=this.Symbol; if (this.DayCount>1) { frame.XSplitOperator.DayCount=this.DayData.length; frame.XSplitOperator.DayData=this.DayData; frame.DayCount=this.DayData.length; } //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(); 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; } this.AddNewSubFrame=function(option) { var mainFrame=this.Frame.SubFrame[0].Frame; var index=this.Frame.SubFrame.length; var subFrame=this.CreateSubFrameItem(index,mainFrame); var pixelRatio=GetDevicePixelRatio(); subFrame.Frame.ChartBorder.TitleHeight*=pixelRatio; 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); }; titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint[index+1]=titlePaint; this.SetSubFrameOption(subFrame,option); //最后一个显示X轴坐标 for(var i=0;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; } } } //删除某一个窗口的指标 this.DeleteIndexPaint=function(windowIndex,bCallDestroy) { var subFrame=this.Frame.SubFrame[windowIndex].Frame; if (!subFrame) return; var paint=[]; //踢出当前窗口的指标画法 for(var i=0;i{ return this.GetEventCallback(id); }; this.ChartPaint[0]=minuteLine; //分钟线均线 var averageLine=new ChartMinutePriceLine(); averageLine.Canvas=this.Canvas; averageLine.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder; averageLine.ChartFrame=this.Frame.SubFrame[0].Frame; averageLine.Name="Minute-Average-Line"; averageLine.Identify="Minute-Average-Line"; averageLine.Color=g_JSChartResource.Minute.AvPriceColor; averageLine.IsDrawArea=false; this.ChartPaint[1]=averageLine; //成交量 var volLine=g_ChartPaintFactory.Create("ChartMinuteVolumBar"); volLine.Color=g_JSChartResource.Minute.VolBarColor; volLine.Canvas=this.Canvas; volLine.ChartBorder=this.Frame.SubFrame[1].Frame.ChartBorder; volLine.ChartFrame=this.Frame.SubFrame[1].Frame; volLine.Name="Minute-Vol-Bar"; volLine.Identify="Minute-Vol-Bar"; volLine.ShareAfterVol=this.ShareAfterVol; this.ChartPaint[2]=volLine; this.TitlePaint[0]=new DynamicMinuteTitlePainting(); this.TitlePaint[0].Frame=this.Frame.SubFrame[0].Frame; this.TitlePaint[0].Canvas=this.Canvas; this.TitlePaint[0].OverlayChartPaint=this.OverlayChartPaint; //绑定叠加 this.TitlePaint[0].LanguageID=this.LanguageID; this.TitlePaint[0].CallAcutionXOperator=new CallAcutionXOperator(); this.TitlePaint[0].CallAcutionXOperator.Frame=this.Frame.SubFrame[0].Frame; this.TitlePaint[0].HQChart=this; } //切换成 脚本指标 this.ChangeScriptIndex=function(windowIndex,indexData,option) { this.DeleteIndexPaint(windowIndex, true); this.WindowIndex[windowIndex]=new ScriptIndex(indexData.Name,indexData.Script,indexData.Args,indexData); //脚本执行 var bindData=this.SourceData; this.BindIndexData(windowIndex,bindData); //执行脚本 this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } //切换api指标 this.ChangeAPIIndex=function(windowIndex,indexData) { this.DeleteIndexPaint(windowIndex, true); //使用API挂接指标数据 API:{ Name:指标名字, Script:指标脚本可以为空, Args:参数可以为空, Url:指标执行地址 } var apiItem=indexData.API; this.WindowIndex[windowIndex]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,indexData); if (indexData) { if (indexData.Window) this.SetFrameToolbar(windowIndex,indexData.Window); } this.Frame.ClearUpDonwFrameYData({ Index:windowIndex }); var bindData=this.ChartPaint[0].Data; this.BindIndexData(windowIndex,bindData); //执行脚本 this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } this.ChangeIndex=function(windowIndex,indexName,option) { if (this.Frame.SubFrame.length<3) return; if (option && option.API) return this.ChangeAPIIndex(windowIndex,option); //查找系统指标 let scriptData = new JSIndexScript(); let indexInfo = scriptData.Get(indexName); if (!indexInfo) return; if (windowIndex<2) windowIndex=2; if (windowIndex>=this.Frame.SubFrame.length) windowIndex=2; JSIndexScript.ModifyAttribute(indexInfo, option) return this.ChangeScriptIndex(windowIndex, indexInfo, option); } //设置指标窗口个数 this.ChangeIndexWindowCount=function(count) { if (count<2) return; //1,2个窗口固定的不能动 if (this.Frame.SubFrame.length==count) return; var currentLength=this.Frame.SubFrame.length; if (currentLength>count) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); for(var i=currentLength-1;i>=count;--i) { this.DeleteIndexPaint(i); this.DeleteChartPaintExtend({WindowIndex:i}); var item=this.Frame.SubFrame[i].Frame; if (item.ClearToolbar) item.ClearToolbar(); 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 { //创建新的指标窗口 var mainFrame=this.Frame.SubFrame[0].Frame; for(var i=currentLength;i { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint[i+1]=titlePaint; } //创建指标 const indexName=["RSI","MACD","DMA","DMI","KDJ","WR"]; let scriptData = new JSIndexScript(); for(var i=currentLength;icount) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DELETE_FRAME); for(var i=currentLength-1;i>=count;--i) { this.Frame.SubFrame[i].Frame.ClearToolbar(); 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; titlePaint.MainTitlePaint=this.TitlePaint[0]; 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) { if (!this.SourceData) //无数据 不需要执行指标 { this.Draw(); return; } var bindData=this.SourceData; for(var i=0;i=this.Frame.SubFrame.length) return; this.Frame.RestoreIndexWindows(); var delFrame=this.Frame.SubFrame[id].Frame; this.DeleteIndexPaint(id); this.DeleteChartPaintExtend({WindowIndex:id}); this.Frame.SubFrame[id].Frame.ClearToolbar(); 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 in this.ChartDrawPicture) { var item=this.ChartDrawPicture[i]; if (item.Frame==delFrame) continue; aryDrawPicture.push(item); } this.ChartDrawPicture=aryDrawPicture; } */ this.Frame.SetSizeChage(true); this.UpdateFrameMaxMin(); this.ResetFrameXYSplit(); this.Draw(); } this.AutoUpdateEvent=function(bStart, explain) //自定更新事件, 是给websocket使用 { var eventID=bStart ? JSCHART_EVENT_ID.RECV_START_AUTOUPDATE:JSCHART_EVENT_ID.RECV_STOP_AUTOUPDATE; if (!this.mapEvent.has(eventID)) return; var self=this; var event=this.mapEvent.get(eventID); var data={ Stock:{ Symbol:this.Symbol, Name:this.Name, DayCount:this.DayCount }, Explain: explain }; if (bStart) { data.Callback=function(data) //数据到达更新回调 { self.RecvMinuteData(data); } } event.Callback(event,data,this); } this.ClearIndexPaint=function() { //清空指标 if (this.Frame && this.Frame.SubFrame) { for(var i=0;i=2) this.DeleteIndexPaint(i, true); var item=this.Frame.SubFrame[i]; if (IFrameSplitOperator.IsNonEmptyArray(item.OverlayIndex)) { for(var j=0; j=this.WindowIndex.length) break; //暂时不支持 动态增加/减少 var item=option.Windows[i]; if (!item) continue; if (item.Script) { this.WindowIndex[index]=new ScriptIndex(item.Name,item.Script,item.Args,item); //脚本执行 } else if (item.API) { var apiItem=item.API; this.WindowIndex[index]=new APIScriptIndex(apiItem.Name,apiItem.Script,apiItem.Args,item); } else { var systemScript = new JSIndexScript(); var indexID=item.Index; var indexInfo = systemScript.Get(indexID); if (indexInfo) { JSIndexScript.ModifyAttribute(indexInfo,item); indexInfo.ID=indexID; this.WindowIndex[index]=new ScriptIndex(indexInfo.Name,indexInfo.Script,indexInfo.Args,indexInfo); //脚本执行 } } } } //清空叠加股票 if (option.ClearOverlay===true) { for(var i=0; i1) this.RequestData(); } //[{ Symbol: , Color, Option: }] this.OverlaySymbols=function(aryData, option) { if (option && option.ClearAll===true) //全部清空 { for(var i=0; iitem.VolMin) range.Min=item.VolMin; } afterRange=range; } if (IFrameSplitOperator.IsNonEmptyArray(this.MultiDayBeforeOpenData)) { var range={ Max:null, Min:null }; for(var i=0; iitem.VolMin) range.Min=item.VolMin; } beforeRange=range; } if (this.ShareAfterVol==2) // 公用坐标 { if (afterRange && beforeRange) { var max=Math.max(afterRange.Max, beforeRange.Max); var min=Math.min(afterRange.Min, beforeRange.Min); afterRange.Max=beforeRange.Max=max; afterRange.Min=beforeRange.Min=min; } } if (afterRange) { for(var i=0; i2) { var bindData=new ChartData(); bindData.Data=allMinuteData; for(var i=2; i=0;--i) { var item=data[i]; for(var j=0; j0) { if (this.DayData[0].Date1) { if (!this.DayData) return; var findItem=null; for(var i=0; i1) { if (IFrameSplitOperator.IsNonEmptyArray(this.DayData)) { var dayData=this.DayData[0]; dateRange=dayData.GetDateRange(); } } else { if (this.SourceData) dateRange=this.SourceData.GetDateRange(); } var callCation={ Before:this.IsShowBeforeData, After:this.IsShowAfterData } //集合竞价 if (this.DayCount>1) callCation={ Before:this.IsShowMultiDayBeforeData, After:this.IsShowMultiDayAfterData } //多日集合竞价 var obj= { Name:'MinuteChartContainer::RequestMinuteData', //类名::函数名 Explain:'最新分时数据', Request:{ Url:self.MinuteApiUrl, Data:{field:fields, symbol:[self.Symbol], callcation:callCation }, Type:'POST' }, Self:this, PreventDefault:false }; if (dateRange) obj.DateRange=dateRange; //本地数据日期范围 this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMinuteData(data); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.MinuteApiUrl, data: { "field": fields, "symbol": [self.Symbol], "start": -1 }, type:"post", dataType: "json", async:true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMinuteData(data); } }); } this.RecvMinuteDataEvent=function(option) { if (!this.mapEvent.has(JSCHART_EVENT_ID.RECV_MINUTE_DATA)) return; var event=this.mapEvent.get(JSCHART_EVENT_ID.RECV_MINUTE_DATA); var data={ MinuteData:this.SourceData, Stock:{ Symbol:this.Symbol, Name:this.Name }, Option:option, DataStatus:this.DataStatus }; event.Callback(event,data,this); } this.UpdateLineColorData=function(data, date) { if (!this.ColorLineData) { this.ColorLineData=data; return; } //移除当前的 var aryColorLineData=this.ColorLineData.filter(function(item, index, arr) { return item.Date!=date; }); if (IFrameSplitOperator.IsNonEmptyArray(data)) { for(var i in data) { aryColorLineData.push(data[i]); } } this.ColorLineData=aryColorLineData; } this.UpdateCallCationData=function(beforeOpenData,afterCloseData) { if (beforeOpenData && IFrameSplitOperator.IsNonEmptyArray(this.MultiDayBeforeOpenData)) { var lastItem=this.MultiDayBeforeOpenData[this.MultiDayBeforeOpenData.length-1]; if (lastItem.Date==beforeOpenData.Date) //存在更新 this.MultiDayBeforeOpenData[this.MultiDayBeforeOpenData.length-1]=beforeOpenData; else if (lastItem.Date1) //多日走势图 { this.UpdateCallCationData(beforeOpenData,afterCloseData); this.UpdateLineColorData(aryColorData,minuteData.date); this.UpdateLatestMinuteDataV2(minuteData); this.UpdateHistoryMinuteUI(updateTime); this.RecvMinuteDataEvent({FunctionName:"RecvUpdateMinuteData"} ); this.RequestOverlayMinuteData(); //请求叠加数据 (主数据下载完再下载) this.BindAllOverlayIndexData(this.SourceData); this.AutoUpdateEvent(true, "MinuteChartContainer::RecvUpdateMinuteData"); this.AutoUpdate(); return; } //原始数据 this.UpdateLatestMinuteDataV2(minuteData); var sourceData=this.SourceData; var aryMinuteData=this.SourceData.Data; this.ColorLineData=aryColorData; this.TradeDate=data.stock[0].date; this.Frame.SetDayCount(1); //单日数据 this.SourceData.UpdateTime=updateTime; this.Symbol=minuteData.Symbol; this.Name=minuteData.Name; this.SetCallCationDataBorder( { Left:this.IsBeforeData, Right:this.IsAfterData , MultiDay:{ Left:false, Right:false }} ); if (this.ShareAfterVol==2) //盘前, 盘后成交量公用坐标 { if (this.BeforeOpenData && this.AfterCloseData) { var max=Math.max(this.BeforeOpenData.VolMax, this.AfterCloseData.VolMax); var min=Math.min(this.BeforeOpenData.VolMin, this.AfterCloseData.VolMin); this.BeforeOpenData.VolMax=this.AfterCloseData.VolMax=max; this.BeforeOpenData.VolMin=this.AfterCloseData.VolMin=min; } } var yClose=minuteData.YClose; var upperSymbol=this.Symbol.toUpperCase(); var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); if (minuteData.YClearing>0 && isFutures) yClose=minuteData.YClearing; //期货使用前结算价 this.CaclutateLimitPrice(yClose, minuteData.LimitPrice); //计算涨停价格 var extendData=null; if (minuteData.High>0 && minuteData.Low>0) extendData={ High:minuteData.High, Low:minuteData.Low }; this.BindMainData(sourceData,yClose, extendData); if (this.Frame.SubFrame.length>2) { var bindData=new ChartData(); bindData.Data=aryMinuteData; for(var i=2; i1) //多日走势图 { this.UpdateCallCationData(beforeOpenData,afterCloseData); this.UpdateLineColorData(aryColorData,data.stock[0].date); this.UpdateLatestMinuteData(aryMinuteData, data.stock[0].date, data.stock[0]); this.UpdateHistoryMinuteUI(updateTime); this.RecvMinuteDataEvent({FunctionName:"RecvMinuteData"} ); this.RequestOverlayMinuteData(); //请求叠加数据 (主数据下载完再下载) this.BindAllOverlayIndexData(this.SourceData); this.AutoUpdateEvent(true, "MinuteChartContainer::RecvMinuteData"); 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; sourceData.UpdateTime=updateTime; this.ColorLineData=aryColorData; this.TradeDate=data.stock[0].date; this.Frame.SetDayCount(1); //单日数据 this.SourceData=sourceData; this.Symbol=data.stock[0].symbol; this.Name=data.stock[0].name; this.SetCallCationDataBorder( { Left:this.IsBeforeData, Right:this.IsAfterData , MultiDay:{ Left:false, Right:false }} ); if (this.ShareAfterVol==2) //盘前, 盘后成交量公用坐标 { if (this.BeforeOpenData && this.AfterCloseData) { var max=Math.max(this.BeforeOpenData.VolMax, this.AfterCloseData.VolMax); var min=Math.min(this.BeforeOpenData.VolMin, this.AfterCloseData.VolMin); this.BeforeOpenData.VolMax=this.AfterCloseData.VolMax=max; this.BeforeOpenData.VolMin=this.AfterCloseData.VolMin=min; } } var yClose=data.stock[0].yclose; var upperSymbol=this.Symbol.toUpperCase(); var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); if (data.stock[0].yclearing>0 && isFutures) yClose=data.stock[0].yclearing; //期货使用前结算价 this.CaclutateLimitPrice(yClose, data.stock[0].limitprice); //计算涨停价格 var extendData=null; if (data.stock[0].high>0 && data.stock[0].low>0) extendData={ High:data.stock[0].high, Low:data.stock[0].low }; this.BindMainData(sourceData,yClose, extendData); if (this.Frame.SubFrame.length>2) { var bindData=new ChartData(); bindData.Data=aryMinuteData; for(var i=2; 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.RequestSingleOverlayMinuteData=function(symbol, date, item) { var self = this; item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID; if (this.NetworkFilter) { var obj= { Name:'MinuteChartContainer::RequestOverlayMinuteData', //类名::函数名 Explain:'叠加股票最新分时数据', Request:{ Url:this.HistoryMinuteApiUrl, Data:{days:[date], symbol:symbol}, Type:'POST' }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID; self.RecvOverlayMinuteData(data,item); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } //请求数据 JSNetwork.HttpRequest({ url: this.HistoryMinuteApiUrl, data: { "symbol":symbol, "days": [date], }, type:"post", dataType: "json", async:true, success: function (data) { item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID; //self.RecvMultiOverlayMinuteData([data]); self.RecvOverlayMinuteData(data,item); } }); } //请求叠加数据 (主数据下载完再下载)) this.RequestOverlayMinuteData=function() { var self = this; var date=this.TradeDate; //最后一个交易日期 for(var i=0; i1) //多日数据 { if (aryMinuteData.length<=0) return; var minuteData=aryMinuteData[0]; for(var i in paint.SourceData) { var item=paint.SourceData[i]; if (item.Date==minuteData.Date) { paint.SourceData[i]=minuteData; var allMinuteData=this.HistoryMinuteDataToArray(paint.SourceData); 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.RequestSingleOverlayHistoryMinuteData=function(symbol, days, item) { var self = this; item.Status=OVERLAY_STATUS_ID.STATUS_REQUESTDATA_ID; if (this.NetworkFilter) { var obj= { Name:'MinuteChartContainer::RequestOverlayHistoryMinuteData', //类名::函数名 Explain:'叠加股票多日分时数据', Request:{ Url:self.HistoryMinuteApiUrl, Data:{days:days, symbol:symbol}, Type:'POST' }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID; self.RecvOverlayHistoryMinuteData(data,item); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.HistoryMinuteApiUrl, data:{ "symbol": symbol, "days": days }, type:"post", dataType: "json", async:true, success: function (data) { item.Status=OVERLAY_STATUS_ID.STATUS_RECVDATA_ID; self.RecvOverlayHistoryMinuteData(data,item); } }); } 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.OverlayIdentify=overlayFrame.Identify; var chart=new ChartMinutePositionLine(); chart.Canvas=this.Canvas chart.Name='Position-Line'; chart.ChartBorder=frame.ChartBorder; chart.ChartFrame=frame chart.Identify=overlayFrame.Identify; chart.Color=g_JSChartResource.Minute.PositionColor; overlayFrame.ChartPaint.push(chart); subFrame.OverlayIndex.push(overlayFrame); subFrame.Frame.RightFrame=frame; //右边坐标绑定到主坐标上 } else { frame=overlayFrame.Frame; 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) { 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.BindAllOverlayIndexData=function(hisData, option) { if (!this.Frame || !this.Frame.SubFrame) return; //叠加指标 for(var i=0;i0) return; this.ClickModel.IsShowCorssCursor=false; this.DrawDynamicInfo(); return; } if (this.CorssCursorTouchEnd===true) //手势离开十字光标消失 { this.DrawDynamicInfo(); return; } /* 以后放日线的tooltip for(var i in this.ExtendChartPaint) { var item=this.ExtendChartPaint[i]; if (item.ClassName==='KLineTooltipPaint') { this.DrawDynamicInfo(); } } */ } 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; case "MinutePCTooltip": if (option.Create && typeof(option.Create)=="function") chart=option.Create(); else chart=new MinuteLeftTooltipPaint(); 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; case "MinuteBackgroundPaint": chart=new MinuteBackgroundPaint(); 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.HQChartBorder=this.Frame.ChartBorder; 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.RecvWindowIndex=function(index, data) { var indexItem=this.WindowIndex[index]; if (!indexItem) return; if (typeof(indexItem.RecvSubscribeData)=="function") { var bindData=this.SourceData; indexItem.RecvSubscribeData(data,this,index,bindData); } } this.UpdateWindowIndex=function(index) { if (index<2) return; var bindData=this.SourceData; this.BindIndexData(index,bindData) this.UpdataDataoffset(); //更新数据偏移 this.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.Draw(); } this.CreateChartDrawPicture=function(name, option, callback) { var drawPicture=null; var item=IChartDrawPicture.GetDrawPictureByName(name); if (item) { drawPicture=item.Create(); if (drawPicture.ClassName=='ChartDrawPictureText') drawPicture.HQChart=this; } if (!drawPicture) //iconfont图标 { if (IChartDrawPicture.MapIonFont.has(name)) { var iconItem=IChartDrawPicture.MapIonFont.get(name); drawPicture=new ChartDrawPictureIconFont(); drawPicture.FontOption.Family=iconItem.Family drawPicture.Text=iconItem.Text; if (iconItem.Color) drawPicture.LineColor=iconItem.Color; } } if (!drawPicture) return false; drawPicture.Canvas=this.Canvas; drawPicture.Status=0; drawPicture.Symbol=this.Symbol; drawPicture.Period=888888888; drawPicture.Option=this.ChartDrawOption; if (callback) drawPicture.FinishedCallback=callback; //完成通知上层回调 if (option) drawPicture.SetOption(option); var self=this; drawPicture.Update=function() //更新回调函数 { self.DrawDynamicInfo(); }; drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); } this.CurrentChartDrawPicture=drawPicture; JSConsole.Chart.Log("[MinuteChartContainer::CreateChartDrawPicture] ", name,this.CurrentChartDrawPicture); return true; } //手动添加画线 this.AddChartDrawPicture=function(obj) { if (!obj) return null; if (obj.FrameID<0 || obj.FrameID>=this.Frame.SubFrame.length) return null; var self=this; var item=IChartDrawPicture.GetDrawPictureByClassName(obj.ClassName); if (!item) return null; var drawPicture=item.Create(); drawPicture.Canvas=this.Canvas; drawPicture.Status=10; drawPicture.Frame=this.Frame.SubFrame[obj.FrameID].Frame; //绑定框架坐标 drawPicture.Symbol=this.Symbol; drawPicture.Period=888888888; if (obj.Value) drawPicture.Value=obj.Value; if (obj.Guid) drawPicture.Guid=obj.Guid; if (drawPicture.ImportStorageData) drawPicture.ImportStorageData(obj); drawPicture.SetOption(obj); if (obj.EnableUpdateXValue) drawPicture.UpdateXValue(); drawPicture.ValueToPoint(); drawPicture.GetActiveDrawPicture=function() { return self.GetActiveDrawPicture(); } if (drawPicture.ClassName==='ChartDrawPictureText') drawPicture.IsInitialized=true; this.ChartDrawPicture.push(drawPicture); if (obj.Draw==true) this.DrawDynamicInfo(); return drawPicture; } this.ReloadChartDrawPicture=function() { this.ChartDrawPicture=[]; if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.IsSelected=false; this.SelectChartDrawPicture=null; this.CurrentChartDrawPicture=null; this.MoveOnChartDrawPicture=null; if (this.ChartDrawStorage) { this.ChartDrawStorageCache=this.ChartDrawStorage.GetDrawData( { Symbol:this.Symbol, Period:888888888 } ); } } this.CreateChartDrawPictureByStorage=function() //把缓存(this.ChartDrawStorageCache) 画图工具创建出来 { if (!this.ChartDrawStorageCache || this.ChartDrawStorageCache.length<=0) return; var self=this; for(var i=0; i{ return this.GetActiveDrawPicture(); } if (drawPicture.ClassName==='ChartDrawPictureText') drawPicture.IsInitialized=true; this.ChartDrawPicture.push(drawPicture); } this.ChartDrawStorageCache=null; //清空缓存 } this.SetSizeChange=function(bChanged) { this.Frame.SetSizeChage(bChanged); for(var i in this.ExtendChartPaint) { var item=this.ExtendChartPaint[i]; item.SizeChange=bChanged; } } this.SetSizeChage=this.SetSizeChange; //根据X坐标获取数据索引 this.GetDataIndexByPoint=function(x) { var frame=this.Frame; if (this.Frame.SubFrame && this.Frame.SubFrame.length>0) frame=this.Frame.SubFrame[0].Frame; if (!frame) return; var value=frame.GetXData(x); var index=parseInt(value.toFixed(0)); return index; } //不支持未来时间 目前只支持主图 this.GetDateTimeByPoint=function(x,y) { var clientPos=this.PtInClient_V2(x,y); // 100-199=多日分时主图 200-299=盘前 300-399=盘后 1=主图 2=盘前 3=盘后 if (clientPos<=0) return null; if (!this.Frame.SubFrame[0] || !this.Frame.SubFrame[0].Frame) return null; var frame=this.Frame.SubFrame[0].Frame; var data=this.Frame.SourceData; if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) return null; var index=-1; var result={ ClientPos:clientPos }; if (clientPos==1) { var value=frame.GetXData(x); index=parseInt(value.toFixed(0)); if (IFrameSplitOperator.IsNumber(data.DataOffset)) index+=data.DataOffset; //加上数据偏移 } else if (clientPos>=100 && clientPos<=199) { var dayIndex=clientPos-100; var value=frame.GetXData(x); index=parseInt(value.toFixed(0)); var dataIndex=index%frame.MinuteCount; result.DayIndex=dayIndex; result.DataIndex=dataIndex; } else { return null; } if (index<0 || index>=data.Data.length) return null; result.Index=index; var item=data.Data[index]; if (!item) return null; result.Date=item.Date; result.Time=item.Time; return result; } //获取主数据 this.GetSelectRectData=function(selectData) { if (Math.abs(selectData.XStart-selectData.XEnd)<5) return false; var startClientPos=this.PtInClient(selectData.XStart, selectData.YStart); var endClientPos=this.PtInClient(selectData.XEnd, selectData.YEnd); selectData.StartClientPos=startClientPos; selectData.EndClientPos=endClientPos; var data=this.SourceData; if (!data) return false; if (!IFrameSplitOperator.IsNonEmptyArray(data.Data)) return false; var start=this.GetDataIndexByPoint(selectData.XStart); var end=this.GetDataIndexByPoint(selectData.XEnd); if (Math.abs(start-end)<2) return false; selectData.Data=data; var offset=data.DataOffset; start+=offset; end+=offset; if (start>end) { selectData.Start=end; selectData.End=start; } else { selectData.Start=start; selectData.End=end; } var count=data.Data.length; if (selectData.End>=count) selectData.End=count-1; return true; } this.Super_UpdateFrameMaxMin=this.UpdateFrameMaxMin; this.UpdateFrameMaxMin=function() { this.Super_UpdateFrameMaxMin(); if (this.DayCount==1) //集合竞价多坐标,Y轴强制都计算 { var subFrame=this.Frame.SubFrame[1]; if (subFrame.Frame) subFrame.Frame.XYSplit=true; } } this.ExportMainData=function(data, option) { var aryData=data.ExportMinuteData(option); //导出K线 return aryData; } this.DisplayLatest=function() { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DISPLAY_LATEST); //选中画图工具事件 if (event) { var sendData={ PreventDefault:false }; event.Callback(event,sendData,this); if (sendData.PreventDefault) return; } this.CursorIndex=null; this.LastPoint.X=0; this.LastPoint.Y=0; this.GlobalOption.IsDisplayLatest=true; this.DrawDynamicInfo(); } this.TryClickIndexTitle=function(x,y) { for(var i=0; irtClient.Left && xrtClient.Top && y=rtDay.Left && x<=rtDay.Right) { var dayItem=this.DayData[this.DayData.length-1-i]; if (!dayItem) return null; return dayItem.Date; } } } else { var mainFrame=this.Frame.SubFrame[0].Frame; //主图框架 var xPointCount=mainFrame.XPointCount; var minuteCount=mainFrame.MinuteCount; var lDayCount=xPointCount/minuteCount; var dayWidth=rtClient.Width/lDayCount; var rtDay={ Left:rtClient.Left, Right:dayWidth+rtClient.Left }; for(var i=0;i=rtDay.Left && x<=rtDay.Right) { var dayItem=this.DayData[this.DayData.length-1-i]; if (!dayItem) return null; return dayItem.Date; } rtDay.Left+=dayWidth; rtDay.Right+=dayWidth; } } return null; } this.DrawTooltipDialog=function() { if (!this.DialogTooltip) return; this.UpdateTooltipDialog(); } this.UpdateTooltipDialog=function() { if (!this.DialogTooltip) return false; if (!this.ChartCorssCursor) return false; var minuteItem=null; //{ Type:0=连续交易 1=集合竞价, Data:数据 } var dataType=0; //0=全部更新 2=分时实时数据更新 if (this.ChartCorssCursor.ClientPos>=0) { var titlePaint=this.TitlePaint[0]; if (titlePaint && titlePaint.PointInfo) { var pointInfo=titlePaint.PointInfo; if ((pointInfo.ClientPos==2 || pointInfo.ClientPos==3 || (pointInfo.ClientPos>=200&& pointInfo.ClientPos<=299) || (pointInfo.ClientPos>=300&& pointInfo.ClientPos<=399))) { var auctionData=titlePaint.GetCurrentAuctionData(); if (!auctionData) return false; minuteItem={ Type:1, Data:auctionData }; } else { var minuteData=titlePaint.GetCurrentKLineData(); if (!minuteData) return false; minuteItem={ Type:0, Data:minuteData }; } } } else //实时数据更新 { if (!this.SourceData || !IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) return false; var minuteData=this.SourceData.Data[this.SourceData.Data.length-1]; var dataID={ Symbol:this.Symbol, Date:minuteData.Date, Time:minuteData.Time }; if (!this.DialogTooltip.IsEqualDataID(dataID)) return false; minuteItem={ Type:0, Data:minuteData }; dataType=2; } var sendData= { DataType:dataType, ClientPos:this.ChartCorssCursor.ClientPos, //位置 IsShowCorss:this.ChartCorssCursor.IsShowCorss, //是否显示十字线 MinItem:minuteItem, Symbol:this.Symbol, Name:this.Name, LastValue:this.ChartCorssCursor.LastValue, }; this.DialogTooltip.Update(sendData); return true; } this.DrawSelectRectDialog=function(e) { if (!this.DialogSelectRect) return; this.UpdateSelectRectDialog(e); } this.UpdateSelectRectDialog=function(e) { if (!this.DialogSelectRect) return false; var data=e.data; //区间统计数据 var x,y; if (data && IFrameSplitOperator.IsNumber(data.X) && IFrameSplitOperator.IsNumber(data.Y)) { var pixelRatio=GetDevicePixelRatio(); var rtClient=this.UIElement.getBoundingClientRect(); var rtScroll=GetScrollPosition(); x=data.X y=data.Y; x+=(rtClient.left+rtScroll.Left); y+=(rtClient.top+rtScroll.Top); } var sendData= { Symbol:this.Symbol, Name:this.Name, SelectData:data.SelectData, X:x, Y:y, e:e } this.DialogSelectRect.Update(sendData); } } //盘前数据 MinuteChartContainer.JsonDataToBeforeOpenData=function(data) { var symbol=data.stock[0].symbol; var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var yClose=data.stock[0].yclose; var preClose=data.stock[0].yclose; //前一个数据价格 var stockData=data.stock[0]; var date=stockData.date; //日期 var beforeOpenData={ Data:[], TotalCount:15, Ver:1.0, Date:date }; var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_BEFOREOPEN_EXTENDDATA; //扩展数据序号 if (stockData.beforeinfo) { if (IFrameSplitOperator.IsNumber(stockData.beforeinfo.totalcount)) beforeOpenData.TotalCount=stockData.beforeinfo.totalcount; if (IFrameSplitOperator.IsNumber(stockData.beforeinfo.ver)) beforeOpenData.Ver=stockData.beforeinfo.ver; } if (beforeOpenData.Ver==1.0) { if (IFrameSplitOperator.IsNonEmptyArray(stockData.before)) { for(var i=0; i19000101) //日期 item.Date=jsData[4]; item.DateTime=`${item.Date} ${item.Time}`; beforeOpenData.Data.push(item); } } } else if (beforeOpenData.Ver==2.0) { var max=0; for(var i in stockData.before) { var item=new BeforeOpenData(); var jsData=stockData.before[i]; item.YClose=yClose; item.Time=jsData[0]; item.Date=date; item.Price=jsData[1]; item.Vol[0]=jsData[2]; //匹配量 item.Vol[1]=jsData[3]; //未匹配量 item.ColorID=jsData[4]; //柱子颜色ID if (IFrameSplitOperator.IsNumber(jsData[6])) item.Date=jsData[6] //日期 item.DateTime=`${item.Date} ${item.Time})`; var totalVol=item.Vol[0]+item.Vol[1]; if (IFrameSplitOperator.IsNumber(jsData[5])) totalVol=jsData[5]; if (totalVol>max) max=totalVol; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; beforeOpenData.Data.push(item); } beforeOpenData.VolMax=max; beforeOpenData.VolMin=0; } else if (beforeOpenData.Ver==3.0) { var max=0; for(var i in stockData.before) { var item=new BeforeOpenData(); var jsData=stockData.before[i]; item.YClose=yClose; item.Time=jsData[0]; item.Date=date; item.Price=jsData[1]; item.AvPrice=jsData[2]; //均价 item.Vol[0]=jsData[3]; //匹配量 item.ColorID=jsData[4]; //柱子颜色ID item.DateTime=date.toString()+" "+item.Time.toString(); var totalVol=item.Vol[0]; if (IFrameSplitOperator.IsNumber(jsData[5])) totalVol=jsData[5]; if (totalVol>max) max=totalVol; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; beforeOpenData.Data.push(item); } beforeOpenData.VolMax=max; beforeOpenData.VolMin=0; } return beforeOpenData; } //收盘集合竞价 MinuteChartContainer.JsonDataToAfterCloseData=function(data) { var yClose=data.stock[0].yclose; var preClose=data.stock[0].yclose; //前一个数据价格 var stockData=data.stock[0]; var date=stockData.date; //日期 if (!stockData.afterinfo) return null; var afterCloseData={ Data:[], TotalCount:3*60, Ver:2.0, Date:date }; var item=stockData.afterinfo; if (IFrameSplitOperator.IsNumber(item.totalcount)) afterCloseData.TotalCount=item.totalcount; if (IFrameSplitOperator.IsNumber(item.ver)) afterCloseData.Ver=item.ver; var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_AFTERCLOSE_EXTENDDATA; //扩展数据序号 if (afterCloseData.Ver==1.0) { for(var i=0; imax) max=totalVol; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; afterCloseData.Data.push(item); } afterCloseData.VolMax=max; afterCloseData.VolMin=0; } else if (afterCloseData.Ver==3.0) { var max=0; for(var i in stockData.after) { var item=new AfterCloseData(); var jsData=stockData.after[i]; item.YClose=yClose; item.Time=jsData[0]; item.Date=date; item.Price=jsData[1]; item.AvPrice=jsData[2]; //均价 item.Vol[0]=jsData[3]; //匹配量 item.ColorID=jsData[4]; //柱子颜色ID item.DateTime=date.toString()+" "+item.Time.toString(); var totalVol=item.Vol[0]; if (IFrameSplitOperator.IsNumber(jsData[5])) totalVol=jsData[5]; if (totalVol>max) max=totalVol; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; afterCloseData.Data.push(item); } afterCloseData.VolMax=max; afterCloseData.VolMin=0; } return afterCloseData; } //API 返回数据 转化为array[] MinuteChartContainer.JsonDataToMinuteData=function(data,isBeforeData) { 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 isSHO=MARKET_SUFFIX_NAME.IsSHO(upperSymbol); //上海股票期权 var isSZO=MARKET_SUFFIX_NAME.IsSZO(upperSymbol); //深证股票期权 var aryMinuteData=[]; var preClose=data.stock[0].yclose; //前一个数据价格 var preAvPrice=data.stock[0].yclose; //前一个均价 var yClose=data.stock[0].yclose; var yClearing=data.stock[0].yclearing; if (isFutures && yClearing) preClose=preAvPrice=yClearing; //期货使用昨结算价 if (!IFrameSplitOperator.IsNonEmptyArray(data.stock[0].minute)) return aryMinuteData; var date=data.stock[0].date; //默认使用外部日期, 但跨天的 走势图使用内部的日期 for(var i=0; i0) 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; //期货 期权有持仓 else if (IFrameSplitOperator.IsNumber(jsData.position)) item.Position=jsData.position; item.Increase=jsData.increase; item.Risefall=jsData.risefall; item.AvPrice=jsData.avprice; if (IFrameSplitOperator.IsNumber(jsData.lead)) item.Lead=jsData.lead; //领先指标 指数才有 if (!IFrameSplitOperator.IsNumber(item.Close)) //当前没有价格 使用上一个价格填充 { item.Close=preClose; item.Open=item.High=item.Low=item.Close; } if (!item.AvPrice) item.AvPrice=preAvPrice; 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 (IFrameSplitOperator.IsNumber(jsData.price)) preClose=jsData.price; if (IFrameSplitOperator.IsNumber(jsData.avprice) && item.AvPrice===jsData.avprice) preAvPrice=jsData.avprice; if (jsData.ExtendData) item.ExtendData=jsData.ExtendData; //扩展数据 aryMinuteData[i]=item; } return aryMinuteData; } //分钟增量数据 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.IsNonEmptyArray(stock.minute)) { for(var i=0;i=item.end) continue; var newItem={ Type:item.type, Date:item.date, Start:item.start, End:item.end, Color:item.color }; if (IFrameSplitOperator.IsPlusNumber(item.linewidth)) newItem.LineWidth=item.linewidth; aryLineColor.push(newItem); } return aryLineColor; } //获取最后的数据更新时间 MinuteChartContainer.JsonDataToMinuteLastUpdateTime=function(data) { if (!data || !data.stock[0]) return null; var stock=data.stock[0]; if (!IFrameSplitOperator.IsNumber(stock.date) || !IFrameSplitOperator.IsNumber(stock.time)) return null; return { Date:stock.date, Time:stock.time }; } MinuteChartContainer.JsonDataToHistoryMinuteLastUpdateTime=function(data) { if (!data || !data.updatetime) return null; var item=data.updatetime; if (!IFrameSplitOperator.IsNumber(item.date) || !IFrameSplitOperator.IsNumber(item.time)) return null; return { Date:item.date, Time:item.time }; } //多日日线数据API 转化成array[]; MinuteChartContainer.JsonDataToMinuteDataArray=function(data) { var symbol=data.symbol; var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var isSHO=MARKET_SUFFIX_NAME.IsSHO(upperSymbol); //上海股票期权 var isSZO=MARKET_SUFFIX_NAME.IsSZO(upperSymbol); //深证股票期权 var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); //国内期货, 纽约期货交易所 var result=[]; var extendDataIndex=JSCHART_DATA_FIELD_ID.MINUTE_MULTI_DAY_EXTENDDATA; //扩展数据序号 for(var i in data.data) { var minuteData=[]; var dayData=data.data[i]; var date=dayData.date; var yClearing=dayData.yclearing; //昨结算价 var yClose=dayData.yclose; //前收盘 计算涨幅 var preClose=yClose; //前一个数据价格 var preAvPrice=null; //上一个均价 if (isFutures && yClearing) preClose=preAvPrice=yClearing; //期货使用昨结算价 for(var j in dayData.minute) { var jsData=dayData.minute[j]; if (jsData[2]) preClose=jsData[2]; //保存上一个收盘数据 var item=new MinuteData(); item.YClearing=yClearing; item.YClose=yClose; item.Close=jsData[2]; item.Open=jsData[1]; item.High=jsData[3]; item.Low=jsData[4]; item.Increase=null; if (isSHSZ) item.Vol=jsData[5]/100; //原始单位股 else item.Vol=jsData[5]; item.Amount=jsData[6]; if (70) item.AvPrice=jsData[7]; //均价 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) && 97 && jsData[7]>0 && item.AvPrice===jsData[7]) preAvPrice=jsData[7]; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; minuteData[j]=item; } var newData=new ChartData(); newData.Data=minuteData; newData.YClose=yClose; if (IFrameSplitOperator.IsNumber(yClearing)) newData.YClearing=yClearing; newData.Close=dayData.close; newData.Date=date; result.push(newData); } return result; } MinuteChartContainer.JsonDataToHistoryMinuteLineColorData=function(data) { if (!data) return null; var aryLineColor=[]; for(var i in data.data) { var dayData=data.data[i]; if (!dayData.linecolor) continue; for(var j in dayData.linecolor.data) { var item=dayData.linecolor.data[j]; if (!IFrameSplitOperator.IsNumber(item.type) || !IFrameSplitOperator.IsNumber(item.date) || !IFrameSplitOperator.IsNumber(item.start) || !IFrameSplitOperator.IsNumber(item.end) || !item.color) continue; if (item.start>=item.end) continue; var newItem={ Type:item.type, Date:item.date, Start:item.start, End:item.end, Color:item.color }; if (IFrameSplitOperator.IsPlusNumber(item.linewidth)) newItem.LineWidth=item.linewidth; aryLineColor.push(newItem); } } return aryLineColor.length>0? aryLineColor : null; } MinuteChartContainer.JsonDataToCallAuctionItem=function(data, callAuctionData, isBeforeOpen, symbol) { var isSHSZ=false; if (symbol) { var upperSymbol=symbol.toUpperCase(); isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); } var date=callAuctionData.Date; var yClose=callAuctionData.YClose; var yClearing=callAuctionData.YClearing; var extendDataIndex=isBeforeOpen? JSCHART_DATA_FIELD_ID.MINUTE_BEFOREOPEN_EXTENDDATA:JSCHART_DATA_FIELD_ID.MINUTE_AFTERCLOSE_EXTENDDATA; //扩展数据序号 if (callAuctionData.Ver==1.0) { var preClose=null; for(var i in data) { var item=isBeforeOpen? new BeforeOpenData() : new AfterCloseData(); var jsData=data[i]; item.YClose=yClose; item.YClearing=yClearing; item.Time=jsData[0]; item.Date=date; item.Price=jsData[1]; if (!item.Price) item.Price=preClose; else preClose=item.Price; item.Vol[0]=isSHSZ ? jsData[2]/100 : jsData[2]; //沪深股票原始单位股 item.Amount=jsData[3]; if (IFrameSplitOperator.IsNumber(jsData[4])) //日期 item.Date=jsData[4]; item.DateTime=`${item.Date} ${item.Time}`; callAuctionData.Data.push(item); } } else if (callAuctionData.Ver==2.0) { var max=0; for(var i in data) { var item=isBeforeOpen? new BeforeOpenData() : new AfterCloseData(); var jsData=data[i]; item.YClose=yClose; item.YClearing=yClearing; item.Time=jsData[0]; item.Date=date; item.Price=jsData[1]; item.Vol[0]=jsData[2]; //匹配量 item.Vol[1]=jsData[3]; //未匹配量 item.ColorID=jsData[4]; //柱子颜色ID item.DateTime=date.toString()+" "+item.Time.toString(); var totalVol=item.Vol[0]+item.Vol[1]; if (IFrameSplitOperator.IsNumber(jsData[5])) totalVol=jsData[5]; if (totalVol>max) max=totalVol; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; callAuctionData.Data.push(item); } callAuctionData.VolMax=max; callAuctionData.VolMin=0; } else if (beforeOpenData.Ver==3.0) { var max=0; for(var i in data) { var item=isBeforeOpen? new BeforeOpenData() : new AfterCloseData(); var jsData=data[i]; item.YClose=yClose; item.YClearing=yClearing; item.Time=jsData[0]; item.Date=date; item.Price=jsData[1]; item.AvPrice=jsData[2]; //均价 item.Vol[0]=jsData[3]; //匹配量 item.ColorID=jsData[4]; //柱子颜色ID item.DateTime=date.toString()+" "+item.Time.toString(); var totalVol=item.Vol[0]; if (IFrameSplitOperator.IsNumber(jsData[5])) totalVol=jsData[5]; if (totalVol>max) max=totalVol; if (jsData[extendDataIndex]) item.ExtendData=jsData[extendDataIndex]; callAuctionData.Data.push(item); } callAuctionData.VolMax=max; callAuctionData.VolMin=0; } } MinuteChartContainer.JosnDataToBeforeOpenDataArray=function(data) { if (!data || !data.data) return null; var aryDay=[]; for(var i in data.data) { var dayItem=data.data[i]; var beforeOpenData={ Data:[], TotalCount:15, Ver:1.0, Date:dayItem.date, YClose:dayItem.yclose, YClearing:dayItem.YClearing }; if (dayItem.beforeinfo) { if (IFrameSplitOperator.IsNumber(dayItem.beforeinfo.totalcount)) beforeOpenData.TotalCount=dayItem.beforeinfo.totalcount; if (IFrameSplitOperator.IsNumber(dayItem.beforeinfo.ver)) beforeOpenData.Ver=dayItem.beforeinfo.ver; } MinuteChartContainer.JsonDataToCallAuctionItem(dayItem.before, beforeOpenData, true, data.symbol); aryDay.push(beforeOpenData); } aryDay.sort((left, right)=>{return left.Date - right.Date}); return aryDay; } MinuteChartContainer.JosnDataToAfterCloseDataArray=function(data) { if (!data || !data.data) return null; var aryDay=[]; for(var i in data.data) { var dayItem=data.data[i]; var afterCloseData={ Data:[], TotalCount:15, Ver:1.0, Date:dayItem.date, YClose:dayItem.yclose, YClearing:dayItem.YClearing }; if (dayItem.afterinfo) { if (IFrameSplitOperator.IsNumber(dayItem.afterinfo.totalcount)) afterCloseData.TotalCount=dayItem.afterinfo.totalcount; if (IFrameSplitOperator.IsNumber(dayItem.afterinfo.ver)) afterCloseData.Ver=dayItem.afterinfo.ver; } MinuteChartContainer.JsonDataToCallAuctionItem(dayItem.after, afterCloseData, false, data.symbol); aryDay.push(afterCloseData); } aryDay.sort((left, right)=>{return left.Date - right.Date}); return aryDay; } /* 历史分钟走势图 */ /* 废弃 统一使用 MinuteChartContainer function HistoryMinuteChartContainer(uielement) { this.newMethod=MinuteChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.HistoryMinuteApiUrl="http://127.0.0.1:8080/cache/minuteday/day/"; this.ClassName='HistoryMinuteChartContainer'; //创建主图K线画法 this.CreateMainKLine=function() { //分钟线 var minuteLine=new ChartMinutePriceLine(); minuteLine.Canvas=this.Canvas; minuteLine.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder; minuteLine.ChartFrame=this.Frame.SubFrame[0].Frame; minuteLine.Name="Minute-Line"; minuteLine.Color=g_JSChartResource.Minute.PriceColor; this.ChartPaint[0]=minuteLine; //分钟线均线 var averageLine=new ChartLine(); averageLine.Canvas=this.Canvas; averageLine.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder; averageLine.ChartFrame=this.Frame.SubFrame[0].Frame; averageLine.Name="Minute-Average-Line"; averageLine.Color=g_JSChartResource.Minute.AvPriceColor; this.ChartPaint[1]=averageLine; var averageLine=new ChartMinuteVolumBar(); averageLine.Color=g_JSChartResource.Minute.VolBarColor; averageLine.Canvas=this.Canvas; averageLine.ChartBorder=this.Frame.SubFrame[1].Frame.ChartBorder; averageLine.ChartFrame=this.Frame.SubFrame[1].Frame; averageLine.Name="Minute-Vol-Bar"; this.ChartPaint[2]=averageLine; this.TitlePaint[0]=new DynamicMinuteTitlePainting(); this.TitlePaint[0].Frame=this.Frame.SubFrame[0].Frame; this.TitlePaint[0].Canvas=this.Canvas; this.TitlePaint[0].IsShowDate=true; } //设置交易日期 this.ChangeTradeDate=function(trdateDate) { if (!trdateDate) return; this.TradeDate=trdateDate; this.RequestData(); //更新数据 } this.RequestData=function() { var date=new Date(); var nowDate=date.getFullYear()*10000+(date.getMonth()+1)*100+date.getDate(); if (nowDate==this.TradeDate) this.RequestMinuteData(); else this.RequestHistoryMinuteData(); } //请求分钟数据 this.RequestHistoryMinuteData=function() { var self=this; var url=this.HistoryMinuteApiUrl+this.TradeDate.toString()+"/"+this.Symbol+".json"; JSNetwork.HttpRequest({ url: url, type:"get", dataType: "json", async:true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvHistoryMinuteData(data); }, error:function(reqeust) { self.ChartSplashPaint.EnableSplash(false); self.RecvHistoryMinuteError(reqeust); } }); } this.RecvHistoryMinuteError=function(reqeust) { if (reqeust.status!=404) return; var sourceData=new ChartData(); this.SourceData=sourceData; for(var i in this.ChartPaint) { this.ChartPaint[i].Data=sourceData; if (i==0) this.ChartPaint[i].NotSupportMessage='没有权限访问!'; } this.TitlePaint[0].Data=this.SourceData; //动态标题 this.TitlePaint[0].Symbol=this.Symbol; this.TitlePaint[0].Name=null; this.Draw(); } this.RecvHistoryMinuteData=function(data) { var aryMinuteData=HistoryMinuteChartContainer.JsonDataToMinuteData(data); //原始数据 var sourceData=new ChartData(); sourceData.Data=aryMinuteData; this.TradeDate=data.date; this.SourceData=sourceData; this.Symbol=data.symbol; this.Name=data.name; this.BindMainData(sourceData,data.day.yclose); if (this.Frame.SubFrame.length>2) { var bindData=new ChartData(); bindData.Data=aryMinuteData; for(var i=2; i0) //当前这一分钟价格为空,使用上一分钟的数据 { 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]; //原始单位股 item.Amount=data.minute.amount[i]; item.DateTime=data.date.toString()+" "+data.minute.time[i].toString(); //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]; //原始单位股 item.Amount=data.minute.amount[i]; item.DateTime=data.date.toString()+" "+data.minute.time[i].toString(); //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.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 } }, type:"post", dataType: "json", async:true, success: function (data) { self.ChartSplashPaint.EnableSplash(false); self.RecvHistoryData(data); } }); } this.RecvHistoryData=function(data) { var aryDayData=KLineChartContainer.JsonDataToHistoryData(data); //原始数据 var sourceData=new ChartData(); sourceData.Data=aryDayData; sourceData.DataType=0; //0=日线数据 1=分钟数据 //显示的数据 var bindData=new ChartData(); bindData.Data=aryDayData; bindData.Right=this.Right; bindData.Period=this.Period; bindData.DataType=0; if (bindData.Right>0) //复权 { var rightData=bindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); bindData.Data=rightData; } 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.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-lEnd1) step=option.Step; var moveStep=0; for(var i=0; i=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; if (option && option.PageSize>0) this.PageSize=option.PageSize; 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() { JSConsole.Chart.Log('[KLineTrainChartContainer::FinishTrainData] trian end '); } 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); } this.RecvFlowCapitalData=function(data) { if (!data.stock || data.stock.length!=1) return; let stock=data.stock[0]; var aryData=new Array(); for(let i in stock.stockday) { var item=stock.stockday[i]; let indexData=new SingleData(); indexData.Date=item.date; var financeData=item.capital; if (!financeData) continue; if (financeData.a>0) { indexData.Value=financeData.a; //流通股本(股) aryData.push(indexData); } } if (ChartData.IsMinutePeriod(this.Period,true)) //分钟数据 { var aryFixedData=this.SourceData.GetMinuteFittingFinanceData(aryData); for(let i in this.SourceData.Data) { var item=this.SourceData.Data[i]; if (!aryFixedData[i]) continue; item.FlowCapital=aryFixedData[i].Value; } var bindData=this.ChartPaint[0].Data; var newBindData=new ChartData(); newBindData.Data=this.SourceData.Data; if (ChartData.IsMinutePeriod(bindData.Period,false)) //周期数据 { var periodData=newBindData.GetPeriodData(bindData.Period); newBindData.Data=periodData; } bindData.Data=newBindData.Data; var aryFixedData=this.KLineSourceData.GetMinuteFittingFinanceData(aryData); //数据添加到备份数据中 for(let i in this.KLineSourceData.Data) { var item=this.KLineSourceData.Data[i]; if (!aryFixedData[i]) continue; item.FlowCapital=aryFixedData[i].Value; } } else { var aryFixedData=this.SourceData.GetFittingFinanceData(aryData); for(let i in this.SourceData.Data) { var item=this.SourceData.Data[i]; if (!aryFixedData[i]) continue; item.FlowCapital=aryFixedData[i].Value; } var bindData=this.ChartPaint[0].Data; var newBindData=new ChartData(); newBindData.Data=this.SourceData.Data; if (bindData.Right>0) //复权 { var rightData=newBindData.GetRightData(bindData.Right, { AlgorithmType: this.RightFormula }); newBindData.Data=rightData; } if (ChartData.IsDayPeriod(bindData.Period,false)) //周期数据 { var periodData=newBindData.GetPeriodData(bindData.Period); newBindData.Data=periodData; } bindData.Data=newBindData.Data; var aryFixedData=this.KLineSourceData.GetFittingFinanceData(aryData); //数据添加到备份数据中 for(let i in this.KLineSourceData.Data) { var item=this.KLineSourceData.Data[i]; if (!aryFixedData[i]) continue; item.FlowCapital=aryFixedData[i].Value; } } this.FlowCapitalReady=true; var bDraw=false; for(var i in this.ExtendChartPaint) { var item=this.ExtendChartPaint[i]; if (item.ClassName=='StockChip') { bDraw=true; break; } } if (bDraw) this.Draw(); } this.AutoUpdate() { } } 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) { var oneStepWidth=this.GetMoveOneStepWidth(); var moveStep=step; step=parseInt(step/oneStepWidth); //除以4个像素 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 (this.Frame.SubFrame && this.Frame.SubFrame.length>0 && this.Frame.SubFrame[0].Frame) { var fristFrame=this.Frame.SubFrame[0].Frame; if (fristFrame.DataWidth<=1 || fristFrame.DistanceWidth<=1) //K线在缩放很小的时候 移动加速 { if (IFrameSplitOperator.IsPlusNumber(this.StepPixel)) step=moveStep*this.StepPixel; } } 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.DataMoveRight=function() { 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; var end=this.TrainInfo.End.Index+1; if (xPointcount+data.DataOffset>=end) return false; ++data.DataOffset; return true; } } //////////////////////////////////////////////////////////////////////////////// // K线横屏显示 // function KLineChartHScreenContainer(uielement) { this.newMethod=KLineChartContainer; //派生 this.newMethod(uielement); delete this.newMethod; this.ClassName='KLineChartHScreenContainer'; this.OnMouseMove=function(x,y,e,isPhone) { this.LastPoint.X=x; this.LastPoint.Y=y; this.CursorIndex=this.Frame.GetXData(y); var option={ ParentFunction:'OnMouseMove', Point:{X:x, Y:y}, IsPhone:isPhone===true }; this.DrawDynamicInfo(option); } uielement.onmousedown=function(e) //鼠标拖拽 { if(!this.JSChartContainer) return; if(this.JSChartContainer.DragMode==0) return; var pixelTatio = GetDevicePixelRatio(); if (this.JSChartContainer.TryClickLock) { var x = (e.clientX-this.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.getBoundingClientRect().top)*pixelTatio; 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 oneStepWidth=this.JSChartContainer.GetMoveOneStepWidth(); if (moveSetp0) //放大 { var cursorIndex={}; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (!this.Frame.ZoomUp(cursorIndex)) return; this.CursorIndex=cursorIndex.Index; this.UpdatePointByCursorIndex(); this.UpdataDataoffset(); this.UpdateFrameMaxMin(); this.Draw(); this.ShowTooltipByKeyDown(); this.OnKLinePageChange("OnTouchMove"); } else //缩小 { var cursorIndex={}; cursorIndex.Index=parseInt(Math.abs(this.CursorIndex-0.5).toFixed(0)); if (!this.Frame.ZoomDown(cursorIndex)) return; this.CursorIndex=cursorIndex.Index; this.UpdataDataoffset(); this.UpdatePointByCursorIndex(); this.UpdateFrameMaxMin(); this.Draw(); this.ShowTooltipByKeyDown(); 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) { JSConsole.Chart.Log('[KLineChartHScreenContainer:OnTouchEnd]',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(); } } this.IsOnTouch = false; this.VerticalDrag=null; this.StopDragTimer(); this.TouchEvent({ EventID:JSCHART_EVENT_ID.ON_PHONE_TOUCH, FunctionName:"OnTouchEnd"}, e); this.OnTouchFinished(); this.TouchDrawCount=0; } //创建 //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.StringFormatY.ExtendChartPaint=this.ExtendChartPaint; 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.LanguageID=this.LanguageID; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; this.TitlePaint.push(titlePaint); } this.UIElement.addEventListener("keydown", OnKeyDown, true); //键盘消息 } //创建子窗口 this.CreateChildWindow=function(windowCount) { for(var i=0;i{ return this.GetExtraCanvas(name); }; frame.ChartBorder=border; frame.Identify=i; //窗口序号 frame.RightSpaceCount=this.RightSpaceCount; //右边 if (this.ModifyIndexDialog) frame.ModifyIndexEvent=this.ModifyIndexDialog.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'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } //主图上下间距 var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 border.TopSpace=12*pixelTatio; border.BottomSpace=12*pixelTatio; } else { frame.YSplitOperator=new FrameSplitY(); frame.YSplitOperator.LanguageID=this.LanguageID; 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,isPhone) { this.LastPoint.X=x; this.LastPoint.Y=y; this.CursorIndex=this.Frame.GetXData(y); var clientPos=this.PtInClient(x,y); var option={ ParentFunction:'OnMouseMove', Point:{X:x, Y:y}, IsPhone:isPhone===true,ClientPos:clientPos }; this.DrawDynamicInfo(option); } //创建 //windowCount 窗口个数 this.Create=function(windowCount) { this.UIElement.JSChartContainer=this; //创建十字光标 this.ChartCorssCursor=new ChartCorssCursor(); this.ChartCorssCursor.PtInClient=(x,y)=>{ return this.PtInClient(x,y); } this.ChartCorssCursor.Canvas=this.Canvas; this.ChartCorssCursor.StringFormatX=g_DivTooltipDataForamt.Create("CorssCursor_Minute_XStringFormat"); 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.CallAcutionXOperator=new CallAcutionXOperator(); 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=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.LanguageID=this.LanguageID; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; this.TitlePaint.push(titlePaint); } this.ChartCorssCursor.StringFormatX.Frame=this.Frame.SubFrame[0].Frame; this.ChartCorssCursor.StringFormatY.Frame=this.Frame; this.ChartCorssCursor.CallAcutionXOperator.Frame=this.Frame.SubFrame[0].Frame; this.UIElement.addEventListener("keydown", OnKeyDown, true); //键盘消息 } //创建子窗口 this.CreateChildWindow=function(windowCount) { for(var i=0;i { 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'); frame.YSplitOperator.GetEventCallback=(id)=> { return this.GetEventCallback(id); } frame.YSplitOperator.DayOffset=this.DayOffset; frame.YSplitOperator.HQChart=this; } else { frame.YSplitOperator=new FrameSplitY(); frame.YSplitOperator.LanguageID=this.LanguageID; frame.YSplitOperator.FrameSplitData=this.FrameSplitData.get('double'); 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.DayOffset=this.DayOffset; 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; } } } ///////////////////////////////////////////////////////////////////////////////// // 深度图 // 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; 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.SetTitle(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.LineType=3; ySplitOper.IgnoreYValue=[0]; //ySplitOper.SplitType=2; 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); var bRegisterKeydown=true; var bRegisterWheel=true; if (option) { if (option.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[DepthChartContainer::Create] not register wheel event.'); } } if (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 } this.OnWheel=function(e) { JSConsole.Chart.Log('[KLineChartContainer::OnWheel]',e); var x = e.clientX-this.UIElement.getBoundingClientRect().left; var y = e.clientY-this.UIElement.getBoundingClientRect().top; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); var wheelValue=e.wheelDelta; if (!IFrameSplitOperator.IsObjectExist(e.wheelDelta)) wheelValue=e.deltaY* -0.01; var enableZoomUpDown=true; //是否允许缩放 if (this.EnableZoomUpDown && this.EnableZoomUpDown.Wheel===false) enableZoomUpDown=false; if (isInClient && wheelValue<0 && enableZoomUpDown) //缩小 { if (this.Frame.ZoomDown()) { this.UpdateFrameMaxMin(); this.Draw(); } } else if (isInClient && wheelValue>0 && enableZoomUpDown) //放大 { if (this.Frame.ZoomUp()) { this.UpdateFrameMaxMin(); this.Draw(); } } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.UIOnMouseDown=function(e) { } this.OnTouchStart=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; this.IsOnTouch=true; this.TouchDrawCount=0; this.PhonePinch=null; var isSingleTouch=this.IsSingleTouch(e); if (this.EnableScrollUpDown==false || !isSingleTouch) //多点触屏 { if (e.cancelable) e.preventDefault(); } 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; this.MoveCorssCursor(drag.Click,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 pixelTatio = GetDevicePixelRatio(); var x = touches[0].clientX-uielement.getBoundingClientRect().left*pixelTatio; var y = touches[0].clientY-uielement.getBoundingClientRect().top*pixelTatio; this.OnMouseMove(x,y,e); } 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 ( ((moveUpDown>0 && moveSetp<=3) || moveAngle<=this.TouchMoveMinAngle) && this.EnableScrollUpDown==true ) { return; } this.PreventTouchEvent(e); this.MouseDrag=null; var pixelTatio = GetDevicePixelRatio(); var x = touches[0].clientX-uielement.getBoundingClientRect().left*pixelTatio; var y = touches[0].clientY-uielement.getBoundingClientRect().top*pixelTatio; this.OnMouseMove(x,y,e); } } else if (this.IsPhonePinching(e)) { this.PreventTouchEvent(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.PreventTouchEvent(e); } this.OnTouchEnd=function(e) { JSConsole.Chart.Log('[DepthChartContainer::OnTouchEnd]',e); this.IsOnTouch = false; this.OnTouchFinished(); this.TouchDrawCount=0; } this.OnTouchFinished=function() { if (this.CorssCursorTouchEnd===true) //手势离开十字光标消失 { this.DrawDynamicInfo(); return; } } 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; }); var range={ Max:88, Min:8 }; 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}; 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 (typeof (this.AutoUpdateTimer) == 'number') { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = undefined; } } 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; 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 IndexInfo(name,param) { this.Name=name; //名字 this.Param=param; //参数 this.LineColor; //线段颜色 this.ReqeustData=null; //数据请求 } function BaseIndex(name) { this.Index; //指标阐述 this.Name=name; //指标名字 this.Script=null; //通达信脚本 this.ClassName="BaseIndex"; this.OverlayIndex=null; //叠加指标{ IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame } this.GetEventCallback; //事件回调函数 this.Status=0; //0=空闲 1=计算 this.Guid=Guid(); //指标唯一标准 //默认创建都是线段 this.Create=function(hqChart,windowIndex) { } //指标不支持 周期/复权/股票等 this.NotSupport=function(hqChart,windowIndex,message) { var isOverlay=this.IsOverlay(); if (isOverlay) return; hqChart.DeleteIndexPaint(windowIndex); //清空 var frame=hqChart.Frame.SubFrame[windowIndex].Frame; var paint=new ChartErrorMessage(); paint.Canvas=hqChart.Canvas; paint.ChartBorder=frame.ChartBorder; paint.ChartFrame=frame; paint.NotSupportMessage=message; hqChart.ChartPaint.push(paint); } //格式化指标名字+参数 //格式:指标名(参数1,参数2,参数3,...) this.FormatIndexTitle=function() { var title=this.Name; var param=null; for(var i in this.Index) { var item = this.Index[i]; if (item.Param==null) continue; if (param) param+=','+item.Param.toString(); else param=item.Param.toString(); } if (param) { title+='('+param+')'; } return title; } this.IsOverlay=function() //是否是叠加指标 { if (!this.OverlayIndex || this.OverlayIndex.IsOverlay!=true) return false; return true; } this.CreateChart=function(id) //创建图形 { return new ChartLine(); } this.CreatePaints=function(hqChart,windowIndex) { var frame=null; var isOverlay=this.IsOverlay(); if (isOverlay) { frame=this.OverlayIndex.Frame.Frame; this.OverlayIndex.Frame.ChartPaint=[]; //清空 } else { frame=hqChart.Frame.SubFrame[windowIndex].Frame; hqChart.DeleteIndexPaint(windowIndex); //清空 } var aryPaint=[]; for(var i in this.Index) { var paint=this.CreateChart(i); paint.Color=this.Index[i].LineColor; paint.Canvas=hqChart.Canvas; paint.Name=this.Name+"-"+i.toString(); paint.ChartBorder=frame.ChartBorder; paint.ChartFrame=frame if (isOverlay) this.OverlayIndex.Frame.ChartPaint.push(paint); else hqChart.ChartPaint.push(paint); aryPaint.push(paint); } return aryPaint; } this.SendEvent=function(hqChart,windowIndex,hisData, error) { if (!hqChart.GetIndexEvent) return; var event=hqChart.GetIndexEvent(); //指标计算完成回调 if (!event) return; var data={ Data:this.GetOutData(), WindowIndex: windowIndex, Name: this.Name, HistoryData: hisData, Stock: {Symbol:hqChart.Symbol,Name:hqChart.Name} }; if (error) data.Error=error; event.Callback(event,data,self); } this.GetOutData=function() { return null; } } function JSIndex_OX() { this.newMethod=BaseIndex; //派生 this.newMethod('OX'); delete this.newMethod; this.ClassName="JSIndex_OX"; this.IsUsePageData=true; this.BlockSize=0.5; this.Arguments= [ { Name:"Reversal", Value:3 } ]; this.SetArgs=function(args) { if (!args || !IFrameSplitOperator.IsNonEmptyArray(args)) return; for(var i=0;i0.25 else if (value<=20) return 0.5; //[5,20)=>0.5 else if (value<=100) return 1; //[10,100]=>1 else if (value<=200) return 2; //[100,200]=>2 else if (value<=500) return 5; //[200,500]=>5 else if (value<=1000) return 10; //[500,1000]=>10 else return 50; } this.Calculate=function(hqChart, hisData) { if (!hqChart.ChartPaint[0]) return null; var range=hqChart.ChartPaint[0].ShowRange; if (!range) return null; if (!IFrameSplitOperator.IsNonEmptyArray(hisData.Data)) return null; var max=null, min=null; var startPrice=null; for(var i=range.Start; i<=range.End && iitem.Low) min=item.Low; } if (startPrice==null) { if (IFrameSplitOperator.IsNumber(item.High)) startPrice=item.High; } } var reversal=this.GetParamValue("Reversal"); var blockSize=this.CalculateBlockSize(max, min); this.BlockSize=blockSize; var oxData={ Max:max+blockSize, Min:min-blockSize, StartPrice:startPrice, Data:[], BlockSize:blockSize }; var currentTrend=1; var currentPrice=startPrice; var itemData={ Type:0, Data:[], Start:null, End:null }; for(var i=range.Start, j=0; i<=range.End && i= currentPrice + blockSize) { var count=parseInt((item.High-currentPrice)/blockSize); for(j=0;j= currentPrice + (blockSize*reversal)) { currentTrend=1; if (itemData && IFrameSplitOperator.IsNonEmptyArray(itemData.Data)) oxData.Data.push(itemData); itemData={ Type:0, Data:[], Start:null, End:null }; var count=parseInt((item.High-currentPrice)/blockSize); for(j=0;j { //请求数据 var klineChart=hqChart.ChartPaint[0]; //获取当前K线图实例 var kData=klineChart.Data; //K线数据 if (!kData || IFrameSplitOperator.IsNonEmptyArray(!kData.Data)) return; var pageKRange=klineChart.DrawKRange; //当前显示的K线索引 if (!pageKRange || !IFrameSplitOperator.IsNumber(pageKRange.Start) || !IFrameSplitOperator.IsNumber(pageKRange.End)) return; var startKItem=kData.Data[pageKRange.Start]; var endKItem=kData.Data[pageKRange.End]; var option={ Start:{ Date:startKItem.Date, DataIndex:pageKRange.Start }, End:{ Date:endKItem.Date, DataIndex:pageKRange.End }, Chart:this }; if (IFrameSplitOperator.IsNumber(startKItem.Time)) option.Start.Time=startKItem.Time; if (IFrameSplitOperator.IsNumber(endKItem.Time)) option.End.Time=endKItem.Time; option.ValueAreaVol=this.Arguments[0].Value; if (this.Arguments[1].Value>0) this.BarPosition=1; else this.BarPosition=0; if (this.ChartVolProfile) { this.ChartVolProfile.SetOption( { BarPosition:this.BarPosition} ); } this.DataStatus=0 if (hqChart && hqChart.RequestVolumeProfileData) { hqChart.RequestVolumeProfileData(option); } } if (option && option.Type==1) //页面缩放或移动延迟更新 { this.RequestTimer=setTimeout(function() { T_RequestData(); }, this.DelayRequestFrequency); } else { T_RequestData(); } return true; } this.OnRecvVolumeProfileData=function(data) { this.BindData(data); this.HQChart.UpdataDataoffset(); //更新数据偏移 this.HQChart.UpdateFrameMaxMin(); //调整坐标最大 最小值 this.HQChart.Draw(); return true; } this.BindData=function(data) { if (!this.ChartVolProfile || this.ChartVolProfile.IsDestroy==true) this.CreateChart(this.HQChart, this.WindowIndex); var chart=this.ChartVolProfile; chart.Data=null; if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Data)) return; if (!IFrameSplitOperator.IsNumber(data.MaxPrice) || !IFrameSplitOperator.IsNumber(data.MinPrice)) return; var maxVol=0,vol=0; var maxVolPrice=null; for(var i=0, j=0;i0) strParam+=','; var item=this.Arguments[i]; strParam+='"'+item.Name+'"'+':'+item.Value; } strParam='{'+strParam+'}'; var indexParam=JSON.parse(strParam); var data=JSON.stringify( { code:this.Script, //脚本 symbol:param.HQChart.Symbol, //股票代码 period:param.HQChart.Period, //周期 0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 right:param.HQChart.Right, //复权 0 不复权 1 前复权 2 后复权 params:indexParam, //指标参数 numcount:hqChart.MaxRequestDataCount, }); //请求数据 JSNetwork.HttpRequest({ url: this.ApiUrl, data:data, type:"post", dataType: "json", contentType:' application/json; charset=utf-8', async:true, success: function (recvData) { self.RecvData(recvData,param); }, complete:function(h) { //JSConsole.Chart.Log(h); }, error: function(http,e) { self.RecvError(http,e,param);; } }); return true; } this.RecvError=function(http,e,param) { JSConsole.Chart.Log("[PyScriptIndex::RecvError] error",e); if (param.HQChart.ScriptErrorCallback) param.HQChart.ScriptErrorCallback(e); } this.RecvData=function(recvData,param) { if (recvData.code!=0) { JSConsole.Chart.Log("[PyScriptIndex::RecvData] failed.", recvData); if (param.HQChart.ScriptErrorCallback) param.HQChart.ScriptErrorCallback(recvData.msg); return; //失败了 } JSConsole.Chart.Log('[PyScriptIndex::RecvData] recv data.',recvData); var aryDate=recvData.date; for(var i in recvData.data) { var item=recvData.data[i]; var indexData=[]; for(var j=0;j=item.data.length) continue; var indexItem=new SingleData(); //单列指标数据 indexItem.Date=aryDate[j]; indexItem.Value=item.data[j]; indexData.push(indexItem); } var aryFittingData=param.HistoryData.GetFittingData(indexData); //数据和主图K线拟合 var bindData=new ChartData(); bindData.Data=aryFittingData; bindData.Period=param.HQChart.Period; //周期 bindData.Right=param.HQChart.Right; //复权 var indexInfo={Name:item.name,Type:item.graph,LineWidth:item.width,Data:bindData.GetValue(),Color:item.color}; this.OutVar.push(indexInfo); } this.BindData(param.HQChart,param.WindowIndex,param.HistoryData); //把数据绑定到图形上 param.HQChart.UpdataDataoffset(); //更新数据偏移 param.HQChart.UpdateFrameMaxMin(); //调整坐标最大 最小值 param.HQChart.Draw(); } this.BindData=function(hqChart,windowIndex,hisData) { hqChart.DeleteIndexPaint(windowIndex); //清空指标图形 for(let i in this.OutVar) { let item=this.OutVar[i]; switch(item.Type) { case 'line': this.CreateLine(hqChart,windowIndex,item,i); break; case 'colorstick': //上下柱子 this.CreateColorStock(hqChart,windowIndex,item,i); break; } } var titleIndex=windowIndex+1; hqChart.TitlePaint[titleIndex].Title=this.Name; //这是指标名称 let indexParam=''; //指标参数 for(let i in this.Arguments) { let item=this.Arguments[i]; if (indexParam.length>0) indexParam+=','; indexParam+=item.Value.toString(); } if (indexParam.length>0) hqChart.TitlePaint[titleIndex].Title=this.Name+'('+indexParam+')'; return true; } this.CreateLine=function(hqChart,windowIndex,varItem,id) { let line=new ChartLine(); line.Canvas=hqChart.Canvas; line.DrawType=1; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) line.Color=varItem.Color; else line.Color=this.GetDefaultColor(id); if (varItem.LineWidth>0) line.LineWidth=varItem.LineWidth; if (varItem.IsShow==false) line.IsShow=false; let titleIndex=windowIndex+1; line.Data.Data=varItem.Data; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); hqChart.ChartPaint.push(line); } this.CreateColorStock=function(hqChart,windowIndex,varItem,id) { let chart=new ChartMACD(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(chart.Data,varItem.Name,this.GetDefaultColor(id)); hqChart.ChartPaint.push(chart); } //给一个默认的颜色 this.GetDefaultColor=function(id) { let COLOR_ARRAY= [ "rgb(255,174,0)", "rgb(25,199,255)", "rgb(175,95,162)", "rgb(236,105,65)", "rgb(68,114,196)", "rgb(229,0,79)", "rgb(0,128,255)", "rgb(252,96,154)", "rgb(42,230,215)", "rgb(24,71,178)", ]; let number=parseInt(id); return COLOR_ARRAY[number%(COLOR_ARRAY.length-1)]; } } /* json格式数据指标 用来显示本地数据 */ function JsonDataIndex(name,script,args,option) { this.newMethod=PyScriptIndex; //派生 this.newMethod(name); delete this.newMethod; this.JsonData; //json格式数据 if (option.JsonData) this.JsonData=option.JsonData; this.RequestData=function(hqChart,windowIndex,hisData) { if (!this.JsonData) { console.warn("[PyScriptIndex::RequestData] JsonData is null"); if (param.HQChart.ScriptErrorCallback) param.HQChart.ScriptErrorCallback('json 数据不能为空'); } else { var param= { HQChart:hqChart, WindowIndex:windowIndex, HistoryData:hisData }; this.JsonData.code=0; var recvData=this.JsonData; this.RecvData(recvData,param); } } } //给一个默认的颜色 PyScriptIndex.prototype.GetDefaultColor=function(id) { let COLOR_ARRAY= [ "rgb(255,174,0)", "rgb(25,199,255)", "rgb(175,95,162)", "rgb(236,105,65)", "rgb(68,114,196)", "rgb(229,0,79)", "rgb(0,128,255)", "rgb(252,96,154)", "rgb(42,230,215)", "rgb(24,71,178)", ]; let number=parseInt(id); return COLOR_ARRAY[number%(COLOR_ARRAY.length-1)]; } /* 信息地雷 */ /* 信息地雷列表 */ function JSKLineInfoMap() { } JSKLineInfoMap.Get=function(id) { var infoMap=new Map( [ ["互动易", {Create:function(){ return new InvestorInfo()} }], ["公告", {Create:function(){ return new AnnouncementInfo()} }], ["业绩预告", {Create:function(){ return new PforecastInfo()} }], ["调研", {Create:function(){ return new ResearchInfo()} }], ["大宗交易", {Create:function(){ return new BlockTrading()} }], ["龙虎榜", {Create:function(){ return new TradeDetail()} }] ] ); return infoMap.get(id); } JSKLineInfoMap.GetClassInfo=function(id) { var infoMap=new Map( [ ["互动易", { ClassName:"InvestorInfo" }], ["公告", { ClassName:"AnnouncementInfo" }], ["业绩预告", { ClassName:"PforecastInfo" } ], ["调研", { ClassName:"ResearchInfo" }], ["大宗交易", { ClassName:"BlockTrading" }], ["龙虎榜", { ClassName:"TradeDetail"} ] ] ); return infoMap.get(id); } JSKLineInfoMap.GetIconUrl=function(type) { switch(type) { case KLINE_INFO_TYPE.INVESTOR: return g_JSChartResource.KLine.Info.Investor.Icon; break; case KLINE_INFO_TYPE.PFORECAST: return g_JSChartResource.KLine.Info.Pforecast.Icon; case KLINE_INFO_TYPE.ANNOUNCEMENT: return g_JSChartResource.KLine.Info.Announcement.Icon; case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_1: case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_2: case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_3: case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_4: return g_JSChartResource.KLine.Info.Announcement.IconQuarter; case KLINE_INFO_TYPE.RESEARCH: return g_JSChartResource.KLine.Info.Research.Icon; case KLINE_INFO_TYPE.BLOCKTRADING: return g_JSChartResource.KLine.Info.BlockTrading.Icon; case KLINE_INFO_TYPE.TRADEDETAIL: return g_JSChartResource.KLine.Info.TradeDetail.Icon; default: return g_JSChartResource.KLine.Info.Announcement.Icon; } } JSKLineInfoMap.GetIconLibrary=function(index) { var iconLib=g_JSChartResource.KLine.Info.IconLibrary; if (!iconLib || !iconLib.Icon) return g_JSChartResource.KLine.Info.Announcement.IconFont; if (index>=0 && index=KLINE_INFO_TYPE.ANNOUNCEMENT_EX_START && type<=KLINE_INFO_TYPE.ANNOUNCEMENT_EX_END) { var index=type-KLINE_INFO_TYPE.ANNOUNCEMENT_EX_START; return JSKLineInfoMap.GetIconLibrary(index); } switch(type) { case KLINE_INFO_TYPE.INVESTOR: return g_JSChartResource.KLine.Info.Investor.IconFont; break; case KLINE_INFO_TYPE.PFORECAST: return g_JSChartResource.KLine.Info.Pforecast.IconFont; case KLINE_INFO_TYPE.ANNOUNCEMENT: return g_JSChartResource.KLine.Info.Announcement.IconFont; case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_1: case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_2: case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_3: case KLINE_INFO_TYPE.ANNOUNCEMENT_QUARTER_4: return g_JSChartResource.KLine.Info.Announcement.IconFont2; case KLINE_INFO_TYPE.RESEARCH: return g_JSChartResource.KLine.Info.Research.IconFont; case KLINE_INFO_TYPE.BLOCKTRADING: return g_JSChartResource.KLine.Info.BlockTrading.IconFont; case KLINE_INFO_TYPE.TRADEDETAIL: return g_JSChartResource.KLine.Info.TradeDetail.IconFont; default: return g_JSChartResource.KLine.Info.Announcement.IconFont; } } function IKLineInfo() { this.MaxRequestDataCount=1000; this.StartDate=20160101; this.Data; this.ClassName='IKLineInfo'; this.Explain="IKLineInfo"; this.GetToday=function() { var date=new Date(); var today=date.getFullYear()*10000+(date.getMonth()+1)*100+date.getDate(); return today; } this.GetRequestData=function(hqChart) { var obj= { Symbol:hqChart.Symbol , MaxRequestDataCount: hqChart.MaxRequestDataCount, //日线数据个数 MaxRequestMinuteDayCount:hqChart.MaxRequestMinuteDayCount, //分钟数据请求的天数 Period:hqChart.Period //周期 }; //K线数据范围 var hisData=null; if (hqChart.ChartOperator_Temp_GetHistroyData) hisData=hqChart.ChartOperator_Temp_GetHistroyData(); if (hisData) obj.DateRange=hisData.GetDateRange(); return obj; } this.NetworkFilter=function(hqChart,callInfo) { if (!hqChart.NetworkFilter) return false; var self=this; var param= { HQChart:hqChart, }; var obj= { Name:`${this.ClassName}::RequestData`, //类名::函数 Explain:this.Explain, Request:this.GetRequestData(hqChart), Self:this, HQChart:hqChart, PreventDefault:false }; if (callInfo) { if (callInfo.Update==true) { obj.Update={ Start:{ Date: callInfo.StartDate } }; param.Update={ Start:{ Date: callInfo.StartDate } }; } obj.CallFunctionName=callInfo.FunctionName; //内部调用函数名 } hqChart.NetworkFilter(obj, function(data) { self.RecvData(data,param); }); if (obj.PreventDefault==true) return true; //已被上层替换,不调用默认的网络请求 return false; } } //互动易 function InvestorInfo() { this.newMethod=IKLineInfo; //派生 this.newMethod(); delete this.newMethod; this.ClassName='InvestorInfo'; this.Explain='互动易' this.RequestData=function(hqChart, obj) { var self = this; var param= { HQChart:hqChart, }; this.Data=[]; if (this.NetworkFilter(hqChart,obj)) return; //已被上层替换,不调用默认的网络请求 var postData= { filed: ["question","answerdate","symbol","id"], symbol: [param.HQChart.Symbol], querydate:{"StartDate":this.StartDate,"EndDate":this.GetToday()}, start:0, end:this.MaxRequestDataCount, }; //请求数据 var url=g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Investor.ApiUrl; JSNetwork.HttpRequest({ url: url, data:postData, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvData(recvData,param); } }); return true; } this.RecvData=function(recvData,param) { if (recvData.list.length<=0) return; for(var i in recvData.list) { var item=recvData.list[i]; var infoData=new KLineInfoData(); infoData.Date=item.answerdate; infoData.Title=item.question; infoData.InfoType=KLINE_INFO_TYPE.INVESTOR; this.Data.push(infoData); } param.HQChart.UpdataChartInfo(); param.HQChart.Draw(); } } //公告 支持增量更新 function AnnouncementInfo() { this.newMethod=IKLineInfo; //派生 this.newMethod(); delete this.newMethod; this.ClassName='AnnouncementInfo'; this.Explain='公告'; this.ApiType=1; //0=读API 1=读OSS缓存文件 this.RequestData=function(hqChart,obj) { var self = this; var param= { HQChart:hqChart, }; if (obj && obj.Update===true) //更新模式 不清内存数据 { } else { this.Data=[]; } if (this.NetworkFilter(hqChart, obj)) return; //已被上层替换,不调用默认的网络请求 if (this.ApiType==1) //取缓存文件 { var url=`${g_JSChartResource.CacheDomain}/cache/analyze/shszreportlist/${param.HQChart.Symbol}.json`; JSNetwork.HttpRequest({ url: url, type:"get", dataType: "json", async:true, success: function (recvData) { self.RecvData(recvData,param); }, error: function(http,e) { self.RecvError(http,e,param);; } }); } else //取api { //请求数据 var url=g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Announcement.ApiUrl; JSNetwork.HttpRequest({ url: url, data: { "filed": ["title","releasedate","symbol","id"], "symbol": [param.HQChart.Symbol], "querydate":{"StartDate":this.StartDate,"EndDate":this.GetToday()}, "start":0, "end":this.MaxRequestDataCount, }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvData(recvData,param); }, error: function(http,e) { self.RecvError(http,e,param);; } }); } } this.RecvData=function(recvData,param) { if (!IFrameSplitOperator.IsNonEmptyArray(recvData.report)) return; var aryReport=[]; for(var i=0;i0) { this.UpdateData(aryReport); } else { this.Data=aryReport; } param.HQChart.UpdataChartInfo(); param.HQChart.Draw(); } //增量更新 this.UpdateData=function(aryData) { if (!aryData || aryData.length<=0) return; var setKeys=new Set(); //通过 日期+类型+标题去重 for(var i in this.Data) { var item=this.Data[i]; var strKey=`${item.Date}-${item.Time}-${item.InfoType}-${item.Title}`; setKeys.add(strKey); } var count=0; for(var i in aryData) { var item=aryData[i]; var strKey=`${item.Date}-${item.Time}-${item.InfoType}-${item.Title}`; if (setKeys.has(strKey)) continue; this.Data.push(item); ++count; } JSConsole.Chart.Log(`[AnnouncementInfo::UpdateData] add new count=${count}`); } this.RecvError=function(http,e,param) { console.warn("[AnnouncementInfo::RecvError] error, http ",e, http); //if (param.HQChart.ScriptErrorCallback) param.HQChart.ScriptErrorCallback(e); } } //业绩预告 function PforecastInfo() { this.newMethod=IKLineInfo; //派生 this.newMethod(); delete this.newMethod; this.ClassName='PforecastInfo'; this.Explain='业绩预告'; this.RequestData=function(hqChart,obj) { var self = this; var param= { HQChart:hqChart, }; this.Data=[]; var url=g_JSChartResource.Domain+g_JSChartResource.KLine.Info.Pforecast.ApiUrl; if (this.NetworkFilter(hqChart, obj)) return; //已被上层替换,不调用默认的网络请求 console.warn("[PforecastInfo::RequestData] NetworkFilter error."); return true; } this.RecvData=function(recvData,param) { if (!IFrameSplitOperator.IsNonEmptyArray(recvData.report)) return; for(var i=0; i=3 && item[2] && typeof(item[2])=='string') info.Color=item[2]; //[3]=字体颜色 if (item.length>=4 && item[3] && typeof(item[3])=='string') info.BGColor=item[3]; //[3]=背景颜色 this.Data.push(info); } else //新格式 { if (!IFrameSplitOperator.IsNumber(item.Date) || !IFrameSplitOperator.IsNumber(item.Time) || !item.Title) continue; var info={ Date:item.Date, Time:item.Time, Title:item.Title, Type:0 }; if (item.Color) info.Color=item.Color; if (item.BGColor) info.BGColor=item.BGColor; if (IFrameSplitOperator.IsNumber(item.Price)) info.Price=item.Price; if (item.Content) info.Content=item.Content; if (item.Link) info.Link=item.Link; this.Data.push(info); } } } param.HQChart.UpdataChartInfo(); param.HQChart.Draw(); } } //注意!!! 这个函数已经不用了 //是否是指数代码 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; } //注意!!! 这个函数已经不用了 //是否是基金代码 function IsFundSymbol(symbol) { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); if (upperSymbol.indexOf('.SH')>0) { upperSymbol=upperSymbol.replace('.SH',''); //51XXXX.sh if (upperSymbol.charAt(0)=='5' && upperSymbol.charAt(1)=='1') return true; } else if (upperSymbol.indexOf('.SZ')>0) { upperSymbol=upperSymbol.replace('.SZ',''); //15XXXX.sz, 16XXXX.sz, 17XXXX.sz, 18XXXX.sz if (upperSymbol.charAt(0)=='1' && (upperSymbol.charAt(1)=='5' || upperSymbol.charAt(1)=='6' || upperSymbol.charAt(1)=='7' || upperSymbol.charAt(1)=='8') ) return true; } return false; } //设置对话框工厂类 function DialogFactory() { //[key:name, { Create:function(divElement) { return new class(divElement); }} ] this.DataMap=new Map( [ ["ChartPictureSettingMenu", { Create:function(divElement) { return new ChartPictureSettingMenu(divElement); } }], ["ChartPictureTextSettingMenu", { Create:function(divElement) { return new ChartPictureTextSettingMenu(divElement); } }] ]); this.Create=function(name, option) { if (!this.DataMap.has(name)) { JSConsole.Warn(`[DialogFactory::Create] can't find class=${name}.`); return null; } var item=this.DataMap.get(name); return item.Create(option); } this.Add=function(name, option) { this.DataMap.set(name, { Create:option.Create } ); } } var g_DialogFactory=new DialogFactory(); //设置窗口基类 function IDivDialog(divElement) { this.DivElement=divElement; //父节点 this.ID=null; //div id this.TimeOut=null; //定时器 //隐藏窗口 this.Hide=function() { $("#"+this.ID).hide(); } //显示窗口 this.Show=function(left,top,width,height) { var cssData={display:'block'}; if (IFrameSplitOperator.IsNumber(left)) cssData.left=left+'px'; if (IFrameSplitOperator.IsNumber(top)) cssData.top=top+'px'; if (IFrameSplitOperator.IsNumber(width)) cssData.width=width+'px'; if (IFrameSplitOperator.IsNumber(height)) cssData.height=height+'px'; $("#"+this.ID).css(cssData); } } //修改指标 function ModifyIndexDialog(divElement) { this.newMethod=IDivDialog; //派生 this.newMethod(divElement); delete this.newMethod; this.Title={ ID:Guid() }; //标题 this.ParamList={ID:Guid() }; //参数列表 class='parameter-content' this.ParamData=[]; //{ ID:参数ID, Value:参数值} this.Identify; this.HQChart; this.IsOverlay=false; //是否是叠加指标 this.IndexScript; //创建 this.Create=function() { this.ID=Guid(); var div=document.createElement('div'); div.className='jchart-modifyindex-box'; div.id=this.ID; div.innerHTML= "
\
\ \ \
\
MA
\ \
"; this.DivElement.appendChild(div); //确定按钮 $("#"+this.ID+" .submit").click( { divBox:this, }, function(event) { event.data.divBox.Hide(); }); //给一个id 后面查找方便 var titleElement=div.getElementsByTagName('span')[0]; titleElement.id=this.Title.ID; var paramListElement=div.getElementsByClassName('parameter-content')[0]; paramListElement.id=this.ParamList.ID; } //设置标题 this.SetTitle=function(title) { $("#"+this.Title.ID).html(title); } //清空参数 this.ClearParamList=function() { $("#"+this.ParamList.ID).empty(); this.ParamData=[]; } this.BindParam=function() { for(var i=0; i'+ item.Name +'
'; $("#"+this.ParamList.ID).append(param); this.ParamData.push({ID:guid,Value:item.Value}); } //绑定参数修改事件 var self=this; for(var i=0; i
${this.Title}
`.trim(); this.DivElement.appendChild(div); this.Dialog=div; } //显示 this.DoModal=function(event) { this.Title=event.data.Title; var chart=event.data.Chart; if (this.ID==null) this.Create(); //第1次 需要创建div //居中显示 var border=chart.Frame.ChartBorder; var scrollPos=GetScrollPosition(); var left=border.GetWidth()/2; var top=border.GetHeight()/2; this.Show(left,top,200,40); //显示 } } //画图工具 单个图形设置 function ChartPictureSettingMenu(divElement) { this.newMethod=IDivDialog; //派生 this.newMethod(divElement); delete this.newMethod; this.HQChart; this.ChartPicture; this.SubToolsDiv; this.SettingMenu; this.SettingPV; this.DoModal=function(event) { var $body; if (!this.SubToolsDiv) { this.ID=Guid(); var div=document.createElement("div"); div.className='subTolls'; div.id=this.ID; this.DivElement.appendChild(div); //$body = $("."+event.data.HQChart.ClassName).context.body; //$body.append(div); this.SubToolsDiv=div; } this.HQChart=event.data.HQChart; this.ChartPicture=event.data.ChartPicture; var pixelTatio = GetDevicePixelRatio(); var frame=this.HQChart.Frame.SubFrame[0].Frame; // var top=frame.ChartBorder.GetTopTitle(); var top=frame.ChartBorder.Top + 40; // var right=frame.ChartBorder.GetRight(); var right=frame.ChartBorder.Right; var left=frame.ChartBorder.GetLeft(); var className = this.ChartPicture.ClassName; //='ChartDrawPictureText'时加“设置” var lineColor=this.ChartPicture.LineColor; if (lineColor.indexOf("rgb(")==0 || lineColor.indexOf("RGB(")==0) lineColor=IChartDrawPicture.RGBToHex(lineColor.toLowerCase()); var toolsDiv = ""; if(className === 'ChartDrawPictureText') { toolsDiv = ''+ ''+ ''+ '\n' + ''+ ''; } else if (className=="ChartDrawVolProfile") { toolsDiv=''+ ''; } else { toolsDiv = '

' + '

\n' + '

'; } this.SubToolsDiv.style.right = right/pixelTatio + "px"; this.SubToolsDiv.style.top = top/pixelTatio + "px"; this.SubToolsDiv.innerHTML = toolsDiv; this.SubToolsDiv.style.position = "absolute"; this.SubToolsDiv.style.display = "block"; var hqChart = this.HQChart; var picture = this.ChartPicture; var subToolDiv = this.SubToolsDiv; $(".subtool-del").click(function(){ hqChart.SelectChartDrawPicture=null; hqChart.ClearChartDrawPicture(picture); // subToolDiv.innerHTML = ""; $(".subTolls").css("display","none"); }); var self = this; $(".subtool-set").click(function(){ $(self.SubToolsDiv).hide(); //创建div设置窗口 if (!self.SettingMenu) self.SettingMenu=new ChartPictureTextSettingMenu(frame.ChartBorder.UIElement.parentNode); self.SettingMenu.ChartPicture=picture; self.SettingMenu.HQChart=hqChart; self.SettingMenu.Position={Left:right + 80,Top:top + 20}; self.SettingMenu.DoModal(); }); $(".changes-color").click(function () { document.getElementById('color').click(); $(".change-color").change(function () { var color = $(".change-color").val(); picture.LineColor = color; picture.PointColor = color; if (hqChart.ChartDrawStorage) hqChart.ChartDrawStorage.SaveDrawData(picture); //保存下 }); }); //成交量分布图设置 $(".vp-set").click(function() { if (!self.SettingPV) self.SettingPV=new ChartPictureVolProfileSettingMenu(frame.ChartBorder.UIElement.parentNode); self.SettingPV.ChartPicture=picture; self.SettingPV.HQChart=hqChart; self.SettingPV.Position={Left:right + 80,Top:top + 20}; self.SettingPV.DoModal(); }); JSConsole.Chart.Log("[ChartPictureSettingMenu::DoModal]", {Top:top,Left:left, Right:right}); } } //画图工具 文本设置窗口 function ChartPictureTextSettingMenu(divElement) { this.newMethod=IDivDialog; //派生 this.newMethod(divElement); delete this.newMethod; this.ChartPicture; this.SettingDiv; this.Position; this.BackupData; //画图工具备份数据 this.Close=function() { if (this.SettingDiv) this.DivElement.removeChild(this.SettingDiv); //直接删除 } this.DoModal=function() { var text=this.ChartPicture.Text; //显示的文本 var fontOption=this.ChartPicture.FontOption; //字体设置 var lineColor=this.ChartPicture.LineColor; //数据备份, 点取消的时候把备份数据设置回去 this.BackupData= { Text:text, LineColor:lineColor, FontOption:{Family: fontOption.Family, Size: fontOption.Size, Weight: fontOption.Weight, Style: fontOption.Style } }; JSConsole.Chart.Log('[ChartPictureTextSettingMenu::DoModal] picture info',this.BackupData); var self=this; var div=this.DivElement.getElementsByClassName('chartpicture-text-setting')[0]; if (!div) { div=document.createElement("div"); div.className='chartpicture-text-setting'; this.DivElement.appendChild(div); this.SettingDiv=div; } else { this.SettingDiv=div; } var titleContainerStr = '
'+ '样式设置'+ ''+ '
'; var fontSizeArray = [10,11,12,14,16,20,24,28,32,40]; var fontArray = ['微软雅黑','宋体','Arial','仿宋']; var sizeListStr = ""; var fontListStr = ""; fontArray.forEach(function(item,index){ fontListStr += index !== 0 ? '

'+item+'

' : '

'+item+'

'; }); fontSizeArray.forEach(function(item,index){ sizeListStr += index !== 5 ? '

'+item+'

' : '

'+item+'

'; }); var contentContainerStr = '
'+ '
'+ ''+ '
微软雅黑
'+fontListStr+'
'+ '
20
'+sizeListStr+'
'+ ''+ ''+ '
'+ ''+ '
'; var btnContainer = '
'+ '确认'+ '取消'+ '
'; var pixelTatio = GetDevicePixelRatio(); var DoModalStr = titleContainerStr+contentContainerStr+btnContainer; this.SettingDiv.style.left = this.Position.Left/pixelTatio + "px"; this.SettingDiv.style.top = this.Position.Top/pixelTatio + "px"; this.SettingDiv.innerHTML=DoModalStr; this.SettingDiv.style.position = "absolute"; this.SettingDiv.style.display = "block"; $(".chartpicture-text-setting .colorPicker").css({ //初始设置 "borderColor":self.ChartPicture.LineColor, "background-color":self.ChartPicture.LineColor }); var family = this.ChartPicture.FontOption.Family; $('.chartpicture-text-setting .fontSelect .choicedText').html(family); fontArray.forEach(function(item,index){ if(item == family){ $('.chartpicture-text-setting .fontSelect p').removeClass('active'); $('.chartpicture-text-setting .fontSelect p').eq(index).addClass('active'); } }); var size = this.ChartPicture.FontOption.Size; $('.chartpicture-text-setting .fontSizeSelect .choicedText').html(size); fontSizeArray.forEach(function(item,index){ if(item == size){ $('.chartpicture-text-setting .fontSizeSelect p').removeClass('active'); $('.chartpicture-text-setting .fontSizeSelect p').eq(index).addClass('active'); } }); var weight = this.ChartPicture.FontOption.Weight; if( weight != null && weight == 'bold'){ $('.chartpicture-text-setting .strongFont').addClass('hot'); } var style = this.ChartPicture.FontOption.Style; if( style != null && style == 'italic'){ $('.chartpicture-text-setting .italicsFont').addClass('hot'); } var text = this.ChartPicture.Text; $('.chartpicture-text-setting .tArea').val(text); //结束初始设置 var defaultTextOption = { Family:'微软雅黑', Size:20, Weight:null, Style:null }; $(".chartpicture-text-setting #fontColor").change( { Picture:this.ChartPicture }, function(event) { //颜色选择 var value = $(this).val(); $(this).parent().css({ "borderColor":value, "background-color":value }); var chart=event.data.Picture; chart.LineColor = value; if (chart.Update) chart.Update(); //更新界面 } ); $(".chartpicture-text-setting .fontSelect,.chartpicture-text-setting .fontSizeSelect").click(function(){ $(this).find('.selectList').toggle(); $(this).toggleClass('hot'); }); $(".chartpicture-text-setting .fontSelect p").click( { Picture:this.ChartPicture }, function(event){ //字体选择 var choicedText = $(this).closest(".fontSelect").find('.choicedText').html(); var currentSelect = event.currentTarget.innerHTML; if(choicedText !== currentSelect){ $(this).closest(".fontSelect").find('.choicedText').html(currentSelect); $(this).siblings().removeClass('active'); $(this).addClass('active'); var chart = event.data.Picture; chart.FontOption.Family = currentSelect; if (chart.Update) chart.Update(); //更新界面 } }); $(".chartpicture-text-setting .fontSizeSelect p").click( { Picture:this.ChartPicture }, function(event){ //字号选择 var choicedText = $(this).closest(".fontSizeSelect").find('.choicedText').html(); var currentSelect = event.currentTarget.innerHTML; if(choicedText !== currentSelect){ $(this).closest(".fontSizeSelect").find('.choicedText').html(currentSelect); $(this).siblings().removeClass('active'); $(this).addClass('active'); var chart = event.data.Picture; chart.FontOption.Size = Number(currentSelect); if (chart.Update) chart.Update(); //更新界面 } }); $(".chartpicture-text-setting .strongFont").click( { Picture:this.ChartPicture }, function(event){ $(this).toggleClass('hot'); var classnames = $(this).attr('class'); if(classnames.indexOf('hot') > 0){ var chart = event.data.Picture; chart.FontOption.Weight = 'bold'; if (chart.Update) chart.Update(); //更新界面 } }); $(".chartpicture-text-setting .italicsFont").click( { Picture:this.ChartPicture }, function(event){ $(this).toggleClass('hot') var classnames = $(this).attr('class'); if(classnames.indexOf('hot') > 0){ var chart = event.data.Picture; chart.FontOption.Style = 'italic'; if (chart.Update) chart.Update(); //更新界面 } }); $(".chartpicture-text-setting .titleWrap .closeBtn,.chartpicture-text-setting .btnsContainer .cancelBtn").click( //取消 { Picture:this.ChartPicture }, function(event){ var picture = event.data.Picture; picture.Text = self.BackupData.Text; picture.LineColor = self.BackupData.LineColor; picture.FontOption = self.BackupData.FontOption; if (picture.Update) picture.Update(); self.Close(); }); $(".chartpicture-text-setting .tArea").keyup( //文本内容 { Picture:this.ChartPicture }, function(event){ JSConsole.Chart.Log('[ChartPictureTextSettingMenu::DoModal] $(".chartpicture-text-setting .tArea").keyup()'); var content = $(this).val(); var chart = event.data.Picture; chart.Text = content; if (chart.Update) chart.Update(); //更新界面 }); //确定按钮 $(".chartpicture-text-setting .btnsContainer .okBtn").click( function() { self.Close(); if (self.HQChart && self.HQChart.ChartDrawStorage) self.HQChart.ChartDrawStorage.SaveDrawData(self.ChartPicture); //保存下 } ); } } function ChartPictureVolProfileSettingMenu(divElement) { this.newMethod=IDivDialog; //派生 this.newMethod(divElement); delete this.newMethod; this.ChartPicture; this.SettingDiv; this.Position; this.ID=Guid(); this.Close=function() { if (this.SettingDiv) this.DivElement.removeChild(this.SettingDiv); //直接删除 } this.DoModal=function() { var valueAreaVol=this.ChartPicture.VAVol; //Value area volume var barPosition=this.ChartPicture.BarPosition; var self=this; var div=document.getElementById(this.ID); if (!div) { div=document.createElement("div"); div.className='jchart-modifyindex-box'; div.id=this.ID; this.DivElement.appendChild(div); this.SettingDiv=div; } else { this.SettingDiv=div; } div.innerHTML= `
\
\ 固定范围成交量分布设置\ \
\
VAVol
BarPosition
\ \
`; var pixelTatio = GetDevicePixelRatio(); var frame=this.HQChart.Frame.SubFrame[0].Frame; var top=frame.ChartBorder.Top + 40; var right=frame.ChartBorder.Right; var left=frame.ChartBorder.GetLeft(); this.SettingDiv.style.right = right/pixelTatio + "px"; this.SettingDiv.style.top = top/pixelTatio + "px"; this.SettingDiv.style.position = "absolute"; this.SettingDiv.style.display = "block"; var btnCancel=div.getElementsByClassName("cancel")[0]; btnCancel.onclick=function() { self.Close(); } var btnClose=div.getElementsByClassName("icon iconfont icon-close")[0]; btnClose.onclick=function() { self.Close(); } var btnSubmit=div.getElementsByClassName("submit")[0]; btnSubmit.onclick=function() { var value=div.getElementsByClassName("row-line")[0].value; self.ChartPicture.VAVol=parseFloat(value); var value=parseInt(div.getElementsByClassName("row-line")[1].value); self.ChartPicture.BarPosition=value>0?1:0; self.ChartPicture.RequestVolumeProfileData(); self.Close(); } } } /////////////////////////////////////////////////////////////////////////////////////// // // 各个品种分钟走势图坐标信息 // ////////////////////////////////////////////////////////////////////////////////////// var MARKET_SUFFIX_NAME= { SH:'.SH', SZ:'.SZ', SHSZ_C_Index:'.CI', //自定义指数 BJ:".BJ", //北交所 BeiJing stock exchange SHO:'.SHO', //上海交易所 股票期权 SZO:".SZO", //深证交易所 股票期权 HK:'.HK', //港股 FHK:'.FHK', //港股期货 SHFE: '.SHF', //上期所 (Shanghai Futures Exchange) | 上期所-能源 SHFE2:'.SHFE', //上期所 (Shanghai Futures Exchange) | 上期所-能源 CFFEX: '.CFE', //中期所 (China Financial Futures Exchange) CFFEX2:'.CFFEX', //中期所 (China Financial Futures Exchange) CFFEX3:'.CF', //中期所 (China Financial Futures Exchange) DCE: '.DCE', //大连商品交易所(Dalian Commodity Exchange) CZCE: '.CZC', //郑州期货交易所 GZFE:".GZFE", //广州期货交易所 USA:'.USA', //美股 FTSE:'.FTSE', //富时中国 BIT:'.BIT', //数字货币 如比特币 BIZ:'.BIZ', //数字货币 FOREX:'.FOREX', //外汇 (Foreign Exchange) NYMEX:'.NYMEX', //纽约商品期货交易所(New York Mercantile Exchange) COMEX:".COMEX", //纽约商品期货交易所(New York Mercantile Exchange) NYBOT:".NYBOT", //美國紐約商品交易所 CBOT:".CBOT", //芝商所 LME:".LME", //伦敦金属交易所 TOCOM:".TOCOM", //东京商品交易所(TOCOM) IPE:".IPE", //美国洲际交易所 (ICE EUROPE) TW:".TW", //台湾股票 9:00-13:30 JP:".JP", //日本股票 9:00-11:30, 12:30-15:00 //越南股市 HSX:".HSX", //HSX胡志明交易所 HNX:".HNX", //HNX河內交易所 UPCOM:".UPCOM", //UPCOM未上市公司交易所 ET:'.ET', //其他未知的品种 IsET:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.ET) > 0; }, IsETShowAvPrice:function(upperSymbol) //是否显示均价 { return false; }, IsHSX:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.HSX)>0; }, IsHNX:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.HNX)>0; }, IsUPCOM:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.UPCOM)>0; }, IsNYMEX:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.NYMEX)>0; }, IsCOMEX:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.COMEX)>0; }, IsNYBOT:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.NYBOT)>0; }, IsCBOT:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.CBOT)>0; }, IsLME:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.LME)>0; }, IsTOCOM:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.TOCOM)>0; }, IsIPE:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.IPE)>0; }, IsForeignExchange(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.FOREX) > 0; }, IsFTSE:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.FTSE) > 0; }, IsFHK:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.FHK) > 0; }, IsBIT:function(upperSymbol) { if (!upperSymbol) return false; if (upperSymbol.indexOf(this.BIT) > 0) return true; if (upperSymbol.indexOf(this.BIZ) > 0) return true; return false; }, IsUSA:function(upperSymbol) //是否是美股 { if (!upperSymbol) return false; return upperSymbol.indexOf(this.USA) > 0; }, IsSH: function (upperSymbol) { //需要精确匹配最后3位 var pos = upperSymbol.length-this.SH.length; var find = upperSymbol.indexOf(this.SH); return find == pos; }, IsSZ: function (upperSymbol) { var pos = upperSymbol.length - this.SZ.length; var find = upperSymbol.indexOf(this.SZ); return find == pos; }, IsBJ:function(upperSymbol) { var pos = upperSymbol.length - this.BJ.length; var find = upperSymbol.indexOf(this.BJ); return find == pos; }, //自定义指数 IsSHSZCustomIndex:function(upperSymbol) { var pos = upperSymbol.length - this.SHSZ_C_Index.length; var find = upperSymbol.indexOf(this.SHSZ_C_Index); return find == pos; }, IsSHO: function(upperSymbol) { if (this.IsSH(upperSymbol)) //10007211.sh { if (upperSymbol.length==11 && upperSymbol[0]=='1') return true; } var pos = upperSymbol.length - this.SHO.length; var find = upperSymbol.indexOf(this.SHO); return find == pos; }, IsSZO: function(upperSymbol) { if (this.IsSZ(upperSymbol)) //90004047.sz { if (upperSymbol.length==11 && upperSymbol[0]=='9') return true; } var pos = upperSymbol.length - this.SZO.length; var find = upperSymbol.indexOf(this.SZO); return find == pos; }, IsHK: function (upperSymbol) { var pos = upperSymbol.length - this.HK.length; var find = upperSymbol.indexOf(this.HK); return find == pos; }, IsTW:function(upperSymbol) { var pos = upperSymbol.length - this.TW.length; var find = upperSymbol.indexOf(this.TW); return find == pos; }, IsJP:function(upperSymbol) { var pos = upperSymbol.length - this.JP.length; var find = upperSymbol.indexOf(this.JP); return find == pos; }, IsSHFE: function (upperSymbol) { if (!upperSymbol) return false; if (upperSymbol.indexOf(this.SHFE) > 0) return true; if (upperSymbol.indexOf(this.SHFE2) > 0) return true; return false; }, IsCFFEX: function (upperSymbol) { if (!upperSymbol) return false; if (upperSymbol.indexOf(this.CFFEX) > 0) return true; if (upperSymbol.indexOf(this.CFFEX2) > 0) return true; var index=upperSymbol.indexOf(this.CFFEX3); //必须已.CF结尾 if (index > 0 && index+this.CFFEX3.length==upperSymbol.length) return true; return false; }, IsDCE: function (upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.DCE) > 0; }, IsCZCE: function (upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.CZCE) > 0; }, IsGZFE:function(upperSymbol) { if (!upperSymbol) return false; return upperSymbol.indexOf(this.GZFE) > 0; }, IsChinaFutures:function(upperSymbol) //是否是国内期货 /期权 { return this.IsSHO(upperSymbol) || this.IsSZO(upperSymbol) || this.IsGZFE(upperSymbol) || this.IsCFFEX(upperSymbol) || this.IsCZCE(upperSymbol) || this.IsDCE(upperSymbol) || this.IsSHFE(upperSymbol); }, IsFutures:function(upperSymbol) //是否是期货 包含国外的 { if (!upperSymbol) return false; return this.IsChinaFutures(upperSymbol) || this.IsNYMEX(upperSymbol) || this.IsCOMEX(upperSymbol) || this.IsNYBOT(upperSymbol) || this.IsCBOT(upperSymbol) || this.IsLME(upperSymbol) || this.IsTOCOM(upperSymbol); }, IsSHSZ:function(upperSymbol) //是否是沪深的股票 { return this.IsSZ(upperSymbol)|| this.IsSH(upperSymbol) || this.IsSHSZCustomIndex(upperSymbol); }, IsSHSZFund:function(upperSymbol) //是否是交易所基金 { if (!upperSymbol) return false; if (this.IsSH(upperSymbol)) //51XXXX.SH { if (upperSymbol.charAt(0)=='5' && upperSymbol.charAt(1)=='1') return true; } else if (this.IsSZ(upperSymbol)) //15XXXX.sz, 16XXXX.sz, 17XXXX.sz, 18XXXX.sz { if (upperSymbol.charAt(0)=='1' && (upperSymbol.charAt(1)=='5' || upperSymbol.charAt(1)=='6' || upperSymbol.charAt(1)=='7' || upperSymbol.charAt(1)=='8') ) return true; } return false; }, IsSHSZIndex:function(symbol) //是否是沪深指数代码 { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); if (this.IsSH(upperSymbol)) { var temp=upperSymbol.replace('.SH',''); if (upperSymbol.charAt(0)=='0' && parseInt(temp)<=3000) return true; } else if (this.IsSZ(upperSymbol)) { if (upperSymbol.charAt(0)=='3' && upperSymbol.charAt(1)=='9') return true; } else if (this.IsSHSZCustomIndex(upperSymbol)) //自定义指数 { return true; } return false; }, IsSHSZStockA:function(symbol) //是否是沪深A股 { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); if (this.IsSH(upperSymbol)) { var temp=upperSymbol.replace('.SH',''); if (upperSymbol.charAt(0)=='6') return true; } else if (this.IsSZ(upperSymbol)) { if (upperSymbol.charAt(0)=='0') { if (upperSymbol.charAt(1)=='0' && upperSymbol.charAt(2)=='2') return true; //002 中小板 if (upperSymbol.charAt(1)!='7' && upperSymbol.charAt(1)!='8') return true; } else if (upperSymbol.charAt(0)=='3') { if (upperSymbol.charAt(1)=='0') { if (upperSymbol.charAt(2)=='0') return true; //创业板 300XXX.sz if (upperSymbol.charAt(2)=='1') return true; //创业板 301XXX.sz } } } return false; }, IsBJStock:function(symbol) //北交所股票 { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); if (!this.IsBJ(upperSymbol)) return false; var value=upperSymbol.charAt(0); if (value=='4' || value=='8') return true; return false; }, IsSHStockSTAR:function(symbol) // 是否是科创板 Sci-Tech innovAtion boaRd (STAR Market) { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); if (!this.IsSH(upperSymbol)) return false; if (upperSymbol.charAt(0)=='6' && upperSymbol.charAt(1)=='8' && upperSymbol.charAt(2)=='8') return true; return false; }, IsSHGEM:function(symbol) //创业板(growth enterprise market) 30开头 { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); if (!this.IsSH(upperSymbol)) return false; if (upperSymbol.charAt(0)=='3' && upperSymbol.charAt(1)=='0') return true; return false; }, GetMarketStatus:function(symbol) //获取市场状态 0=闭市 1=盘前 2=盘中 3=盘后 { if (!symbol) return 0; var upperSymbol=symbol.toUpperCase(); var nowDate= new Date(); var day = nowDate.getDay(); var time = nowDate.getHours() * 100 + nowDate.getMinutes(); if (this.IsUSA(upperSymbol)) { var usaDate=GetLocalTime(-4); var day = usaDate.getDay(); var time = usaDate.getHours() * 100 + usaDate.getMinutes(); if(day == 6 || day== 0) return 0; //周末 //9:30 - 16:00 考虑夏令时间时间增加1小时 9:30 - 17:00 if (time>1730) return 3; if (time<930) return 1; return 2; } else if (this.IsBIT(upperSymbol)) //数字货币24小时 { return 2; } else if (this.IsForeignExchange(upperSymbol)) //外汇24小时 { return 2; } else if (this.IsFTSE(upperSymbol)) //富时中国 9:00-16:30 17:00-04:45 { if(day == 6 || day== 0) return 0; //周末 if (time>=830 && time<=2359) return 2; if (time>=0 && time<=500) return 2; return 0; } else if (this.IsFHK(upperSymbol)) //港股指数期货 9:15-12:00 13:00-16:30 17:15-01:00 { if(day == 6 || day== 0) return 0; //周末 if (time>=900 && time<=2359) return 2; if (time>=0 && time<=320) return 2; return 0; } else if (this.IsET(upperSymbol)) { return this.GetETMarketStatus(symbol); } else if (this.IsHK(upperSymbol)) //港股 { if(day == 6 || day== 0) return 0; //周末 if(time>1630) return 3; if(time<925) return 1; return 2; } else if (this.IsTW(upperSymbol)) //台湾股票 上午9:00——下午1:30 { if(day == 6 || day== 0) return 0; //周末 if(time>1410) return 3; if(time<820) return 1; return 2; } else if (this.IsJP(upperSymbol)) //日本股票 9:00-11:30 12:30-15:00 { if(day == 6 || day== 0) return 0; //周末 if(time>1520) return 3; if(time<830) return 1; return 2; } else if (this.IsNYMEX(upperSymbol)) { return this.GetNYMEXMarketStatus(upperSymbol); } else if (this.IsCOMEX(upperSymbol)) { return this.GetCOMEXMarketStatus(upperSymbol); } else if (this.IsNYBOT(upperSymbol)) { return this.GetNYBOTMarketStatus(upperSymbol); } else if (this.IsCBOT(upperSymbol)) { return this.GetCBOTMarketStatus(upperSymbol); } else if (this.IsLME(upperSymbol)) { return this.GetLMEMarketStatus(upperSymbol); } else if (this.IsTOCOM(upperSymbol)) { return this.GetTOCOMMarketStatus(upperSymbol); } else if (this.IsChinaFutures(upperSymbol)) //国内期货 { if(day == 6 || day== 0) return 0; //周末 if (this.IsCFFEX(upperSymbol)) //中金所期货 9:10-15:40 { if(time>1540) return 3; if(time<910) return 1; return 2; } //21:00-2:30 if(time>=2100) return 2; if (time<=240) return 2; //8:55-11:30, 13:00-15:00 if(time>=830 && time<=1510) return 2; return 1; } else //9:30 - 15:40 (默认9:10-15:40) { if(day == 6 || day== 0) return 0; //周末 if(time>1540) return 3; if(time<910) return 1; return 2; } }, GetLimitPriceRange:function(symbol, name) //涨停范围 { if (!this.IsSHSZStockA(symbol)) return null; if (this.IsSHStockSTAR(symbol)) return {Max:0.2 , Min:-0.2}; //科创板 [20% - -20%] if (this.IsSHGEM(symbol)) return { Max:0.2 , Min:-0.2}; //创业板 [20% - -20%] if (!name) return null; if (name.indexOf('ST')>=0) return { Max:0.05, Min:-0.05 }; //ST 股票 [5% - -5%] return {Max:0.1 , Min:-0.1}; //[10% - -10%] }, GetDefaultDecimal:function(symbol) //默认小数位数 { return 2; }, GetSHDecimal:function(symbol) { return 2; }, GetSZDecimal:function(symbol) { return 2; }, GetFHKDecimal:function(symbol) //港股指数期货 小数位数 { return 0; }, GetFTSEDecimal:function(symbol) //富时中国A50期货 小数位数 { return 0; }, GetBITDecimal:function(symbol) { return 2; }, GetSHODecimal:function(symbol) { return 4; }, GetETDecimal:function(symbol) { return 2; }, GetHKDecimal:function(symbol) { return 2; }, GetTWDecimal:function(symbol) { return 2; }, GetJPDecimal:function(symbol) { return 2; }, GetHSXDecimal:function(symbol) { return 2; }, GetHNXDecimal:function(symbol) { return 2; }, GetUPCOMDecimal:function(symbol) { return 2; }, GetForeignExchangeDecimal:function(symbol) { return 4; }, GetNYMEXDecimal:function(symbol) //纽约期货交易所 { return g_NYMEXTimeData.GetDecimal(symbol); }, GetCOMEXDecimal:function(symbol) { return g_COMEXTimeData.GetDecimal(symbol); }, GetNYBOTDecimal:function(symbol) { return g_NYBOTTimeData.GetDecimal(symbol); }, GetCBOTDecimal:function(symbol) { return g_CBOTTimeData.GetDecimal(symbol); }, GetLMEDecimal:function(symbol) { return g_LMETimeData.GetDecimal(symbol); }, GetTOCOMDecimal:function(symbol) { return g_TOCOMTimeData.GetDecimal(symbol); }, GetIPEDecimal:function(symbol) { return g_IPETimeData.GetDecimal(symbol); }, GetETMarketStatus:function(symbol) { // 0=闭市 1=盘前 2=盘中 3=盘后 return 2; }, GetNYMEXMarketStatus:function(symbol) { return g_NYMEXTimeData.GetMarketStatus(symbol); }, GetCOMEXMarketStatus:function(symbol) { return g_COMEXTimeData.GetMarketStatus(symbol); }, GetNYBOTMarketStatus:function(symbol) { return g_NYBOTTimeData.GetMarketStatus(symbol); }, GetCBOTMarketStatus:function(symbol) { return g_CBOTTimeData.GetMarketStatus(symbol); }, GetLMEMarketStatus:function(symbol) { return g_LMETimeData.GetMarketStatus(symbol); }, GetTOCOMMarketStatus:function(symbol) { return g_TOCOMTimeData.GetMarketStatus(symbol); }, GetIPEMarketStatus:function(symbol) { return g_IPETimeData.GetMarketStatus(symbol); }, IsShowMinuteVolTitle:function(symbol) //是否画走势图成交量标题 { if (!symbol) return false; var upperSymbol=symbol.toUpperCase(); //if (this.IsChinaFutures(upperSymbol)) return true; return false; }, IsShowMinutePostionLine:function(upperSymbol) //分时图 成交量图中是否显示持仓线 { if(MARKET_SUFFIX_NAME.IsFutures(upperSymbol) || MARKET_SUFFIX_NAME.IsSHO(upperSymbol) || MARKET_SUFFIX_NAME.IsSZO(upperSymbol)) return true; return false; }, IsShowMinuteColorVolBar:function(symobl) //是否分时图成绩量柱子使用彩色柱 { if (g_JSChartResource.Minute.VolBarColor) return true; return false; }, IsEnableRight:function(period, symbol, rightFormula) //是否支持复权 { if (!MARKET_SUFFIX_NAME.IsSHSZStockA(symbol) && !MARKET_SUFFIX_NAME.IsBJStock(symbol)) return false; if (ChartData.IsTickPeriod(period)) return false; //分笔没有复权 if (IFrameSplitOperator.IsPlusNumber(rightFormula)) return true; //复权因子复权 if (ChartData.IsMinutePeriod(period,true)) return false; //内置分钟K线不支持复权 return true; } } //走势图分钟数据对应的时间 function MinuteTimeStringData() { this.SHSZ = null; //上海深证交易所时间 this.BJ=null; this.SHO=null; //上海期权交易时间 this.SZO=null; //深证期权交易时间 this.HK = null; //香港交易所时间 this.Futures=new Map(); //期货交易时间 key=时间名称 Value=数据 this.USA = null; //美股交易时间 this.FTSE=null; //富时中国 this.FHK=null; //港股指数期货 this.ForeEx=null; //外汇 this.BIT=null; //数字货币 this.TW=null; //台湾股票 this.JP=null; //日本股票 this.HSX=null; //HSX胡志明交易所 this.HNX=null; //HNX河內交易所 this.UPCOM=null; //UPCOM未上市公司交易所 this.Initialize = function () //初始化 默认只初始化沪深的 其他市场动态生成 { //this.SHSZ = this.CreateSHSZData(); //this.HK = this.CreateHKData(); } this.GetET=function(upperSymbol) //当天所有的分钟 { throw {Name:'MinuteTimeStringData::GetET', Error:'not implement'}; } this.GetSHSZ=function(upperSymbol) //动态创建 { if (!this.SHSZ) this.SHSZ=this.CreateSHSZData(); return this.SHSZ; } this.GetBJ=function(upperSymbol) { if (!this.BJ) this.BJ=this.CreateBJData(); return this.BJ; } this.GetSHO=function(upperSymbol) { if (!this.SHO) this.SHO=this.CreateSHOData(); return this.SHO; } this.GetSZO=function(upperSymbol) { if (!this.SZO) this.SZO=this.CreateSZOData(); return this.SZO; } this.GetHK=function(upperSymbol) { if (!this.HK) this.HK = this.CreateHKData(); return this.HK; } this.GetTW=function(upperSymbol) { if (this.TW) this.TW=this.CreateTWData(); return this.TW; } this.GetJP=function(upperSymbol) { if (this.JP) this.JP=this.CreateJPData(); return this.JP; } this.GetHSX=function(upperSymbol) { if (this.HSX) this.HSX=this.CreateHSXData(); return this.HSX; } this.GetHNX=function(upperSymbol) { if (this.HNX) this.HSX=this.CreateHNXData(); return this.HNX; } this.GetUPCOM=function(upperSymbol) { if (this.UPCOM) this.UPCOM=this.CreateUPCOMData(); return this.UPCOM; } this.GetFutures=function(splitData) { if (!this.Futures.has(splitData.Name)) { var data = this.CreateTimeData(splitData.Data); this.Futures.set(splitData.Name,data); } return this.Futures.get(splitData.Name); } // type=时间类型 this.GetUSA=function(upperSymbol) { if (!this.USA) this.USA=this.CreateUSAData(0); return this.USA; } this.GetFTSE=function() { if (!this.FTSE) this.FTSE=this.CreateFTSEData(); return this.FTSE; } this.GetFHK=function() { if (!this.FHK) this.FHK=this.CreateFHKData(); return this.FHK; } this.GetForeignExchange=function(upperSymbol) { if (!this.ForeEx) this.ForeEx=this.CreateForeignExchangeData(); return this.ForeEx; } this.GetBIT=function(upperSymbol) { if (!this.BIT) this.BIT=this.CreateBITData(); return this.BIT; } this.CreateSHSZData = function () { const TIME_SPLIT = [ { Start: 925, End: 925 }, { Start: 930, End: 1130 }, { Start: 1300, End: 1500 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateBJData=function() { const TIME_SPLIT = [ { Start: 925, End: 925 }, { Start: 930, End: 1130 }, { Start: 1300, End: 1500 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateSHOData=function() { const TIME_SPLIT = [ { Start: 930, End: 1129 }, { Start: 1300, End: 1500 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateSZOData=function() { const TIME_SPLIT = [ { Start: 930, End: 1129 }, { Start: 1300, End: 1500 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateHKData = function () { const TIME_SPLIT = [ { Start: 930, End: 1200 }, { Start: 1300, End: 1600 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateTWData=function() { const TIME_SPLIT = [ { Start: 900, End: 1330 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateJPData=function() { const TIME_SPLIT = [ { Start: 900, End: 1130 }, { Start: 1230, End: 1500 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateFTSEData=function() { const TIME_SPLIT= [ { Start:1700, End:2359 }, { Start:0, End:445 }, { Start:900, End:1630 } ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateFHKData=function() { //港股指数期货 9:15-12:00 13:00-16:30 17:15-03:00 const TIME_SPLIT= [ { Start:1715, End:2359 }, { Start:0, End:300 }, { Start:915, End:1200 }, { Start:1300, End:1630 }, ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateHSXData=function() { throw {Name:'MinuteTimeStringData::CreateHSXData', Error:'not implement'}; } this.CreateHNXData=function() { throw {Name:'MinuteTimeStringData::CreateHNXData', Error:'not implement'}; } this.CreateUPCOMData=function() { throw {Name:'MinuteTimeStringData::CreateUPCOMData', Error:'not implement'}; } this.CreateUSAData=function(type) { if (type==1) //美国夏令时 { const TIME_SPLIT = [ { Start: 2130, End: 2359 }, { Start: 0, End: 400 } ]; return this.CreateTimeData(TIME_SPLIT); } else if (type==2) //非夏令时 { const TIME_SPLIT = [ { Start: 2230, End: 2359 }, { Start: 0, End: 500 } ]; return this.CreateTimeData(TIME_SPLIT); } else //使用美国本地时间 { const TIME_SPLIT = [ { Start: 930, End: 1600 } //美国东部时间9:30到16:00 ]; return this.CreateTimeData(TIME_SPLIT); } } this.CreateForeignExchangeData=function() { //外汇 7:00 - 6:59 const TIME_SPLIT= [ { Start:600, End:2359 }, { Start:0, End:559 }, ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateBITData=function() { //数字货币 7:00 - 6:59 const TIME_SPLIT= [ { Start:600, End:2359 }, { Start:0, End:559 }, ]; return this.CreateTimeData(TIME_SPLIT); } this.CreateTimeData = function (timeSplit) { var data = []; for (var i in timeSplit) { var item = timeSplit[i]; for (var j = item.Start; j <= item.End; ++j) { if (j % 100 >= 60) continue; //大于60分钟的数据去掉 data.push(j); } } return data; } this.GetTimeData = function (symbol) { if (!symbol) return this.SHSZ; var upperSymbol = symbol.toLocaleUpperCase(); //转成大写 if (MARKET_SUFFIX_NAME.IsSHO(upperSymbol)) return this.GetSHO(); if (MARKET_SUFFIX_NAME.IsSZO(upperSymbol)) return this.GetSZO(); if (MARKET_SUFFIX_NAME.IsSH(upperSymbol) || MARKET_SUFFIX_NAME.IsSZ(upperSymbol)) return this.GetSHSZ(upperSymbol); if (MARKET_SUFFIX_NAME.IsBJ(upperSymbol)) return this.GetBJ(upperSymbol); if (MARKET_SUFFIX_NAME.IsHK(upperSymbol)) return this.GetHK(upperSymbol); if (MARKET_SUFFIX_NAME.IsTW(upperSymbol)) return this.GetTW(upperSymbol); if (MARKET_SUFFIX_NAME.IsJP(upperSymbol)) return this.GetJP(upperSymbol); if (MARKET_SUFFIX_NAME.IsUSA(upperSymbol)) return this.GetUSA(upperSymbol); if (MARKET_SUFFIX_NAME.IsCFFEX(upperSymbol) || MARKET_SUFFIX_NAME.IsCZCE(upperSymbol) || MARKET_SUFFIX_NAME.IsDCE(upperSymbol) || MARKET_SUFFIX_NAME.IsSHFE(upperSymbol) || MARKET_SUFFIX_NAME.IsGZFE(upperSymbol)) { var splitData = g_FuturesTimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsFTSE(upperSymbol)) return this.GetFTSE(); if (MARKET_SUFFIX_NAME.IsFHK(upperSymbol)) return this.GetFHK(); if (MARKET_SUFFIX_NAME.IsForeignExchange(upperSymbol)) return this.GetForeignExchange(upperSymbol); if (MARKET_SUFFIX_NAME.IsET(upperSymbol)) return this.GetET(upperSymbol); if (MARKET_SUFFIX_NAME.IsBIT(upperSymbol)) return this.GetBIT(upperSymbol); //越南股市 if (MARKET_SUFFIX_NAME.IsHSX(upperSymbol)) return this.GetHSX(upperSymbol); if (MARKET_SUFFIX_NAME.IsHNX(upperSymbol)) return this.GetHNX(upperSymbol); if (MARKET_SUFFIX_NAME.IsUPCOM(upperSymbol)) return this.GetUPCOM(upperSymbol); if (MARKET_SUFFIX_NAME.IsNYMEX(upperSymbol)) //纽约期货交易所 { var splitData = g_NYMEXTimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsCOMEX(upperSymbol)) //纽约期货交易所 { var splitData = g_COMEXTimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsNYBOT(upperSymbol)) //纽约期货交易所 { var splitData = g_NYBOTTimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsCBOT(upperSymbol)) //芝商所 { var splitData = g_CBOTTimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsLME(upperSymbol)) //伦敦LME { var splitData = g_LMETimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsTOCOM(upperSymbol)) //东京商品交易所(TOCOM) { var splitData = g_TOCOMTimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } if (MARKET_SUFFIX_NAME.IsIPE(upperSymbol)) //东京商品交易所(TOCOM) { var splitData = g_IPETimeData.GetSplitData(upperSymbol); if (!splitData) return null; return this.GetFutures(splitData); } } } //走势图刻度分钟线 function MinuteCoordinateData() { //沪深走势图时间刻度 const SHZE_MINUTE_X_COORDINATE = { Full: //完整模式 [ [0, 0, "rgb(200,200,200)", "09:30"], //[0]=索引 [1]=线段类型(预留) [2]=文字颜色(弃用) [3]=刻度文字 [4]=线段颜色 [5]=背景色 [31, 0, "RGB(200,200,200)", "10:00"], [61, 0, "RGB(200,200,200)", "10:30"], [91, 0, "RGB(200,200,200)", "11:00"], [122, 1, "RGB(200,200,200)", "13:00"], [152, 0, "RGB(200,200,200)", "13:30"], [182, 0, "RGB(200,200,200)", "14:00"], [212, 0, "RGB(200,200,200)", "14:30"], [242, 1, "RGB(200,200,200)", "15:00"], // 15:00 ], Simple: //简洁模式 [ [0, 0, "rgb(200,200,200)", "09:30"], [61, 0, "RGB(200,200,200)", "10:30"], [122, 1, "RGB(200,200,200)", "13:00"], [182, 0, "RGB(200,200,200)", "14:00"], [242, 1, "RGB(200,200,200)", "15:00"] ], Min: //最小模式 [ [0, 0, "rgb(200,200,200)", "09:30"], [122, 1, "RGB(200,200,200)", "13:00"], [242, 1, "RGB(200,200,200)", "15:00"] ], Count: 243, MiddleCount: 122, GetData: function (width) { if (width < 200) return this.Min; else if (width < 400) return this.Simple; return this.Full; } }; //上海股票期权时间刻度 const SHO_MINUTE_X_COORDINATE = { Full: //完整模式 [ [0, 0, "rgb(200,200,200)", "09:30"], [30, 0, "RGB(200,200,200)", "10:00"], [60, 0, "RGB(200,200,200)", "10:30"], [90, 0, "RGB(200,200,200)", "11:00"], [120, 1, "RGB(200,200,200)", "13:00"], [150, 0, "RGB(200,200,200)", "13:30"], [180, 0, "RGB(200,200,200)", "14:00"], [210, 0, "RGB(200,200,200)", "14:30"], [240, 1, "RGB(200,200,200)", "15:00"], // 15:00 ], Simple: //简洁模式 [ [0, 0, "rgb(200,200,200)", "09:30"], [60, 0, "RGB(200,200,200)", "10:30"], [120, 1, "RGB(200,200,200)", "13:00"], [180, 0, "RGB(200,200,200)", "14:00"], [240, 1, "RGB(200,200,200)", "15:00"] ], Min: //最小模式 [ [0, 0, "rgb(200,200,200)", "09:30"], [120, 1, "RGB(200,200,200)", "13:00"], [240, 1, "RGB(200,200,200)", "15:00"] ], Count: 241, MiddleCount: 120, GetData: function (width) { if (width < 200) return this.Min; else if (width < 400) return this.Simple; return this.Full; } }; //港股走势图时间刻度 const HK_MINUTE_X_COORDINATE = { Full: //完整模式 [ [0, 1, "RGB(200,200,200)", "09:30"], [30, 0, "RGB(200,200,200)", "10:00"], [60, 1, "RGB(200,200,200)", "10:30"], [90, 0, "RGB(200,200,200)", "11:00"], [120, 1, "RGB(200,200,200)", "11:30"], [151, 0, "RGB(200,200,200)", "13:00"], [181, 1, "RGB(200,200,200)", "13:30"], [211, 0, "RGB(200,200,200)", "14:00"], [241, 1, "RGB(200,200,200)", "14:30"], [271, 0, "RGB(200,200,200)", "15:00"], [301, 1, "RGB(200,200,200)", "15:30"], [331, 1, "RGB(200,200,200)", "16:00"] ], Simple: //简洁模式 [ [0, 1, "RGB(200,200,200)", "09:30"], [60, 1, "RGB(200,200,200)", "10:30"], [120, 1, "RGB(200,200,200)", "11:30"], [211, 0, "RGB(200,200,200)", "14:00"], [271, 0, "RGB(200,200,200)", "15:00"], [331, 1, "RGB(200,200,200)", "16:00"] ], Min: //最小模式 [ [0, 1, "RGB(200,200,200)", "09:30"], [151, 0, "RGB(200,200,200)", "13:00"], [331, 1, "RGB(200,200,200)", "16:00"] ], Count: 332, MiddleCount: 151, GetData: function (width) { if (width < 200) return this.Min; else if (width < 450) return this.Simple; return this.Full; } }; //美股走势图时间刻度 const USA_MINUTE_X_COORDINATE = { /* Full: //完整模式 [ [0, 0, "rgb(200,200,200)", "21:30"], [60, 0, "RGB(200,200,200)", "22:30"], [120, 1, "RGB(200,200,200)", "23:30"], [210, 0, "RGB(200,200,200)", "01:00"], [270, 0, "RGB(200,200,200)", "02:00"], [330, 0, "RGB(200,200,200)", "03:00"], [390, 0, "RGB(200,200,200)", "04:00"], ], Simple: //简洁模式 [ [0, 0, "rgb(200,200,200)", "21:30"], [160, 1, "RGB(200,200,200)", "00:00"], [270, 0, "RGB(200,200,200)", "02:00"], [390, 0, "RGB(200,200,200)", "04:00"], ], Min: //最小模式 [ [0, 0, "rgb(200,200,200)", "21:30"], [160, 1, "RGB(200,200,200)", "00:00"], [390, 0, "RGB(200,200,200)", "04:00"], ], */ //美国本地时间 Full: //完整模式 [ [0, 0, "rgb(200,200,200)", "9:30"], [30, 0, "RGB(200,200,200)", "10:00"], [90, 1, "RGB(200,200,200)", "11:00"], [150, 0, "RGB(200,200,200)", "12:00"], [210, 0, "RGB(200,200,200)", "13:00"], [270, 0, "RGB(200,200,200)", "14:00"], [330, 0, "RGB(200,200,200)", "15:00"], [390, 0, "RGB(200,200,200)", "16:00"], ], Simple: //简洁模式 [ [30, 0, "rgb(200,200,200)", "10:00"], [150, 1, "RGB(200,200,200)", "12:00"], [270, 0, "RGB(200,200,200)", "14:00"], [390, 0, "RGB(200,200,200)", "16:00"], ], Min: //最小模式 [ [30, 0, "rgb(200,200,200)", "10:00"], [210, 1, "RGB(200,200,200)", "13:00"], [390, 0, "RGB(200,200,200)", "16:00"], ], Count: 391, MiddleCount: 211, GetData: function (width) { if (width < 200) return this.Min; else if (width < 400) return this.Simple; return this.Full; } }; //富时中国 const FTSE_MINUTE_X_COORDINATE= { Full: //完整模式 [ [0, 1, "RGB(200,200,200)", "17:00"], //[60, 0, "RGB(200,200,200)", "18:00"], [120, 1, "RGB(200,200,200)", "19:00"], //[180, 0, "RGB(200,200,200)", "20:00"], [240, 1, "RGB(200,200,200)", "21:00"], //[300, 0, "RGB(200,200,200)", "22:00"], [360, 1, "RGB(200,200,200)", "23:00"], //[420, 0, "RGB(200,200,200)", "00:00"], [480, 1, "RGB(200,200,200)", "01:00"], //[540, 0, "RGB(200,200,200)", "02:00"], [600, 1, "RGB(200,200,200)", "03:00"], //[660, 1, "RGB(200,200,200)", "04:00"], [706, 1, "RGB(200,200,200)", "09:00"], //[766, 1, "RGB(200,200,200)", "10:00"], [826, 1, "RGB(200,200,200)", "11:00"], //[886, 1, "RGB(200,200,200)", "12:00"], [946, 1, "RGB(200,200,200)", "13:00"], //[1006, 1, "RGB(200,200,200)", "14:00"], [1066, 1, "RGB(200,200,200)", "15:00"], [1156, 1, "RGB(200,200,200)", "16:30"], ], Simple: //简洁模式 [ [0, 1, "RGB(200,200,200)", "17:00"], //[60, 0, "RGB(200,200,200)", "18:00"], //[120, 1, "RGB(200,200,200)", "19:00"], //[180, 0, "RGB(200,200,200)", "20:00"], [240, 1, "RGB(200,200,200)", "21:00"], //[300, 0, "RGB(200,200,200)", "22:00"], //[360, 1, "RGB(200,200,200)", "23:30"], //[420, 0, "RGB(200,200,200)", "00:00"], [480, 1, "RGB(200,200,200)", "01:00"], //[540, 0, "RGB(200,200,200)", "02:00"], //[600, 1, "RGB(200,200,200)", "03:00"], //[660, 1, "RGB(200,200,200)", "04:00"], [706, 1, "RGB(200,200,200)", "09:00"], //[766, 1, "RGB(200,200,200)", "10:00"], //[826, 1, "RGB(200,200,200)", "11:00"], //[886, 1, "RGB(200,200,200)", "12:00"], [946, 1, "RGB(200,200,200)", "13:00"], //[1006, 1, "RGB(200,200,200)", "14:00"], //[1066, 1, "RGB(200,200,200)", "15:00"], [1156, 1, "RGB(200,200,200)", "16:30"], ], Min: //最小模式 [ [0, 1, "RGB(200,200,200)", "17:00"], [706, 1, "RGB(200,200,200)", "09:00"], [1156, 1, "RGB(200,200,200)", "16:30"], ], Count: 1157, MiddleCount: 707, GetData: function (width) { if (width < 200) return this.Min; else if (width < 450) return this.Simple; return this.Full; } } //港股指数期货 const FHK_MINUTE_X_COORDINATE= { Full: //完整模式 [ [0, 1, "RGB(200,200,200)", "17:15"], [105, 1, "RGB(200,200,200)", "19:00"], [225, 1, "RGB(200,200,200)", "21:00"], [345, 1, "RGB(200,200,200)", "23:00"], [586, 0, "RGB(200,200,200)", "09:15"], [691, 1, "RGB(200,200,200)", "11:00"], [812, 1, "RGB(200,200,200)", "14:00"], [963, 1, "RGB(200,200,200)", "16:30"], ], Simple: //简洁模式 [ [0, 1, "RGB(200,200,200)", "17:15"], [225, 1, "RGB(200,200,200)", "21:00"], [586, 0, "RGB(200,200,200)", "09:15"], [752, 1, "RGB(200,200,200)", "13:00"], [963, 1, "RGB(200,200,200)", "16:30"], ], Min: //最小模式 [ [0, 1, "RGB(200,200,200)", "17:15"], [586, 0, "RGB(200,200,200)", "09:15"], [963, 1, "RGB(200,200,200)", "16:30"], ], Count: 963, MiddleCount: 526, GetData: function (width) { if (width < 200) return this.Min; else if (width < 450) return this.Simple; return this.Full; } } //外汇 const FOREX_MINUTE_X_COORDINATE= { Full: //完整模式 [ [0, 1, "RGB(200,200,200)", "06:00"], [120, 1, "RGB(200,200,200)", "08:00"], [240, 1, "RGB(200,200,200)", "10:00"], [360, 1, "RGB(200,200,200)", "12:00"], [480, 0, "RGB(200,200,200)", "14:00"], [600, 1, "RGB(200,200,200)", "16:00"], [720, 1, "RGB(200,200,200)", "18:00"], [840, 1, "RGB(200,200,200)", "20:00"], [960, 1, "RGB(200,200,200)", "22:00"], [1080, 1, "RGB(200,200,200)", "0:00"], [1200, 1, "RGB(200,200,200)", "02:00"], [1320, 1, "RGB(200,200,200)", "04:00"], ], Simple: //简洁模式 [ [0, 1, "RGB(200,200,200)", "06:00"], [240, 1, "RGB(200,200,200)", "10:00"], [480, 0, "RGB(200,200,200)", "14:00"], [720, 1, "RGB(200,200,200)", "18:00"], [960, 1, "RGB(200,200,200)", "22:00"], [1200, 1, "RGB(200,200,200)", "02:00"], ], Min: //最小模式 [ [0, 1, "RGB(200,200,200)", "06:00"], [480, 0, "RGB(200,200,200)", "14:00"], [960, 1, "RGB(200,200,200)", "22:00"], ], Count: 1440, MiddleCount: 600, GetData: function (width) { if (width < 200) return this.Min; else if (width < 450) return this.Simple; return this.Full; } } //台湾股票 const TW_MINUTE_X_COORDINATE= { Full: //完整模式 [ [0, 1, "RGB(200,200,200)", "09:00"], [30, 0, "RGB(200,200,200)", "09:30"], [60, 1, "RGB(200,200,200)", "10:00"], [90, 0, "RGB(200,200,200)", "10:30"], [120, 1, "RGB(200,200,200)", "11:00"], [150, 0, "RGB(200,200,200)", "11:30"], [180, 1, "RGB(200,200,200)", "12:00"], [210, 0, "RGB(200,200,200)", "12:30"], [240, 1, "RGB(200,200,200)", "13:00"], [270, 0, "RGB(200,200,200)", "13:30"], ], Simple: //简洁模式 [ [0, 1, "RGB(200,200,200)", "09:00"], [60, 1, "RGB(200,200,200)", "10:00"], [120, 1, "RGB(200,200,200)", "11:00"], [180, 1, "RGB(200,200,200)", "12:00"], [270, 0, "RGB(200,200,200)", "13:30"], ], Min: //最小模式 [ [0, 1, "RGB(200,200,200)", "09:00"], [60, 1, "RGB(200,200,200)", "11:00"], [270, 0, "RGB(200,200,200)", "13:30"], ], Count: 271, MiddleCount: 151, GetData: function (width) { if (width < 200) return this.Min; else if (width < 450) return this.Simple; return this.Full; } } this.GetCoordinateData = function (symbol, width) { var data = null; if (!symbol) { data = SHZE_MINUTE_X_COORDINATE; //默认沪深股票 } else { var upperSymbol = symbol.toLocaleUpperCase(); //转成大写 if (MARKET_SUFFIX_NAME.IsSHO(upperSymbol)) data=this.GetSHOData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsSZO(upperSymbol)) data=this.GetSZOData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsSH(upperSymbol) || MARKET_SUFFIX_NAME.IsSZ(upperSymbol) || MARKET_SUFFIX_NAME.IsSHSZIndex(upperSymbol)) data = this.GetSHSZData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsBJ(upperSymbol)) data=this.GetBJData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsHK(upperSymbol)) data=this.GetHKData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsTW(upperSymbol)) data=this.GetTWData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsJP(upperSymbol)) data=this.GetJPData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsCFFEX(upperSymbol) || MARKET_SUFFIX_NAME.IsCZCE(upperSymbol) || MARKET_SUFFIX_NAME.IsDCE(upperSymbol) || MARKET_SUFFIX_NAME.IsSHFE(upperSymbol) || MARKET_SUFFIX_NAME.IsGZFE(upperSymbol)) return this.GetChinatFuturesData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsUSA(upperSymbol)) data = this.GetUSAData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsFTSE(upperSymbol)) data=this.GetFTSEData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsFHK(upperSymbol)) data=this.GetFHKData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsForeignExchange(upperSymbol)) data=this.GetForeignExchangeData(upperSymbol); else if ((MARKET_SUFFIX_NAME.IsBIT(upperSymbol,width))) data=this.GetBITData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsET(upperSymbol)) data=this.GetETData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsNYMEX(upperSymbol)) return data=this.GetNYMEXData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsCOMEX(upperSymbol)) return data=this.GetCOMEXData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsNYBOT(upperSymbol)) return data=this.GetNYBOTData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsCBOT(upperSymbol)) return data=this.GetCBOTData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsLME(upperSymbol)) return data=this.GetLMEData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsTOCOM(upperSymbol)) return data=this.GetTOCOMData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsIPE(upperSymbol)) return data=this.GetIPEData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsHSX(upperSymbol)) return data=this.GetHSXData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsHNX(upperSymbol)) return data=this.GetHNXData(upperSymbol,width); else if (MARKET_SUFFIX_NAME.IsUPCOM(upperSymbol)) return data=this.GetUPCOMData(upperSymbol,width); } //JSConsole.Chart.Log('[MiuteCoordinateData]', width); var result = { Count: data.Count, MiddleCount: data.MiddleCount, Data: data.GetData(width) }; return result; } this.GetSHSZData=function(upperSymbol,width) { var result=SHZE_MINUTE_X_COORDINATE; return result; } this.GetBJData=function(upperSymbol,width) { var result=SHZE_MINUTE_X_COORDINATE; return result; } this.GetUSAData=function(upperSymbol,width) { var result=USA_MINUTE_X_COORDINATE; return result; } this.GetHKData=function(upperSymbol,width) { var result=HK_MINUTE_X_COORDINATE; return result; } this.GetTWData=function(upperSymbol,width) { return TW_MINUTE_X_COORDINATE; } this.GetSHOData=function(upperSymbol,width) { var result=SHO_MINUTE_X_COORDINATE; return result; } this.GetSZOData=function(upperSymbol,width) { var result=SHO_MINUTE_X_COORDINATE; return result; } this.GetFuturesData = function (upperSymbol,width,timeData) { var splitData = timeData.GetSplitData(upperSymbol); if (!splitData) return null; var stringData = g_MinuteTimeStringData.GetFutures(splitData); if (!stringData) return null; var result = { Count: stringData.length }; var coordinate=null; var minWidth=200, simpleWidth=480; /* if (splitData.Name =='21:00-1:00,9:00-10:15,10:30-11:30,13:30-15:00') { minWidth=250; simpleWidth=500; } */ if (width < minWidth) coordinate = splitData.Coordinate.Min; else if (width < simpleWidth) coordinate = splitData.Coordinate.Simple; else coordinate = splitData.Coordinate.Full; var data=[]; for(var i=0;i430 && time<730) return 1; return 2; } this.AddNewFutures=function(obj) //{ Symbol:品种代码, Time:时间id, Decimal:小数位数, Name:名字 } { if (!obj) return; var newItem={ Symbol:obj.Symbol, Time:obj.Time, Decimal:obj.Decimal, Name:obj.Name }; for(var i=0;i300 && time<1400) return 2; } else if (find.Symbol=="CT") //美棉 21:00-14:20 { if( (time>=0 && time<=1500 ) || (time>=2000 && time<=2359) ) return 2; return 1; } return 0; } } //芝加哥期货交易所 function CBOTTimeData() { this.newMethod=NYMEXTimeData; //派生 this.newMethod(); delete this.newMethod; //标准时间 this.TIME_SPLIT= [ //ID=0 8:00-2:20 { Name:'8:00-2:20', Data: [ //6:00 - 5:00 { Start: 800, End: 2359 }, { Start: 0, End: 220 }, ], Coordinate: { Full://完整模式 [ { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } ], Simple: //简洁模式 [ { Value: 800, Text: '8:00' }, //{ Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, //{ Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, //{ Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, //{ Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' } //{ Value: 200, Text: '2:00' } ], Min: //最小模式 [ { Value: 800, Text: '8:00' }, { Value: 1800, Text: '18:00' }, { Value: 200, Text: '2:00' } ] } }, //ID=1 8:00-2:45 { Name:'8:00-2:45', Data: [ //6:00 - 5:00 { Start: 800, End: 2359 }, { Start: 0, End: 245 }, ], Coordinate: { Full://完整模式 [ { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } ], Simple: //简洁模式 [ { Value: 800, Text: '8:00' }, //{ Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, //{ Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, //{ Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, //{ Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' } //{ Value: 200, Text: '2:00' } ], Min: //最小模式 [ { Value: 800, Text: '8:00' }, { Value: 1800, Text: '18:00' }, { Value: 200, Text: '2:00' } ] } }, //ID=2 6:00-5:00 { Name:'6:00-5:00', Data: [ //6:00 - 5:00 { Start: 600, End: 2359 }, { Start: 0, End: 500 }, ], Coordinate: { Full://完整模式 [ { Value: 600, Text: '6:00' }, { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' }, { Value: 400, Text: '4:00' }, ], Simple: //简洁模式 [ { Value: 600, Text: '6:00' }, //{ Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, //{ Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, //{ Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, //{ Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, //{ Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } //{ Value: 400, Text: '4:00' }, ], Min: //最小模式 [ { Value: 600, Text: '6:00' }, { Value: 1800, Text: '18:00' }, { Value: 500, Text: '5:00' } ] } }, //ID=3 08:00-20:45 21:31-02:20 { Name:'08:00-20:45 21:31-02:20', Data: [ { Start: 800, End: 2045 }, { Start: 2131, End: 2359 }, { Start: 0, End: 220 }, ], Coordinate: { Full://完整模式 [ { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } ], Simple: //简洁模式 [ { Value: 800, Text: '8:00' }, //{ Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, //{ Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, //{ Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, //{ Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' } //{ Value: 200, Text: '2:00' } ], Min: //最小模式 [ { Value: 800, Text: '8:00' }, { Value: 1800, Text: '18:00' }, { Value: 200, Text: '2:00' } ] } }, //ID=4 8:00-20:45 21:31-2:45 { Name:'8:00-2:45', Data: [ { Start: 800, End: 2045 }, { Start: 2131, End: 2359 }, { Start: 0, End: 245 }, ], Coordinate: { Full://完整模式 [ { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } ], Simple: //简洁模式 [ { Value: 800, Text: '8:00' }, //{ Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, //{ Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, //{ Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, //{ Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' } //{ Value: 200, Text: '2:00' } ], Min: //最小模式 [ { Value: 800, Text: '8:00' }, { Value: 1800, Text: '18:00' }, { Value: 200, Text: '2:00' } ] } }, //ID=5 06:00-04:15 04:31-05:00 { Name:'06:00-04:15 04:31-05:00', Data: [ { Start: 600, End: 2359 }, { Start: 0, End: 415 }, { Start: 431, End: 500 }, ], Coordinate: { Full://完整模式 [ { Value: 600, Text: '6:00' }, { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' }, { Value: 400, Text: '4:00' }, ], Simple: //简洁模式 [ { Value: 600, Text: '6:00' }, //{ Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, //{ Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, //{ Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, //{ Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, //{ Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } //{ Value: 400, Text: '4:00' }, ], Min: //最小模式 [ { Value: 600, Text: '6:00' }, { Value: 1800, Text: '18:00' }, { Value: 500, Text: '5:00' } ] } } ] //夏令时间 this.TIME_SPLIT2= [ //ID=0 9:00-3:20 { Name:'9:00-3:20', Data: [ { Start: 900, End: 2359 }, { Start: 0, End: 320 }, ], Coordinate: { Full://完整模式 [ { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' } ], Simple: //简洁模式 [ { Value: 900, Text: '9:00' }, //{ Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, //{ Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, //{ Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, //{ Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' } //{ Value: 300, Text: '3:00' } ], Min: //最小模式 [ { Value: 900, Text: '9:00' }, { Value: 1900, Text: '19:00' }, { Value: 300, Text: '3:00' } ] } }, //ID=1 9:00-3:45 { Name:'9:00-3:45', Data: [ { Start: 900, End: 2359 }, { Start: 0, End: 345 }, ], Coordinate: { Full://完整模式 [ { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' } ], Simple: //简洁模式 [ { Value: 900, Text: '9:00' }, //{ Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, //{ Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, //{ Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, //{ Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' } //{ Value: 300, Text: '3:00' } ], Min: //最小模式 [ { Value: 900, Text: '9:00' }, { Value: 1900, Text: '19:00' }, { Value: 300, Text: '3:00' } ] } }, //ID=2 7:00-6:00 { Name:'7:00-6:00', Data: [ { Start: 700, End: 2359 }, { Start: 0, End: 600 }, ], Coordinate: { Full://完整模式 [ { Value: 700, Text: '7:00' }, { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' }, { Value: 500, Text: '5:00' } ], Simple: //简洁模式 [ { Value: 700, Text: '7:00' }, //{ Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, //{ Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, //{ Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, //{ Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, //{ Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' } //{ Value: 500, Text: '5:00' } ], Min: //最小模式 [ { Value: 700, Text: '7:00' }, { Value: 1800, Text: '18:00' }, { Value: 500, Text: '5:00' } ] } }, //ID=3 09:00-21:45 22:31-03:20 { Name:'09:00-21:45 22:31-03:20', Data: [ { Start: 900, End: 2145 }, { Start: 2231, End: 2359 }, { Start: 0, End: 320 }, ], Coordinate: { Full://完整模式 [ { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' } ], Simple: //简洁模式 [ { Value: 900, Text: '9:00' }, //{ Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, //{ Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, //{ Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, //{ Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' } //{ Value: 300, Text: '3:00' } ], Min: //最小模式 [ { Value: 900, Text: '9:00' }, { Value: 1900, Text: '19:00' }, { Value: 300, Text: '3:00' } ] } }, //ID=4 09:00-21:45 22:31-03:45 { Name:'09:00-21:45 22:31-03:45', Data: [ { Start: 900, End: 2145 }, { Start: 2231, End: 2359 }, { Start: 0, End: 345 }, ], Coordinate: { Full://完整模式 [ { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' } ], Simple: //简洁模式 [ { Value: 900, Text: '9:00' }, //{ Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, //{ Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, //{ Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, //{ Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' } //{ Value: 300, Text: '3:00' } ], Min: //最小模式 [ { Value: 900, Text: '9:00' }, { Value: 1900, Text: '19:00' }, { Value: 300, Text: '3:00' } ] } }, //ID=5 07:00-05:15 05:31-06:00 { Name:'07:00-05:15 05:31-06:00', Data: [ { Start: 700, End: 2359 }, { Start: 0, End: 515 }, { Start: 531, End: 600 }, ], Coordinate: { Full://完整模式 [ { Value: 700, Text: '7:00' }, { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' }, { Value: 500, Text: '5:00' } ], Simple: //简洁模式 [ { Value: 700, Text: '7:00' }, //{ Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, //{ Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, //{ Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, //{ Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, //{ Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' } //{ Value: 500, Text: '5:00' } ], Min: //最小模式 [ { Value: 700, Text: '7:00' }, { Value: 1800, Text: '18:00' }, { Value: 500, Text: '5:00' } ] } } ] this.FUTURES_LIST= [ { Symbol:"ZC", Decimal:2, Time:0, Name:"玉米" }, //玉米 { Symbol:"XC", Decimal:2, Time:1, Name:"迷你玉米" }, //迷你玉米 { Symbol:"ZS", Decimal:2, Time:0, Name:'大豆' }, //大豆 { Symbol:"XK", Decimal:2, Time:1, Name:"迷你大豆" }, //迷你大豆 { Symbol:"ZL", Decimal:2, Time:0, Name:"豆油"}, //豆油 { Symbol:"ZR", Decimal:2, Time:0, Name:"稻谷" }, //稻谷 { Symbol:"ZO", Decimal:2, Time:0, Name:"燕麦" }, //燕麦 { Symbol:"ZW", Decimal:2, Time:0, Name:'小麦'}, //小麦 { Symbol:"XW", Decimal:2, Time:1, Name:"迷你小麦" }, //迷你小麦 { Symbol:"ZM", Decimal:1, Time:0, Name:"豆粕" }, //豆粕 { Symbol:"EH", Decimal:3, Time:2 }, //乙醇 { Symbol:"YM", Decimal:0, Time:2, Name:"小型道指"}, //小型道指 { Symbol:"ES", Decimal:2, Time:2, Name:"小型标普" }, //小型标普 { Symbol:"NQ", Decimal:2, Time:2, Name:"小型纳指" }, //小型纳指 { Symbol:"TY", Decimal:4, Time:2, Name:"10年美国债" }, //10年美国债 { Symbol:"TU", Decimal:4, Time:2, Name:"2年美国债" }, //2年美国债 { Symbol:"FV", Decimal:4, Time:2, Name:"5年美国债" }, //5年美国债 { Symbol:"US", Decimal:4, Time:2, Name:"30年美国债" }, //30年美国债 { Symbol:"UL", Decimal:4, Time:2, Name:"超国债" }, //超国债 ] this.MarketSuffix=".CBOT"; } //伦敦金属交易所 LME function LMETimeData() { this.newMethod=NYMEXTimeData; //派生 this.newMethod(); delete this.newMethod; //标准时间 this.TIME_SPLIT= [ { Name:'LME 9:00-3:00', Data: [ { Start: 900, End: 2359 }, { Start: 0, End: 300 }, ], Coordinate: { Full://完整模式 [ { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 100, Text: '1:00' }, { Value: 300, Text: '3:00' } ], Simple: //简洁模式 [ { Value: 900, Text: '9:00' }, //{ Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, //{ Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, //{ Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, //{ Value: 2300, Text: '23:00' }, { Value: 100, Text: '1:00' } // { Value: 300, Text: '3:00' } ], Min: //最小模式 [ { Value: 900, Text: '9:00' }, { Value: 1800, Text: '18:00' }, { Value: 300, Text: '3:00' } ] } } ] //夏令 this.TIME_SPLIT= [ { Name:'LME 8:00-2:00', Data: [ { Start: 800, End: 2359 }, { Start: 0, End: 200 }, ], Coordinate: { Full://完整模式 [ { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' } ], Simple: //简洁模式 [ { Value: 800, Text: '8:00' }, //{ Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, //{ Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, //{ Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, //{ Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' } //{ Value: 200, Text: '2:00' } ], Min: //最小模式 [ { Value: 800, Text: '8:00' }, { Value: 1800, Text: '18:00' }, { Value: 200, Text: '2:00' } ] } } ] this.FUTURES_LIST= [ { Symbol:"SN", Decimal:0, Time:0, Name:"LME锡" }, //综合锡03 { Symbol:"AH", Decimal:2, Time:0, Name:"LME铝" }, //综合铝03 { Symbol:"PB", Decimal:2, Time:0, Name:"LME铅" }, //综合铅03 { Symbol:"ZS", Decimal:2, Time:0, Name:"LME锌" }, //综合锌03 { Symbol:"CA", Decimal:2, Time:0, Name:"LME铜" }, //综合铜03 { Symbol:"NI", Decimal:0, Time:0, Name:"LME镍" }, //综合镍03 ] this.MarketSuffix=".LME"; } //东京商品交易所(TOCOM) function TOCOMTimeData() { this.newMethod=NYMEXTimeData; //派生 this.newMethod(); delete this.newMethod; this.TimeType=0; this.TIME_SPLIT= [ //ID=0 15:30-04:30 07:46-14:15 { Name:'15:30-04:30 07:46-14:15', Data: [ { Start: 1530, End: 2359}, { Start: 0, End: 430 }, { Start: 746, End: 1415 }, ], Coordinate: { Full://完整模式 [ { Value: 1530, Text: '15:30' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 100, Text: '1:00' }, { Value: 300, Text: '3:00' }, { Value: 430, Text: '4:30' }, { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1415, Text: '14:15' } ], Simple: //简洁模式 [ { Value: 1530, Text: '15:30' }, { Value: 1900, Text: '19:00' }, { Value: 2300, Text: '23:00' }, { Value: 100, Text: '1:00' }, { Value: 430, Text: '4:30' }, { Value: 1100, Text: '11:00' }, { Value: 1415, Text: '14:15' } ], Min: //最小模式 [ { Value: 1530, Text: '15:30' }, { Value: 100, Text: '1:00' }, { Value: 1415, Text: '14:15' } ] } } ]; this.FUTURES_LIST= [ { Symbol:"JRV", Decimal:0, Time:0, Name:"东京TSR20橡胶" }, { Symbol:"JPL", Decimal:0, Time:0, Name:"东京铂金" }, { Symbol:"JAU", Decimal:0, Time:0, Name:"东京黄金" }, { Symbol:"JCO", Decimal:0, Time:0, Name:"中东原油" }, { Symbol:"JRU", Decimal:1, Time:0, Name:"东京RSS3橡胶橡胶" }, { Symbol:"JAG", Decimal:1, Time:0, Name:"日白银" } , { Symbol:"JPA", Decimal:1, Time:0, Name:"日钯金" } ] this.MarketSuffix=".TOCOM"; } //美国洲际交易所(ICE EUROPE) function IPETimeData() { this.newMethod=NYMEXTimeData; //派生 this.newMethod(); delete this.newMethod; this.MarketSuffix=".IPE"; //美国标准时间 this.TIME_SPLIT= [ //ID=0 8:00-6:00 { Name:'8:00-6:00', Data: [ { Start: 800, End: 2359 }, { Start: 0, End: 600 }, ], Coordinate: { Full://完整模式 [ { Value: 800, Text: '8:00' }, { Value: 1000, Text: '10:00' }, { Value: 1200, Text: '12:00' }, { Value: 1400, Text: '14:00' }, { Value: 1600, Text: '16:00' }, { Value: 1800, Text: '18:00' }, { Value: 2000, Text: '20:00' }, { Value: 2200, Text: '22:00' }, { Value: 0, Text: '0:00' }, { Value: 200, Text: '2:00' }, { Value: 400, Text: '4:00' }, { Value: 600, Text: '6:00' }, ], Simple: //简洁模式 [ { Value: 800, Text: '8:00' }, { Value: 1200, Text: '12:00' }, { Value: 1600, Text: '16:00' }, { Value: 2000, Text: '20:00' }, { Value: 0, Text: '0:00' }, { Value: 400, Text: '4:00' }, { Value: 600, Text: '6:00' }, ], Min: //最小模式 [ { Value: 800, Text: '8:00' }, { Value: 2000, Text: '20:00' }, { Value: 600, Text: '6:00' } ] } } ] //美国夏时令 this.TIME_SPLIT2= [ //ID=0 09:00-07:00 { Name:'09:00-07:00', Data: [ { Start: 900, End: 2359 }, { Start: 0, End: 700 }, ], Coordinate: { Full://完整模式 [ { Value: 900, Text: '9:00' }, { Value: 1100, Text: '11:00' }, { Value: 1300, Text: '13:00' }, { Value: 1500, Text: '15:00' }, { Value: 1700, Text: '17:00' }, { Value: 1900, Text: '19:00' }, { Value: 2100, Text: '21:00' }, { Value: 2300, Text: '23:00' }, { Value: 1, Text: '1:00' }, { Value: 300, Text: '3:00' }, { Value: 500, Text: '5:00' }, { Value: 700, Text: '7:00' } ], Simple: //简洁模式 [ { Value: 900, Text: '9:00' }, { Value: 1300, Text: '13:00' }, { Value: 1700, Text: '17:00' }, { Value: 2100, Text: '21:00' }, { Value: 1, Text: '1:00' }, { Value: 500, Text: '5:00' }, { Value: 700, Text: '7:00' } ], Min: //最小模式 [ { Value: 900, Text: '9:00' }, { Value: 2100, Text: '21:00' }, { Value: 700, Text: '7:00' } ] } } ] this.FUTURES_LIST= [ { Symbol:"RC", Decimal:2, Time:0, Name:"罗布斯塔咖啡" }, { Symbol:"W", Decimal:2, Time:0, Name:"白糖" }, { Symbol:"C", Decimal:2, Time:0, Name:"伦敦可可" }, { Symbol:"R", Decimal:2, Time:0, Name:"长期英国国债" }, { Symbol:"L", Decimal:2, Time:0, Name:"3个月英镑利率" }, { Symbol:"T", Decimal:2, Time:0, Name:"WTI原油" }, { Symbol:"G", Decimal:2, Time:0, Name:"低硫柴油" }, { Symbol:"B", Decimal:2, Time:0, Name:"布伦特原油" } ] } var g_MinuteTimeStringData = new MinuteTimeStringData(); var g_MinuteCoordinateData = new MinuteCoordinateData(); var g_FuturesTimeData = new FuturesTimeData(); var g_NYMEXTimeData=new NYMEXTimeData(); var g_COMEXTimeData=new COMEXTimeData(); var g_NYBOTTimeData=new NYBOTTimeData(); var g_CBOTTimeData=new CBOTTimeData(); var g_LMETimeData=new LMETimeData(); var g_TOCOMTimeData=new TOCOMTimeData(); var g_IPETimeData=new IPETimeData(); function GetfloatPrecision(symbol) //获取小数位数 { var defaultfloatPrecision=2; //默认2位 if (!symbol) return defaultfloatPrecision; var upperSymbol=symbol.toUpperCase(); //全部由外部控制 if (typeof(MARKET_SUFFIX_NAME.GetCustomDecimal)=='function') return MARKET_SUFFIX_NAME.GetCustomDecimal(upperSymbol); if (MARKET_SUFFIX_NAME.IsSHSZFund(upperSymbol)) defaultfloatPrecision=3; //基金3位小数 else if (MARKET_SUFFIX_NAME.IsSHO(upperSymbol) || MARKET_SUFFIX_NAME.IsSZO(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetSHODecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol)) defaultfloatPrecision=g_FuturesTimeData.GetDecimal(upperSymbol); //期货小数位数读配置 else if (MARKET_SUFFIX_NAME.IsFHK(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetFHKDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsFTSE(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetFTSEDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsBIT(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetBITDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsET(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetETDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsForeignExchange(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetForeignExchangeDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsNYMEX(upperSymbol)) defaultfloatPrecision=g_NYMEXTimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsCOMEX(upperSymbol)) defaultfloatPrecision=g_COMEXTimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsNYBOT(upperSymbol)) defaultfloatPrecision=g_NYBOTTimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsCBOT(upperSymbol)) defaultfloatPrecision=g_CBOTTimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsLME(upperSymbol)) defaultfloatPrecision=g_LMETimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsTOCOM(upperSymbol)) defaultfloatPrecision=g_TOCOMTimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsIPE(upperSymbol)) defaultfloatPrecision=g_IPETimeData.GetDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsHK(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetHKDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsTW(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetTWDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsJP(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetJPDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsHSX(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetHSXDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsHNX(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetHNXDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsUPCOM(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetUPCOMDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsSZ(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetSZDecimal(upperSymbol); else if (MARKET_SUFFIX_NAME.IsSH(upperSymbol)) defaultfloatPrecision=MARKET_SUFFIX_NAME.GetSHDecimal(upperSymbol); else defaultfloatPrecision=MARKET_SUFFIX_NAME.GetDefaultDecimal(upperSymbol); return defaultfloatPrecision; } //把不连续的分时数据转成连续的分时数据 function GenerateMinuteStockJsonData(data) { var stock = { symbol:data.symbol, name:data.name,time:data.time, date:data.date, price:data.price, open:data.open, yclose:data.yclose, high:data.high, low:data.low, vol:data.vol,amount:data.amount, minute:[] }; var mapMinute=new Map(); for(var i in data.minute) { var item=data.minute[i]; mapMinute.set(item.time,item); } var timeData=g_MinuteTimeStringData.GetTimeData(stock.symbol); for(var i in timeData) //根据交易时间产生数据 { var time=timeData[i]; var minuteItem={ time:time, vaild:false }; if (mapMinute.has(time)) { var find=mapMinute.get(time); minuteItem.vaild=true; minuteItem.price=find.price; minuteItem.open=find.open; minuteItem.high=find.high; minuteItem.low=find.low; minuteItem.avprice=find.avprice; minuteItem.vol=find.vol; minuteItem.amount=find.amount; if (IFrameSplitOperator.IsNumber(find.increase)) minuteItem.increase=find.increase; if (IFrameSplitOperator.IsNumber(find.risefall)) minuteItem.risefall=find.risefall; if (IFrameSplitOperator.IsNumber(find.position)) minuteItem.position=find.position; } stock.minute.push(minuteItem); } var vaildCount=0; for(var i=stock.minute.length-1;i>=0;--i) { vaildCount=i+1; var item=stock.minute[i]; if (item.vaild==true) break; } stock.minute=stock.minute.slice(0,vaildCount); //去掉最后无用的数据 return stock; } function GetLocalTime(i) //得到标准时区的时间的函数 { if (typeof i !== 'number') return; var d = new Date(); //得到1970年一月一日到现在的秒数 var len = d.getTime(); //本地时间与GMT时间的时间偏移差 var offset = d.getTimezoneOffset() * 60000; //得到现在的格林尼治时间 var utcTime = len + offset; return new Date(utcTime + 3600000 * i); } /* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 分析家语法编译执行器 (H5版本) */ //日志输出类 if (!JSConsole) { var JSConsole= { Chart:{ Log:console.log, Warn:console.warn }, //图形日志 Complier:{ Log:console.log, Warn:console.warn } //编译器日志 }; } //API默认地址 var g_JSComplierResource= { Domain : "http://127.0.0.1:8080", //API域名 CacheDomain : "http://127.0.0.1:8087", //缓存域名 DrawIcon: { Family:'iconfont', Data:new Map([ [1, { Text:'\ue660', Color:'rgb(243,28,15)'}], //向上箭头 [2, { Text:'\ue661', Color:'rgb(87,247,41)'}], //向下箭头 [3, { Text:'\ue662', Color:'rgb(237,153,0)'}], [4, { Text:'\ue663', Color:'rgb(237,153,0)'}], [5, { Text:'\ue664', Color:'rgb(237,153,0)'}], [6, { Text:'\ue665', Color:'rgb(140,57,208)'}], [7, { Text:'\ue666', Color:'rgb(246,135,37)'}], [8, { Text:'\ue667', Color:'rgb(85,231,56)'}], [9, { Text:'\ue668', Color:'rgb(227,61,41)'}], [10, { Text:'\ue669', Color:'rgb(216,78,48)'}], [11, { Text:'\ue66a', Color:'rgb(249,187,0)'}], //点赞 [12, { Text:'\ue66b', Color:'rgb(249,187,0)'}], [13, { Text:'\ue66c', Color:'rgb(216,42,0)'}], [14, { Text:'\ue66d', Color:'rgb(58,90,236)'}], [15, { Text:'\ue66e', Color:'rgb(227,149,0)'}], [16, { Text:'\ue66f', Color:'rgb(208,82,78)'}], [17, { Text:'\ue670', Color:'rgb(234,114,26)'}], [18, { Text:'\ue671', Color:'rgb(116,25,255)'}], [19, { Text:'\ue672', Color:'rgb(102,9,11)'}], [20, { Text:'\ue673', Color:'rgb(127,125,137)'}], [21, { Text:'\ue674', Color:'rgb(110,188,255)'}], [22, { Text:'\ue675', Color:'rgb(238,79,51)'}], [23, { Text:'\ue676', Color:'rgb(244,71,0)'}], [24, { Text:'\ue677', Color:'rgb(102,183,248)'}], [25, { Text:'\ue678', Color:'rgb(234,88,231)'}], [26, { Text:'\ue679', Color:'rgb(242,171,0)'}], [27, { Text:'\ue67a', Color:'rgb(87,247,168)'}], [28, { Text:'\ue67b', Color:'rgb(97,204,113)'}], [29, { Text:'\ue67c', Color:'rgb(84,115,193)'}], [30, { Text:'\ue67d', Color:'rgb(141,51,255)'}], [31, { Text:'\ue67e', Color:'rgb(200,126,24)'}], [32, { Text:'\ue67f', Color:'rgb(195,41,32)'}], [33, { Text:'\ue68f', Color:'rgb(215,85,194)'}], [34, { Text:'\ue690', Color:'rgb(250,222,105)'}], [35, { Text:'\ue691', Color:'rgb(112,249,224)'}], [36, { Text:'\ue692', Color:'rgb(217,107,98)'}], [37, { Text:'\ue693', Color:'rgb(114,231,17)'}], [38, { Text:'\ue694', Color:'rgb(238,31,25)'}], [39, { Text:'\ue695', Color:'rgb(92,247,113)'}], [40, { Text:'\ue696', Color:'rgb(175,175,175)'}], [41, { Text:'\ue697', Color:'rgb(252,228,23)'}], [42, { Text:'\ue698', Color:'rgb(88,195,235)'}], [43, { Text:'\ue699', Color:'rgb(55,74,94)'}], [44, { Text:'\ue69a', Color:'rgb(248,175,33)'}], [45, { Text:'\ue69b', Color:'rgb(194,180,112)'}], [46, { Text:'\ue69c', Color:'rgb(50,153,28)'}], [47, { Text:'\ue69d', Color:'rgb(17,65,152)'}], [48, { Text:'\ue69e', Color:'rgb(194,55,26)'}], [49, { Text:'\ue69f', Color:'rgb(243,0,0)'}], /* [11,{ Text:'\ue624', Color:'rgb(245,159,40)'}], [12,{ Text:'\ue600', Color:'rgb(245,159,40)'}], [13,{Text:'\ue70f',Color:'rgb(209,37,35)'}, ], //B [14,{Text:'\ue64c',Color:'rgb(127,209,59)'} ], //S [9, {Text:'\ue626',Color:'rgb(245,159,40)'} ], //$ [36,{Text:'\ue68c',Color:'rgb(255,106,106)'} ], //关闭 红色 [37,{Text:'\ue68c',Color:'rgb(46,139,87)'} ], //关闭 绿色 [38,{Text:'\ue68d',Color:'rgb(238,44,44)'} ], //▲ [39,{Text:'\ue68e',Color:'rgb(0,139,69)'} ], //▼ [46,{Text:'\ue64d',Color:'rgb(51,51,51)'} ], //message */ ]) }, CustomDrawIcon: { Data:new Map() //自定义图标 key=id //value={ID:, Text:, Color, Family: } //svg //value={ ID:1, Symbol:'↑', Color:'rgb(238,44,44)' } //文字 }, CustomFunction: //定制函数 { Data:new Map() //自定义函数 key=函数名, Value:{ID:函数名, Callback: } }, CustomVariant: //自定义变量 { Data:new Map() //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息 } }, CustomDataFunction: //自定义数据函数 { //自定义函数 key=变量名, Value:{ Name:变量名, Description:描述信息, ArgCount:参数个数 } Data:new Map( [ [ "L2_VOLNUM", { Name:"L2_VOLNUM", Description:"单数分档,按: N(0--1):(超大+大)/(中+小),M(0--1):买/卖二类,沪深京品种的资金流向,仅日线以上周期,用于特定版本", ArgCount:2 } ], [ "L2_VOL", { Name:"L2_VOL", Description:"成交量分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本", ArgCount:2 } ], [ "L2_AMO", { Name:"L2_AMO", Description:"成交额分档,按: N(0--3):超大/大/中/小四档处理,M(0--3):买入/卖出/主买/主卖四类,沪深京品种的资金流向,仅日线以上周期,用于特定版本", ArgCount:2 } ] ]) }, GetDrawIcon:function(id) { var icon; if (g_JSComplierResource.CustomDrawIcon.Data.has(id)) { const iconfont=g_JSComplierResource.CustomDrawIcon.Data.get(id); if (iconfont.Symbol) //文字 icon={ Symbol:iconfont.Symbol, Color:iconfont.Color, IconFont:false, ID:id }; else //SVG图标 icon={ Symbol:iconfont.Text, Color:iconfont.Color, Family:iconfont.Family, IconFont:true, ID:id }; return icon; } if (g_JSComplierResource.DrawIcon.Data.has(id)) { const iconfont=g_JSComplierResource.DrawIcon.Data.get(id); icon={ Symbol:iconfont.Text, Color:iconfont.Color, Family:g_JSComplierResource.DrawIcon.Family, IconFont:true, ID:id }; return icon; } return null; }, GetDrawTextIcon:function(id) { //图标对应的字符代码 let mapIcon=new Map([ [1,{Symbol:'↑',Color:'rgb(238,44,44)'} ],[2,{Symbol:'↓',Color:'rgb(0,139,69)'} ], [3,{Symbol:'😧'} ],[4,{Symbol:'😨'} ],[5,{Symbol:'😁'} ],[6,{Symbol:'😱'} ], [7,{Symbol:'B',Color:'rgb(238,44,44)'} ],[8,{Symbol:'S',Color:'rgb(0,139,69)'} ], [9,{Symbol:'💰'} ],[10,{Symbol:'📪'} ],[11,{Symbol:'👆'} ],[12,{Symbol:'👇'} ], [13,{Symbol:'B',Color:'rgb(178,34,34)'}, ],[14,{Symbol:'S',Color:'rgb(0,139,69)'} ], [36,{Symbol:'Χ',Color:'rgb(238,44,44)'} ],[37,{Symbol:'X',Color:'rgb(0,139,69)'} ], [38,{Symbol:'▲',Color:'rgb(238,44,44)'} ],[39,{Symbol:'▼',Color:'rgb(0,139,69)'} ], [40,{Symbol:'◉',Color:'rgb(238,44,44)'}], [41,{Symbol:'◈',Color:'rgb(238,44,44)'}], [42,{Symbol:'📌'}], [43,{Symbol:'💎'}], [44,{Symbol:'🥇'}],[45,{Symbol:'🥈'}],[46,{Symbol:'🥉'}],[47,{Symbol:'🏅'}] ]); var icon=mapIcon.get(id); return icon; }, IsCustomFunction:function(name) { if (g_JSComplierResource.CustomFunction.Data.has(name)) return true; return false; }, IsCustomVariant:function(name) { if (g_JSComplierResource.CustomVariant.Data.has(name)) return true; return false; }, IsCustomDataFunction:function(name) { if (g_JSComplierResource.CustomDataFunction.Data.has(name)) return true; return false; } } var Messages = { BadGetterArity: 'Getter must not have any formal parameters', BadSetterArity: 'Setter must have exactly one formal parameter', BadSetterRestParameter: 'Setter function argument must not be a rest parameter', ConstructorIsAsync: 'Class constructor may not be an async method', ConstructorSpecialMethod: 'Class constructor may not be an accessor', DeclarationMissingInitializer: 'Missing initializer in %0 declaration', DefaultRestParameter: 'Unexpected token =', DuplicateBinding: 'Duplicate binding %0', DuplicateConstructor: 'A class may only have one constructor', DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer', GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts', IllegalBreak: 'Illegal break statement', IllegalContinue: 'Illegal continue statement', IllegalExportDeclaration: 'Unexpected token', IllegalImportDeclaration: 'Unexpected token', IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list', IllegalReturn: 'Illegal return statement', InvalidEscapedReservedWord: 'Keyword must not contain escaped characters', InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence', InvalidLHSInAssignment: 'Invalid left-hand side in assignment', InvalidLHSInForIn: 'Invalid left-hand side in for-in', InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', InvalidModuleSpecifier: 'Unexpected token', InvalidRegExp: 'Invalid regular expression', LetInLexicalBinding: 'let is disallowed as a lexically bound name', MissingFromClause: 'Unexpected token', MultipleDefaultsInSwitch: 'More than one default clause in switch statement', NewlineAfterThrow: 'Illegal newline after throw', NoAsAfterImportNamespace: 'Unexpected token', NoCatchOrFinally: 'Missing catch or finally after try', ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', Redeclaration: '%0 \'%1\' has already been declared', StaticPrototype: 'Classes may not have static property named prototype', StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', StrictDelete: 'Delete of an unqualified identifier in strict mode.', StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block', StrictFunctionName: 'Function name may not be eval or arguments in strict mode', StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', StrictModeWith: 'Strict mode code may not include a with statement', StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', StrictParamDupe: 'Strict mode function may not have duplicate parameter names', StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', StrictReservedWord: 'Use of future reserved word in strict mode', StrictVarName: 'Variable name may not be eval or arguments in strict mode', TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', UnexpectedEOS: 'Unexpected end of input', UnexpectedIdentifier: 'Unexpected identifier', UnexpectedNumber: 'Unexpected number', UnexpectedReserved: 'Unexpected reserved word', UnexpectedString: 'Unexpected string', UnexpectedTemplate: 'Unexpected quasi %0', UnexpectedToken: 'Unexpected token %0', UnexpectedTokenIllegal: 'Unexpected token ILLEGAL', UnknownLabel: 'Undefined label \'%0\'', UnterminatedRegExp: 'Invalid regular expression: missing /' }; var Regex = { // Unicode v8.0.0 NonAsciiIdentifierStart: NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/, // Unicode v8.0.0 NonAsciiIdentifierPart: NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ } var Character = { FromCodePoint: function (cp) { return (cp < 0x10000) ? String.fromCharCode(cp) : String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); }, //是否是空格 https://tc39.github.io/ecma262/#sec-white-space IsWhiteSpace:function(cp) { return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) || (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0); }, //是否换行 https://tc39.github.io/ecma262/#sec-line-terminators IsLineTerminator:function(cp) { return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029); }, // https://tc39.github.io/ecma262/#sec-names-and-keywords IsIdentifierStart:function(cp) { return (cp === 0x24) || (cp === 0x5F) || (cp >= 0x41 && cp <= 0x5A) || (cp >= 0x61 && cp <= 0x7A) || (cp === 0x5C) || //【】▲▼ (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) || ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(Character.FromCodePoint(cp))); }, IsIdentifierPart: function (cp) { return (cp === 0x24) || (cp === 0x5F) || (cp >= 0x41 && cp <= 0x5A) || (cp >= 0x61 && cp <= 0x7A) || (cp >= 0x30 && cp <= 0x39) || (cp === 0x5C) || (cp===0x23) || //【】▲▼ (cp===0x3010 || cp===0x3011 || cp===0x25B2 || cp===0x25BC) || ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(Character.FromCodePoint(cp))); }, // https://tc39.github.io/ecma262/#sec-literals-numeric-literals IsDecimalDigit: function (cp) { return (cp >= 0x30 && cp <= 0x39); // 0..9 }, IsHexDigit: function (cp) { return (cp >= 0x30 && cp <= 0x39) || (cp >= 0x41 && cp <= 0x46) || (cp >= 0x61 && cp <= 0x66); // a..f }, isOctalDigit: function (cp) { return (cp >= 0x30 && cp <= 0x37); // 0..7 } } var TOKEN_NAME={}; TOKEN_NAME[1 /* BooleanLiteral */] = 'Boolean'; TOKEN_NAME[2 /* EOF */] = ''; TOKEN_NAME[3 /* Identifier */] = 'Identifier'; TOKEN_NAME[4 /* Keyword */] = 'Keyword'; TOKEN_NAME[5 /* NullLiteral */] = 'Null'; TOKEN_NAME[6 /* NumericLiteral */] = 'Numeric'; TOKEN_NAME[7 /* Punctuator */] = 'Punctuator'; TOKEN_NAME[8 /* StringLiteral */] = 'String'; TOKEN_NAME[9 /* RegularExpression */] = 'RegularExpression'; TOKEN_NAME[10 /* Template */] = 'Template'; //公共方法 function JSComplierHelper() { } JSComplierHelper.GetPeriodInfo=function(obj) { const PERIOD_LIST= [ {Name:'MIN1', Period:4, Order:1}, {Name:'MIN5', Period:5, Order:2}, {Name:'MIN15', Period:6, Order:3}, {Name:'MIN30', Period:7, Order:4}, {Name:'MIN60', Period:8, Order:5}, {Name:'DAY', Period:0, Order:1000}, {Name:'MULTIDAY', Period:40002, Order:1002}, {Name:'DAY2', Period:40002, Order:1002}, {Name:'DAY3', Period:40003, Order:1003}, {Name:'DAY4', Period:40004, Order:1004}, {Name:'DAY5', Period:40005, Order:1005}, {Name:'WEEK', Period:1, Order:1005}, {Name:'DAY6', Period:40006, Order:1006}, {Name:'DAY7', Period:40007, Order:1007}, {Name:'DAY8', Period:40008, Order:1008}, {Name:'DAY9', Period:40009, Order:1009}, {Name:'DAY10', Period:40009, Order:1010}, {Name:"WEEK2", Period:21, Order:1010}, {Name:'DAY11', Period:40011, Order:1011}, {Name:'DAY12', Period:40012, Order:1012}, {Name:'DAY13', Period:40013, Order:1013}, {Name:'DAY14', Period:40014, Order:1014}, {Name:'MONTH', Period:2, Order:1030}, {Name:"SEASON", Period:9, Order:1090}, {Name:"HALFYEAR", Period:22, Order:1180}, {Name:"YEAR", Period:3, Order:1365} ]; if (obj.Name) { for(var i in PERIOD_LIST) { if (obj.Name && PERIOD_LIST[i].Name==obj.Name) return PERIOD_LIST[i]; } return null; } if (IFrameSplitOperator.IsNumber(obj.PeriodID)) { for(var i in PERIOD_LIST) { if (PERIOD_LIST[i].Period==obj.PeriodID) return PERIOD_LIST[i]; } return null; } return null; } JSComplierHelper.GetConvertValueName=function(funcName) { var valueName; if (funcName=='COVER_C') valueName='CLOSE'; else if (funcName=='COVER_O') valueName="OPEN"; else if (funcName=='COVER_H') valueName="HIGH"; else if (funcName=='COVER_L') valueName="LOW"; else if (funcName=='COVER_A') valueName="AMOUNT"; else if (funcName=='COVER_V') valueName="VOL"; return valueName; } //编译异常, 错误类 function ErrorHandler() { this.Error=[]; this.RecordError=function(error) { this.Error.push(error); } this.ConstructError=function(msg,column) { let error=new Error(msg); //通过自己抛异常并自己截获 来获取调用堆栈信息 try { throw error; } catch(base) { if (Object.create && Object.defineProperties) { error=Object.create(base); error.Column=column; } } return error; } this.CreateError=function(index, line, col, description, word) { let msg='Line ' + line + ': ' + description; let error=this.ConstructError(msg,col); error.Index=index; error.LineNumber=line; error.Description=description; error.Word=word; //错误单词 return error; } this.ThrowError=function(index, line, col, description, word) { let error=this.CreateError(index,line,col,description,word); throw error; } //重新下载数据 this.ThrowDownloadJob=function(index, line, col, description,job) { let error=this.CreateError(index,line,col,description); error.Job=job; throw error; } } //扫描类 function Scanner(code, ErrorHandler) { this.Source=code; this.ErrorHandler=ErrorHandler; this.Length=code.length; this.Index=0; this.LineNumber=(code.length>0)?1:0; this.LineStart=0; this.CurlyStack=[]; this.SaveState=function() //保存当前扫描状态 { return { Index:this.Index, LineNumber:this.LineNumber, LineStart:this.LineStart }; } this.RestoreState=function(state) //还原扫描状态 { this.Index=state.Index; this.LineNumber=state.LineNumber; this.LineStart=state.LineStart; } this.IsEOF=function() //否是已经结束 { return this.Index>=this.Length; } this.IsKeyword=function(id) { return false; } this.CodePointAt = function (i) { let cp = this.Source.charCodeAt(i); if (cp >= 0xD800 && cp <= 0xDBFF) { let second = this.Source.charCodeAt(i + 1); if (second >= 0xDC00 && second <= 0xDFFF) { var first = cp; cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; } } return cp; } this.Lex=function() { if (this.IsEOF()) return { Type:2/*EOF*/, Value:'', LineNumber:this.LineNumber, LineStart:this.LineStart, Start:this.Index, End:this.Index }; let cp=this.Source.charCodeAt(this.Index); //变量名 或 关键字 if (Character.IsIdentifierStart(cp)) return this.ScanIdentifier(); //( ) ; 开头 操作符扫描 if (cp === 0x28 || cp === 0x29 || cp === 0x3B) return this.ScanPunctuator(); //' " 开头 字符串扫描 if (cp === 0x27 || cp === 0x22) return this.ScanStringLiteral(); //. 开头 浮点型 if (cp==0x2E) { if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index + 1))) return this.ScanNumericLiteral(); return this.ScanPunctuator(); } //数字 if (Character.IsDecimalDigit(cp)) return this.ScanNumericLiteral(); if (cp >= 0xD800 && cp < 0xDFFF) { if (Character.IsIdentifierStart(this.CodePointAt(this.Index))) return this.ScanIdentifier(); } return this.ScanPunctuator(); } //关键字 变量名 https://tc39.github.io/ecma262/#sec-names-and-keywords this.ScanIdentifier=function() { let type; let start=this.Index; //0x5C 反斜杠 let id=(this.Source.charCodeAt(start)=== 0x5C) ? this.GetComplexIdentifier() : this.GetIdentifier(); if (id.length) type=3; //Identifier else if (this.IsKeyword(id)) type=4; //Keyword else if (id==null) type=5; //NullLiteral else if (id=='true' || id=='false') type=1; //BooleanLiteral else type=3; //Identifier if (type!=3 && (start+id.length!=this.Index)) { let restore=this.Index; this.Index=start; throw Messages.InvalidEscapedReservedWord; this.Index=restore; } if (id=='AND' || id=='OR') type=7 /*Punctuator*/; return { Type:type, Value:id, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index}; } this.GetIdentifier=function() { let start=this.Index++; //start 保存进来的位置 while(!this.IsEOF()) { let ch=this.Source.charCodeAt(this.Index); if (ch==0x5C) { this.Index=start; return this.GetComplexIdentifier(); } else if (ch >= 0xD800 && ch < 0xDFFF) { this.Index=start; return this.GetComplexIdentifier(); } if (Character.IsIdentifierPart(ch)) ++this.Index; else break; } return this.Source.slice(start,this.Index); } //操作符 https://tc39.github.io/ecma262/#sec-punctuators this.ScanPunctuator=function() { let start=this.Index; let str=this.Source[this.Index]; switch(str) { case '(': ++this.Index; break; case ')': case ';': case ',': ++this.Index; break; case '.': ++this.Index; /*if (this.Source[this.Index] === '.' && this.Source[this.Index + 1] === '.') { //Spread operator: ... this.Index += 2; str = '...'; } */ break; default: str=this.Source.substr(this.Index,3); if (str=='AND') { this.Index+=3; } else { str = this.Source.substr(this.Index, 2); if (str === '&&' || str === '||' || str === '==' || str === '!=' || str === '<=' || str === '>=' || str === '=>' || str==':=' || str=='OR' || str=='<>') { this.Index += 2; } else { str=this.Source[this.Index]; if ('<>=!+-*%&|^/:'.indexOf(str) >= 0) ++this.Index; } } } if (this.Index==start) this.ThrowUnecpectedToken(); return { Type:7/*Punctuator*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index }; } //字符串 https://tc39.github.io/ecma262/#sec-literals-string-literals this.ScanStringLiteral=function() { let start=this.Index; let quote=this.Source[this.Index]; ++this.Index; var octal=false; let str=''; while(!this.IsEOF()) { let ch=this.Source[this.Index++]; if (ch==quote) { quote=''; break; } else if (ch=='\\') //字符串转义 { throw "not complete"; } else if (Character.IsLineTerminator(ch.charCodeAt(0))) { break; } else { str+=ch; } } if (quote!='') { this.Index=start; this.ThrowUnecpectedToken(); } return {Type:8/*StringLiteral*/, Value:str, LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index}; } this.ScanNumericLiteral=function() { let start=this.Index; let ch=this.Source[this.Index]; let num=''; if (ch!='.') { num=this.Source[this.Index++]; ch=this.Source[this.Index]; // Hex number starts with '0x'. 16进制 if (num=='0') { if (ch=='x' || ch=='X') { ++this.Index; return this.ScanHexLiteral(start); } } while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index))) { num+=this.Source[this.Index++]; } ch=this.Source[this.Index]; } if (ch=='.') { num+=this.Source[this.Index++]; while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index))) { num+=this.Source[this.Index++]; } ch=this.Source[this.Index]; } //科学计数法 if (ch=='e' || ch=='E') { num+=this.Source[this.Index++]; ch=this.Source[this.Index]; if (ch=='+' || ch=='-') num+=this.Source[this.Index]; if (Character.IsDecimalDigit(this.Source.charCodeAt(this.Index))) { while(Character.IsDecimalDigit(this.Source.charCodeAt(this.Index))) { num+=this.Source[this.Index++]; } } else { this.ThrowUnecpectedToken(); } } if (Character.IsIdentifierStart(this.Source.charCodeAt(this.Index))) { this.ThrowUnecpectedToken(); } return { Type:6/*NumericLiteral*/, Value:parseFloat(num), LineNumber:this.LineNumber, LineStart:this.LineStart, Start:start, End:this.Index }; } //空格 或 注释 this.ScanComments=function() { let comments; let start=(this.Index==0); while(!this.IsEOF()) { let ch=this.Source.charCodeAt(this.Index); if (Character.IsWhiteSpace(ch)) //过滤掉空格 { ++this.Index; } else if (Character.IsLineTerminator(ch)) { ++this.Index; if (ch==0x0D && this.Source.charCodeAt(this.Index)==0x0A) ++this.Index; //回车+换行 ++this.LineNumber; this.LineStart=this.Index; start=true; } else if (ch==0x2F) // //注释 { ch=this.Source.charCodeAt(this.Index+1); if (ch==0x2F) { this.Index+=2; let comment=this.SkipSingleLineComment(2); start=true; } else { break; } } else if (ch==0x7B) //{ } 注释 { this.Index+=1; let comment = this.SkipMultiLineComment(); } else { break; } } return comments; } this.SkipMultiLineComment=function() { var comments = []; while(!this.IsEOF()) { var ch=this.Source.charCodeAt(this.Index); if (Character.IsLineTerminator(ch)) { ++this.LineNumber; ++this.Index; this.LineStart=this.Index; } else if (ch==0x7D) { this.Index+=1; return comments; } else { ++this.Index; } } return comments; } //单行注释 https://tc39.github.io/ecma262/#sec-comments this.SkipSingleLineComment=function(offset) { let comments=[]; while(!this.IsEOF()) { let ch=this.Source.charCodeAt(this.Index); ++this.Index; if (Character.IsLineTerminator(ch)) { if (ch === 13 && this.Source.charCodeAt(this.Index) === 10) ++this.Index; ++this.LineNumber; this.LineStart=this.Index; return comments; } } return comments; } this.ThrowUnecpectedToken=function(message,word) { if (!message) message = Messages.UnexpectedTokenIllegal; return this.ErrorHandler.ThrowError(this.Index, this.LineNumber, this.Index - this.LineStart + 1, message, word); } } function Tokenizer(code) { this.ErrorHandler=new ErrorHandler(); //错误信息处理类 this.Scanner=new Scanner(code,this.ErrorHandler); this.Buffer=[]; this.GetNextToken=function() { if (this.Buffer.length==0) { let comments=this.Scanner.ScanComments(); if (!this.Scanner.IsEOF()) { let token=this.Scanner.Lex(); let entry={ Type:TOKEN_NAME[token.Type], Value:this.Scanner.Source.slice(token.Start, token.End)}; this.Buffer.push(entry); } } return this.Buffer.shift(); } } var Syntax = { AssignmentExpression: 'AssignmentExpression', AssignmentPattern: 'AssignmentPattern', ArrayExpression: 'ArrayExpression', ArrayPattern: 'ArrayPattern', ArrowFunctionExpression: 'ArrowFunctionExpression', AwaitExpression: 'AwaitExpression', BlockStatement: 'BlockStatement', BinaryExpression: 'BinaryExpression', BreakStatement: 'BreakStatement', CallExpression: 'CallExpression', CatchClause: 'CatchClause', ClassBody: 'ClassBody', ClassDeclaration: 'ClassDeclaration', ClassExpression: 'ClassExpression', ConditionalExpression: 'ConditionalExpression', ContinueStatement: 'ContinueStatement', DoWhileStatement: 'DoWhileStatement', DebuggerStatement: 'DebuggerStatement', EmptyStatement: 'EmptyStatement', ExportAllDeclaration: 'ExportAllDeclaration', ExportDefaultDeclaration: 'ExportDefaultDeclaration', ExportNamedDeclaration: 'ExportNamedDeclaration', ExportSpecifier: 'ExportSpecifier', ExpressionStatement: 'ExpressionStatement', ForStatement: 'ForStatement', ForOfStatement: 'ForOfStatement', ForInStatement: 'ForInStatement', FunctionDeclaration: 'FunctionDeclaration', FunctionExpression: 'FunctionExpression', Identifier: 'Identifier', IfStatement: 'IfStatement', ImportDeclaration: 'ImportDeclaration', ImportDefaultSpecifier: 'ImportDefaultSpecifier', ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', ImportSpecifier: 'ImportSpecifier', Literal: 'Literal', LabeledStatement: 'LabeledStatement', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', MetaProperty: 'MetaProperty', MethodDefinition: 'MethodDefinition', NewExpression: 'NewExpression', ObjectExpression: 'ObjectExpression', ObjectPattern: 'ObjectPattern', Program: 'Program', Property: 'Property', RestElement: 'RestElement', ReturnStatement: 'ReturnStatement', SequenceExpression: 'SequenceExpression', SpreadElement: 'SpreadElement', Super: 'Super', SwitchCase: 'SwitchCase', SwitchStatement: 'SwitchStatement', TaggedTemplateExpression: 'TaggedTemplateExpression', TemplateElement: 'TemplateElement', TemplateLiteral: 'TemplateLiteral', ThisExpression: 'ThisExpression', ThrowStatement: 'ThrowStatement', TryStatement: 'TryStatement', UnaryExpression: 'UnaryExpression', UpdateExpression: 'UpdateExpression', VariableDeclaration: 'VariableDeclaration', VariableDeclarator: 'VariableDeclarator', WhileStatement: 'WhileStatement', WithStatement: 'WithStatement', YieldExpression: 'YieldExpression' }; function Node(ErrorHandler) { this.IsNeedIndexData=false; //是否需要大盘数据 this.IsNeedLatestIndexData=false; //是否需要下载最新大盘数据 this.IsNeedSymbolData=false; //是否需要下载股票数据 this.IsNeedMarginData=new Set(); this.IsNeedNewsAnalysisData=new Set(); //新闻统计数据 this.NeedBlockIncreaseData=[]; //是否需要市场涨跌股票数据统计 this.IsNeedSymbolExData=new Set(); //下载股票行情的其他数据 this.NeedHK2SHSZData=[]; //下载北上资金数据 this.IsNeedSectionFinance=new Map(); //下载截面财务数据 { key= 报告期 , Set() 字段} this.FunctionData=[]; //{ID:, Args:, FunctionName: } //FINVALUE(ID),FINONE(ID,Y,MMDD) this.Dynainfo=[]; //最新的个股行情数据 {ID:, Args:, FunctionName: } this.IsAPIData=[] //加载API数据 this.ExecuteIndex=[]; //执行调用指标 this.OtherSymbolData=[]; //其他股票数据 key=股票代码(小写) this.PeriodSymbolData=[]; //跨周期数据 { Period:, VarName: } this.ErrorHandler=ErrorHandler; this.GetDataJobList=function() //下载数据任务列表 { let jobs=[]; if (this.IsNeedSymbolData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA}); if (this.IsNeedIndexData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA}); if (this.IsNeedLatestIndexData) jobs.push({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_LATEST_INDEX_DATA}); //最新的个股行情数据 for(var i=0;i0) { var aryWrods = varName.split('#'); if (aryWrods.length!=2) { var errorMessage=`${varName}, 跨周期语法错误, 变量名#周期`; this.ThrowUnexpectedToken(token,errorMessage); } else { const VAR_NAME=["C", "CLOSE", "O","OPEN", "H","HIGH", "L", "LOW", "AMOUNT", "AMO", "VOL", "V" , "VOLINSTK"]; if (VAR_NAME.indexOf(aryWrods[0])<0) { var errorMessage=`${varName}, 跨周期语法错误, 数据只支持'OPEN,HIGH,LOW,CLOSE,VOL,AMOUNT,VOLINSTK'`; this.ThrowUnexpectedToken(token,errorMessage); } const VAR_PERIOD_NAME= [ "MIN1","MIN5","MIN15","MIN30","MIN60","MIN120","MIN240","DAY","WEEK","MONTH","SEASON","YEAR","HALFYEAR","WEEK2", "MULTIDAY","DAY2","DAY3","DAY4","DAY5","DAY6","DAY7","DAY8","DAY9","DAY10", "DAY11","DAY12","DAY13","DAY14","DAY15" ]; if (VAR_PERIOD_NAME.indexOf(aryWrods[1])<0) { var errorMessage=`${varName}, 跨周期语法错误, 周期只支持'MIN1,MIN5,MIN15,MIN30,MIN60,DAY,WEEK,MONTH,SEASON,YEAR'`; this.ThrowUnexpectedToken(token,errorMessage); } var item={ID: JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_PERIOD_DATA, VarName:varName, ValueName:aryWrods[0], PeriodName:aryWrods[1] }; if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; this.PeriodSymbolData.push(item); } return; } if (g_JSComplierResource.IsCustomVariant(varName)) //自定义函数 { var item={ VariantName:varName, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA }; if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; this.FunctionData.push(item); return; } } this.VerifySymbolLiteral=function(value,token) { if (IFrameSplitOperator.IsString(value)) { if (value.indexOf('$')>0) { var aryValue=value.split('$'); if (aryValue.length!=2) return; var item= { Literal:value, ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA }; if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; this.OtherSymbolData.push(item); } } } this.VerifySymbolFunction=function(callee,args, token) { //自定义函数 可以覆盖系统内置函数 if (g_JSComplierResource.IsCustomFunction(callee.Name)) { var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA, Args:args} if (token) item.Token={ Index:token.Start, Line:token.LineNumber}; this.FunctionData.push(item); return; } //自定义数据函数 if (g_JSComplierResource.IsCustomDataFunction(callee.Name)) { var item={FunctionName:callee.Name, ID:JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION, Args:args} if (token) item.Token={ Index:token.Start, Line:token.LineNumber}; this.FunctionData.push(item); return; } if (callee.Name=='DYNAINFO') { var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA, Args:args, FunctionName:callee.Name }; this.Dynainfo.push(item); return; } //财务函数 if (callee.Name=='FINANCE') { var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE, Args:args, FunctionName:callee.Name }; if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; this.FunctionData.push(item); return; } if (callee.Name=="FINVALUE") { var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE, Args:args, FunctionName:callee.Name }; if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; this.FunctionData.push(item); return; } if (callee.Name=="FINONE") { var item={ ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE, Args:args, FunctionName:callee.Name }; if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; this.FunctionData.push(item); return; } //专业财务数据 for(var i=0;i':6, '===': 6, '!==': 6, '<': 7, '>': 7, '<=': 7, '>=': 7, '<<': 8, '>>': 8, '>>>': 8, '+': 9, '-': 9, '*': 11, '/': 11, '%': 11 }; this.StartMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 }; this.LastMarker={Index:0, Line: this.Scanner.LineNumber, Column:0 }; this.Initialize=function() { this.NextToken(); this.LastMarker={ Index:this.Scanner.Index, Line:this.Scanner.LineNumber, Column:this.Scanner.Index-this.Scanner.LineStart }; } this.CreateNode=function() { return { Index:this.StartMarker.Index, Line:this.StartMarker.Line, Column:this.StartMarker.Column }; } this.StartNode=function(token, lastLineStart) { if (lastLineStart==void 0) { lastLineStart=0; } let column = token.Start - token.LineStart; let line = token.LineNumber; if (column < 0) { column += lastLineStart; line--; } return { Index: token.Start, Line: line, Column: column }; } this.Match=function(value) { return this.LookAhead.Type==7 /*Punctuator*/ && this.LookAhead.Value==value; } this.Expect=function(value, message) { let token=this.NextToken(); if (token.Type!=7 /*Punctuator*/ || token.Value!=value) this.ThrowUnexpectedToken(token, message); } //是否是赋值操作符 this.MatchAssign=function() { if (this.LookAhead.Type!=7 /*Punctuator*/) return false; let op=this.LookAhead.Value; return op==':' || op==':='; } this.GetTokenRaw=function(token) { return this.Scanner.Source.slice(token.Start, token.End); } this.NextToken=function() { let token=this.LookAhead; this.LastMarker.Index=this.Scanner.Index; this.LastMarker.Line=this.Scanner.LineNumber; this.LastMarker.Column=this.Scanner.Index-this.Scanner.LineStart; this.CollectComments(); //过滤注释 空格 if (this.Scanner.Index !== this.StartMarker.Index) { this.StartMarker.Index = this.Scanner.Index; this.StartMarker.Line = this.Scanner.LineNumber; this.StartMarker.Column = this.Scanner.Index - this.Scanner.LineStart; } let next=this.Scanner.Lex(); this.HasLineTerminator=(token.LineNumber!=next.LineNumber); if (next && this.Context.Strict && next.Type==3/*Identifier */) { //TODO: } this.LookAhead=next; return token; } this.CollectComments=function() { this.Scanner.ScanComments(); } this.ParseScript=function() { let node=this.CreateNode(); let body=this.ParseDirectivePrologues(); while(this.LookAhead.Type!=2 /*EOF*/) { body.push(this.ParseStatementListItem()) } return this.Finalize(node,this.Node.Script(body)); } //https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive this.ParseDirective=function() { let token=this.LookAhead; let node=this.CreateNode(); let expr=this.ParseExpression(); let directive = (expr.Type === Syntax.Literal) ? this.GetTokenRaw(token).slice(1, -1) : null; this.ConsumeSemicolon(); return this.Finalize(node, directive ? this.Node.Directive(expr, directive) : this.Node.ExpressionStatement(expr)); } this.ParseDirectivePrologues=function() { let firstRestricted=null; let body=[]; while(true) { let token=this.LookAhead; if (token.Type!=8 /*StringLiteral*/) break; let statement=this.ParseDirective(); body.push(statement); } return body; } // https://tc39.github.io/ecma262/#sec-block this.ParseStatementListItem=function() { let statement; this.Context.IsAssignmentTarget=true; this.Context.IsBindingElement=true; if (this.LookAhead.Type==4 /*Keyword*/) { } else { statement=this.ParseStatement(); } return statement; } // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations this.ParseStatement=function() { let statement; switch(this.LookAhead.Type) { case 1 /* BooleanLiteral */: case 5 /* NullLiteral */: case 6 /* NumericLiteral */: case 8 /* StringLiteral */: case 10 /* Template */: case 9 /* RegularExpression */: statement = this.ParseExpressionStatement(); break; case 7 /* Punctuator */: let value = this.LookAhead.Value; if (value === '(') statement = this.ParseExpressionStatement(); else if (value === ';') statement = this.ParseEmptyStatement(); else statement = this.ParseExpressionStatement(); break; case 3 /* Identifier */: statement = this.ParseLabelledStatement(); break; case 4 /* Keyword */: break; default: statement="error"; } return statement; } // https://tc39.github.io/ecma262/#sec-empty-statement this.ParseEmptyStatement=function() { let node=this.CreateNode(); this.Expect(';'); return this.Finalize(node, this.Node.EmptyStatement()); } //https://tc39.github.io/ecma262/#sec-labelled-statements this.ParseLabelledStatement=function() { let node=this.CreateNode(); let expr=this.ParseExpression(); this.ConsumeSemicolon(); let statement = new this.Node.ExpressionStatement(expr); return this.Finalize(node, statement); } // https://tc39.github.io/ecma262/#sec-comma-operator this.ParseExpression=function() { let startToken=this.LookAhead; let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression); if (this.Match(',')) { let expressions=[]; expressions.push(expr); while(this.LookAhead.Type!=2 /*EOF*/) { if (!this.Match(',')) break; this.NextToken(); expressions.push(this.IsolateCoverGrammar(this.ParseAssignmentExpression)); } expr=this.Finalize(this.StartNode(startToken),this.Node.SequenceExpression(expressions)); } return expr; } this.ParseAssignmentExpression=function() { let expr; let startToken=this.LookAhead; let token=startToken; expr=this.ParseConditionalExpression(); if (this.MatchAssign()) { if (!this.Context.IsAssignmentTarget) { let marker=expr.Marker; this.ThrowUnexpectedError(marker.Index,marker.Line,marker.Column,Messages.InvalidLHSInAssignment); } if (!this.Match('=') && !this.Match(':')) { this.Context.IsAssignmentTarget=false; this.Context.IsBindingElement=false; } else { this.ReinterpretExpressionAsPattern(expr); } token=this.NextToken(); let operator=token.Value; let right=this.IsolateCoverGrammar(this.ParseAssignmentExpression); expr=this.Finalize(this.StartNode(startToken), this.Node.AssignmentExpression(operator, expr, right)); this.Context.FirstCoverInitializedNameError=null; } return expr; } this.ParseConditionalExpression=function() { let startToken=this.LookAhead; let expr=this.InheritCoverGrammar(this.ParseBinaryExpression); return expr; } this.ParseBinaryExpression=function() { let startToken=this.LookAhead; let expr=this.InheritCoverGrammar(this.ParseExponentiationExpression); let token=this.LookAhead; var prec=this.BinaryPrecedence(token); if (prec>0) { this.NextToken(); this.Context.IsAssignmentTarget=false; this.Context.IsBindingElement=false; let markers=[startToken,this.LookAhead]; let left=expr; let right=this.IsolateCoverGrammar(this.ParseExponentiationExpression); let stack=[left,token.Value,right]; let precedences = [prec]; while(true) { prec=this.BinaryPrecedence(this.LookAhead); if (prec<=0) break; while(stack.length>2 && prec<=precedences[precedences.length-1]) { right=stack.pop(); let operator=stack.pop(); precedences.pop(); left=stack.pop(); markers.pop(); let node=this.StartNode(markers[markers.length - 1]); stack.push(this.Finalize(node, this.Node.BinaryExpression(operator, left, right))); } //Shift stack.push(this.NextToken().Value); precedences.push(prec); markers.push(this.LookAhead); stack.push(this.IsolateCoverGrammar(this.ParseExponentiationExpression)); } let i=stack.length-1; expr=stack[i]; let lastMarker=markers.pop(); while(i>1) { let marker=markers.pop(); let lastLineStart=lastMarker && lastMarker.LineStart; let node=this.StartNode(marker, lastLineStart); let operator=stack[i-1]; expr=this.Finalize(node, this.Node.BinaryExpression(operator, stack[i - 2], expr)); i-=2; lastMarker=marker; } } return expr; } this.ParseExponentiationExpression=function() { let startToken=this.LookAhead; let expr=this.InheritCoverGrammar(this.ParseUnaryExpression); return expr; } this.ParseUnaryExpression=function() { let expr; if (this.Match('+') || this.Match('-')) { let node=this.StartNode(this.LookAhead); let token=this.NextToken(); expr=this.InheritCoverGrammar(this.ParseUnaryExpression); expr=this.Finalize(node, this.Node.UnaryExpression(token.Value, expr)); this.Context.IsAssignmentTarget=false; this.Context.IsBindingElement=false; } else { expr=this.ParseUpdateExpression(); } return expr; } // https://tc39.github.io/ecma262/#sec-update-expressions this.ParseUpdateExpression=function() { let expr; let startToken=this.LookAhead; expr=this.InheritCoverGrammar(this.ParseLeftHandSideExpressionAllowCall); return expr; } this.ParseLeftHandSideExpressionAllowCall=function() { let startToken=this.LookAhead; let expr; expr=this.InheritCoverGrammar(this.ParsePrimaryExpression); while(true) { if (this.Match('.')) { this.Context.IsBindingElement = false; this.Context.IsAssignmentTarget = true; this.Expect('.'); const property = this.ParseMemberIdentifierName(); expr = this.Finalize(this.StartNode(startToken), this.Node.StaticMemberExpression(expr, property,startToken)); } else if (this.Match('(')) { this.Context.IsBindingElement=false; this.Context.IsAssignmentTarget=false; var args=this.ParseArguments(); //解析 调用参数 expr=this.Finalize(this.StartNode(startToken), this.Node.CallExpression(expr,args,startToken)); } else { break; } } return expr; } /* BooleanLiteral = 1, EOF=2, Identifier=3, Keyword=4, NullLiteral=5, NumericLiteral=6, Punctuator=7, StringLiteral=9, RegularExpression=9, Template=10 */ this.IsIdentifierName=function(token) { return token.Type === 3 //Identifier || token.Type === 4 //Keyword || token.Type === 1 //BooleanLiteral || token.Type === 5 ;//NullLiteral; } this.ParseIdentifierName=function() { const node = this.CreateNode(); const token = this.NextToken(); if (!this.IsIdentifierName(token)) { this.ThrowUnexpectedToken(token); } return this.Finalize(node, this.Node.Identifier(token.Value, token)); } this.ParseMemberIdentifierName=function() { const node = this.CreateNode(); const token = this.NextToken(); if (!this.IsIdentifierName(token)) { this.ThrowUnexpectedToken(token); } return this.Finalize(node, this.Node.MemberIdentifier(token.Value, token)); } // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions this.ParseArguments=function() { this.Expect('('); var args=[]; if (!this.Match(')')) { while(true) { let expr=this.IsolateCoverGrammar(this.ParseAssignmentExpression); args.push(expr); if (this.Match(')')) break; this.ExpectCommaSeparator(); if (this.Match(')')) break; } } this.Expect(')'); return args; } // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). this.ExpectCommaSeparator=function() { this.Expect(',',"函数参数格式错误"); } // https://tc39.github.io/ecma262/#sec-primary-expression this.ParsePrimaryExpression=function() { let node=this.CreateNode(); let expr; var token, raw; switch(this.LookAhead.Type) { case 3:/* Identifier */ token=this.NextToken(); expr=this.Finalize(node, this.Node.Identifier(token.Value, token)); break; case 6:/* NumericLiteral */ case 8:/* StringLiteral */ this.Context.IsAssignmentTarget=false; this.Context.IsBindingElement=false; token=this.NextToken(); raw=this.GetTokenRaw(token); expr=this.Finalize(node, this.Node.Literal(token.Value,raw,token)); break; case 7:/* Punctuator */ switch(this.LookAhead.Value) { case '(': this.Context.IsBindingElement=false; expr=this.InheritCoverGrammar(this.ParseGroupExpression); break; default: expr=this.ThrowUnexpectedToken(this.NextToken()) } break; default: expr = this.ThrowUnexpectedToken(this.NextToken()); } return expr; } this.ParseGroupExpression=function() { let expr; this.Expect('('); if (this.Match(')')) { this.NextToken(); } else { let startToken=this.LookAhead; let params=[]; let arrow=false; this.Context.IsBindingElement=true; expr=this.InheritCoverGrammar(this.ParseAssignmentExpression); if (this.Match(',')) { let expressions=[]; this.Context.IsAssignmentTarget=false; expressions.push(expr); while(this.LookAhead.Type!=2 /* EOF */) { if (!this.Match(',')) break; this.NextToken(); if (this.Match(')')) { } } } if (!arrow) { this.Expect(')'); this.Context.IsBindingElement=false; } } return expr; } // https://tc39.github.io/ecma262/#sec-expression-statement this.ParseExpressionStatement=function() { let node=this.CreateNode(); let expr=this.ParseExpression(); this.ConsumeSemicolon(); return this.Finalize(node,this.Node.ExpressionStatement(expr)); } this.ConsumeSemicolon=function() { if (this.Match(';')) { this.NextToken(); } else if (!this.HasLineTerminator) { //if (this.LookAhead.Type!=2/*EOF*/ && !this.Match('}')) this.LastMarker.Index=this.StartMarker.Index; this.LastMarker.Line=this.StartMarker.Line; this.LastMarker.Column=this.StartMarker.Column; } } this.ReinterpretExpressionAsPattern=function(expr) { switch(expr.Type) { case Syntax.Identifier: case Syntax.MemberExpression: case Syntax.AssignmentExpression: break; default: break; } } this.Finalize=function(marker,node) { node.Marker={ Line:marker.Line, Column:marker.Column, Index:marker.Index }; return node; } this.BinaryPrecedence = function (token) { let op = token.Value; let precedence; if (token.Type === 7 /* Punctuator */) precedence = this.PeratorPrecedence[op] || 0; else precedence = 0; return precedence; }; this.IsolateCoverGrammar=function(parseFunction) { let previousIsBindingElement=this.Context.IsBindingElement; let previousIsAssignmentTarget=this.Context.IsAssignmentTarget; let previousFirstCoverInitializedNameError=this.Context.FirstCoverInitializedNameError; this.Context.IsBindingElement=true; this.Context.IsAssignmentTarget=true; this.Context.FirstCoverInitializedNameError=null; let result=parseFunction.call(this); if (this.Context.FirstCoverInitializedNameError!=null) { //错误 this.throwUnexpectedToken(this.context.firstCoverInitializedNameError); } this.Context.IsBindingElement=previousIsBindingElement; this.Context.IsAssignmentTarget=previousIsAssignmentTarget; this.Context.FirstCoverInitializedNameError=previousFirstCoverInitializedNameError; return result; } this.InheritCoverGrammar = function (parseFunction) { let previousIsBindingElement = this.Context.IsBindingElement; let previousIsAssignmentTarget = this.Context.IsAssignmentTarget; let previousFirstCoverInitializedNameError = this.Context.FirstCoverInitializedNameError; this.Context.IsBindingElement = true; this.Context.IsAssignmentTarget = true; this.Context.FirstCoverInitializedNameError = null; let result = parseFunction.call(this); this.Context.IsBindingElement = this.Context.IsBindingElement && previousIsBindingElement; this.Context.IsAssignmentTarget = this.Context.IsAssignmentTarget && previousIsAssignmentTarget; this.Context.FirstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.Context.FirstCoverInitializedNameError; return result; }; this.ThrowUnexpectedToken=function(token,message) { throw this.UnexpectedTokenError(token,message); } this.ThrowUnexpectedError=function(index,line,column,message) { let msg=message || "执行异常"; return this.ErrorHandler.ThrowError(index,line,column,msg); } this.UnexpectedTokenError=function(token,message) { let msg=message || Messages.UnexpectedToken; let value='ILLEGAL'; if (token) { if (!message) { } value=token.Value; } msg=msg.replace("%0",value); if (token && typeof(token.LineNumber)=='number') { let index=token.Start; let line=token.LineNumber; let lastMarkerLineStart=this.LastMarker.Index-this.LastMarker.Column; let column=token.Start-lastMarkerLineStart+1; return this.ErrorHandler.CreateError(index,line,column,msg); } else { let index=this.LastMarker.Index; let line=this.LastMarker.Line; let column=this.LastMarker.Column+1; return this.ErrorHandler.CreateError(index,line,column,msg); } } } /* 算法类 */ function JSAlgorithm(errorHandler,symbolData) { this.ErrorHandler=errorHandler; this.SymbolData=symbolData; //股票数据 //相加 this.Add=function(data,data2) { let isNumber=typeof(data)=='number'; let isNumber2=typeof(data2)=='number'; //单数值相加 if (isNumber && isNumber2) return data+data2; //都是数组相加 let result=[]; if (!isNumber && !isNumber2) { let count=Math.max(data.length, data2.length); for(let i=0;idata2 ? 1 : 0); //都是数组比较 let result=[]; if (Array.isArray(data) && Array.isArray(data2)) { let count=Math.max(data.length, data2.length); for(let i=0;idata2[i] ? 1:0); } } return result; } if (isNumber && Array.isArray(data2)) //单数据-数组 { for(let i in data2) { result[i]=null; if (!IFrameSplitOperator.IsVaild(data)) continue; if (!IFrameSplitOperator.IsVaild(data2[i])) continue; if ( !isNaN(data) && !isNaN(data2[i]) ) result[i]=(data>data2[i] ? 1 : 0); } } else if (isNumber2 && Array.isArray(data)) //数组-单数据 { for(let i in data) { result[i]=null; if (!IFrameSplitOperator.IsVaild(data[i])) continue; if (!IFrameSplitOperator.IsVaild(data2)) continue; if ( !isNaN(data[i]) && !isNaN(data2) ) result[i]=(data[i]>data2 ? 1 : 0); } } return result; } //大于等于 this.GTE=function(data,data2) { let isNumber=IFrameSplitOperator.IsNumber(data); let isNumber2=IFrameSplitOperator.IsNumber(data2); //单数值比较 if (isNumber && isNumber2) return (data>=data2 ? 1 : 0); //都是数组比较 let result=[]; if (Array.isArray(data) && Array.isArray(data2)) { let count=Math.max(data.length, data2.length); for(let i=0;i=data2[i] ? 1:0); } } return result; } if (isNumber && Array.isArray(data2)) //单数据-数组 { for(let i in data2) { result[i]=null; if (!IFrameSplitOperator.IsVaild(data)) continue; if (!IFrameSplitOperator.IsVaild(data2[i])) continue; result[i]=(data>=data2[i] ? 1 : 0); } } else if (isNumber2 && Array.isArray(data)) //数组-单数据 { for(let i in data) { result[i]=null; if (!IFrameSplitOperator.IsVaild(data[i])) continue; if (!IFrameSplitOperator.IsVaild(data2)) continue; result[i]=(data[i]>=data2 ? 1 : 0); } } return result; } //小于 this.LT=function(data,data2) { let isNumber=IFrameSplitOperator.IsNumber(data); let isNumber2=IFrameSplitOperator.IsNumber(data2); //单数值比较 if (isNumber && isNumber2) return (data=data2 ? 1 : 0); //都是数组比较 let result=[]; if (Array.isArray(data) && Array.isArray(data2)) { let count=Math.max(data.length, data2.length); for(let i=0;iOPEN,HIGH,LOW)表示该周期收阴则返回最高值,否则返回最低值 */ this.IFN=function(data,trueData,falseData) { return this.IF(data,falseData,trueData); } //指标函数 函数名全部大写 //引用若干周期前的数据(平滑处理). //用法: REF(X,A),引用A周期前的X值.A可以是变量. //平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值. //例如: REF(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价. this.REF=function(data,n) { let result=[]; if (typeof(n)=='number') { if (IFrameSplitOperator.IsNumber(data)) //单数值 { if (n<0) return result; var kData=this.SymbolData.Data.Data; if (!kData || kData.length<=0) return result; var count=kData.length; for(var i=n;i=data.length) return result; result=data.slice(0,data.length-n); //平滑处理 var firstData=data[0]; for(let i=0;i=n.length) continue; var value=n[i]; if (value>=0 && value<=i) result[i]=data[i-value]; else if (i) result[i]=result[i-1]; else result[i]=data[i]; } } return result; } //引用若干周期前的数据(未作平滑处理). //用法: REFV(X,A),引用A周期前的X值.A可以是变量. //平滑处理:当引用不到数据时进行的操作. //例如: REFV(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价. this.REFV=function(data,n) { let result=[]; if (typeof(n)=='number') { if (data.length<=0) return result; if (n>=data.length) return result; result=data.slice(0,data.length-n); for(let i=0;i=n.length) continue; var value=n[i]; if (value>=0 && value<=i) result[i]=data[i-value]; } } return result; } //属于未来函数,引用若干周期后的数据(平滑处理). //用法: REFX(X,A),引用A周期后的X值.A可以是变量. //平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值. //例如: TT:=IF(C>O,1,2); // REFX(CLOSE,TT);表示阳线引用下一周期的收盘价,阴线引用日后第二周期的收盘价. this.REFX=function(data,n) { let result=[]; if (typeof(n)=='number') { if (data.length<=0) return result; if (n>=data.length) { if (data.length>0) return data[data.length-1]; //取最后一个数据 return result; } result=data.slice(n,data.length); //平滑处理 var lastData=data[data.length-1]; for(let i=0;i=n.length) continue; var value=n[i]; if (value>=0 && value+i=data.length) return result; result=data.slice(n,data.length); //平滑处理 for(let i=0;i=n.length) continue; var value=n[i]; if (value>=0 && value+i0) { maxNumber=aryNumber[0]; for(var i=1; i0) { maxAryData=aryData[0].slice(0); for(var i=1;i0) { minNumber=aryNumber[0]; for(var i=1; i0) { minAryData=aryData[0].slice(0); for(var i=1;i=0;--j) { var value=data[i-j]; if (!this.IsNumber(value)) { value=preValue; //空数据就取上一个数据 data[i-j]=value; } else { preValue=value; } sum+=value; } result[i]=sum/dayCount; } } else { for(var i=0;i=dayCount.length) continue; var sumCount=dayCount[i]; if (!this.IsNumber(sumCount)) continue; if (sumCount<=0) continue; var sum=0; var count=0; for(var j=i, k=0;j>=0 && k0) result[i]=sum/count; } } return result; } //指数平均数指标 EMA(close,10) //N 支持周期数组 this.EMA=function(data,dayCount) { var result = []; if (data.length<=0) return result; if (Array.isArray(dayCount)) { for(var i=0;ii+1) period=i+1; //EMA(N) = 2/(N+1)*C + (N-1)/(N+1)*EMA', EMA'为前一天的ema var EMAFactor=[ 2/ (period + 1), (period - 1) / (period + 1)]; var ema=null; var lastEMA=null; for(var j=0;j= 0 && ji+1) period=i+1; var lastSMA=null; var sma=null; for(var j=0;j=period) continue; var sum=0, count=0; for(var j=start, k=1;j= 0; --j) { var value = data[i-j]; if (!this.IsNumber(value)) { value = preValue; data[i-j] = value; } else preValue = value; count += dayCount - j; sum += value * (dayCount - j); } result[i] = sum / count; } return result; } } /* 返回平滑移动平均 用法:MEMA(X,N):X的N日平滑移动平均,如Y=(X+Y'*(N-1))/N MEMA(X,N)相当于SMA(X,N,1) */ this.MEMA=function(data, dayCount) { let result=[]; if (!data || !data.length) return result; var i = 0, j = 0; for (j = 0; j < data.length && !this.IsNumber(data[j]); ++j) { result[j] = null; } i = j; if (dayCount < 1 || i+dayCount >= data.length) return result; var sum = 0; var data = data.slice(0); for (; i < j+dayCount; ++i) { result[i] = null; if (!this.IsNumber(data[i]) && i-1 >= 0) data[i] = data[i-1]; sum += data[i]; } result[i-1] = sum / dayCount; for (; i < data.length; ++i) { if (this.IsNumber(result[i-1]) && this.IsNumber(data[i])) result[i] = (data[i]+result[i-1]*(dayCount-1)) / dayCount; else if (i-1 > -1 && this.IsNumber(result[i-1])) result[i] = result[i-1]; else result[i] = null; } return result; } /* 加权移动平均 返回加权移动平均 用法:EXPMA(X,M):X的M日加权移动平均 EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para) */ this.EXPMA=function(data,dayCount) { let result=[]; if (dayCount>=data.length) return result; let i=dayCount; for(;i=data.length) return result; var index=0; for(;index= start; --i) { var total = 0; for (j = i, total = 0; j >= start && total < data2[i]; --j) total += data[j]; if (j < start) result[i] = null; else result[i] = i - j; } for(i = start+1; i < data.length; ++i) { if (result[i]==null) result[i] = result[i-1]; } return result; } /* 求相反数. 用法:REVERSE(X)返回-X. 例如:REVERSE(CLOSE)返回-CLOSE */ this.REVERSE=function(data) { if (this.IsNumber(data)) { return 0-data; } var result = []; var i = 0; for (; iOPEN, 20)表示统计20周期内收阳的周期数 N 支持数组 */ this.COUNT=function(data,n) { if (Array.isArray(n)) { var start=null; var dataCount=data.length; for(var i=0;i=0 && k=n.length) continue; max=null; var count=n[i]; if (count>0 && count<=i) { for(j=i-count;j<=i;++j) { if (max==null || maxdata.length) n=data.length; var nStart=this.GetFirstVaildIndex(data); if (nStart>=data.length) return result; var nMax=nStart; if (nMax=data[nMax]) nMax=i; result[i]=data[nMax]; } for(;iREF(DATE,1))+1; ZH:VALUEWHEN(DATE<>REF(DATE,1),HV(H,N));//在分钟周期上,求昨天最高价。 例3: HV(H,5) 和 REF(HHV(H,5),1) 的结果是一样的,用HV编写更加方便。 */ this.HV=function(data,n) { var result=this.HHV(data,n); return this.REF(result,1); } /* LLV 最低值 求最低值。 用法: LLV(X,N) 求N周期内X最低值,N=0则从第一个有效值开始。 例如: LLV(LOW,0) 表示求历史最低价。 */ this.LLV=function(data,n) { var result = []; if (Array.isArray(n)) { for(var i=0;i=n.length) continue; var min=null; var count=n[i]; if (count>0 && count<=i) { for(var j=i-count;j<=i;++j) { if (min==null || min>data[j]) min=data[j]; } } else { count=i; for(var j=0;j<=i;++j) { if (min==null || min>data[j]) min=data[j]; } } result[i]=min; } } else { if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result; n=parseInt(n); if (n<=0) n=data.length; else if (n>data.length) n=data.length; var nStart=this.GetFirstVaildIndex(data); if (nStart>=data.length) return result; var nMin=nStart; if (nMindata[nMin]?nMin:i; } else { for(j=nMin=(i-n+1);j<=i;++j) { nMin=data[j]>data[nMin]?nMin:j; } } result[i]=data[nMin]; } } return result; } /* LV(X,N) 求X在N个周期内的最小值(不包含当前k线) 注: 1、若N为0则从第一个有效值开始算起; 2、当N为有效值,但当前的k线数不足N根,按照实际的根数计算; 3、N为空值时,返回空值。 4、N可以是变量。 例1: LL:LV(L,10);//求前面10根k线的最低点。(不包含当前k线) 例2: N:=BARSLAST(DATE<>REF(DATE,1))+1;//分钟周期,日内k线根数 ZL:VALUEWHEN(DATE<>REF(DATE,1),LV(L,N));//在分钟周期上,求昨天最低价。 例3: LV(L,5) 和 REF(LLV(L,5),1) 的结果是一样的,用LV编写更加方便。 */ this.LV=function(data,n) { var result=this.LLV(data,n); return this.REF(result,1); } this.STD=function(data,n) { var result=[]; if (!Array.isArray(data)) return result; var nStart=this.GetFirstVaildIndex(data); if (!IFrameSplitOperator.IsNumber(n)) return result; if(nStart+n>data.length || n<1) return result; var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0; for(i+=n-1;idata.length || n<1) return result; var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0; for(i+=n-1;idata2[index] && data[index-1]data2 && data[index-1]data) ? 1:0; } } return result; } /* CROSSDOWN(A,B):表示当A从上方向下穿B,成立返回1(Yes),否则返回0(No) 注:1、CROSSDOWN(A,B)等同于CROSS(B,A),CROSSDOWN(A,B)编写更利于理解 例1: MA5:=MA(C,5); MA10:=MA(C,10); CROSSDOWN(MA5,MA10)//MA5下穿MA10 */ this.CROSSDOWN=function(data,data2) { return this.CROSS(data2,data); } /* CROSSUP(A,B) 表当A从下方向上穿过B,成立返回1(Yes),否则返回0(No) 注: 1、CROSSUP(A,B)等同于CROSS(A,B),CROSSUP(A,B)编写更利于理解。 例1: MA5:=MA(C,5); MA10:=MA(C,10); CROSSUP(MA5,MA10),ICON(1,'ICO4');//MA5上穿MA10,标注红箭头。 //CROSSUP(MA5,MA10),ICON(1,'ICO4'); 与 CROSSUP(MA5,MA10)=1,ICON(1,'ICO4');表达同等意义 */ this.CROSSUP=function(data,data2) { return this.CROSS(data,data2); } //累乘 this.MULAR=function(data,n) { var result=[]; if (!Array.isArray(n)) { if(data.length=0 && k0)) continue; for(var j=i, k=0 ;j>=0 && k=0;--i) { if (this.IsNumber(n[i])) { num = parseInt(n[i]); break; } } } else { num = parseInt(n); } if (!this.IsNumber(num)) return result; var datanum = data.length; var i = 0, j = 0, k = 0; var E = 0, DEV = 0; for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i) { result[i] = null; } if (num < 1 || i+num>datanum) return result; for(E=0; i < datanum && j < num; ++i,++j) E += data[i]/num; if (j == num) { DEV = 0; for(i--; k < num; k++) DEV += (data[i-k]-E) * (data[i-k]-E); result[i] = DEV; i++; } for(; i < datanum; ++i) { E += (data[i] - data[i-num]) / num; for(DEV=0, k = 0; k < num; ++k) DEV += (data[i-k]-E) * (data[i-k]-E); result[i] = DEV; } } return result; } //NOT 取反 //求逻辑非。 //用法: NOT(X) 返回非X,即当X=0时返回1,否则返回0。 //例如: NOT(ISUP) 表示平盘或收阴。 this.NOT=function(data) { let isNumber=typeof(data)=='number'; if (isNumber) return data? 0:1; let result=[]; for(let i in data) { result[i]=null; if (this.IsNumber(data[i])) result[i]=data[i]?0:1; } return result; } //FORCAST 线性回归预测值 //FORCAST(X,N)  返回线性回归预测值。 this.FORCAST=function(data,n) { var result=[]; if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型 var num = n; var datanum = data.length; if (num < 1 || num >= datanum) return result; var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope; var i, j,x; for(j = 0; j < datanum && !this.IsNumber(data[j]); ++j) { result[j] = null; } for(i = j+num-1; i < datanum; ++i) { Ex = Ey = Sxy = Sxx = 0; for(j = 0, x=num; j < num && j <= i; ++j, --x) { Ex += x; Ey += data[i - j]; } Ex /= num; Ey /= num; for(j = 0, x=num; j < num && j <= i; ++j,--x) { Sxy += (x-Ex)*(data[i-j]-Ey); Sxx += (x-Ex)*(x-Ex); } Slope = Sxy / Sxx; Const = Ey - Ex*Slope; result[i] = Slope * num + Const; } return result; } //TSMA(X,N):求X在N个周期内的时间序列三角移动平均 //TSMA(a,n) 算法如下: //ysum=a[i]+a[i-1]+...+a[i-n+1] //xsum=i+i-1+..+i-n+1 //xxsum=i*i+(i-1)*(i-1)+...+(i-n+1)*(i-n+1) //xysum=i*a[i]+(i-1)*a[i-1]+...+(i-n+1)*a[i-n+1] //k=(xysum -(ysum/n)*xsum)/(xxsum- xsum/n * xsum) //斜率 //b= ysum/n - k*xsum/n //forcast[i]=k*i+b //线性回归 //tsma[i] = forcast[i]+k //线性回归+斜率 this.TSMA=function(data,n) { var result=[]; if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型 var num = n; var datanum = data.length; if (num < 1 || num >= datanum) return result; var Ex = 0, Ey = 0, Sxy = 0, Sxx = 0, Const, Slope; var i, j,x; for(j = 0; j < datanum && !this.IsNumber(data[j]); ++j) { result[j] = null; } for(i = j+num-1; i < datanum; ++i) { Ex = Ey = Sxy = Sxx = 0; for(j = 0, x=num; j < num && j <= i; ++j, --x) { Ex += x; Ey += data[i - j]; } Ex /= num; Ey /= num; for(j = 0, x=num; j < num && j <= i; ++j,--x) { Sxy += (x-Ex)*(data[i-j]-Ey); Sxx += (x-Ex)*(x-Ex); } Slope = Sxy / Sxx; Const = Ey - Ex*Slope; result[i] = (Slope * num + Const) + Slope; } return result; } //SLOPE 线性回归斜率 //SLOPE(X,N)  返回线性回归斜率。 this.SLOPE=function(data,n) { let result=[]; if (typeof(n)!='number') n=parseInt(n); //字符串的转成数值型 if (n<1 || !data.length) return result; if (n>=data.length) return result; let start=0; for(let i=0;idata.length || n<1) return result; var i=nStart, j=0, bFirst=true, dTotal=0, dAvg=0; for(i+=n-1;i= datanum) return result; var i, j; for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i) { result[i] = null; } var SigmaPowerX, SigmaX; for (j = 0, i = i+num-1; i < datanum; ++i) { SigmaPowerX = SigmaX = 0; for(j=0; j < num && j <= i; ++j) { SigmaPowerX += data[i-j] * data[i-j]; SigmaX += data[i-j]; } result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1); } } else if (Array.isArray(data) && Array.isArray(n)) { var start=this.GetFirstVaildIndex(data); for(var i=start; i= datanum) return result; var i = 0, j = 0; for(i = 0; i < datanum && !this.IsNumber(data[i]); ++i) { result[i] = null; } var SigmaPowerX = 0, SigmaX = 0; for (; i < datanum && j < num; ++i, ++j) { SigmaPowerX += data[i] * data[i]; SigmaX += data[i]; } if (j == num) result[i-1] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num); for(; i < datanum; ++i) { SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num]; SigmaX += data[i] - data[i-num]; result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num); } return result; } //RANGE(A,B,C)表示A>B AND AMath.min(range,range2) && data=range.length) continue; rangeValue=range[i]; } else { rangeValue=range; } if (!this.IsNumber(rangeValue)) continue; if (!isNumber3) { if (i>=range2.length) continue; rangeValue2=range2[i]; } else { rangeValue2=range2; } if (!this.IsNumber(rangeValue2)) continue; result[i]= (value>Math.min(rangeValue,rangeValue2) && valueOPEN,10) 表示10日内存在着阳线 */ this.EXIST=function(data,n) { if (typeof(data)=='number') return 0; if (Array.isArray(n)) { var result=[]; if (data.length<=0) return result; for( var i in data) //初始化 { result[i]=0; } for(var i=0;ii+1) period=i+1; var bExist=false; var index=0, value=0; for(var j=0;j0) { bExist=true; break; } } result[i]=bExist?1:0; } return result; } else { n=parseInt(n); var latestID=null; //最新满足条件的数据索引 var result=[]; var value; for(let i=0;i0) latestID=i; if (latestID!=null && i-latestID0) result[i]=2; } return result; } return []; } /* 过滤连续出现的信号. 用法:FILTER(X,N):X满足条件后,将其后N周期内的数据置为0,N为常量. 例如: FILTER(CLOSE>OPEN,5)查找阳线,5天内再次出现的阳线不被记录在内 */ this.FILTER=function(data,n) { var result=[]; for(let i=0,j=0; iOPEN,5)查找阳线,前5天内出现过的阳线不被记录在内 this.FILTERX=function(data, n, node) { var result=[]; for(let i=0,j=0; i=0;++j) { result[i-j-1]=0; } i+=n; } else { result[i]=0; } } return result; } //上一次条件成立到当前的周期数. //用法:BARSLAST(X):上一次X不为0到现在的周期数 //例如:BARSLAST(CLOSE/REF(CLOSE,1)>=1.1)表示上一个涨停板到当前的周期数 this.BARSLAST=function(data) { var result=[]; if (!data) return result; let day=null; for(let i=0;i0) day=0; else if (day!=null) ++day; if (day!=null) result[i]=day; } return result; } //倒数第N次成立时距今的周期数. //用法:BARSLASTS(X,N):X倒数第N满足到现在的周期数,N支持变量 this.BARSLASTS=function(data, n, node) { var result=[]; if (!data) return result; if (n<=0) n=data.length; var day=null; var SingleValue=0; //单词数 var periodCount=0; for(let i=0;i0) { if (day==null) { day=0; ++periodCount; } else { ++periodCount; if (periodCount>n) day-=SingleValue; } SingleValue=0; } else { if (day!=null) { ++day; ++SingleValue; } } if (day!=null) result[i]=day; } return result; } /* N周期内第一个条件成立到当前的周期数. 用法: BARSSINCEN(X,N):N周期内第一次X不为0到现在的天数,N为常量 例如: BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数 */ this.BARSSINCEN=function(data,n) { var result=[]; if (this.IsNumber(n) && Array.isArray(data)) { var nPeriod=n; if (nPeriod<1) nPeriod=data.length; var i=this.GetFirstVaildIndex(data); if (i>=data.length) return result; var j=0; if (i <= nPeriod - 1) j = nPeriod - 1; else j = i; result[j] = j - i; for (; j < data.length; ++j) { if (this.IsNumber(result[j - 1])) { if (result[j - 1] + 1 < nPeriod) { result[j] = result[j - 1] + 1; } else { for (var k = j - nPeriod+1; k <= j; ++k) { if (!(Math.abs(data[k]) < 0.000001)) { result[j] = j - k; break; } } } } else { if (!(Math.abs(data[j]) < 0.000001)) result[j] = 0; } } } return result; } /* 第一个条件成立到当前的周期数. 用法: BARSSINCE(X):第一次X不为0到现在的天数 例如: BARSSINCE(HIGH>10)表示股价超过10元时到当前的周期数 */ this.BARSSINCE=function(data) { var result=[]; var day=null; for(let i=0;i=-1 && item<=1) { result[i]=Math.asin(item); } else if (i-1>=0) { var preItem=result[i-1]; if (this.IsNumber(preItem)) result[i]=preItem; } } } return result; } } //反余弦值. 用法: ACOS(X)返回X的反余弦值 this.ACOS=function(data) { if (!Array.isArray(data)) { if (this.IsNumber(data)) return Math.acos(data); return null; } else { var result=[]; for(let i in data) { var item=data[i]; result[i]=null; if (this.IsNumber(item)) { if (item>=-1 && item<=1) { result[i]=Math.acos(item); } else if (i-1>=0) { var preItem=result[i-1]; if (this.IsNumber(preItem)) result[i]=preItem; } } } return result; } } /* LAST(X,A,B):持续存在. 用法: LAST(CLOSE>OPEN,10,5) 表示从前10日到前5日内一直阳线 若A为0,表示从第一天开始,B为0,表示到最后日止 */ this.LAST=function(data,n,n2) { if (!Array.isArray(data)) return []; var result=[]; var lCount=data.length; var nStart = n; var nEnd = n2, k = 0, i = 0, j = 0, t = 0; for (; k < lCount; ++k) { if (data[k]) break; } for (i = k, t = k - nEnd + 1; i= dRate*data[m] ? (data[i]>data[m] ? i : -i) : m; } for (; i= data[i - 1] && data[i] >= data[i + 1]) { if (lState<0) { if ((data[i] - data[-lState]) * 100= lLastPos; j--) dest[j]=data[-lState] + (-lState - j)*dif; lLastPos = -lState; lState = i; } } else if (data[i]>data[lState]) lState = i; } else if (data[i] <= data[i - 1] && data[i] <= data[i + 1]) { if (lState>0) { if ((data[lState] - data[i]) * 100= nDataCount - 2) { if (lState>0 && data[nDataCount - 1] >= data[lState]) lState = nDataCount - 1; if (lState<0 && data[nDataCount - 1] <= data[-lState]) lState = 1 - nDataCount; } if (lState>0) { dif = (data[lState] - data[j = lLastPos]) / (lState - lLastPos ); dest[j++]=data[lLastPos]; for (; j <= lState; ++j) dest[j]=data[lLastPos] + (j - lLastPos)*dif; } else { dif = (data[lLastPos] - data[j = -lState]) / (-lState - lLastPos); dest[j--]=data[-lState]; for (; j >= lLastPos; j--) dest[j]=(data[-lState] + (-lState - j)*dif); } if ((lState = Math.abs(lState))= data[lState]) { dif = (data[nDataCount - 1] - data[j = lState]) / (nDataCount - lState); dest[j++]=(data[lState]); for (; j= lState; j--) dest[j]=(data[nDataCount - 1] + (nDataCount - j)*dif); } } return dest; } this.JSDraw=null; this.CalculateZIGLine=function(firstData,secondData,thridData,data,result) { if (this.JSDraw==null) this.JSDraw=new JSDraw(this.ErrorHandler); var isUp=secondData.Up; var findData=firstData; if (isUp) { for(var i=firstData.ID+1;isubItem) findData={ID:i, Value:subItem}; } } secondData.Value=findData.Value; secondData.ID=findData.ID; var lineCache={ Start:{ID:firstData.ID, Value:firstData.Value}, End:{ID:secondData.ID,Value:secondData.Value}}; var lineData=this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值 for(var i in lineData) { var lineItem=lineData[i]; result[lineItem.ID]=lineItem.Value; } if (thridData.ID==data.length-1) //最后一组数据 { //最后2个点的数据连成线 lineCache={ Start:{ID:secondData.ID, Value:secondData.Value}, End:{ID:thridData.ID,Value:thridData.Value} }; lineData=this.JSDraw.CalculateDrawLine(lineCache);//计算2个点的线上 其他点的数值 for(var i in lineData) { var lineItem=lineData[i]; result[lineItem.ID]=lineItem.Value; } } else { firstData.ID=secondData.ID; firstData.Value=secondData.Value; secondData.ID=thridData.ID; secondData.Value=thridData.Value; secondData.Up=firstData.Value < secondData.Value; } } /* 属于未来函数,前M个ZIG转向波谷到当前距离. 用法: TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1 例如: TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数 */ this.TROUGHBARS=function(data,n,n2) { var zigData=this.ZIG(data,n); //计算ZIG var dest=[]; var lEnd =n2; if (lEnd<1) return dest; var nDataCount = zigData.length; var trough = []; for(var i=0;izigData[i - 1]; ++i); for (; izigData[i-1]; ++i); for(; izigData[i - 1]; ++i); for (peak[0] = --i; izigData[i + 1]) { if (lFlag) { if (lEnd) { var tempPeak=peak.slice(0); for(var j=0;jzigData[i - 1]; ++i); for (peak[0] = --i; izigData[i + 1]) { if (lFlag) { if (lEnd) { var tempPeak=peak.slice(0); for(var j=0;jOPEN,N) 表示N日内一直阳线(N应大于0,小于总周期数,N支持变量) */ this.EVERY=function(data,n) { var result=[]; if (n<1) return result; if (IFrameSplitOperator.IsNumber(n)) { n=parseInt(n); var i=0; for(;i=0 && k1) return result; var kData=this.SymbolData.Data.Data; if (!kData || kData.length<=0) return result; var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本 var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low; for(var i=0;i 2000 || dMinPrice < 0 || dMaxPrice>2000 || dMinPrice < 0) this.ThrowUnexpectedNode(node,'COST() 历史K线最大最小值错误, 超出(0,1000)范围'); var lMaxPrice = parseInt(dMaxPrice * 100 + 1); var lMinPrice = parseInt(dMinPrice * 100 - 1); var lLow = 0, lHigh = 0, lClose = 0; //去掉小数 dMaxPrice = lMaxPrice / 100.0; dMinPrice = lMinPrice / 100.0; var lSpeed = lMaxPrice - lMinPrice + 1; if (lSpeed < 1) return result; var aryVolPrice=[],aryPerVol=[]; for(var i=0;i= aryCapital.length) continue; if (aryCapital[i]>1) { var kItem=kData[i] dHSL = kItem.Vol/aryCapital[i]; for( var j=0;j=dTotalVol*rate) { dCost=(dMaxPrice-dMinPrice)*j/lSpeed+dMinPrice; break; } } } result[i]=dCost; } return result; } /* this.COST=function(data) { var result=[]; var exchangeID=201; var exchangeData=this.SymbolData.GetFinanceCacheData(exchangeID); //换手率 if (!exchangeData) return result; var isNumber=Array.isArray(data)?false:true; var singleData=null; if (isNumber) singleData=parseFloat(data); var compareData=null; for(let i=this.SymbolData.Data.Data.length-1, j=0,k=0 ; i>=0; --i) { result[i]=null; var chipData=this.CalculateChip(i,exchangeData,this.SymbolData.Data.Data,1); if (chipData.Max==null || chipData.Min==null || chipData.Max<=0 || chipData.Min<=0) continue; var max=parseInt(chipData.Max*100); var min=parseInt(chipData.Min*100); if (singleData!=null) { compareData=singleData; } else { if (i>=data.length) continue; compareData=data[i]; } var totalVol=0,vol=0; var aryMap=new Map(); for(j=i; j>=0; --j) { var item=chipData.Data[j]; var start=parseInt(item.Low*100); var end=parseInt(item.High*100); if ((end-start+1)<=0) continue; var iAverageVolume=item.Vol; iAverageVolume=iAverageVolume/(end-start+1); if (iAverageVolume<=0) continue; for(k=start;k<=end && k<=max;++k) { if (aryMap.has(k)) { vol=aryMap.get(k); aryMap.set(k,vol+iAverageVolume); } else { aryMap.set(k,iAverageVolume); } } totalVol+=item.Vol; } //计算获利盘 vol=0; for(var priceData of aryMap) { vol+=priceData[1]; result[i]=priceData[0]/100; if (vol/totalVol*100>compareData) break; } } return result; } */ /* 获利盘比例. 用法: WINNER(CLOSE),表示以当前收市价卖出的获利盘比例,例如返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例 该函数仅对日线分析周期有效 */ this.WINNER=function(data, node) { var result=[]; var kData=this.SymbolData.Data.Data; if (!kData || kData.length<=0) return result; var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本 var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low; for(var i=0;i 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0) this.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,5000)范围'); var lMaxPrice = parseInt(dMaxPrice * 100 + 1); var lMinPrice = parseInt(dMinPrice * 100 - 1); var lLow = 0, lHigh = 0, lClose = 0; //去掉小数 dMaxPrice = lMaxPrice / 100.0; dMinPrice = lMinPrice / 100.0; var lSpeed = lMaxPrice - lMinPrice + 1; if (lSpeed < 1) return result; var aryVolPrice=[],aryPerVol=[]; for(var i=0;i= aryCapital.length) continue; if (!(aryCapital[i]>1)) continue; var kItem=kData[i] dHSL = kItem.Vol/aryCapital[i]; for( var j=0;j 0) result[i]=dVol / dTotalVol; else if (i - 1 >= 0) result[i] = result[i - 1]; } return result; } /* this.WINNER=function(data) { var result=[]; var exchangeID=201; var exchangeData=this.SymbolData.GetFinanceCacheData(exchangeID); //换手率 if (!exchangeData) return result; var isNumber=Array.isArray(data)?false:true; var singleData=null; if (isNumber) singleData=parseInt(parseFloat(data)*100); var compareData=null; for(let i=this.SymbolData.Data.Data.length-1, j=0,k=0 ; i>=0; --i) { result[i]=null; var chipData=this.CalculateChip(i,exchangeData,this.SymbolData.Data.Data,1); if (chipData.Max==null || chipData.Min==null || chipData.Max<=0 || chipData.Min<=0) continue; var max=parseInt(chipData.Max*100); var min=parseInt(chipData.Min*100); if (singleData!=null) { compareData=singleData; } else { if (i>=data.length) continue; compareData=parseInt(data[i]*100); } var totalVol=0,vol=0; for(j=i; j>=0; --j) { var item=chipData.Data[j]; var start=parseInt(item.Low*100); var end=parseInt(item.High*100); if ((end-start+1)<=0) continue; var iAverageVolume=item.Vol; iAverageVolume=iAverageVolume/(end-start+1); if (iAverageVolume<=0) continue; var profitVol=0; //获利的成交量 if (compareData>end) profitVol=item.Vol; else if (compareData0) result[i]=vol/totalVol; } return result; } */ /* 区间成本. 用法: 例如COSTEX(CLOSE,REF(CLOSE,1)),表示近两日收盘价格间筹码的成本 该函数仅对日线分析周期有效 */ this.COSTEX=function(data, data2, node) { var result=[]; var kData=this.SymbolData.Data.Data; if (!kData || kData.length<=0) return result; var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本 var dMaxPrice=kData[0].High,dMinPrice=kData[0].Low; for(var i=0;i 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0) this.ThrowUnexpectedNode(node,'COSTEX() 历史K线最大最小值错误, 超出(0,5000)范围'); var lMaxPrice = parseInt(dMaxPrice * 100 + 1); var lMinPrice = parseInt(dMinPrice * 100 - 1); var lLow = 0, lHigh = 0, lClose = 0; //去掉小数 dMaxPrice = lMaxPrice / 100.0; dMinPrice = lMinPrice / 100.0; var lSpeed = lMaxPrice - lMinPrice + 1; if (lSpeed < 1) return result; var aryVolPrice=[],aryPerVol=[]; for(var i=0;i= aryCapital.length) continue; if (aryCapital[i]>1) { var kItem=kData[i] dHSL = kItem.Vol/aryCapital[i]; for( var j=0;j 0.001 && dVol!=0 ) result[i]=dPerVolRange / dVol; else if (i-1>=0) result[i] = result[i - 1]; } } return result; } /* 远期成本分布比例. 用法: PPART(10),表示10前的成本占总成本的比例,0.2表示20% */ this.PPART=function(n,node) { var result=[]; var startDay=n; if (startDay<0) return result; var kData=this.SymbolData.Data.Data; if (!kData || kData.length<=0) return result; var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本 for (var i = startDay, j = 0; i < kData.length; ++i) { var start = i - startDay; if (start < 0) continue; var partVol = 0; for (j = 0; j < startDay; ++j) //前n日成交量和 { var kItem=kData[j + start]; partVol += kItem.Vol; } if (i < aryCapital.length) { if (aryCapital[i]>0) { var value=1 - (partVol / aryCapital[i]); result[i]=value; } } } return result; } /* 近期获利盘比例. 用法: LWINNER(5,CLOSE),表示最近5天的那部分成本以当前收市价卖出的获利盘比例 例如: 返回0.1表示10%获利盘 */ this.LWINNER=function(n, data, node) { var startDay =n; if (startDay<=0) this.ThrowUnexpectedNode(node,'LWINNER() 第1个参数错误'); var result=[]; var kData=this.SymbolData.Data.Data; if (!kData || kData.length<=0) return result; var aryCapital=this.SymbolData.GetStockCacheData({ FunctionName:"FINANCE", Args:[7], ArgCount:1, Node:node } ); //流通股本 var dTotalVol=0,dVol=0; for (var i = startDay-1, j=0, k=0 ; i < kData.length; ++i) { var index = i - startDay + 1; var dMaxPrice=kData[index].High,dMinPrice=kData[index].Low; for(var j=0;j 5000 || dMinPrice < 0 || dMaxPrice>5000 || dMinPrice < 0) this.ThrowUnexpectedNode(node,'LWINNER() 历史K线最大最小值错误, 超出(0,5000)范围'); var lMaxPrice = parseInt(dMaxPrice * 100 + 1); var lMinPrice = parseInt(dMinPrice * 100 - 1); var lLow = 0, lHigh = 0, lClose = 0; dMaxPrice = lMaxPrice / 100.0; dMinPrice = lMinPrice / 100.0; var lSpeed = lMaxPrice - lMinPrice + 1; if (lSpeed < 1) return result; var aryVolPrice=[],aryPerVol=[]; for(var j=0;j 0 && dVol > 0 && dVol <= dTotalVol) result[i]=dVol / dTotalVol; else if (i - 1 >= 0) result[i] = result[i - 1]; } return result; } this.PWINNER=function(n, data, node) { var result=[]; return result; } //计算截至到某一天的历史所有筹码 this.CalculateChip=function(index,exchangeData,hisData,dRate) { var result={Min:null,Max:null,Data:[]}; var seed=1;//筹码历史衰减换手系数 var max=null, min=null; for(let i=index; i>=0; --i) { let item={}; //Vol:量 High:最高 Low:最低 var kData=hisData[i]; if (i==index) item.Vol=kData.Vol*exchangeData[i]; else item.Vol=kData.Vol*seed; item.Date=kData.Date; item.High=kData.High; item.Low=kData.Low; if (max==null) max=item.High; else if (maxdata.length) return result; var days=0; for(let i=0;idata[i-1]) ++days; else days=0; if (days==n) { result[i]=1; --days; } } return result; } /* 返回是否连跌周期. 用法: DOWNNDAY(CLOSE,M) 表示连跌M个周期,M为常量 */ this.DOWNNDAY=function(data,n) { var result=[]; if (n<1) return result; if (data==null || n>data.length) return result; var days=0; for(let i=0;iY 用法: NDAY(CLOSE,OPEN,3) 表示连续3日收阳线 */ this.NDAY=function(data,data2,n) { var result=[]; if (n<1) return result; if (!Array.isArray(data) && !Array.isArray(data2)) return result; if (data==null || data2==null ) return result; if (Array.isArray(data) && Array.isArray(data2)) { if (n>=data.length || n>=data2.length) return result; var count=Math.max(data.length,data2.length); var days=0; for(let i=0;i=data.length || i>=data2.length) continue; if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i])) { days=0; continue; } if (data[i]>data2[i]) ++days; else days=0; if (days==n) { result[i]=1; --days; } } } else if (Array.isArray(data) && !Array.isArray(data2)) { if (n>=data.length || !this.IsNumber(data2)) return; var days=0; for(let i in data) { result[i]=0; if (!this.IsNumber(data[i])) { days=0; continue; } if (data[i]>data2) ++days; else days=0; if (days==n) { result[i]=1; --days; } } } else if (!Array.isArray(data) && Array.isArray(data2)) { if (n>=data2.length || !this.IsNumber(data)) return; var days=0; for(let i in data2) { result[i]=0; if (!this.IsNumber(data2[i])) { days=0; continue; } if (data>data2[i]) ++days; else days=0; if (days==n) { result[i]=1; --days; } } } return result; } /* 两条线维持一定周期后交叉. 用法:LONGCROSS(A,B,N)表示A在N周期内都小于B,本周期从下方向上穿过B时返回1,否则返回0 */ this.LONGCROSS=function(data,data2,n) { var result=[]; var count=Math.max(data.length,data2.length); for(let i=0;i=data.length || i>=data2.length) continue; if (!this.IsNumber(data[i]) || !this.IsNumber(data2[i]) || !this.IsNumber(data[i-1]) || !this.IsNumber(data2[i-1])) continue; if (data[i]>data2[i] && data[i-1]=0;++j) { if (data[i-j]>=data2[i-j]) { result[i]=0; break; } } } return result; } this.ISVALID=function(data) { if (Array.isArray(data)) { var result=[]; for(var i=0;iOPEN,10,5) 表示从前10日内到前5日内存在着阳线 若A为0,表示从第一天开始,B为0,表示到最后日止 */ this.EXISTR=function(data,n,n2) { var result=[]; if (!Array.isArray(data)) return result; n=parseInt(n); n2=parseInt(n2); if (n<=0) n=data.length; if (n2<=0) n2=1; if (n2>n) return result; var result=[]; var value; for(let i=0,j=0;i=n2;--j) { var value=data[i-j]; if (this.IsNumber(value) && value) { result[i]=1; break; } } } return result; } /* RELATE(X,Y,N) 返回X和Y的N周期的相关系数 RELATE(X,Y,N)=(∑[(Xi-Avg(X))(Yi-Avg(y))])/N ÷ √((∑(Xi-Avg(X))^2)/N * (∑(Yi-Avg(Y))^2)/N) 其中 avg(x)表示x的N周期均值: avg(X) = (∑Xi)/N √(...)表示开平方 */ this.RELATE=function(data,data2,n) { var result=[]; if (n<1) n=1; if (!Array.isArray(data)|| !Array.isArray(data2)) return result; var dataAverage=this.CalculateAverage(data,n); var data2Average=this.CalculateAverage(data2,n); var count=Math.max(data.length,data2.length); for(let i=0,j=0;i=data.length || i>=data2.length || i>=dataAverage.length || i>=data2Average.length) continue; var average=dataAverage[i]; var average2=data2Average[i]; var total=0,total2=0,total3=0; for(j=i-n+1;j<=i;++j) { total+=(data[j]-average)*(data2[j]-average2); //∑[(Xi-Avg(X))(Yi-Avg(y))]) total2+=Math.pow(data[j]-average,2); //∑(Xi-Avg(X))^2 total3+=Math.pow(data2[j]-average2,2); //∑(Yi-Avg(Y))^2) } result[i]=(total/n)/(Math.sqrt(total2/n)*Math.sqrt(total3/n)); } return result; } //计算数组n周期内的均值 this.CalculateAverage=function(data,n) { var result=[]; if (n<1) return result; var total=0; for(var i=0;i=data.length || i>=data2.length || i>=dataAverage.length || i>=data2Average.length) continue; var average=dataAverage[i]; var average2=data2Average[i]; var total=0; for(j=i-n+1;j<=i;++j) { total+=(data[j]-average)*(data2[j]-average2); } result[i]=(total/n); } return result; } /* 求上一高点到当前的周期数. 用法: HHVBARS(X,N):求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计 例如: HHVBARS(HIGH,0)求得历史新高到到当前的周期数 */ this.HHVBARS=function(data,n) { var result=[]; if (!Array.isArray(data)) return result; if (Array.isArray(n)) { for(var i=0;i=data[nMax]) nMax=j; } if (nMax!=null) result[i]=(i-nMax); } } else { if (n<1) n=data.length; var nMax=null; //最大值索引 for(var i=0;i=data[nMax]) nMax=i; if(n==data.length) result[i]=(i-nMax); } for(;i=data[nMax]) nMax=i; } else { nMax=i-n+1; for(j=nMax;j<=i;++j) //计算区间最大值 { if (data[j]>=data[nMax]) nMax=j; } } result[i]=i-nMax; } } return result; } /* 求上一低点到当前的周期数. 用法: LLVBARS(X,N):求N周期内X最低值到当前周期数,N=0表示从第一个有效值开始统计 例如: LLVBARS(HIGH,20)求得20日最低点到当前的周期数 */ this.LLVBARS=function(data,n) { var result=[]; if (!Array.isArray(data)) return result; if (Array.isArray(n)) { for(var i=0;i0 && stockItem.YClose>0) stockProfit[i]=(stockItem.Close-stockItem.YClose)/stockItem.YClose; if (indexItem.Close>0 && indexItem.YClose>0) indexProfit[i]=(indexItem.Close-indexItem.YClose)/indexItem.YClose; } //计算均值数组 var averageStockProfit=this.CalculateAverage(stockProfit,n); var averageIndexProfit=this.CalculateAverage(indexProfit,n); for(var i=0,j=0;i=stockProfit.length || i>=indexProfit.length || i>=averageStockProfit.length || i>=averageIndexProfit.length) continue; var averageStock=averageStockProfit[i]; var averageIndex=averageIndexProfit[i]; var covariance=0; //协方差 var variance=0; //方差 for(j=i-n+1;j<=i;++j) { var value=(indexProfit[j]-averageIndex); var value2=(stockProfit[j]-averageStock); covariance+=value*value2; variance+=value*value; } if (this.IsDivideNumber(variance) && this.IsNumber(covariance)) result[i]=covariance/variance; //(covariance/n)/(variance/n)=covariance/variance; } return result; } /* 用法:BETA2(X,Y,N)为X与Y的N周期相关放大系数,表示Y变化1%,则X将变化N% 例如:BETA2(CLOSE,INDEXC,10)表示收盘价与大盘指数之间的10周期相关放大率 */ this.BETA2=function(x,y,n) { var result=[]; if (n<=0) n=1; var xProfit=[null]; //x数据的涨幅 var yProfit=[null]; //y数据的涨幅 var count=Math.max(x.length,y.length); var lastItem={X:x[0], Y:y[0]}; for(var i=1;i0) xProfit[i]=(xItem-lastItem.X)/lastItem.X; if (lastItem.Y>0) yProfit[i]=(yItem-lastItem.Y)/lastItem.Y; lastItem={X:xItem, Y:yItem}; } //计算均值数组 var averageXProfit=this.CalculateAverage(xProfit,n); var averageYProfit=this.CalculateAverage(yProfit,n); for(var i=0,j=0;i=xProfit.length || i>=yProfit.length || i>=averageXProfit.length || i>=averageYProfit.length) continue; var averageX=averageXProfit[i]; var averageY=averageYProfit[i]; var covariance=0; //协方差 var variance=0; //方差 for(j=i-n+1;j<=i;++j) { var value=(xProfit[j]-averageX); var value2=(yProfit[j]-averageY); covariance+=value*value2; variance+=value*value; } if (this.IsDivideNumber(variance) && this.IsNumber(covariance)) result[i]=covariance/variance; //(covariance/n)/(variance/n)=covariance/variance; } return result; } /* 抛物转向. 用法: SAR(N,S,M),N为计算周期,S为步长,M为极值 例如: SAR(10,2,20)表示计算10日抛物转向,步长为2%,极限值为20% */ this.SAR=function(n,step,exValue) { var result=[]; var stockData= this.SymbolData.Data; if (n>=stockData.Data.length) return result; var high=null,low=null; for(var i=0;iitem.Low) low=item.Low; } const SAR_LONG=0, SAR_SHORT=1; var position=SAR_LONG; result[n-1]=low; var nextSar=low, sip=stockData.Data[0].High,af=step/100; for(var i=n;iysip) { sip=item.High; af=Math.min(af+step/100,exValue/100); } nextSar=Math.min(item.Low,yitem.Low); nextSar=Math.min(nextSar,result[i-1]+af*(sip-result[i-1])); } } else if (position==SAR_SHORT) { if(item.High>result[i-1]) { position=SAR_LONG; sip=item.High; af=step/100; nextSar =Math.min(item.Low,yitem.Low); nextSar =Math.min(nextSar,result[i-1]+af*(sip-ysip)); } else { position = SAR_SHORT; if(item.Lowsar[index]; for(var i=index+1;isar[i] && !flag)? 1:0; flag=item.Close>sar[i]; } return result; } /* 属于未来函数,将当前位置到若干周期前的数据设为1. 用法: BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1. 例如: BACKSET(CLOSE>OPEN,2)若收阳则将该周期及前一周期数值设为1,否则为0 */ this.BACKSET=function(condition,n) { var result=[]; if (!condition) return result; var dataCount=condition.length; if (!this.IsNumber(dataCount) || dataCount<=0) return result; if (Array.isArray(n)) { for(var i=0;i=0 && k=0;--i) { var value=condition[i]; if (this.IsNumber(value) && value) { for(j=i;j>i-num;--j) { result[j]=1; } } } if (condition[i]) { for(j=i;j>=pos;--j) result[j]=1; } } return result; } //用法:BETWEEN(A,B,C)表示A处于B和C之间时返回1,否则返回0 //例如:BETWEEN(CLOSE,MA(CLOSE,20),MA(CLOSE,10))表示收盘价介于10日均线和20日均线之间 this.BETWEEN=function(condition, data, data2) { var result=[]; var isNumber=typeof(condition)=='number'; var isNumber2=typeof(data)=='number'; var isNumber3=typeof(data2)=='number'; if (isNumber && isNumber2 && isNumber3) //单数值 { return (condition>=data && condition<=data2) ? 1 : 0; } for(var i in condition) { result[i]=0; var item=condition[i]; var left=null, right=null; if (isNumber2) left=data; else if (iright) { if (item>=right && item<=left) result[i]=1; } else { if (item<=right && item>=left) result[i]=1; } } return result; } //STRCAT(A,B):将两个字符串A,B(非序列化)相加成一个字符串C. //用法: STRCAT('多头','开仓')将两个字符串'多头','开仓'相加成一个字符串'多头开仓' this.STRCAT=function(str1, str2) { var result=[]; if (IFrameSplitOperator.IsString(str1) && IFrameSplitOperator.IsString(str2)) result=str1+str2; return result; } //VARCAT(A,B):将两个字符串A,B相加成一个字符串C. //用法: DRAWTEXT(CLOSE>OPEN,LOW,VARCAT('多头',VAR2STR(C,2))) 将两个字符串相加成一个字符串并按条件显示出来 this.VARCAT=function(data,data2) { var result=[]; if (Array.isArray(data) && Array.isArray(data2)) { var nCount=Math.max(data.length, data2.length); var strValue=""; for(var i=0;i=0) return 1; else return 0; } else if (Array.isArray(data) && IFrameSplitOperator.IsString(str2)) { for(var i=0;i=0?1:0; } else if (IFrameSplitOperator.IsNumber(item)) { str=item.toString(); result[i]=str.indexOf(str2)>=0?1:0; } else { result[i]=0; } } } return result; } this.STRLEN=function(data) { if (IFrameSplitOperator.IsString(data)) return data.length; if (Array.isArray(data)) { var result=[]; for(var i=0;i=0; --i) { var item=data[i]; if (this.IsNumber(item)) { result=item.toFixed(n); return result; } } } else { if (this.IsNumber(data)) result=data.toFixed(n); } return result; } //VAR2STR(A,N):取A的每一个值转为字符串,小数位数N. //用法: VAR2STR(C,3)表示取收盘价,以3位小数转为字符串 this.VAR2STR=function(data,n) { var result=[]; if (Array.isArray(data)) { for(var i=0;i0,X=0,X<0分别返回1,0,-1 */ this.SIGN=function(data) { if (Array.isArray(data)) { var result=[]; for(var i=0;i0) result[i]=1; else if (item==0) result[i]=0; else result[i]=-1; } return result; } else { if (data>0) return 1; else if (data==0) return 0; else return -1; } } /* 统计连续满足条件的周期数. 用法: BARSLASTCOUNT(X),统计连续满足X条件的周期数. 例如: BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数 */ this.BARSLASTCOUNT=function(data) { var result=null; if (Array.isArray(data)) { result=[]; if (data.length>0) { var count=0; for(var i=data.length-1;i>=0;--i) { count=0; for(var j=i;j>=0;--j) { if (data[j]) ++count; else break; } result[i]=count; } } } else { if (data) result=1; else result=0; } return result; } //取整. //用法: INTPART(A)返回沿A绝对值减小方向最接近的整数 //例如:INTPART(12.3)求得12,INTPART(-3.5)求得-3 this.INTPART=function(data) { var result=null; if (Array.isArray(data)) { result=[]; for(var i in data) { var item=data[i]; if (this.IsNumber(item)) result[i]=parseInt(item); else result[i]=null; } } else if (this.IsNumber(data)) { result=parseInt(data); } return result; } //用法:CONST(A),取A最后的值为常量. //例如:CONST(INDEXC),表示取大盘现价 this.CONST=function(data) { if (Array.isArray(data)) { var count=data.length; if (count>0) return data[count-1]; return null; } else { return data; } } //当前值是近多少周期内的最大值. //用法: TOPRANGE(X):X是近多少周期内X的最大值 //例如: TOPRANGE(HIGH)表示当前最高价是近多少周期内最高价的最大值 this.TOPRANGE=function(data) { if (this.IsNumber(data)) return 0; var result=[]; if (Array.isArray(data)) { var count=data.length; for(var i=count-1; i>=0;--i) { result[i]=0; var item=data[i]; if (!this.IsNumber(item)) continue; var value=0; for(var j=i-1;j>=0;--j) { if (data[j]>item) { break; } ++value; } result[i]=value; } } return result; } //当前值是近多少周期内的最小值. //用法:LOWRANGE(X):X是近多少周期内X的最小值 //例如:LOWRANGE(LOW)表示当前最低价是近多少周期内最低价的最小值 this.LOWRANGE=function(data) { if (this.IsNumber(data)) return 0; var result=[]; if (Array.isArray(data)) { var count=data.length; for(var i=count-1; i>=0;--i) { result[i]=0; var item=data[i]; if (!this.IsNumber(item)) continue; var value=0; for(var j=i-1;j>=0;--j) { if (data[j]=0;--i) { result[i]=null; var aryValue=[]; for(var j=n;j0) { aryValue.sort(function(a,b) { return a-b;}); var index=t-1; if (index<0) index=0; else if (index>=aryValue.length) index=aryValue.length-1; result[i]=aryValue[index]; } } } return result; } //N周期前的M周期内的第T个最大值. //用法:FINDHIGH(VAR,N,M,T):VAR在N日前的M天内第T个最高价 this.FINDHIGH=function(data,n,m,t) { if (this.IsNumber(data)) return data; var result=[]; if (Array.isArray(data)) { var count=data.length; for(var i=count-1;i>=0;--i) { result[i]=null; var aryValue=[]; for(var j=n;j0) { aryValue.sort(function(a,b) { return b-a;}); var index=t-1; if (index<0) index=0; else if (index>=aryValue.length) index=aryValue.length-1; result[i]=aryValue[index]; } } } return result; } //N周期前的M周期内的第T个最大值到当前周期的周期数. //用法:FINDHIGHBARS(VAR,N,M,T):VAR在N日前的M天内第T个最高价到当前周期的周期数 this.FINDHIGHBARS=function(data, n, m, t) { if (this.IsNumber(data)) return (m-n-t); var result=[]; if (Array.isArray(data)) { var count=data.length; for(var i=count-1;i>=0;--i) { result[i]=null; var aryValue=[]; for(var j=n;j0) { aryValue.sort(function(a,b) { return b.Value-a.Value;}); var index=t-1; if (index<0) index=0; else if (index>=aryValue.length) index=aryValue.length-1; result[i]=aryValue[index].Period; } } } return result; } //N周期前的M周期内的第T个最小值到当前周期的周期数. //用法:FINDLOWBARS(VAR,N,M,T):VAR在N日前的M天内第T个最低价到当前周期的周期数. this.FINDLOWBARS=function(data, n, m, t) { if (this.IsNumber(data)) return (m-n-t); var result=[]; if (Array.isArray(data)) { var count=data.length; for(var i=count-1;i>=0;--i) { result[i]=null; var aryValue=[]; for(var j=n;j0) { aryValue.sort(function(a,b) { return a.Value-b.Value;}); var index=t-1; if (index<0) index=0; else if (index>=aryValue.length) index=aryValue.length-1; result[i]=aryValue[index].Period; } } } return result; } //求高值名次. //用法:HOD(X,N):求当前X数据是N周期内的第几个高值,N=0则从第一个有效值开始. //例如:HOD(HIGH,20)返回是20日的第几个高价 this.HOD=function(data, n) { var result=[]; if (IFrameSplitOperator.IsNumber(data)) return 1; if (Array.isArray(data)) { var count=data.length; for(var i=count-1;i>=0;--i) { var value=data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; if (Array.isArray(n)) var subCount=parseInt(n[i]); else var subCount=parseInt(n); if (n<=0) subCount=i; var index=1; for(var j=i-1, k=1; j>=0 && kvalue) ++index; } result[i]=index; } } return result; } //求低值名次. //用法:LOD(X,N):求当前X数据是N周期内的第几个低值,N=0则从第一个有效值开始. //例如:LOD(LOW,20)返回是20日的第几个低价 this.LOD=function(data, n) { var result=[]; if (IFrameSplitOperator.IsNumber(data)) return 1; if (Array.isArray(data)) { var count=data.length; for(var i=count-1;i>=0;--i) { var value=data[i]; if (!IFrameSplitOperator.IsNumber(value)) continue; if (Array.isArray(n)) var subCount=parseInt(n[i]); else var subCount=parseInt(n); if (n<=0) subCount=i; var index=1; for(var j=i-1, k=1; j>=0 && k=1.1)表示下一个涨停板到当前的周期数 this.BARSNEXT=function(data) { if (!Array.isArray(data)) return 0; var result=[]; for(var i=0;i0) { result[i]=k; break; } } } return result; } //取随机数. //用法:RAND(N),返回一个范围在1-N的随机整数 this.RAND=function(n) { if (Array.isArray(n)) { var result=[]; for(var i in n) { result[i]=null; var item=n[i]; var value=parseInt(item); if (value<=0) continue; result[i]=Math.ceil(Math.random()*value); } return result; } else { var value=parseInt(n); if (value<=0) return null; var stockData= this.SymbolData.Data; var count=stockData.Data.length; var result=[]; for(var i=0;i=0;--i) { if (this.IsNumber(n[i])) { period=n[i]; break; } } } else { period=n; } if (this.IsNumber(period)) { if (period>1) return result; var index=0; var value=0; for(index;index=ROUND2_SEED.length) decimal=ROUND2_SEED.length-1; if (this.IsNumber(data)) { return Math.round(data*ROUND2_SEED[decimal])/ROUND2_SEED[decimal]; } var result=[]; if (Array.isArray(data)) { for(var i in data) { var item=data[i]; if (this.IsNumber(item)) { result[i]=Math.round(item*ROUND2_SEED[decimal])/ROUND2_SEED[decimal]; } else { result[i]=null; } } } return result; } /* 文华 TRMA(X,N): 求X在N个周期的三角移动平均值。 算法:三角移动平均线公式,是采用算数移动平均,并且对第一个移动平均线再一次应用算数移动平均。 TRMA(X,N) 算法如下 ma_half= MA(X,N/2) trma=MA(ma_half,N/2) 注: 1、N包含当前k线。 2、当N为有效值,但当前的k线数不足N根,函数返回空值。 3、N为0或空值的情况下,函数返回空值。 例1: TRMA5:TRMA(CLOSE,5);//计算5个周期内收盘价的三角移动平均。(N不能被2整除) //TRMA(CLOSE,5)=MA(MA(CLOSE,(5+1)/2)),(5+1)/2); 例2: TRMA10:TRMA(CLOSE,10);// 计算10个周期内收盘价的三角移动平均。(N能被2整除) TRMA(CLOSE,10)=MA(MA(CLOSE,10/2),(10/2)+1)); */ this.TRMA=function(data,n) { if (!this.IsNumber(n) || n<=0) return []; n=parseInt(n); var nFalf=0,nFalf2=0; if (n%2==0) { nFalf=parseInt(n/2); nFalf2=nFalf+1; } else { nFalf=parseInt((n+1)/2); nFalf2=nFalf; } var maFalf=this.MA(data,nFalf); var result=this.MA(maFalf,nFalf2); return result; } //VALUEWHEN(COND,X) //当COND条件成立时,取X的当前值,否则取VALUEWHEN的上个值. this.VALUEWHEN=function(cond,data) { if (Array.isArray(cond)) { var result=[]; if (Array.isArray(data)) { var preValue=null; for(var i in cond) { if (i>=data.length) { result[i]=preValue; continue; } var item=data[i]; if (cond[i]) { result[i]=item; preValue=item; } else { result[i]=preValue; } } } else { var preValue=null; for(var i in cond) { if (cond[i]) { result[i]=data; preValue=data; } else { result[i]=preValue; } } } return result; } else { return cond? 1:0; } } /* HARMEAN(X,N) 求X在N个周期内的调和平均值。 算法举例:HARMEAN(X,5)=1/[(1/X1+1/X2+1/X3+1/X4+1/X5)/5] 注: 1、N包含当前k线。 2、调和平均值与倒数的简单平均值互为倒数。 3、当N为有效值,但当前的k线数不足N根,函数返回空值。 4、N为0或空值的情况下,函数返回空值。 5、X为0或空值的情况下,函数返回空值。 6、N可以为变量。 例:HM5:=HARMEAN(C,5);//求5周期收盘价的调和平均值。 */ this.HARMEAN=function(data, n) { var result=[]; if (Array.isArray(data)) { if (Array.isArray(n)) { for(var i=0;i=n.length) { result[i]=null; continue; } var count=parseInt(n[i]); if (count<=0 || count>i) { result[i]=null; continue; } var sum=0; for(var j=0;ji) { result[i]=null; continue; } var sum=0; for(var j=0;j=startValue) { var year=parseInt(value/10000); var month=parseInt((value%10000)/100); var day=parseInt(value%100); var dateItem=new Date(`${year}-${month}-${day}`); return Math.round((dateItem-dateItem)/ONE_DAY); } } return result; } //求1990.12.19后第若干天的日期. //用法:DAYTODATE(N) //DAYTODATE(N).返回1990.12.19后第N天的日期.有效天数为(0-20000) //例如:DAYTODATE(0)返回901219. this.DAYTODATE=function(data) { var startDate=new Date('1990-12-19') var result=[]; if (Array.isArray(data)) { for(var i in data) { result[i]=null; var item=data[i]; if (!this.IsNumber(item)) continue; startDate.setDate(startDate.getDate()+item); var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate(); value-=19000000; result[i]=value; startDate.setDate(startDate.getDate()-item); } } else if (this.IsNumber(data)) { startDate.setDate(startDate.getDate()+data); var value=startDate.getFullYear()*10000+(startDate.getMonth()+1)*100+startDate.getDate(); value-=19000000; return value; } return result; } /* 求指定时刻距0时有多长时间. 用法: TIMETOSEC(time) TIMETOSEC(time).返回time时刻距0时有多长时间,单位为秒.有效时间为(0-235959) 例如: TIMETOSEC(93000)返回34200. */ this.TIMETOSEC=function(time) { var hour=parseInt(time/10000); var minute=parseInt((time%10000)/100); var sec=time%100; var value=hour*60*60+minute*60+sec; return value; } /* 求0时后若干秒是什么时间. 用法: SECTOTIME(N) SECTOTIME(N).返回0时后N秒是什么时间.有效秒数为(0-86399) 例如: SECTOTIME(34200)返回93000. */ this.SECTOTIME=function(data) { var daySec = 24 * 60 * 60; var hourSec= 60 * 60; var minuteSec=60; var dd = Math.floor(data / daySec); var hh = Math.floor((data % daySec) / hourSec); var mm = Math.floor((data % hourSec) / minuteSec); var ss=data%minuteSec; var value=hh*10000+mm*100+ss; return value; } //用法:ANY(CLOSE>OPEN,10),表示前10日内存在着阳线 this.ANY=function(data, n) { if (n<=0) n=1; var result=[]; if (Array.isArray(data)) { if (n>=data.length) return 0; for(var i=n, j=0;i0) { value=1; break; } } result[i]=value; } return result; } else if (IFrameSplitOperator.IsNumber(data)) { if (data<=0) return 0; if (n>=this.SymbolData.Data.Data.length) return 0; for(var i=n; iOPEN,10),表示前10日内一直阳线 this.ALL=function(data, n) { if (n<=0) n=1; var result=[]; if (Array.isArray(data)) { if (n>=data.length) return 0; for(var i=n, j=0;i0)) { value=0; break; } } result[i]=value; } return result; } else if (IFrameSplitOperator.IsNumber(data)) { if (data<=0) return 0; if (n>=this.SymbolData.Data.Data.length) return 0; for(var i=n; iOPEN,HIGH,TESTSKIP(1));L;表示当日收阳则返回最高值,并执行下一句"L;",否则退出公式计算 */ this.IFC=function(data) { if (Array.isArray(data)) { var item=data[data.length-1]; if (IFrameSplitOperator.IsNumber(item)) return item>0; return false; } else if (IFrameSplitOperator.IsNumber(data)) { return data>0; } else { return false; } } /* 有效数据右对齐. 用法: ALIGNRIGHT(X)有效数据向右移动,左边空出来的周期填充无效值 例如:TC:=IF(CURRBARSCOUNT=2 || CURRBARSCOUNT=5,DRAWNULL,C);XC:ALIGNRIGHT(TC);删除了两天的收盘价,并将剩余数据右移 */ this.ALIGNRIGHT=function(data) { if (Array.isArray(data)) { var result=[]; var index=data.length-1; for(var i=data.length-1;i>=0;--i) { var item=data[i]; if (IFrameSplitOperator.IsNumber(item) || IFrameSplitOperator.IsString(item)) { result[index]=item; --index; } } for(var i=index;i>=0;--i) { result[i]=null; } return result; } else { return data; } } /* 向前累加到指定值到现在的周期数. 用法: SUMBARS(X,A):将X向前累加直到大于等于A,返回这个区间的周期数,若所有的数据都累加后还不能达到A,则返回此时前面的总周期数. 例如:SUMBARS(VOL,CAPITAL)求完全换手到现在的周期数 */ this.SUMBARS=function(data, data2) { var isArray=Array.isArray(data); var isArray2=Array.isArray(data2); var isNumber=IFrameSplitOperator.IsNumber(data); var isNumber2=IFrameSplitOperator.IsNumber(data2); var result=[]; if (isArray && isNumber2) { for(var i=0, n=0;i=0; --j, ++n) { var item=data[i]; if (!IFrameSplitOperator.IsNumber(item)) continue; sum+=data[j]; if (sum>data2) { break; } } result[i]=n; } } else if (isArray && isArray2) { var count=Math.max(data.length, data2.length); for(var i=0;i=0; --j,++n) { var item=data[i]; if (!IFrameSplitOperator.IsNumber(item)) continue; sum+=data[j]; if (sum>value) { break; } } result[i]=n; } } else if (isNumber && isArray2) { for(var i=0;i=0; --j, ++n) { sum+=data; if (sum>value) { break; } } result[i]=n; } } else if (isNumber && isNumber2) { //TODO: 后面再写吧 } return result; } //格式化字符串 "{0}-{1}", C, O; 小数位数 {0:0.00} this.STRFORMAT=function(strFormat,args,node) { var aryParam=strFormat.match(/{[0-9.:]+}/g); if (!IFrameSplitOperator.IsNonEmptyArray(aryParam)) return null; var mapParam=new Map(); //key=index, value={Text} var maxIndex=-1; for(var i=0;i0) { var aryTemp=value.split(":"); if (aryTemp) { if (aryTemp[0]) index=parseInt(aryTemp[0]); if (aryTemp[1]) { if (aryTemp[1].indexOf(".")>=0) { var zeroCount=0; var strTemp=aryTemp[1]; for(var j=strTemp.length-1; j>=0; --j) { if (strTemp[j]=="0") ++zeroCount; else break; } if (zeroCount>0) decimal=zeroCount; } else if (aryTemp[1]=="0") { decimal=0; } } } } else { index=parseInt(value); } if (index<0) continue; var paramItem={ Src:item, Index:index, Text:null, Decimal:null }; if (decimal>=0) paramItem.Decimal=decimal; if (maxIndexOPEN,CLOSE,OPEN,0.8,1)表示画K线中阳线的空心柱体部分。 */ this.STICKLINE=function(condition,data,data2,width,type) { let drawData=[]; let result={DrawData:drawData, DrawType:'STICKLINE',Width:width, Type:type}; if (result.Width<0) result.Width=3; //<0的宽度 使用K线宽度 var IsNumber=typeof(data)=="number"; var IsNumber2=typeof(data2)=="number"; if (Array.isArray(condition)) //数组 { if(condition.length<=0) return result; for(var i in condition) { drawData[i]=null; if (isNaN(condition[i]) || !condition[i]) continue; if (IsNumber && IsNumber2) { drawData[i]={Value:data,Value2:data2}; } else if (IsNumber && !IsNumber2) { if (isNaN(data2[i])) continue; drawData[i]={Value:data,Value2:data2[i]}; } else if (!IsNumber && IsNumber2) { if (isNaN(data[i])) continue; drawData[i]={Value:data[i],Value2:data2}; } else { if (isNaN(data[i]) || isNaN(data2[i])) continue; drawData[i]={Value:data[i],Value2:data2[i]}; } } } else //单值 { if(!condition) return result; for(var i=0;i=HHV(HIGH,20),HIGH,LOW<=LLV(LOW,20),LOW,1) 表示在创20天新高与创20天新低之间画直线并且向右延长。 */ this.DRAWLINE=function(condition,data,condition2,data2,expand) { let drawData=[]; let result={DrawData:drawData, DrawType:'DRAWLINE', Expand:expand}; if(condition.length<=0) return result; let count=Math.max(condition.length,condition2.length); let bFirstPoint=false; let bSecondPont=false; let lineCache={Start:{ },End:{ }, List:new Array()}; for(let i=0;iVAL2时,在VAL1和VAL2之间填充COLOR1;当VAL1MA2, MA1,MA2),colorred 表示MA1>MA2时以红色填充MA1和MA2之间的区域 */ this.FILLRGN=function(condition, data,data2) { let drawData=[]; let result={DrawData:drawData, DrawType:'FILLRGN'}; var isNumber=this.IsNumber(data); var isNumber2=this.IsNumber(data2); if (Array.isArray(condition)) //数组 { for(var i in condition) { drawData[i]=null; var condItem=condition[i]; if (!condItem) continue; var value=this.GetDataByIndex(data, i); if (!value.Result) continue; var value2=this.GetDataByIndex(data2, i); if (!value2.Result) continue; var item={ Value:value.Data, Value2:value2.Data }; drawData[i]=item; } } else { if (condition) { for(var i=0;iO,COLORBLUE,0);//收盘价大于开盘价,用蓝色绘制实心K线 */ this.DRAWCOLORKLINE=function(condition, color, empty) { let drawData=[]; let result={ DrawData:drawData, DrawType:'DRAWCOLORKLINE', IsEmptyBar:!(empty==0), Color:color }; if (Array.isArray(condition)) //数组 { for(var i=0; i=HHV(HIGH,20),HIGH)表示在创20天新高点之间画折线。 */ this.POLYLINE=function(condition,data) { let drawData=[]; let result={DrawData:drawData, DrawType:'POLYLINE'}; let isNumber=IFrameSplitOperator.IsNumber(data); let bFirstPoint=false; let bSecondPont=false; if (isNumber) { if (this.IsNumber(condition)) { if (condition) { var count=this.SymbolData.Data.Data.length; for(var i=0;i=data.length || !this.IsNumber(data[i])) continue; bFirstPoint=true; lineCache.Start={ID:parseInt(i), Value:data[i]}; //第1个点 } else if (bFirstPoint==true && bSecondPont==false) { if (condition[i]==null || !condition[i]) continue; if (i>=data.length || !this.IsNumber(data[i])) continue; lineCache.End={ID:parseInt(i), Value:data[i]}; //第2个点 //根据起始点和结束点 计算中间各个点的数据 let lineData=this.CalculateDrawLine(lineCache); //计算2个点的线上 其他点的数值 for(let j in lineData) { let item=lineData[j]; drawData[item.ID]=item.Value; } let start={ ID:lineCache.End.ID,Value:lineCache.End.Value }; lineCache={Start:start,End:{ } }; } } this.CalculateDrawDataExtendLine(drawData); } } return result } this.CalculateDrawDataExtendLine=function(drawData, maxCount) { if (maxCount<0) return; var x2=null; var count=drawData.length; if (this.IsNumber(maxCount) && maxCount=0;--i) { if (this.IsNumber(drawData[i])) { x2=i; break; } } //y3=(y1-y2)*(x3-x1)/(x2-x1) if (x2!=null && x2-1>=0) { var x1=x2-1; for(var i=x2+1;i1.08,LOW,C)表示当日实体阳线大于8%时在最低价位置显示收盘价. decimal=小数位数 默认2 */ this.DRAWNUMBER=function(condition,data,data2,decimal) { let drawData={ Value:[], Text:[] }; let result={ DrawData:drawData, DrawType:'DRAWNUMBER' }; var dec=2; //小数位数 if (IFrameSplitOperator.IsNumber(decimal)) dec=decimal; var priceData={ DataType:0, SingleValue:null, ArrayValue:null }; //SingleValue=单值 ArrayValue=数组 if (Array.isArray(data)) { priceData.ArrayValue=data; priceData.DataType=2; } else { if (data==="TOP"|| data==="BOTTOM") result.FixedPosition=data; priceData.SingleValue=data; priceData.DataType=1; } var numberData={ DataType:0, SingleValue:null,ArrayValue:null }; if (Array.isArray(data2)) { numberData.ArrayValue=data2; numberData.DataType=2; } else { //单值 numberData.SingleValue=data2; numberData.DataType=1; if (IFrameSplitOperator.IsNumber(data2)) { if (IFrameSplitOperator.IsInteger(data2)) numberData.SingleValue=data2.toString(); else text=data2.toFixed(dec); } } if (Array.isArray(condition)) { for(var i=0; i1.08,0.5,0.5,0,C)表示最后一个交易日实体阳线大于8%时在窗口中间位置显示收盘价. */ this.DRAWNUMBER_FIX=function(condition,x,y,align,data) { var drawData={ Value:[], Text:[], }; var result={ DrawData:drawData, DrawType:'DRAWNUMBER_FIX', Position:{ X:x, Y:y, Type:align } }; var isNumber=IFrameSplitOperator.IsNumber(data); if (Array.isArray(condition)) { for(var i in condition) { drawData.Text[i]=null; drawData.Value[i]=null; if (!condition[i]) continue; if (isNumber) { drawData.Text[i]=this.RemoveZero(data.toFixed(2)); drawData.Value[i]=data; } else { if (i>=data.length || !IFrameSplitOperator.IsNumber(data[i])) continue; var item=data[i]; drawData.Text[i]=this.RemoveZero(item.toFixed(2)); drawData.Value[i]=item; } } } else { if(!condition) { } else { for(var i=0;i=data.length || !IFrameSplitOperator.IsNumber(data[i])) continue; var item=data[i]; drawData.Text[i]=this.RemoveZero(item.toFixed(2)); drawData.Value[i]=item; } } } } return result; } /* 通达信语法: 在图形上绘制小图标. 用法: DRAWICON(COND,PRICE,TYPE),当COND条件满足时,在PRICE位置画TYPE号图标(TYPE为1--41). 例如: DRAWICON(CLOSE>OPEN,LOW,1)表示当收阳时在最低价位置画1号图标. 文华语法: DRAWICON:绘制小图标。 用法: DRAWICON(COND,PRICE,ICON); 当COND条件满足时,在PRICE位置画图标ICON。 注: 1、该函数可以指定位置PRICE标注图标ICON 2、ICON位置可以写成'ICON'的形式,也可以写为数字的形式,即DRAWICON(COND,PRICE,'ICO1');等价于DRAWICON(COND,PRICE,1); 3、不支持将该函数定义为变量,即不支持下面的写法: A:DRAWICON(COND,PRICE,ICON); 4、该函数可以用ALIGN,VALIGN设置图标的对齐方式。 例1: DRAWICON(CLOSEMA5,MA5,2);//表示在收盘价大于5周期均线的k线对应的MA5数值位置上画出图标ICON2。 写完“DRAWICON(C>MA5,MA5,” 以后,点击插入图标按钮,再单击选中的图标插入到函数中,图标用ICO1~ICO105(或1~105)表示。 */ this.DRAWICON=function(condition,data,type) { if (IFrameSplitOperator.IsString(type)) //把ICO1=>1 { var value=type.replace('ICO',""); type=parseInt(value); } var icon=g_JSComplierResource.GetDrawIcon(type); if (!icon) g_JSComplierResource.GetDrawTextIcon(type); if (!icon) icon={Symbol:'🚩'}; let drawData=[]; let result={ DrawData:drawData, DrawType:'DRAWICON',Icon:icon, IconType:type }; if (condition.length<=0) return result; var IsNumber=typeof(data)=="number"; if (typeof(condition)=='number') { if (!condition) return result; for(var i=0;iOPEN,ICON(1,'ICO1');//表示K线收盘大于开盘时,在最高价上显示图标1。 写完“ICON(1,” 以后,点击插入图标按钮,再单击选中的图标插入到函数中,图标用 'ICO1'~'ICO105'表示 */ this.ICON=function(position, type) { if (IFrameSplitOperator.IsString(type)) //把ICO1=>1 { var value=type.replace('ICO',""); type=parseInt(value); } var icon=g_JSComplierResource.GetDrawIcon(type); if (!icon) g_JSComplierResource.GetDrawTextIcon(type); if (!icon) icon={Symbol:'🚩'}; let drawData=[]; let result={DrawData:drawData, DrawType:'ICON',Icon:icon}; for(var i=0;i1 { var value=type.replace('ICO',""); type=parseInt(value); } var icon=g_JSComplierResource.GetDrawIcon(type); let drawData=[]; let result={ DrawData:drawData, DrawType:'TIPICON',Icon:icon, IconType:type, Text:text }; if (condition.length<=0) return result; var IsNumber=typeof(data)=="number"; if (IFrameSplitOperator.IsNumber(condition)) { if (!condition) return result; for(var i=0;i0) result.Border.Width=borderWidth; if (dotted) { if (dotted=='0') { result.Border.Dotted=[]; } else { let ary=dotted.split(','); result.Border.Dotted=[]; for(var i in ary) { var item=ary[i]; if (!item) continue; var value=parseInt(ary[i]); if (!IFrameSplitOperator.IsNumber(value)) continue; if (value<=0) continue; result.Border.Dotted.push(value); } if (result.Border.Dotted.length<=0) result.Border.Dotted=null; } } var IsNumber=typeof(data)=="number"; var IsNumber2=typeof(data2)=="number"; if (typeof(condition)=='number') { if (!condition) return result; //条件是否 for(var i=0;iOPEN,SOUND('A');//表示K线收盘大于开盘时,播放声音"A" */ this.SOUND=function(value) { return { Name:"SOUND", Value: value }; } /* PLAYSOUND 条件满足时,播放指定声音。用法:PLAYSOUND(COND, 'N') 当条件满足时,播放声音'N' 注: 1、点击设置声音按钮,在弹出来的界面中设置声音,声音用字符'A'~'J'表示。 2、自定义声音可以在设置菜单的设置声音文件中设置 3、条件如果一直满足,则只播放一次,不重复播放。 4、历史数据不触发该函数 例: PLAYSOUND(CLOSE>OPEN,'A');//表示CLOSE>OPEN时播放自定义声音'A'。 */ this.PLAYSOUND=function(cond, value) { return null; } //用法:PARTLINE(PRICE,COND1,COLOR1,COND2,COLOR2...), //绘制PRICE线,当COND1条件满足时,用COLOR1颜色,当COND2条件满足时,用COLOR2颜色,否则不绘制,从COLOR1之后的参数均可以省略,最多可以有10组条件 //例如:PARTLINE(CLOSE,CLOSE>OPEN,RGB(255,0,0),CLOSEOPEN,RGB(255,0,0),CLOSE=price.length) continue; if (!this.IsNumber(price[i])) continue; drawItem.Value=price[i]; } else if (this.IsNumber(price)) { drawItem.Value=price; } else { continue; } if (Array.isArray(price2)) { if (i>=price2.length) continue; if (!this.IsNumber(price2[i])) continue; drawItem.Value2=price2[i]; } else if (this.IsNumber(price2)) { drawItem.Value2=price2; } else { continue; } drawData[i]=drawItem; } return result; } //用法:FLOATRGN(PRICE,WIDTH,COND1,COLOR1,COND2,COLOR2...),以PRICE为基础填充宽度为WIDTH像素的区域,WIDTH为负则向下填充,当COND1条件满足时,用COLOR1颜色,当COND2条件满足时,用COLOR2颜色,否则不填充,从COND1之后的参数均可以省略,最多可以有10组条件 //例如:FLOATRGN(CLOSE,VOL/HHV(VOL,10)*15,CLOSE>OPEN,RGB(255,0,0),1,RGB(0,255,0))表示沿收盘价填充宽度为成交量的区域,区域最大宽度为15像素,阳线时用红色,阴线时用绿色。 this.FLOATRGN=function(args) { let drawData=[]; let result={DrawData:drawData, DrawType:'FLOATRGN'}; if (args.length<4) return result; var price=args[0]; var width=args[1]; var condition=[]; for(var i=2;i=price.length) continue; if (!this.IsNumber(price[i])) continue; drawItem.Value=price[i]; } else if (this.IsNumber(price)) { drawItem.Value=price; } else { continue; } if (Array.isArray(width)) { if (i>=width.length) continue; if (!this.IsNumber(width[i])) continue; drawItem.Value2=width[i]; } else if (this.IsNumber(width)) { drawItem.Value2=width; } else { continue; } drawData[i]=drawItem; } return result; } //函数:FILLTOPRGN / FILLBOTTOMRGN 根据条件填充顶部或底部区域 //用法 FILLTOPRGN(PRICE, COND1, COLOR, COND2, COLOR2) this.FILLBGRGN=function(type,args) { let drawData=[]; let result={DrawData:drawData, DrawType:(type==1 ?'FILLTOPRGN':"FILLBOTTOMRGN")}; if (args.length<3) return result; var price=args[0]; var condition=[]; for(var i=1;i=price.length) continue; if (!this.IsNumber(price[i])) continue; drawItem.Value=price[i]; } else if (this.IsNumber(price)) { drawItem.Value=price; } else { continue; } drawData[i]=drawItem; } return result; } //函数:FILLVERTICALRGN 根据条件填充顶部到底部区域 //用法 FILLVERTICALRGN(COND1, COLOR, COND2, COLOR2) this.FILLVERTICALRGN=function(args) { let drawData=[]; let result={DrawData:drawData, DrawType:"FILLVERTICALRGN"}; if (args.length<2) return result; var condition=[]; for(var i=0;iC,RGB(0,255,0),RGB(255,0,0),0); this.DRAWGBK=function(condition, color, color2, colorAngle) { let drawData={ Color:[], Angle:colorAngle }; if (color) drawData.Color.push(color); if (color2) drawData.Color.push(color2); let result={DrawData:null, DrawType:'DRAWGBK'}; if (Array.isArray(condition)) { for(var i in condition) { var item=condition[i]; if (item) { result.DrawData=drawData; break; } } } else { if (condition) result.DrawData=drawData; } return result; } this.DRAWGBK2=function(condition, color, color2, colorAngle) { let drawData={ Color:[], Angle:colorAngle }; if (color) drawData.Color.push(color); if (color2) drawData.Color.push(color2); let result={DrawData:null, DrawType:'DRAWGBK2'}; if (Array.isArray(condition)) { drawData.Data=[]; for(var i in condition) { var item=condition[i]; drawData.Data[i]=item ? 1:0; } result.DrawData=drawData; } else { if (condition) { result.DrawData=drawData; result.DrawType="DRAWGBK"; } } return result; } //填充部分背景. //用法: //DRAWGBK_DIV(COND,COLOR1,COLOR2,填色方式,填充范围),填充满足COND条件的背景区域 //填色方式:0是上下渐进 1是左右渐进 2是用COLOR1画框线 3是用COLOR1画框线, 用COLOR2填充 //填充范围:0为整个区域 1为最高最低区 2为开盘收盘区 //例如: //DRAWGBK_DIV(C>O,RGB(0,255,0),RGB(255,0,0),0,0); this.DRAWGBK_DIV=function(condition, color, color2, colorType, fillType) { var drawData={ AryColor:[color, color2], ColorType:colorType, FillType:fillType, Data:[] }; var result={ DrawData:drawData, DrawType:'DRAWGBK_DIV' }; if (!this.SymbolData || !this.SymbolData.Data || !IFrameSplitOperator.IsNonEmptyArray(this.SymbolData.Data.Data)) return result; var aryKData=this.SymbolData.Data.Data; if (Array.isArray(condition)) { for(var i=0; i0) value=price[price.length-1]; drawData.Price=value; } else { drawData.Price=price; } result.DrawData=drawData; } } return result; } // 相对位置上画矩形. //用法: DRAWRECTREL(LEFT,TOP,RIGHT,BOTTOM,COLOR),以图形窗口(LEFT,TOP)为左上角,(RIGHT,BOTTOM)为右下角绘制矩形,坐标单位是窗口沿水平和垂直方向的1/1000,取值范围是0—999,超出范围则可能显示在图形窗口外,矩形中间填充颜色COLOR,COLOR为0表示不填充. //例如: DRAWRECTREL(0,0,500,500,RGB(255,255,0))表示在图形最左上部1/4位置用黄色绘制矩形 this.DRAWRECTREL=function(left, top, right,bottom, color) { let drawData={ Rect:{Left:Math.min(left,right), Top:Math.min(top,bottom), Right:Math.max(right,left), Bottom:Math.max(bottom,top) }, Color:color }; if (color==0) drawData.Color=null; let result={DrawData:drawData, DrawType:'DRAWRECTREL'}; return result; } //DRAWTEXTREL(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是窗口沿水平和垂直方向的1/1000,X、Y取值范围是0—999,超出范围则可能显示在图形窗口外。 //例如:DRAWTEXTREL(500,500,'注意')表示在图形中间位置显示'注意'字样。 this.DRAWTEXTREL=function(x, y, text) { let drawData={ Point:{X:x, Y:y} }; if (IFrameSplitOperator.IsString(text)) drawData.Text=text; else if (IFrameSplitOperator.IsNonEmptyArray(text)) drawData.Text=text[0]; let result={DrawData:drawData, DrawType:'DRAWTEXTREL'}; return result; } //DRAWTEXTABS(X,Y,TEXT),在图形窗口(X,Y)坐标位置书写文字TEXT,坐标单位是像素,图形窗口左上角坐标为(0,0)。 //例如:DRAWTEXTABS(0,0,'注意')表示在图形最左上角位置显示'注意'字样。 this.DRAWTEXTABS=function(x, y, text) { let drawData={ Point:{X:x, Y:y} }; if (IFrameSplitOperator.IsString(text)) drawData.Text=text; else if (IFrameSplitOperator.IsNonEmptyArray(text)) drawData.Text=text[0]; let result={DrawData:drawData, DrawType:'DRAWTEXTABS'}; return result; } //画百分比叠加线 this.DRAWOVERLAYLINE=function(data, mainData, title) { let drawData={ Data:data, MainData:mainData }; if (title && typeof(title)=='string') drawData.Title=title; let result={ DrawData:drawData, DrawType:'DRAWOVERLAYLINE' }; return result; } //绘制斜线. //用法:DRAWSL(COND,PRICE,SLOPE,LEN,DIRECT),当COND条件满足时,在PRICE位置画斜线,SLOPE为斜率,LEN为长度,DIRECT为0向右延伸,1向左延伸,2双向延伸. //注意: //1.K线间的纵向高度差为SLOPE; //2.SLOPE为0时,为水平线; //3.SLOPE为10000时,为垂直线,LEN为向上的像素高度,DIRECT表示向上或向下延伸; //4.SLOPE和LEN支持变量; this.DRAWSL=function(condition, data, slope, len, direct) { let drawData={ Data:[], Option:[] }; let result={ DrawData:drawData, DrawType:'DRAWSL' }; var isNumber=this.IsNumber(data); if (Array.isArray(condition)) { for(var i in condition) { drawData.Data[i]=null; if (!condition[i]) continue; if (isNumber) { drawData.Data[i]=data; drawData.Option[i]={Slope:slope, Length:len, Direct:direct }; } else { if (i=HHV(HIGH,20),1)表示在创20天新高画垂直虚线。 this.VERTLINE=function(condition, type) { let drawData={ Data:[], LineType:type }; let result={ DrawData:drawData, DrawType:'VERTLINE' }; if (Array.isArray(condition)) { for(var i=0;i=HHV(HIGH,20),HIGH,1,2)表示在创20天新高时画水平虚线向右延伸。 this.HORLINE=function(condition, data, type, extend) { let drawData={ Data:[], LineType:type, Extend:extend }; let result={ DrawData:drawData, DrawType:'HORLINE' }; if (Array.isArray(condition) && Array.isArray(data)) { for(var i=0;i=data.length) continue; var value=data[i]; if (IFrameSplitOperator.IsNumber(value)) drawData.Data[i]=value; } } else if (Array.isArray(condition) && IFrameSplitOperator.IsNumber(data)) { for(var i=0;i=data.length) continue; var value=data[i]; if (IFrameSplitOperator.IsNumber(value)) drawData.Data[i]=value; } } else if (IFrameSplitOperator.IsNumber(data)) { var count=this.SymbolData.Data.Data.length; for(var i=0; i0) drawData.LineDotted=dotted; } drawData.Data=[]; for(var i=0;i0) { } return result; } } JSDraw.prototype.CalculateDrawLine=function(lineCache) { lineCache.List=[]; for(let i=lineCache.Start.ID; i<=lineCache.End.ID; ++i) lineCache.List.push(i); let height=Math.abs(lineCache.Start.Value-lineCache.End.Value); let width=lineCache.List.length-1; var result=[]; result.push({ID:lineCache.Start.ID, Value:lineCache.Start.Value}); //第1个点 if (lineCache.Start.Value>lineCache.End.Value) { for(let i=1;i0) { var index=strValue.length-1; var ch=strValue[index]; if (ch=="0") { strValue=strValue.substr(0,index); } else if (ch==".") { strValue=strValue.substr(0,index); break; } else { break; } } return strValue; } //http://www.newone.com.cn/helpcontroller/index?code=zszy_pc var DYNAINFO_ARGUMENT_ID= { YCLOSE:3, OPEN:4, HIGH:5, LOW:6, CLOSE:7, VOL:8, AMOUNT:10, AMPLITUDE:13, //振幅 INCREASE:14, //涨幅 EXCHANGERATE:37, //换手率 }; function JSSymbolData(ast,option,jsExecute) { this.AST=ast; //语法树 this.Execute=jsExecute; this.Symbol='600000.sh'; this.Name; this.Data=null; //个股数据 this.PeriodData=new Map(); //跨周期数据 {Key=period, value=[histroydata]} this.IsApiPeriod=false; //是否是后台api周期数据 this.SourceData=null; //不复权的个股数据 this.MarketValue=null; //总市值 this.Period=0; //周期 this.Right=0; //复权 this.DataType=0; //默认K线数据 2=分钟走势图数据 3=多日分钟走势图 this.IsBeforeData=false; //当日走势图数据是否包含开盘前数据 this.DayCount; //多日分时图天数 this.Arguments=[]; //指标参数 this.KLineApiUrl= g_JSComplierResource.Domain+"/API/KLine2"; //日线 this.MinuteKLineApiUrl= g_JSComplierResource.Domain+'/API/KLine3'; //分钟K线 this.RealtimeApiUrl= g_JSComplierResource.Domain+'/API/stock'; //实时行情 this.HistoryMinuteApiUrl=g_JSChartResource.Domain+'/API/StockMinuteData'; //历史分钟数据(多日分时图) this.StockHistoryDayApiUrl= g_JSComplierResource.Domain+'/API/StockHistoryDay'; //历史财务数据 this.StockHistoryDay3ApiUrl= g_JSComplierResource.Domain+'/API/StockHistoryDay3'; //历史财务数据 this.StockHistoryDay2ApiUrl= g_JSComplierResource.Domain+'/API/StockHistoryDay2'; //历史财务数据 this.StockNewsAnalysisApiUrl= g_JSComplierResource.CacheDomain+'/cache/newsanalyze'; //新闻分析数据 this.HKToSHSZApiUrl= //北上资金 !!顺序不要变 后面都是写死的 [ g_JSComplierResource.CacheDomain+'/cache/historyday/all/hk2shsz.json', //日线数据 g_JSComplierResource.CacheDomain+'/cache/analyze/hk2shsz/hk2shsz.json', //最新分钟 g_JSComplierResource.Domain+'/API/HKToSHSZMinuteData', //多日分时分钟 g_JSComplierResource.CacheDomain+'/cache/analyze/hk2szshanalyze' //个股的北上 ] ; this.MaxRequestDataCount=1000; this.MaxRequestMinuteDayCount=5; this.KLineDateTimeRange; //请求的K线日期范围 this.LatestData=new Map(); //最新行情 key=id value=数据 this.IndexData; //大盘指数 this.LatestIndexData; //最新大盘数据 this.MarginData=new Map(); //融资融券 this.HKToSHSZData=new Map(); //北上资金 this.NewsAnalysisData=new Map(); //新闻统计 this.ExtendData=new Map(); //其他的扩展数据 this.UserData=new Map(); //用户数据 this.CustomAPIData=new Map(); //自定义API数据 this.ScriptIndexOutData=new Map(); //调用脚本执行返回的数据 this.OtherSymbolData=new Map(); //其他股票信息 key=symbol value=[historydata] //股票数据缓存 key=函数名(参数) { Data: value=拟合的数据 , Error: } //FinValue(id) this.StockData=new Map(); this.SectionFinanceData=new Map(); //截面报告数据 this.ThrowSFPeirod=new Set(); //重新获取数据 this.NetworkFilter; //网络请求回调 function(data, callback); this.DrawInfo; //使用option初始化 if (option) { if (option.HQDataType) this.DataType=option.HQDataType; if (option.Data) { this.Data=option.Data; if (this.DataType!=HQ_DATA_TYPE.MINUTE_ID && this.DataType!=HQ_DATA_TYPE.MULTIDAY_MINUTE_ID && this.DataType!=HQ_DATA_TYPE.HISTORY_MINUTE_ID) //分钟走势图数据 没有周期和复权 { this.Period=option.Data.Period; //周期 this.Right=option.Data.Right; //复权 } //this.Data=null; } if (option.SourceData) this.SourceData=option.SourceData; if (option.Symbol) this.Symbol=option.Symbol; if (option.Name) this.Name=option.Name; if (option.MaxRequestDataCount>0) this.MaxRequestDataCount=option.MaxRequestDataCount; if (option.MaxRequestMinuteDayCount>0) this.MaxRequestMinuteDayCount=option.MaxRequestMinuteDayCount; if (option.KLineApiUrl) this.KLineApiUrl=option.KLineApiUrl; if (option.Right) this.Right=option.Right; if (option.Period) this.Period=option.Period; if (option.IsBeforeData===true) this.IsBeforeData=option.IsBeforeData; if (option.NetworkFilter) this.NetworkFilter=option.NetworkFilter; if (option.DayCount>0) this.DayCount=option.DayCount; if (option.Arguments) this.Arguments=option.Arguments; if (option.KLineRange) this.KLineDateTimeRange=option.KLineRange; if (option.IsApiPeriod) this.IsApiPeriod=option.IsApiPeriod; if (option.DrawInfo) this.DrawInfo=option.DrawInfo; } this.RecvError=function(request) { JSConsole.Complier.Log('[JSSymbolData::RecvError] ajax error.',request.status); throw {FunctionName:'RecvError', Request:request}; } this.GetLatestDataKey=function(key) { var key=`DYNAINFO-${key}`; return key; } //最新行情 this.GetLatestData=function(jobItem) { var aryArgs=this.JobArgumentsToArray(jobItem, 1); var lID=aryArgs[0]; var key=this.GetLatestDataKey(lID); if (this.LatestData.has(key)) return this.Execute.RunNextJob(); var self=this; if (this.NetworkFilter) { var obj= { Name:'JSSymbolData::GetLatestData', //类名:: Explain:'DYNAINFO()', Args:aryArgs, Request:{ Url:self.RealtimeApiUrl, Type:'POST' , Data: { symbol:[this.Symbol], field: ["name","symbol","yclose","open","price","high","low","vol","amount","date","time","increase","exchangerate","amplitude"] } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvLatestData(data); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.RealtimeApiUrl, data: { "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","time","increase","exchangerate","amplitude"], "symbol": [this.Symbol] }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvLatestData(recvData); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } this.RecvLatestData=function(data) { if (data.ver==2.0) { this.RecvLatestDataVer2(data); return; } if (!data.stock || data.stock.length!=1) return; let stock=data.stock[0]; if (!stock) return; if (IFrameSplitOperator.IsNumber(stock.yclose)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.YCLOSE,stock.yclose); if (IFrameSplitOperator.IsNumber(stock.open)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.OPEN,stock.open); if (IFrameSplitOperator.IsNumber(stock.high)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.HIGH,stock.high); if (IFrameSplitOperator.IsNumber(stock.low)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.LOW,stock.low); if (IFrameSplitOperator.IsNumber(stock.price)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.CLOSE,stock.price); if (IFrameSplitOperator.IsNumber(stock.vol)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.VOL,stock.vol); if (IFrameSplitOperator.IsNumber(stock.amount)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.AMOUNT,stock.amount); if (IFrameSplitOperator.IsNumber(stock.increase)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.INCREASE,stock.increase); if (IFrameSplitOperator.IsNumber(stock.exchangerate)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.EXCHANGERATE,stock.exchangerate); if (IFrameSplitOperator.IsNumber(stock.amplitude)) this.LatestData.set(DYNAINFO_ARGUMENT_ID.AMPLITUDE,stock.amplitude); /* this.LatestData={ Symbol:stock.symbol, Name:stock.name, Date:stock.date, Time:stock.time, YClose:stock.yclose,Price:stock.price, Open:stock.open, High:stock.high, Low:stock.low, Vol:stock.vol, Amount:stock.amount, Increase:stock.increase, Exchangerate:stock.exchangerate, Amplitude:stock.amplitude}; */ JSConsole.Complier.Log('[JSSymbolData::RecvLatestData] symbol, LatestData', stock.symbol, this.LatestData); } //data:[{ id:, value: }] this.RecvLatestDataVer2=function(data) { if (!IFrameSplitOperator.IsNonEmptyArray(data.data)) return; var symbol=data.symbol; for(var i=0;i=0 && dayCount<5;--j, ++dayCount) { var item=data.data[j]; if (IFrameSplitOperator.IsNumber(item[6])) sumVol+=item[6]; } if (dayCount>0) { avgVol5=sumVol/dayCount/minuteCount; var item=data.data[i]; mapAvgVol5.set(item[0], { //for debug //Vol5:sumVol, MinuteCount:minuteCount,,Count:dayCount, AvgVol5:avgVol5 } ); } } } if (mapAvgVol5.size>0) this.ExtendData.set(key,mapAvgVol5); JSConsole.Complier.Log('[JSSymbolData::RecvVolRateData]', mapAvgVol5); } this.GetVolRateCacheData=function(node) { var key=JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA.toString()+'-VolRate-'+this.Symbol; if (!key || !this.ExtendData.has(key)) this.Execute.ThrowUnexpectedNode(node,'不支持VOLR'); var result=[]; var mapAvgVol5=this.ExtendData.get(key); var totalVol=0, preDate=0, avgVol5=null; for(var i=0, j=0;i0) { var arySymbol=symbol.split("_"); symbol=`${arySymbol[1]}.${arySymbol[0]}`; } else return null; return { Symbol:symbol.toLowerCase(), DataName:args[1] }; } //获取其他股票数据 this.GetOtherSymbolData=function(job) { var symbol=this.Symbol; if (job.Literal) { var args=this.GetOtherSymbolParam(job.Literal.toUpperCase()); if (!args) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.Literal} Error.`); } symbol=args.Symbol; } else { var args=job.Args; if (args.length>0) { var item=args[0]; if (item.Type==Syntax.Literal) { symbol=item.Value; } else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值 { var isFind=false; for(var j in this.Arguments) { const argItem=this.Arguments[j]; if (argItem.Name==item.Name) { symbol=argItem.Value; isFind=true; break; } } if (!isFind) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName}() Error: can't read ${item.Name}`); } } } } job.Symbol=symbol.toLowerCase(); if (job.Symbol==this.Symbol) return this.Execute.RunNextJob(); if (this.OtherSymbolData.has(job.Symbol)) return this.Execute.RunNextJob(); var self=this; if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //请求日线数据 { if (this.NetworkFilter) { var dateRange=this.Data.GetDateRange(); var obj= { Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名 Explain:'指定个股数据', Request: { Data: { symbol:job.Symbol, right:self.Right, period:self.Period, dateRange:dateRange } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvOtherSymbolKData(data,job); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.KLineApiUrl, data: { "field": [ "name", "symbol","yclose","open","price","high","low","vol"], "symbol": job.Symbol, "start": -1, "count": self.MaxRequestDataCount+500 //多请求2年的数据 确保股票剔除停牌日期以后可以对上 }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvOtherSymbolKDayData(recvData,job); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } else if (ChartData.IsMinutePeriod(this.Period, true) || this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) //请求分钟数据 { if (this.NetworkFilter) { var dateRange=this.Data.GetDateRange(); var obj= { Name:'JSSymbolData::GetOtherSymbolData', //类名::函数名 Explain:'指定个股数据', Request: { Data: { symbol:job.Symbol, right:self.Right, period:self.Period, dateRange:dateRange } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvOtherSymbolKData(data,job); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.MinuteKLineApiUrl, data: { "field": ["name","symbol","yclose","open","price","high","low","vol"], "symbol": job.Symbol, "start": -1, "count": self.MaxRequestMinuteDayCount+5 }, type:"post", dataType: "json", async:true, success: function (data) { self.RecvOtherSymbolKMinuteData(data,job); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } } //第3方数据对接 this.RecvOtherSymbolKData=function(data,job) { JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKData] recv data' , data); var kData=new ChartData(); var hisData=null; var period=this.Period; if (this.DataType==HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //日线数据 { hisData=this.JsonDataToHistoryData(data); kData.DataType=0; } else //分钟线数据 { hisData=this.JsonDataToMinuteHistoryData(data); kData.DataType=1; //走势图使用1分钟K线模式 if (this.DataType==HQ_DATA_TYPE.MINUTE_ID || this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) period=4; } kData.Period=this.Period; kData.Right=this.Right; kData.Data=this.Data.FixKData(hisData,period); this.OtherSymbolData.set(job.Symbol, kData); } this.RecvOtherSymbolKDayData=function(data,job) { JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKDayData] recv data' , data); let hisData=this.JsonDataToHistoryData(data); var kData=new ChartData(); kData.DataType=0; //日线数据 kData.Data=hisData; var aryOverlayData=this.SourceData.GetOverlayData(kData.Data); //和主图数据拟合以后的数据 kData.Data=aryOverlayData; if (ChartData.IsDayPeriod(this.Period,false)) //周期数据 { let periodData=kData.GetPeriodData(this.Period); kData.Data=periodData; } this.OtherSymbolData.set(job.Symbol, kData); } this.RecvOtherSymbolKMinuteData=function(data, job) { JSConsole.Complier.Log('[JSSymbolData::RecvOtherSymbolKMinuteData] recv data' , data); let hisData=this.JsonDataToMinuteHistoryData(data); var kData=new ChartData(); kData.DataType=1; /*分钟线数据 */ kData.Data=hisData; if (ChartData.IsMinutePeriod(this.Period,false)) //周期数据 { let periodData=kData.GetPeriodData(this.Period); kData.Data=periodData; } this.OtherSymbolData.set(job.Symbol, kData); } this.GetOtherSymolCacheData=function(obj) { var symbol,dataName; if (obj.FunctionName) { dataName=obj.FunctionName; var args=obj.Args; if (args.length<=0) return this.GetSymbolCacheData(dataName); symbol=args[0].toString().toLowerCase(); } else if (obj.Literal) { var args=this.GetOtherSymbolParam(obj.Literal.toUpperCase()); if (!args) return []; symbol=args.Symbol; dataName=args.DataName; } if (symbol==this.Symbol) return this.GetSymbolCacheData(dataName); if (!this.OtherSymbolData.has(symbol)) return []; var kData=this.OtherSymbolData.get(symbol); var upperSymbol=symbol.toUpperCase(); switch(dataName) { case 'CLOSE': case 'C': return kData.GetClose(); case 'VOL': case 'V': if (MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) return kData.GetVol(100); //A股的 把股转成手 return kData.GetVol(); case 'OPEN': case 'O': return kData.GetOpen(); case 'HIGH': case 'H': return kData.GetHigh(); case 'LOW': case 'L': return kData.GetLow(); case 'AMOUNT': case 'AMO': return kData.GetAmount(); case 'VOLINSTK': return kData.GetPosition(); } } //获取大盘指数缓存数据 this.GetIndexCacheData=function(dataName) { if (!this.IndexData) return new Array(); switch(dataName) { case 'INDEXA': return this.IndexData.GetAmount(); case 'INDEXC': return this.IndexData.GetClose(); case 'INDEXH': return this.IndexData.GetHigh(); case 'INDEXL': return this.IndexData.GetLow(); case 'INDEXO': return this.IndexData.GetOpen(); case 'INDEXV': return this.IndexData.GetVol(); case 'INDEXADV': return this.IndexData.GetUp(); case 'INDEXDEC': return this.IndexData.GetDown(); } } //指数转成对应的板块 this.GetBlockSymbol=function(symbol) { //中文对应板块代码 const BLOCK_CN_NAME_MAP=new Map([ ["沪深A股","CNA.ci"], ["创业板","GEM.ci"], ["沪市A股","SHA.ci"], ["中小板","SME.ci"], ["深市A股","SZA.ci"] ]); if (BLOCK_CN_NAME_MAP.has(symbol)) return BLOCK_CN_NAME_MAP.get(symbol); if (!symbol) return null; var blockSymbol=null; var upperSymbol=symbol.toUpperCase(); if (upperSymbol.indexOf('.SH')>0 || upperSymbol.indexOf('.SZ')>0 ) { const INDEX_SYMBOL_SET=new Set(["000001.SH", "000003.SH", "000016.SH", "000300.SH", "000905.SH", "399001.SZ", " 399005.SZ", "399006.SZ"]); if (!INDEX_SYMBOL_SET.has(upperSymbol)) return null; blockSymbol=symbol.replace('.SH','.sh'); blockSymbol=symbol.replace('.SZ','.sz'); } else if (symbol.indexOf('.CI')>0) { blockSymbol=symbol.replace('.CI','.ci'); } /* const SYMBOL_TO_BLOCK_MAP=new Map([ ["000001.SH","SME.ci"], ["399001.SZ","SZA.ci"],["399001.SZ"," GEM.ci"],["399005.SZ","SME.ci"] ]); if (SYMBOL_TO_BLOCK_MAP.has(upperSymbol)) return SYMBOL_TO_BLOCK_MAP.get(upperSymbol); if(upperSymbol.indexOf('.CI')<0) return null; */ return blockSymbol; } //分钟涨幅股票个数统计数据下载 this.GetIndexIncreaseData=function(job) { var symbol=null; if (job.IsSelfSymbol) { symbol=this.Symbol; } else { if (!job.Args || job.Args.length<=0) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName} Error: 参数不能为空`); } symbol=job.Args[0].Value; } var blockSymbol=this.GetBlockSymbol(symbol); if (!blockSymbol) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`${job.FunctionName} Error: can't support ${symbol}`); } var upKey=job.ID.toString()+'-UpCount-'+blockSymbol; var downKey=job.ID.toString()+'-DownCount-'+blockSymbol; if (this.ExtendData.has(upKey) && this.ExtendData.has(downKey)) return this.Execute.RunNextJob(); var self=this; if (this.NetworkFilter) { var dataType={Type: this.DataType}; if (this.DataType===HQ_DATA_TYPE.KLINE_ID) dataType.Period=this.Period; var dateRange=this.Data.GetDateRange(); var obj= { Name:'JSSymbolData::GetIndexIncreaseData', //类名:: Explain:'涨停家数统计', DateRange:dateRange, DataType:dataType, Request:{ Url:'数据地址', Type:'POST' , Data: { symbol:this.Symbol, blocksymbol:blockSymbol, field: ["up", "down"] } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { if (this.DataType===HQ_DATA_TYPE.KLINE_ID) this.RecvHistoryIncreaseDataV2(data, {UpKey:upKey,DownKey:downKey}); else this.RecvMinuteIncreaseDataV2(data, {UpKey:upKey,DownKey:downKey}); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } if (this.DataType===HQ_DATA_TYPE.MINUTE_ID || this.DataType===HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) //走势图数据 { var apiUrl=g_JSComplierResource.CacheDomain+'/cache/analyze/increaseanalyze/'+blockSymbol+'.json'; JSConsole.Complier.Log('[JSSymbolData::GetIndexIncreaseData] minute Get url=' , apiUrl); JSNetwork.HttpRequest({ url: apiUrl, type:"get", dataType: "json", async:true, success: function (data) { self.RecvMinuteIncreaseData(data, {UpKey:upKey,DownKey:downKey}); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } else if (this.DataType===HQ_DATA_TYPE.KLINE_ID && ChartData.IsDayPeriod(this.Period,true)) //K线图 日线 { JSConsole.Complier.Log('[JSSymbolData::GetIndexIncreaseData] K day Get url=' , self.KLineApiUrl); JSNetwork.HttpRequest({ url: self.KLineApiUrl, data: { "symbol": blockSymbol, "start": -1, "count": self.MaxRequestDataCount, "field":['up', 'down'] }, type:"post", dataType: "json", async:true, success: function (data) { self.RecvHistoryIncreaseData(data, {UpKey:upKey,DownKey:downKey}); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } else { this.Execute.RunNextJob(); } } //格式{ ver:2.0 data:[{date, time, up, down}, .....]} this.RecvHistoryIncreaseDataV2=function(data,key) { JSConsole.Complier.Log('[JSSymbolData::RecvHistoryIncreaseData] recv data, key' , data,key); var upData=[],downData=[]; for(var i in data.data) { var item=data.data[i]; let upItem=new SingleData(); let downItem=new SingleData(); var date=item[0]; var time=null; upItem.Date=date; downItem.Date=date; if (ChartData.IsMinutePeriod(this.Period,true) && IFrameSplitOperator.IsNumber(item[1])) { time=item[1]; upItem.Time=time; downItem.Time=time; } upItem.Value=item[2]; upData[i]=upItem; downItem.Value=item[3]; downData[i]=downItem; } var upFixedData=this.Data.GetFittingData2(upData,0); var downFixedData=this.Data.GetFittingData2(downData,0); this.ExtendData.set(key.UpKey,upFixedData); this.ExtendData.set(key.DownKey,downFixedData); } this.RecvHistoryIncreaseData=function(data,key) { JSConsole.Complier.Log('[JSSymbolData::RecvHistoryIncreaseData] recv data' , data); var upData=[],downData=[]; for(var i in data.data) { var item=data.data[i]; let upItem=new SingleData(); let downItem=new SingleData(); upItem.Date=item[0]; upItem.Value=item[8]; upData[i]=upItem; downItem.Date=item[0]; downItem.Value=item[9]; downData[i]=downItem; } var upFixedData, downFixedData; if (this.SourceData) upFixedData=this.SourceData.GetFittingData(upData); else upFixedData=this.Data.GetFittingData(aryData); if (this.SourceData) downFixedData=this.SourceData.GetFittingData(downData); else downFixedData=this.Data.GetFittingData(aryData); this.ExtendData.set(key.UpKey,upFixedData); this.ExtendData.set(key.DownKey,downFixedData); } this.RecvMinuteIncreaseDataV2=function(data, key) { JSConsole.Complier.Log('[JSSymbolData::RecvMinuteIncreaseDataV2] recv data, key' , data, key); } this.RecvMinuteIncreaseData=function(data,key) { JSConsole.Complier.Log('[JSSymbolData::RecvMinuteIncreaseData] recv data' , data); if (!data.minute) return; var minuteData=data.minute; if (!minuteData.time || !minuteData.up || !minuteData.down) return; var upData=[],downData=[]; if (this.IsBeforeData) { for(var i=0, j=0;i0) //周期数据 { var periodData=bindData.GetPeriodSingleData(bindData.Period); bindData.Data=periodData; } return bindData.GetValue(); } else { return null; } } this.GetSymbolData=function() { if (this.Data) return this.Execute.RunNextJob(); let self=this; if (this.DataType===HQ_DATA_TYPE.MINUTE_ID) //当天分钟数据 { JSNetwork.HttpRequest({ url: self.RealtimeApiUrl, data: { "field": ["name","symbol","yclose","open","price","high","low","vol","amount","date","minute","time","minutecount"], "symbol": [self.Symbol], "start": -1 }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvMinuteData(recvData); self.Execute.RunNextJob(); } }); return; } if (this.DataType===HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) { JSNetwork.HttpRequest({ url: self.HistoryMinuteApiUrl, data: { "symbol": self.Symbol, "daycount": self.DayCount }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvMultiDayMinuteData(recvData); self.Execute.RunNextJob(); } }); return; } if (ChartData.IsDayPeriod(this.Period,true)) //请求日线数据 { if (this.NetworkFilter) { var obj= { Name:'JSSymbolData::GetSymbolData', Explain:"日线数据", Request: { Url:self.RealtimeApiUrl, Type:'POST' , Data: { "field": [ "name", "symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestDataCount, "period":this.Period, "right":this.Right } }, Self:this, PreventDefault:false }; if (this.KLineDateTimeRange) { obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} }; if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time; if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time; } this.NetworkFilter(obj, function(data) { self.RecvHistroyData(data); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.KLineApiUrl, data: { "field": [ "name", "symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestDataCount }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvHistroyData(recvData); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } else if (ChartData.IsMinutePeriod(this.Period, true) || ChartData.IsSecondPeriod(this.Period) || ChartData.IsMilliSecondPeriod(this.Period)) //请求分钟数据 { if (this.NetworkFilter) { var obj= { Name:'JSSymbolData::GetSymbolData', Explain:"分钟K线数据", Request: { Url:self.MinuteKLineApiUrl, Type:'POST' , Data: { "field": ["name","symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestMinuteDayCount, "period":this.Period, "right":this.Right } }, Self:this, PreventDefault:false }; if (this.KLineDateTimeRange) { obj.Request.KLineDataTimeRange={Start:{ Date:this.KLineDateTimeRange.Start.Date}, End:{ Date:this.KLineDateTimeRange.End.Date} }; if (this.IsNumber(this.KLineDateTimeRange.Start.Time)) obj.Request.KLineDataTimeRange.Start.Time=this.KLineDateTimeRange.Start.Time; if (this.IsNumber(this.KLineDateTimeRange.End.Time)) obj.Request.KLineDataTimeRange.End.Time=this.KLineDateTimeRange.End.Time; } this.NetworkFilter(obj, function(data) { self.RecvMinuteHistroyData(data); self.Execute.RunNextJob(); }); 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 }, type:"post", dataType: "json", async:true, success: function (data) { self.RecvMinuteHistroyData(data); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } } this.RecvHistroyData=function(data) { JSConsole.Complier.Log('[JSSymbolData::RecvHistroyData] recv data' , data); let hisData=this.JsonDataToHistoryData(data); this.Data=new ChartData(); this.Data.DataType=0; /*日线数据 */ this.Data.Data=hisData; this.SourceData=new ChartData; this.SourceData.Data=hisData; if (this.IsApiPeriod) //后台周期 前端不处理 { } else { if (this.Right>0) //复权 { let rightData=this.Data.GetRightData(this.Right); this.Data.Data=rightData; } if (ChartData.IsDayPeriod(this.Period,false)) //周期数据 { let periodData=this.Data.GetPeriodData(this.Period); this.Data.Data=periodData; } } this.Data.Right=this.Right; this.Data.Period=this.Period; this.Name=data.name; } this.RecvMinuteHistroyData=function(data) { JSConsole.Complier.Log('[JSSymbolData::RecvMinuteHistroyData] recv data' , data); let hisData=this.JsonDataToMinuteHistoryData(data); this.Data=new ChartData(); this.Data.DataType=1; /*分钟线数据 */ this.Data.Data=hisData; this.SourceData=new ChartData; this.SourceData.Data=hisData; if (this.IsApiPeriod) //后台周期 前端不处理 { } else { if (ChartData.IsMinutePeriod(this.Period,false)) //周期数据 { let periodData=this.Data.GetPeriodData(this.Period); this.Data.Data=periodData; } } this.Data.Period=this.Period; this.Name=data.name; } //最新的分钟数据走势图 this.RecvMinuteData=function(data) { JSConsole.Complier.Log('[JSSymbolData::RecvMinuteData] recv data' , data); var aryMinuteData=this.JsonDataToMinuteData(data); this.Data=new ChartData(); this.Data.DataType=2; /*分钟走势图数据 */ this.Data.Data=aryMinuteData; this.Name=data.stock[0].name; } this.RecvMultiDayMinuteData=function(data) { var aryMinuteData=this.JsonDataToMultiDayMinuteData(data); this.Data=new ChartData(); this.Data.DataType=2; /*分钟走势图数据 */ this.Data.Data=aryMinuteData; this.Name=data.name; } this.GetSymbolCacheData=function(dataName) { if (!this.Data) return new Array(); var upperSymbol=this.Symbol.toUpperCase(); switch(dataName) { case 'CLOSE': case 'C': return this.Data.GetClose(); case 'VOL': case 'V': if (MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol) && this.DataType==HQ_DATA_TYPE.KLINE_ID) //!! A股K线量单位时股,分时图单位还是手 return this.Data.GetVol(100); //A股的 把股转成手 return this.Data.GetVol(); case 'OPEN': case 'O': return this.Data.GetOpen(); case 'HIGH': case 'H': return this.Data.GetHigh(); case 'LOW': case 'L': return this.Data.GetLow(); case 'AMOUNT': case 'AMO': return this.Data.GetAmount(); case "OPI": //文华 持仓量 case 'VOLINSTK': //通达信 持仓量 return this.Data.GetPosition(); case "ZSTJJ": //均价 return this.Data.GetAvPrice(); case "SETTLE": //文华 结算价 case "QHJSJ": //通达信 结算价 return this.Data.GetSettlementPrice(); //结算价 case "ISEQUAL": //平盘 return this.Data.GetIsEqual(); case "ISUP": //收阳 return this.Data.GetIsUp(); case "ISDOWN": //收阴 return this.Data.GetIsDown(); } } this.GetSymbolPeriodData=function(job) { var periodID=JSComplierHelper.GetPeriodInfo({ Name:job.PeriodName }).Period; var periodInfo={ PeriodID:periodID, PeriodName:job.PeriodName }; //同周期不请求 if (periodID==this.Period) this.Execute.RunNextJob(); if (this.IsApiPeriod) { if (this.PeriodData.has(job.PeriodName)) return this.Execute.RunNextJob(); } else { if (ChartData.IsDayPeriod(periodID,true)) { if (ChartData.IsDayPeriod(this.Period,true)) return this.Execute.RunNextJob(); periodInfo={PeriodID:0, PeriodName:'DAY' }; } else if (ChartData.IsMinutePeriod(periodID,true)) { if (ChartData.IsMinutePeriod(this.Period,true)) return this.Execute.RunNextJob(); periodInfo={ PeriodID:4, PeriodName:"MIN1" }; } else { return this.Execute.RunNextJob(); } } var self=this; if (this.NetworkFilter) { var obj= { Name:'JSSymbolData::GetSymbolPeriodData', Explain:"跨周期数据", Request: { Data: { "field": [ 'symbol','name', job.ValueName ], "period":job.PeriodName, "symbol": self.Symbol, } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvSymbolPeriodData(data, periodInfo); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } if (ChartData.IsMinutePeriod(periodID,true)) { JSNetwork.HttpRequest({ url: this.MinuteKLineApiUrl, data: { "field": ["name","symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestMinuteDayCount }, type:"post", dataType: "json", async:true, success: function (data) { self.RecvSymbolPeriodData(data,periodInfo); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } else if (ChartData.IsDayPeriod(periodID,true)) { JSNetwork.HttpRequest({ url: self.KLineApiUrl, data: { "field": [ "name", "symbol","yclose","open","price","high","low","vol"], "symbol": self.Symbol, "start": -1, "count": self.MaxRequestDataCount }, type:"post", dataType: "json", async:true, success: function (data) { self.RecvSymbolPeriodData(data, periodInfo); self.Execute.RunNextJob(); }, error: function(request) { self.RecvError(request); } }); } else { return this.Execute.RunNextJob(); } } this.RecvSymbolPeriodData=function(data, periodInfo) { JSConsole.Complier.Log('[JSSymbolData::RecvSymbolPeriodData] data, periodInfo ' , data, periodInfo); if (ChartData.IsDayPeriod(periodInfo.PeriodID,true)) { var hisData=this.JsonDataToHistoryData(data); var dayData=new ChartData(); dayData.DataType=0; //日线数据 dayData.Data=hisData; //保存原始数据 不复权 dayData.Right=0; dayData.Period=periodInfo.PeriodID; this.PeriodData.set(periodInfo.PeriodName, dayData); } else if (ChartData.IsMinutePeriod(periodInfo.PeriodID,true)) { var hisData=this.JsonDataToMinuteHistoryData(data); var minData=new ChartData(); minData.DataType=1; //分钟线数据 minData.Data=hisData; minData.Right=0; minData.Period=periodInfo.PeriodID; this.PeriodData.set(periodInfo.PeriodName, minData); } } this.GetSymbolPeriodCacheData=function(valueName,periodName) { var periodInfo=JSComplierHelper.GetPeriodInfo({Name:periodName}); if (this.Period==periodInfo.Period) return this.GetSymbolCacheData(valueName); var hisData=null; if (this.IsApiPeriod) { var curPeriodInfo=JSComplierHelper.GetPeriodInfo({PeriodID:this.Period}); if (!curPeriodInfo) return null; if (curPeriodInfo.Order>periodInfo.Order) return null; //只能小周期转大周期 if (!this.PeriodData.has(periodName)) return null; hisData=this.PeriodData.get(periodName); hisData=hisData.Data; } else { var curPeriodInfo=JSComplierHelper.GetPeriodInfo({PeriodID:this.Period}); if (!curPeriodInfo) return null; if (curPeriodInfo.Order>periodInfo.Order) return null; //只能小周期转大周期 if (ChartData.IsDayPeriod(periodInfo.Period,true) && ChartData.IsMinutePeriod(this.Period,true)) { var dayData=this.PeriodData.get('DAY'); //日线 if (periodInfo.Period==0) hisData=dayData.Data; else hisData=dayData.GetPeriodData(periodInfo.Period); //日线周期 } else { var bindData=new ChartData(); bindData.Data=this.SourceData.Data; bindData.Period=this.Period; bindData.Right=this.Right; if (ChartData.IsDayPeriod(periodInfo.Period,true) && bindData.Right>0) //日线数据才复权 { var rightData=bindData.GetRightData(bindData.Right); bindData.Data=rightData; } hisData=bindData.GetPeriodData(periodInfo.Period); } } var data=this.Data.ConverPeriod(hisData, this.Period, periodInfo.Period); var result=new ChartData(); result.Data=data; var upperSymbol=this.Symbol.toUpperCase(); switch(valueName) { case 'C': case "CLOSE": return result.GetClose(); case 'O': case "OPEN": return result.GetOpen(); case 'H': case "HIGH": return result.GetHigh(); case 'L': case "LOW": return result.GetLow(); case 'AMO': case "AMOUNT": return result.GetAmount(); case 'V': case "VOL": if (MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) return result.GetVol(100); return result.GetVol(); case "VOLINSTK": return result.GetPosition(); default: return null; } } this.GetSymbolPeriodCacheData2=function(valueName,periodName,n) { var periodInfo=JSComplierHelper.GetPeriodInfo({Name:periodName}); if (!periodInfo) return null; var curPeriodInfo=JSComplierHelper.GetPeriodInfo({PeriodID:this.Period}); if (!curPeriodInfo) return null; if (curPeriodInfo.Order>periodInfo.Order) return null; //只能小周期转大周期 var result; if (curPeriodInfo.Period==periodInfo.Period) { result=this.Data; } else { var hisData; if (this.IsApiPeriod) { if (!this.PeriodData.has(periodName)) return null; hisData=this.PeriodData.get(periodName); } else { if (ChartData.IsMinutePeriod(curPeriodInfo.Period,true) && ChartData.IsDayPeriod(periodInfo.Period,true)) { var dayData=this.PeriodData.get('DAY'); //日线 if (periodInfo.Period==0) hisData=dayData; else hisData=dayData.GetPeriodData(periodInfo.Period); //日线周期 } else { var bindData=new ChartData(); bindData.Data=this.SourceData.Data; bindData.Period=this.Period; bindData.Right=this.Right; if (ChartData.IsDayPeriod(periodInfo.Period,true) && bindData.Right>0) //日线数据才复权 { var rightData=bindData.GetRightData(bindData.Right); bindData.Data=rightData; } hisData=bindData.GetPeriodData(periodInfo.Period); } } var data=this.Data.ConverPeriod(hisData, this.Period, periodInfo.Period); var result=new ChartData(); result.Data=data; } if (IFrameSplitOperator.IsPlusNumber(n)) { var refResult=new ChartData(); var data=result.GetRef(n); refResult.Data=data; result=refResult; } var upperSymbol=this.Symbol.toUpperCase(); switch(valueName) { case 'C': case "CLOSE": return result.GetClose(); case 'O': case "OPEN": return result.GetOpen(); case 'H': case "HIGH": return result.GetHigh(); case 'L': case "LOW": return result.GetLow(); case 'AMO': case "AMOUNT": return result.GetAmount(); case 'V': case "VOL": if (MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol)) return result.GetVol(100); return result.GetVol(); case "VOLINSTK": return result.GetPosition(); default: return null; } } this.GetCurrBarsCount=function() { let result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; let lCount=this.Data.Data.length; for(let i=lCount-1;i>=0;--i) result.push(i+1); //数据从0开始 return result; } //BARPOS 返回从第一根K线开始到当前的周期数。 //注: //1、BARPOS返回本地已有的K线根数,从本机上存在的数据开始算起。 //2、本机已有的第一根K线上返回值为1。 this.GetBarPos=function() { let result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; let lCount=this.Data.Data.length; for(let i=0;i0) return data.Count-1; return 242; } this.GetTotalBarsCount=function() { let lCount=this.Data.Data.length; return lCount; } this.GetIsLastBar=function() { let result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result let lCount=this.Data.Data.length; for(let i=0;i0) { var item=args[0]; if (item.Type==Syntax.Literal) { code=item.Value; } else if (item.Type==Syntax.Identifier) //变量 !!只支持默认的变量值 { var isFind=false; for(var j in this.Arguments) { const argItem=this.Arguments[j]; if (argItem.Name==item.Name) { code=argItem.Value; isFind=true; break; } } if (!isFind) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`HK2SHSZ() Error: can't read ${item.Name}`); } } } job.Symbol=code; if (code==1 || code==2 || code==3) //下载全市场数据 this.GetHKToSHSZMarketData(code,job); else this.GetHKToSHSZStockData(code,job); //下载个股数据 } this.GetHKToSHSZStockData=function(symbol,job) { if (this.HKToSHSZData.has(symbol)) return this.Execute.RunNextJob(); var upperSymbol=symbol.toLowerCase(); //代码小写 var self=this; var url=`${this.HKToSHSZApiUrl[3]}/${upperSymbol}.json`; //请求数据 JSNetwork.HttpRequest({ url: url, type:"get", dataType: "json", async:true, success: function (recvData) { self.RecvHKToSHSZStockData(recvData,job); self.Execute.RunNextJob(); }, error:function(request) { console.warn(`[JSSymbolData::GetHKToSHSZStockData] request url=${url} failed. error=${request.status}`); self.RecvHKToSHSZStockData(null,job); self.Execute.RunNextJob(); } }); } this.RecvHKToSHSZStockData=function(data,job) { if (!data) return; var symbol=data.symbol; var upperSymbol=symbol.toUpperCase(); var aryData=[]; for(var i=0;i0) //周期数据 { var periodData=bindData.GetPeriodSingleData(bindData.Period); bindData.Data=periodData; } var data=bindData.GetValue(); this.HKToSHSZData.set(upperSymbol,data); } this.GetHKToSHSZMarketData=function(symbol,job) { if (this.HKToSHSZData.has(symbol)) return this.Execute.RunNextJob(); var url, dataType=0; if (this.DataType===HQ_DATA_TYPE.MINUTE_ID) dataType=1; else if (this.DataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) dataType=2; else if (this.Period<=3) dataType=0; url=this.HKToSHSZApiUrl[dataType]; var self=this; JSConsole.Complier.Log(`[JSSymbolData::GetHKToSHSZMarketData] code=${symbol} url=${url}, dataType=${dataType}`); if (dataType===2) //多日分时数据 (取这个股票的多日日期对应的北上数据) { //请求数据 JSNetwork.HttpRequest({ url: url, data: { "symbol": this.Symbol, 'daycount': this.MaxRequestMinuteDayCount }, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvMulitMinuteHKToSHSZData(recvData,job); self.Execute.RunNextJob(); } }); } else { //请求数据 JSNetwork.HttpRequest({ url: url, type:"get", dataType: "json", async:true, success: function (recvData) { if (dataType==0) self.RecvHKToSHSZData(recvData,job); else if (dataType==1) self.RecvMinuteHKToSHSZData(recvData,job); self.Execute.RunNextJob(); } }); } } this.RecvMinuteHKToSHSZData=function(data,job) { var arySHSZData=[], arySHData=[], arySZData=[]; if (this.IsBeforeData) { for( i in this.SourceData.Data) { var item=this.SourceData.Data[i]; if (item.Before) { arySHSZData.push(null); arySHData.push(null); arySZData.push(null); } else { break; } } for(var i=0;i0) //周期数据 { var periodData=bindData.GetPeriodSingleData(bindData.Period); bindData.Data=periodData; } let data=bindData.GetValue(); this.HKToSHSZData.set(allData[i].ID,data); } } this.RecvMulitMinuteHKToSHSZData=function(data,job) //多日分时图北上资金 { if (!data.data || data.data.length<=0) return; var arySHSZData=[], arySHData=[], arySZData=[]; for(var i=0 ,j=0;idate) { ++i; continue; } else if (day.date0) { key+="("; for(var i=0;i0) key+=","; key+=aryArgs[i].toString(); } key+=")"; } return key; } this.GetFinance=function(jobItem) { var aryArgs=this.JobArgumentsToArray(jobItem, 1); var lID=aryArgs[0]; var key=this.GetStockDataKey(jobItem,aryArgs); if (this.StockData.has(key)) return this.Execute.RunNextJob(); var self=this; if (this.NetworkFilter) { var dateRange=this.Data.GetDateRange(); var obj= { Name:'JSSymbolData::GetFinance', //类名:: Explain:'财务数据FINANCE(ID)', JobID:jobItem.ID, Request:{ Url:self.RealtimeApiUrl, Type:'POST', Data:{ id:lID, symbol: this.Symbol, daterange:dateRange } }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(recvData) { if (recvData.Error) self.AddStockValueError(key,recvData.Error); else self.RecvStockValue(recvData,jobItem,key,0); self.Execute.RunNextJob(); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } var apiDownload=new DownloadFinanceData( { Job:jobItem, Symbol:this.Symbol, Url:this.StockHistoryDayApiUrl, RealtimeUrl:this.RealtimeApiUrl, Args:aryArgs, DataKey:key, Callback:function(recvData, jobItem, key) { self.RecvStockValue(recvData, jobItem, key,0); self.Execute.RunNextJob(); }, ErrorCallback:function(strError) { self.AddStockValueError(key,strError); } }); apiDownload.Download(); } this.GetProFinance=function(jobItem) { var jobID=jobItem.ID; var finder=null; for(var i=0;i0) key+=',' key+=args[i]; } return key; } this.GetCustomApiData=function(args) { var key=this.GenerateCustomAPIKey(args); if (!this.CustomAPIData.has(key)) { JSConsole.Complier.Log(`[JSSymbolData::GetCustomApiData] can't find api data key=[${key}]`); return null; } return this.CustomAPIData.get(key); } this.ReadArgumentValue=function(item, result) //读取变量值 { result.Name=item.Name; if (item.Type==Syntax.Literal) { result.Value=item.Value; return true; } if (item.Type==Syntax.Identifier) { var isFind=false; for(var i in this.Arguments) { const argItem=this.Arguments[i]; if (argItem.Name==item.Name) { result.Value=argItem.Value; isFind=true; return true; } } if (!isFind) { result.Error=`can't read ${item.Name}` ; return false; } } result.Error=`can't read ${item.Name}, type error.`; return false; } this.ReadIndexFunctionOut=function(item, result) { var indexParam={}; if (typeof(item)=== 'object') { if (!this.ReadArgumentValue(item,indexParam)) { result.Error=indexParam.Error; return false; } } else { indexParam.Value=item; } result.OutIndex=indexParam.Value; result.Out=null; return true; } //MA.MA1#WEEK this.ReadIndexFunctionValue=function(item, result) //返回 {Period:周期, Out:输出变量, Error:, Name:脚本名字 } { var indexParam={}; if (typeof(item)=== 'object') { if (!this.ReadArgumentValue(item,indexParam)) { result.Error=indexParam.Error; return false; } } else { indexParam.Value=item; } var pos=indexParam.Value.indexOf("\."); if (pos!=-1) { result.Name=indexParam.Value.slice(0, pos); //名字 var pos2=indexParam.Value.indexOf('#', pos+1); if (pos2!=-1) { result.Out=indexParam.Value.slice(pos+1, pos2); //输出变量 result.Period=indexParam.Value.slice(pos2+1); //周期 } else { result.Out=indexParam.Value.slice(pos+1); } } else { var pos2=indexParam.Value.indexOf('#'); if (pos2!=-1) { result.Name=indexParam.Value.slice(0,pos2); result.Period=indexParam.Value.slice(pos2+1); //周期 } else { result.Name=indexParam.Value; } } const PERIOD_MAP=new Map([ ["DAY",0 ], ["WEEK", 1 ], ["MONTH",2 ], ["SEASON",9 ], ["YEAR", 3], ["HALFYEAR",22], ["WEEK2",21], ["MIN1", 4], ["MIN5", 5 ], ["MIN15", 6 ], ["MIN30",7 ], ["MIN60", 8 ],["MIN120",11],["MIN240",12], ["DAY2", 40002],["MULTIDAY",40002],["DAY3", 40003],["DAY4", 40004],["DAY5",40005], ["DAY6", 40006],["DAY7", 40007],["DAY8", 40008],["DAY9", 40009],["DAY10",40010], ["DAY11", 40011],["DAY12", 40012],["DAY13", 40013],["DAY14", 40014],["DAY15", 40015], ]); if (result.Period) { if (!PERIOD_MAP.has(result.Period)) { result.Error=`${result.Period}, 周期错误`; return false; } result.PeriodID=PERIOD_MAP.get(result.Period); } return true; } this.ReadSymbolArgumentValue=function(item, result) //返回{ Value:股票代码, Error:错误信息} { var readArgument={}; if (typeof(item)=== 'object') { if (!this.ReadArgumentValue(item,readArgument)) { result.Error=readArgument.Error; return false; } } else { readArgument.Value=item; } if (readArgument.Value=='') readArgument.Value=this.Symbol; //缺省使用股票代码 var symbol=readArgument.Value; //支持 SH60000, SZ000001 //A股后缀小写 if (symbol.indexOf('.SH')>0) result.Symbol=symbol.replace('.SH', ".sh"); else if (symbol.indexOf('.SZ')>0) result.Symbol=symbol.replace('.SZ', ".sz"); else if (symbol.indexOf("SH")==0) result.Symbol=symbol.slice(2)+".sh"; else if (symbol.indexOf("SZ")==0) result.Symbol=symbol.slice(2)+".sz"; else result.Symbol=symbol; return true; } this.ReadIndexArgumentValue=function(args, result) { result.Args=[]; for(var i in result.SytemIndex.Args) //复制参数 { var item=result.SytemIndex.Args[i]; result.Args.push({Value:item.Value, Name:item.Name}); } if (args.length>2 && result.SytemIndex.Args && result.SytemIndex.Args.length>0) { for(var i=2, j=0; i 输出 this.GenerateScriptIndexKey=function(indexInfo) { var indexParam=''; var args=indexInfo.Args; for(var i in args) { if (indexParam.length>0) indexParam+=','; var item=args[i]; indexParam+=item.Value.toString(); } var out="ALL"; if (indexInfo.Out) out=indexInfo.Out; else if (IFrameSplitOperator.IsPlusNumber(indexInfo.OutIndex)) out=`Out[${indexInfo.OutIndex-1}]`; var key=`(${indexInfo.Symbol},${indexInfo.PeriodID}), ${indexInfo.Name}(${indexParam})=>${out}`; return key; } //TMP2:=KDJ.K#WEEK; this.CallMemberScriptIndex=function(job) { if (job.Member.Object.Type!=Syntax.Identifier ||job.Member.Property.Type!=Syntax.Identifier) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: 参数错误`); } var objName=job.Member.Object.Name; var PropertyName=job.Member.Property.Name; if (PropertyName=="" || PropertyName==null) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: ${objName}.${PropertyName} 指标输出变量错误`); } if (this.Execute.VarTable.has(objName)) { var memberValue=this.Execute.VarTable.get(objName); if (memberValue.hasOwnProperty(PropertyName)) { JSConsole.Complier.Log(`[JSSymbolData::CallMemberScriptIndex] index data ${objName}.${PropertyName} in cache.`); return this.Execute.RunNextJob(); } } var callInfo=objName+"."+PropertyName; var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol }; if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标 { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`); } var systemIndex=new JSIndexScript(); var systemItem=systemIndex.Get(indexInfo.Name); if (!systemItem) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallMemberScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`); } if (Array.isArray(systemItem.Args) && systemItem.Args.length>0) { indexInfo.Args=[]; for(var i in systemItem.Args) //复制参数 { var item=systemItem.Args[i]; indexInfo.Args.push({Value:item.Value, Name:item.Name}); } } JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo); var dateTimeRange=this.Data.GetDateRange(); var option= { HQDataType:this.DataType, Symbol:indexInfo.Symbol, Name:'', Right:this.Right, //复权 Period:indexInfo.PeriodID, //周期 Data:null, SourceData:null, Callback:(outVar,job, symbolData)=> { this.RecvMemberScriptIndexData(outVar,job,symbolData); this.Execute.RunNextJob(); }, CallbackParam:indexInfo, Async:true, MaxRequestDataCount:this.MaxRequestDataCount+30*2, MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2, Arguments:indexInfo.Args, //Condition:this.Condition, IsBeforeData:this.IsBeforeData, NetworkFilter:this.NetworkFilter, IsApiPeriod:this.IsApiPeriod, KLineRange:dateTimeRange //K线数据范围 }; //执行脚本 var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)}); } this.CallDynamicScriptIndex=function(job, varTable) { var callInfo=job.DynamicName; var indexInfo={ Job:job, PeriodID:this.Period , Symbol:this.Symbol }; if (!this.ReadIndexFunctionValue(callInfo,indexInfo)) //读取指标 { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Error}`); } var systemIndex=new JSIndexScript(); //系统指标 var systemItem=systemIndex.Get(indexInfo.Name); if (!systemItem) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() Error: '${callInfo}' ${indexInfo.Name} 指标不存在`); } indexInfo.SytemIndex=systemItem; if (!this.ReadDynamicIndexArgumentValue(job.Args, indexInfo, varTable)) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallDynamicScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `); } JSConsole.Complier.Log('[JSSymbolData::CallMemberScriptIndex] call script index', indexInfo); var dateTimeRange=this.Data.GetDateRange(); var option= { HQDataType:this.DataType, Symbol:indexInfo.Symbol, Name:'', Right:this.Right, //复权 Period:indexInfo.PeriodID, //周期 Data:null, SourceData:null, Callback:(outVar,job, symbolData)=> { this.RecvDynamicScriptIndexData(outVar,job,symbolData); this.Execute.RunNextJob(); }, CallbackParam:indexInfo, Async:true, MaxRequestDataCount:this.MaxRequestDataCount+30*2, MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2, Arguments:indexInfo.Args, //Condition:this.Condition, IsBeforeData:this.IsBeforeData, NetworkFilter:this.NetworkFilter, IsApiPeriod:this.IsApiPeriod, KLineRange:dateTimeRange //K线数据范围 }; //执行脚本 var run=JSComplier.Execute(systemItem.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)}); } this.ReadDynamicIndexArgumentValue=function(args, result, varTable) { result.Args=[]; for(var i =0;i=2)) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${job.FunctionName} 参数错误`); } var indexInfo={ Job:job, PeriodID:this.Period }; if (!this.ReadSymbolArgumentValue(job.Args[0],indexInfo)) //读取代码 { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`); } if (!this.ReadIndexFunctionValue(job.Args[1],indexInfo)) //读取指标 { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`); } if (job.FunctionName=="CALCSTOCKINDEX") { if (!this.ReadIndexFunctionOut(job.Args[2],indexInfo)) //读取返回值索引 { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() Error: ${indexInfo.Error}`); } } var systemIndex=new JSIndexScript(); var systemItem=systemIndex.Get(indexInfo.Name); if (!systemItem) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标不存在`); } indexInfo.SytemIndex=systemItem; //系统指标 if (!this.ReadIndexArgumentValue(job.Args,indexInfo)) { var token=job.Token; this.Execute.ErrorHandler.ThrowError(token.Index,token.Line,0,`CallScriptIndex() ${indexInfo.Name} 指标参数错误 : ${indexInfo.Error} `); } JSConsole.Complier.Log('[JSSymbolData::CallScriptIndex] call script index', indexInfo); var DateTimeRange=null; if (this.Data && this.Data.Data.length>0) { var start=this.Data.Data[0]; var end=this.Data.Data[this.Data.Data.length-1]; DateTimeRange= { Start:{Date:start.Date, Time: start.Time}, End:{Date:end.Date, Time: end.Time}, } } var option= { HQDataType:this.DataType, Symbol:indexInfo.Symbol, Name:'', Right:this.Right, //复权 Period:indexInfo.PeriodID, //周期 Data:null, SourceData:null, Callback:(outVar,job, symbolData)=> { this.RecvScriptIndexData(outVar,job,symbolData); this.Execute.RunNextJob(); }, CallbackParam:indexInfo, Async:true, MaxRequestDataCount:this.MaxRequestDataCount+30*2, MaxRequestMinuteDayCount:this.MaxRequestMinuteDayCount+2, Arguments:indexInfo.Args, //Condition:this.Condition, IsBeforeData:this.IsBeforeData, NetworkFilter:this.NetworkFilter, IsApiPeriod:this.IsApiPeriod, KLineRange:DateTimeRange //K线数据范围 }; //执行脚本 var run=JSComplier.Execute(indexInfo.SytemIndex.Script,option,(error, indexInfo)=>{this.ExecuteScriptIndexError(error,indexInfo)}); } this.RecvMemberScriptIndexData=function(outVar,indexInfo,symbolData) { JSConsole.Complier.Log('[JSSymbolData::RecvMemberScriptIndexData] ', outVar, indexInfo, symbolData); var kLine=symbolData.Data.Data; var aryOutVar=outVar; var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID); var member=indexInfo.Job.Member; var objName=member.Object.Name; var propertyName=member.Property.Name; var memberValue={}; if (this.Execute.VarTable.has(objName)) memberValue=this.Execute.VarTable.get(objName); else this.Execute.VarTable.set(objName, memberValue); //保存所有的指标数据, 下面用到了就可以不用算了 for(var i in data) { var key=outVar[i].Name; if (indexInfo.Period) key+='#'+indexInfo.Period; //带周期的变量 memberValue[key]=data[i].Data; } } this.RecvDynamicScriptIndexData=function(outVar,indexInfo,symbolData) { JSConsole.Complier.Log('[JSSymbolData::RecvDynamicScriptIndexData] ', outVar, indexInfo, symbolData); var kLine=symbolData.Data.Data; var aryOutVar=outVar; var data=this.Data.FitKLineIndex(kLine,aryOutVar,this.Period,indexInfo.PeriodID); var objName=indexInfo.Name; var memberValue={}; if (this.Execute.VarTable.has(objName)) memberValue=this.Execute.VarTable.get(objName); else this.Execute.VarTable.set(objName, memberValue); var strValue=""; for(var i=0; i0) strValue+=","; strValue+=`${item.Value}`; } } var strArgs=`(${strValue})`; //保存所有的指标数据, 下面用到了就可以不用算了 for(var i=0; iup) item.Up=list[i][up]; if (list[i].length>down) item.Down=list[i][down]; if (list[i].length>stop) item.Stop=list[i][stop]; if (list[i].length>unchanged) item.Unchanged=list[i][unchanged]; if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除 aryDayData.push(item); } return aryDayData; } this.JsonDataToMinuteHistoryData=function(data) { 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; for (var i = 0; i < list.length; ++i) { let item = new HistoryData(); item.Date = list[i][date]; item.Open = list[i][open]; item.YClose = list[i][yclose]; item.Close = list[i][close]; item.High = list[i][high]; item.Low = list[i][low]; item.Vol = list[i][vol]; //原始单位股 item.Amount = list[i][amount]; item.Time=list[i][time]; // if (isNaN(item.Open) || item.Open<=0) continue; //停牌的数据剔除 aryDayData.push(item); } // 无效数据处理 for(let i = 0; i < aryDayData.length; ++i) { var minData = aryDayData[i]; if (minData == null) coninue; if (isNaN(minData.Open) || minData.Open <= 0 || isNaN(minData.High) || minData.High <= 0 || isNaN(minData.Low) || minData.Low <= 0 || isNaN(minData.Close) || minData.Close <= 0 || isNaN(minData.YClose) || minData.YClose <= 0) { if (i == 0) { if (minData.YClose > 0) { minData.Open = minData.YClose; minData.High = minData.YClose; minData.Low = minData.YClose; minData.Close = minData.YClose; } } else // 用前一个有效数据填充 { for(let j = i-1; j >= 0; --j) { var minData2 = aryDayData[j]; if (minData2 == null) coninue; if (minData2.Open > 0 && minData2.High > 0 && minData2.Low > 0 && minData2.Close > 0) { if (minData.YClose <= 0) minData.YClose = minData2.Close; minData.Open = minData2.Open; minData.High = minData2.High; minData.Low = minData2.Low; minData.Close = minData2.Close; break; } } } } } return aryDayData; } //API 返回数据 转化为array[] this.JsonDataToMinuteData=function(data) { var aryMinuteData=new Array(); for(var i in data.stock[0].minute) { var jsData=data.stock[0].minute[i]; var item=new MinuteData(); item.Close=jsData.price; item.Open=jsData.open; item.High=jsData.high; item.Low=jsData.low; item.Vol=jsData.vol; //股 item.Amount=jsData.amount; if (i==0) //第1个数据 写死9:25 item.DateTime=data.stock[0].date.toString()+" 0925"; else item.DateTime=data.stock[0].date.toString()+" "+jsData.time.toString(); item.Date=data.stock[0].date; item.Time=jsData.time; item.Increase=jsData.increase; item.Risefall=jsData.risefall; item.AvPrice=jsData.avprice; aryMinuteData[i]=item; } return aryMinuteData; } //多日日线数据API 转化成array[]; this.JsonDataToMultiDayMinuteData=function(data) { var symbol=data.symbol; var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); var isFutures=MARKET_SUFFIX_NAME.IsChinaFutures(upperSymbol); var result=[]; for(var i in data.data) { var minuteData=[]; var dayData=data.data[i]; var date=dayData.date; var yClose=dayData.yclose; //前收盘 计算涨幅 var preClose=yClose; //前一个数据价格 var preAvPrice=null; //上一个均价 //var preAvPrice=data.stock[0].yclose; //前一个均价 for(var j in dayData.minute) { var jsData=dayData.minute[j]; if (jsData[2]) preClose=jsData[2]; //保存上一个收盘数据 var item=new MinuteData(); item.Close=jsData[2]; item.Open=jsData[1]; item.High=jsData[3]; item.Low=jsData[4]; item.Vol=jsData[5]/100; //原始单位股 item.Amount=jsData[6]; if (70) { item.AvPrice=jsData[7]; //均价 preAvPrice=jsData[7]; } item.DateTime=date.toString()+" "+jsData[0].toString(); item.Date=date item.Time=jsData[0]; 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; else item.Increase=null; if (j==0) //第1个数据 写死9:25 { if (isSHSZ) item.DateTime=date.toString()+" 0925"; item.IsFristData=true; } //价格是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; if (item.AvPrice<=0) item.AvPrice=null; minuteData[j]=item; } var newData=new ChartData(); newData.Data=minuteData; newData.YClose=yClose; newData.Close=dayData.close; newData.Date=date; result.push(newData); } var minuteData=[]; for(var i=result.length-1; i>=0;--i) { var item=result[i]; for(var j in item.Data) { minuteData.push(item.Data[j]); } } return minuteData; } //CODELIKE 模糊股票代码 this.CODELIKE=function(value) { if (this.Symbol && this.Symbol.indexOf(value)==0) return 1; return 0; } this.NAMELIKE=function(value) { if (this.Name && this.Name.indexOf(value)==0) return 1; return 0; } /* SETCODE 市场类型 0:深圳 1:上海,47:中金所期货 28:郑州商品 29:大连商品 30:上海商品,27:香港指数 31:香港主板,48:香港创业板... */ this.SETCODE=function() { if (this.Symbol.indexOf('.sh')) return 1; if (this.Symbol.indexOf('.sz')) return 0; return 0; } this.GetSymbol=function() { return this.Symbol; } this.GetName=function() { return this.Name; } this.DATE=function() { var result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; for(let i in this.Data.Data) { var item=this.Data.Data[i]; result[i]=item.Date-19000000; } return result; } this.YEAR=function() { var result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; for(let i in this.Data.Data) { var item=this.Data.Data[i]; if (this.IsNumber(item.Date)) result[i]=parseInt(item.Date/10000); else result[i]=null; } return result; } this.DAY=function() { var result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; for(let i in this.Data.Data) { var item=this.Data.Data[i]; if (this.IsNumber(item.Date)) result[i]=parseInt(item.Date%100); else result[i]=null; } return result; } this.MONTH=function() { var result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; for(let i in this.Data.Data) { var item=this.Data.Data[i]; if (this.IsNumber(item.Date)) result[i]=parseInt(item.Date%10000/100); else result[i]=null; } return result; } this.TIME=function() { var result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; for(let i=0;i0) findDate=date[date.length-1]; } else if (this.IsNumber(date)) { findDate=date; } if (findDate==null) return null; if (findDate<5000000) findDate+=19000000; var index=null; for(let i in this.Data.Data) //查找日期对应的索引 { if (this.Data.Data[i].Date==findDate) { index=parseInt(i); break; } } if (index==null || index>=data.length) return null; return data[index]; } //用法:结果从0到11,依次分别是1/5/15/30/60分钟,日/周/月,多分钟,多日,季,年 this.PERIOD=function() { //Period周期 0=日线 1=周线 2=月线 3=年线 9=季线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟 const PERIOD_MAP=[5,6,7,11, 0,1,2,3,4,5, 9]; if (this.Period>=0 && this.Period<=PERIOD_MAP.length-1) return PERIOD_MAP[this.Period]; return this.Period; } this.GetDrawNull=function() { var result=[]; if (!this.Data || !this.Data.Data || !this.Data.Data.length) return result; for(let i in this.Data.Data) { result[i]=null; } return result; } this.HOUR=function() { var result=[]; if (!this.Data || !this.Data.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return result; for(var i=0;iitem.Low) low=item.Low; } return low; } return []; } } //是否有是有效的数字 JSSymbolData.prototype.IsNumber=function(value) { if (value==null) return false; if (isNaN(value)) return false; return true; } JSSymbolData.prototype.IsDivideNumber=function(value) { if (value==null) return false; if (isNaN(value)) return false; if (value==0) return false; return true; } JSSymbolData.prototype.JsonDataToFinance=function(data) { var financeData; for(let i=1;i<=4;++i) { switch(i) { case 1: var finance=data.finance1; var announcement=data.announcement1; break; case 2: var finance=data.finance2; var announcement=data.announcement2; break; case 3: var finance=data.finance3; var announcement=data.announcement3; break; case 4: var finance=data.finance4; var announcement=data.announcement4; break; default: break; } if (!finance || !announcement || !this.IsNumber(announcement.year) || !this.IsNumber(announcement.quarter)) continue; if (financeData) //如果存在1天公布多个报告期数据 只取最新的一个公告期数据 { if (financeData.Announcement.year=2000 && quarter>=1 && quarter<=4) return { Year:year, Quarter:quarter }; return null; } }; //专业财务数据 var JS_ARRAY_PROFESSIONAL_FINANCE= [ { Name:"GPJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE, Explain:"股票交易类数据GPJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetGPJYValue", ArgCount:3 }, { Name:"GPJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE, Explain:"股票交易类数据GPJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetGPJYOne", ArgCount:4 }, { Name:"SCJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE, Explain:"市场交易类数据SCJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetSCJYValue",ArgCount:3 }, { Name:"SCJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE, Explain:"市场交易类数据SCJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetSCJYOne",ArgCount:4 }, { Name:"BKJYVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE, Explain:"板块交易类数据BKJYVALUE(ID,N,TYPE)", FuncName:"JSSymbolData::GetBKJYValue",ArgCount:3 }, { Name:"BKJYONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE, Explain:"板块交易类数据BKJYONE(ID,N,Y,MMDD)", FuncName:"JSSymbolData::GetBKJYOne",ArgCount:4 }, { Name:"FINVALUE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE, Explain:"财务数据FINVALUE(ID)", FuncName:"JSSymbolData::GetFinValue",ArgCount:1 }, { Name:"FINONE", JobID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE, Explain:"财务数据FINONE(ID,Y,MMDD)", FuncName:"JSSymbolData::GetFinOne",ArgCount:3 } ]; function JSExecute(ast,option) { this.AST=ast; //语法树 this.ErrorHandler=new ErrorHandler(); this.VarTable=new Map(); //变量表 this.VarDrawTable=new Map(); //绘图变量表 this.OutVarTable=[]; //输出变量 this.Arguments=[]; this.ErrorCallback; //执行错误回调 this.GetEventCallback; this.IsUsePageData=false; this.IndexCtrl; this.Debug=0; //0=非debug模式 1=debug 模式 this.DebugFilter; this.Interrupt={ Exit:false }; //中断信息 //脚本自动变量表, 只读 this.ConstVarTable=new Map([ //个股数据 ['CLOSE',null],['VOL',null],['OPEN',null],['HIGH',null],['LOW',null],['AMOUNT',null], ['C',null],['V',null],['O',null],['H',null],['L',null],['AMO',null], ['VOLR',null], //量比 ['VOLINSTK',null], ["OPI",null], //持仓量 ["QHJSJ",null], ["SETTLE",null], //结算价 ["ZSTJJ",null], //分时图均价线,对于分时图周期指标有效. ["ISEQUAL",null], ["ISUP",null],["ISDOWN"], //ISUP=收阳 ISEQUAL=平盘 ISDOWN=收阴 //日期类 ['DATE',null],['YEAR',null],['MONTH',null],['PERIOD', null],['WEEK',null],['WEEKDAY',null],["TIME",null],["DAY",null],["DATETIME",null],["TIME2",null], ["WEEKOFYEAR", null],["DAYSTOTODAY", null], ["HOUR",null],["MINUTE",null], //大盘数据 ['INDEXA',null],['INDEXC',null],['INDEXH',null],['INDEXL',null],['INDEXO',null],['INDEXV',null], ['INDEXADV',null],['INDEXDEC',null], ["ADVANCE",null],['DECLINE', null], ['FROMOPEN',null], //已开盘有多长分钟 ['TOTALFZNUM', null], //该品种的每天的总交易分钟数. ['CURRBARSCOUNT',null], //到最后交易日的周期数 ['TOTALBARSCOUNT',null], ['ISLASTBAR',null], //判断是否为最后一个周期 ['BARSTATUS',null], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置. ["BARPOS", null], //返回从第一根K线开始到当前的周期数 ['CAPITAL',null], //流通股本(手) ["TOTALCAPITAL",null], //TOTALCAPITAL 当前总股本 手 ['EXCHANGE',null], //换手率 ['SETCODE', null], //市场类型 ['CODE',null], //品种代码 ['STKNAME',null], //品种名称 ["TQFLAG",null], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权 ['HYBLOCK',null], //所属行业板块 ['DYBLOCK',null], //所属地域板块 ['GNBLOCK',null], //所属概念 ["FGBLOCK",null], //所属风格板块 ["ZSBLOCK",null], //所属指数板块 ["ZHBLOCK",null], //所属组合板块 ["ZDBLOCK",null], //所属自定义板块 ["HYZSCODE",null], ["GNBLOCKNUM",null], //所属概念板块的个数 ["FGBLOCKNUM",null], //所属风格板块的个数 ["ZSBLOCKNUM",null], //所属指数板块的个数 ["ZHBLOCKNUM",null], //所属组合板块的个数 ["ZDBLOCKNUM",null], //所属自定义板块的个数 ["HYSYL",null], //指数市盈率或个股所属行业的市盈率 ["HYSJL",null], //指数市净率或个股所属行业的市净率 ['DRAWNULL',null], ["NULL",null], ["MACHINEDATE",null],["MACHINETIME",null],["MACHINEWEEK",null], ["TR", null], //真实波幅 ["AUTOFILTER", null], ['LARGEINTRDVOL', null], //逐笔买入大单成交量,相当于L2_VOL(0,0)+L2_VOL(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ['LARGEOUTTRDVOL', null], //逐笔卖出大单成交量,相当于L2_VOL(0,1)+L2_VOL(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["TRADENUM", null], //逐笔成交总单数,沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["TRADEINNUM", null], //逐笔买入成交单数,相当于L2_VOLNUM(0,0)+L2_VOLNUM(1,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["TRADEOUTNUM", null], //逐笔卖出成交单数,相当于L2_VOLNUM(0,1)+L2_VOLNUM(1,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["LARGETRDINNUM", null], //逐笔买入大单成交单数,相当于L2_VOLNUM(0,0),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["LARGETRDOUTNUM", null], //逐笔卖出大单成交单数,相当于L2_VOLNUM(0,1),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["CUR_BUYORDER", null], //总委买量,序列数据,专业版等(资金流向功能)沪深京品种行情专用 ["CUR_SELLORDER", null], //总委卖量,序列数据,专业版等(资金流向功能)沪深京品种行情专用 ["ACTINVOL", null], //主动买成交量,相当于L2_VOL(0,2)+L2_VOL(1,2)+L2_VOL(2,2)+L2_VOL(3,2),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["ACTOUTVOL", null], //主动卖成交量,相当于L2_VOL(0,3)+L2_VOL(1,3)+L2_VOL(2,3)+L2_VOL(3,3),沪深京品种的资金流向,仅日线以上周期,用于特定版本 ["BIDORDERVOL", null], //累计总有效委买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量 ["BIDCANCELVOL", null], //累计总有效撤买量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委买量-累计总有效撤买量=总买+总成交量 ["AVGBIDPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委买均价 ["OFFERORDERVOL", null], //累计总有效委卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量 ["OFFERCANCELVOL", null], //累计总有效撤卖量,专业版等(资金流向功能)沪深京品种行情专用 累计总有效委卖量-累计总有效撤卖量=总卖+总成交量 ["AVGOFFERPX", null], //专业版等(资金流向功能)沪深京品种行情专用:最新委卖均价 //["", null], ]); this.SymbolData=new JSSymbolData(this.AST,option,this); this.Algorithm=new JSAlgorithm(this.ErrorHandler,this.SymbolData); this.Draw=new JSDraw(this.ErrorHandler,this.SymbolData); this.JobList=[]; //执行的任务队列 this.UpdateUICallback=null; //回调 this.CallbackParam=null; this.IsSectionMode=false; if (option) { if (option.Callback) this.UpdateUICallback=option.Callback; if (option.CallbackParam) { this.CallbackParam=option.CallbackParam; if (this.CallbackParam.HQChart) this.GetEventCallback=(id)=> { return this.CallbackParam.HQChart.GetEventCallback(id); } } if (option.Arguments) this.Arguments=option.Arguments; if (option.IsSectionMode) this.IsSectionMode=option.IsSectionMode; if (option.Self) this.IndexCtrl=option.Self; //调试模式信息 if (IFrameSplitOperator.IsNumber(option.Debug)) this.Debug=option.Debug; if (option.DebugFilter) this.DebugFilter=option.DebugFilter; } this.Execute=function() { this.OutVarTable=[]; this.VarTable=new Map(); this.VarDrawTable=new Map(); //绘图变量表 JSConsole.Complier.Log('[JSExecute::Execute] Load Arguments', this.Arguments); for(let i in this.Arguments) //预定义的变量 { let item =this.Arguments[i]; this.VarTable.set(item.Name,item.Value); } this.RunNextJob(); } this.RunNextJob=function() { if (this.JobList.length<=0) return; JSConsole.Complier.Log('[JSExecute::Execute] JobList', this.JobList); var jobItem=this.JobList.shift(); switch(jobItem.ID) { case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA: return this.SymbolData.GetSymbolData(); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_PERIOD_DATA: return this.SymbolData.GetSymbolPeriodData(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_DATA: return this.SymbolData.GetIndexData(); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_LATEST_INDEX_DATA: return this.SymbolData.GetLatestIndexData(); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_INDEX_INCREASE_DATA: return this.SymbolData.GetIndexIncreaseData(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_LATEST_DATA: return this.SymbolData.GetLatestData(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VOLR_DATA: //量比 return this.SymbolData.GetVolRateData(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_OTHER_SYMBOL_DATA: //指定股票数据 return this.SymbolData.GetOtherSymbolData(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_RELEASE_DATE_DATA: return this.SymbolData.GetCompanyReleaseDate(jobItem.ID); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BALANCE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_RATE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_BALANCE: //买入信息-融资余额 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_AMOUNT: //买入信息-买入额 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_REPAY: //买入信息-偿还额 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_BUY_NET: //买入信息-融资净买入 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_BALANCE: //卖出信息-融券余量 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_VOLUME: //卖出信息-卖出量 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_REPAY: //卖出信息-偿还量 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_MARGIN_SELL_NET: //卖出信息-融券净卖出 return this.SymbolData.GetMarginData(jobItem.ID); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_NEGATIVE: //负面新闻 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_RESEARCH: //机构调研 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_INTERACT: //互动易 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE: //股东增持 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_HOLDERCHANGE2: //股东减持 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TRUSTHOLDER: //信托持股 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_BLOCKTRADING: //大宗交易 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_COMPANYNEWS: //官网新闻 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_TOPMANAGERS: //高管要闻 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_NEWS_ANALYSIS_PLEDGE: //股权质押 return this.SymbolData.GetNewsAnalysisData(jobItem.ID); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_HK_TO_SHSZ: return this.SymbolData.GetHKToSHSZData(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SECTION_SF: return this.SymbolData.GetSectionFinanceData(jobItem); //财务截面报告数据 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINANCE: return this.SymbolData.GetFinance(jobItem); //专业财务数据 case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINONE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_FINVALUE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYVALUE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_GPJYONE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYVALUE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SCJYONE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYVALUE: case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_BKJYONE: return this.SymbolData.GetProFinance(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_VARIANT: //CAPITAL, TOTALCAPITAL return this.SymbolData.GetVariantData(jobItem); case JS_EXECUTE_JOB_ID.JOB_CUSTOM_VARIANT_DATA: return this.SymbolData.GetCustomVariantData(jobItem); case JS_EXECUTE_JOB_ID.JOB_CUSTOM_FUNCTION_DATA: return this.SymbolData.GetCustomFunctionData(jobItem); case JS_EXECUTE_JOB_ID.JOB_CUSTOM_DATA_FUNCTION: return this.SymbolData.GetCustomFunctionDataV2(jobItem); case JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_CUSTOM_API_DATA: return this.SymbolData.DownloadCustomAPIData(jobItem); case JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX: return this.SymbolData.CallScriptIndex(jobItem, this.VarTable); case JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT: if (this.Debug===1 && this.DebugFilter) return this.DebugRun(); else return this.Run(); } } this.ReadSymbolData=function(name,node) { switch(name) { case 'CLOSE': case 'C': case 'VOL': case 'V': case 'OPEN': case 'O': case 'HIGH': case 'H': case 'LOW': case 'L': case 'AMOUNT': case 'AMO': case "OPI": case 'VOLINSTK': case "SETTLE": case "QHJSJ": case "ZSTJJ": case "ISEQUAL": //平盘 case "ISUP": //收阳 case "ISDOWN": //收阴 return this.SymbolData.GetSymbolCacheData(name); case 'VOLR': return this.SymbolData.GetVolRateCacheData(node); case "TR": //TR,求真实波幅. return this.SymbolData.GetTRData(node); //大盘数据 case 'INDEXA': case 'INDEXC': case 'INDEXH': case 'INDEXH': case 'INDEXO': case 'INDEXV': case 'INDEXL': case 'INDEXADV': case 'INDEXDEC': return this.SymbolData.GetIndexCacheData(name); case 'CURRBARSCOUNT': return this.SymbolData.GetCurrBarsCount(); case "BARPOS": return this.SymbolData.GetBarPos(); case "TOTALBARSCOUNT": return this.SymbolData.GetTotalBarsCount(); case "TOTALFZNUM": return this.SymbolData.GetTotalTradeMinuteCount(); case 'ISLASTBAR': return this.SymbolData.GetIsLastBar(); case "BARSTATUS": return this.SymbolData.GetBarStatus(); case "TOTALCAPITAL": case 'CAPITAL': case 'EXCHANGE': case "HYBLOCK": case "DYBLOCK": case "GNBLOCK": case "FGBLOCK": case "ZSBLOCK": case "ZHBLOCK": case "ZDBLOCK": case "HYZSCODE": case "GNBLOCKNUM": case "FGBLOCKNUM": case "ZSBLOCKNUM": case "ZHBLOCKNUM": case "ZDBLOCKNUM": case "HYSYL": case "HYSJL": case 'FROMOPEN': case "LARGEINTRDVOL": case "LARGEOUTTRDVOL": case "TRADENUM": case "TRADEINNUM": case "TRADEOUTNUM": case "LARGETRDINNUM": case "LARGETRDOUTNUM": case "CUR_BUYORDER": case "CUR_SELLORDER": case "ACTINVOL": case "ACTOUTVOL": case "BIDORDERVOL": case "BIDCANCELVOL": case "AVGBIDPX": case "OFFERORDERVOL": case "OFFERCANCELVOL": case "AVGOFFERPX": return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node }); case 'SETCODE': return this.SymbolData.SETCODE(); case 'CODE': return this.SymbolData.GetSymbol(); case 'STKNAME': return this.SymbolData.GetName(); case "TIME": return this.SymbolData.TIME(); case "TIME2": return this.SymbolData.TIME2(); case 'DATE': return this.SymbolData.DATE(); case "DATETIME": return this.SymbolData.DateTime(); case 'YEAR': return this.SymbolData.YEAR(); case 'MONTH': return this.SymbolData.MONTH(); case 'WEEK': case "WEEKDAY": return this.SymbolData.WEEK(); case "DAY": return this.SymbolData.DAY(); case 'PERIOD': return this.SymbolData.PERIOD(); case "HOUR": return this.SymbolData.HOUR(); case "MINUTE": return this.SymbolData.MINUTE(); case 'DRAWNULL': case "NULL": return this.SymbolData.GetDrawNull(); case 'ADVANCE': case 'DECLINE': return this.SymbolData.GetIndexIncreaseCacheData(name,this.SymbolData.Symbol,node); case "TQFLAG": return this.SymbolData.Right; case "MACHINEDATE": { var now=new Date(); return (now.getFullYear()*10000+(now.getMonth()*1)*100+now.getDate())-19000000; } case "MACHINETIME": { var now=new Date(); return now.getHours()*10000+(now.getMinutes()*1)*100+now.getSeconds(); } case "MACHINEWEEK": { var now=new Date(); return now.getDay(); } case "WEEKOFYEAR": return this.SymbolData.WEEKOFYEAR(); case "DAYSTOTODAY": return this.SymbolData.DAYSTOTODAY(); } this.ThrowUnexpectedNode(node, '变量'+name+'不存在', name); } this.ReadCustomVariant=function(name,node) { return this.SymbolData.GetStockCacheData({ VariantName:name, Node:node }); } //读取变量 this.ReadVariable=function(name,node) { if (this.ConstVarTable.has(name)) { let data=this.ConstVarTable.get(name); if (data==null) //动态加载,用到再加载 { data=this.ReadSymbolData(name,node); this.ConstVarTable.set(name,data); } return data; } if (g_JSComplierResource.IsCustomVariant(name)) return this.ReadCustomVariant(name,node); //读取自定义变量 if (this.VarTable.has(name)) return this.VarTable.get(name); if (name.indexOf('#')>0) { var aryPeriod=name.split('#'); return this.SymbolData.GetSymbolPeriodCacheData(aryPeriod[0],aryPeriod[1]); } if (name.indexOf("COLOR")==0) { var colorValue=JSComplier.ColorVarToRGB(name); if (colorValue) return colorValue; } this.ThrowUnexpectedNode(node, '变量'+name+'不存在', name); return null; } this.ReadMemberVariable=function(node) { var obj=node.Object; var member=node.Property; let maiObj; if (obj.Type==Syntax.BinaryExpression || obj.Type==Syntax.LogicalExpression ) maiObj=this.VisitBinaryExpression(obj); else if (obj.Type==Syntax.CallExpression) maiObj=this.VisitCallExpression(obj); else maiObj=this.GetNodeValue(obj); if (!maiObj) return null; var value=maiObj[member.Name]; if (value) return value; return null; } //单数据转成数组 个数和历史数据一致 this.SingleDataToArrayData=function(value) { let count=this.SymbolData.Data.Data.length; let result=[]; for(let i=0;i0) outVar=this.SymbolData.GetOtherSymolCacheData({ Literal:outVar }); varName="__temp_li_"+i+"__"; var type=0; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); this.OutVarTable.push({Name:varName, Data:outVar, Type:type, NoneName:true}); } else if (item.Expression.Type==Syntax.BinaryExpression) { var varName="__temp_b_"+i+"__"; let outVar=item.Expression.Out; var type=0; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true}); } else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2 { var varName="__temp_l_"+i+"__"; let outVar=item.Expression.Out; var type=0; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true}); } else if (item.Expression.Type==Syntax.UnaryExpression) { var varName="__temp_u_"+i+"__"; var varInfo={ }; if (this.ReadUnaryExpression(item.Expression, varInfo)) { var type=0; this.OutVarTable.push({Name:varName, Data:varInfo.OutVar,Type:type, NoneName:true}); } } else if (item.Expression.Type==Syntax.MemberExpression) //MA.MA2 { var outVar=this.ReadMemberVariable(item.Expression); if (outVar) { var type=0; var varName="__temp_di_"+i+"__"; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); this.OutVarTable.push({Name:varName, Data:outVar,Type:type, NoneName:true}); } } else if (item.Expression.Type==Syntax.SequenceExpression) { let varName; let draw; let color, upColor, downColor, stickType; let lineWidth; let colorStick=false; let pointDot=false; let upDownDot=false; let circleDot=false; let lineStick=false; let stick=false; let volStick=false; let lineArea=false; let stepLine=false; let isShow=true; let isExData=false; let isDotLine=false; let isOverlayLine=false; //叠加线 let isSingleLine=false; //独立线段 var isNoneName=false; var isShowTitle=true; //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如: //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE; var isDrawAbove=false; var isDrawCenter=false; var isDrawBelow=false; //VALIGN0,VALIGN1,VALIGN2 设置文字垂直对齐方式(上中下) //ALIGN0,ALIGN1,ALIGN2 设置文字水平对齐方式(左中右) var drawAlign=-1, drawVAlign=-1; var fontSize=-1; var bgConfig=null; //背景设置 var vLineConfig=null; var isFirstDraw=null; let xOffset=null, yOffset=null; var klineType=null; var lineDash=null; for(let j=0; j=0) outVar.DrawAlign=drawAlign; if (drawVAlign>=0) outVar.DrawVAlign=drawVAlign; if (fontSize>0) outVar.DrawFontSize=fontSize; if (bgConfig) outVar.Background=bgConfig; if (vLineConfig) outVar.VerticalLine=vLineConfig; if (IFrameSplitOperator.IsNumber(xOffset)) outVar.XOffset=xOffset; if (IFrameSplitOperator.IsNumber(yOffset)) outVar.YOffset=yOffset; if (IFrameSplitOperator.IsBool(isFirstDraw)) outVar.IsFirstDraw=isFirstDraw; if (IFrameSplitOperator.IsNumber(klineType)) outVar.KLineType=klineType; this.OutVarTable.push(outVar); } else if (varName) { let outVar=this.VarTable.get(varName); let value={Name:varName, Data:outVar,Type:0}; if (color) value.Color=color; if (lineWidth) value.LineWidth=lineWidth; if (isShow==false) value.IsShow=false; if (isExData==true) value.IsExData = true; if (isDotLine==true) value.IsDotLine=true; if (IFrameSplitOperator.IsNonEmptyArray(lineDash)) value.LineDash=lineDash; if (isOverlayLine==true) value.IsOverlayLine=true; if (isSingleLine==true) value.IsSingleLine=true; if (isShowTitle==false) value.IsShowTitle=false; if (stepLine==true) value.Type=7; this.OutVarTable.push(value); } } } } this.ReadUnaryExpression=function(item, varInfo) { var argument=item.Argument; var outVar=null; if (argument.Type==Syntax.Literal) { outVar=argument.Value; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); } else if (argument.Type==Syntax.Identifier) { var varName=argument.Name; outVar=this.ReadVariable(varName,item.Expression); if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); } else if (argument.Type==Syntax.BinaryExpression) { outVar=argument.Out; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); } else if (argument.Type==Syntax.CallExpression) { var callItem=argument; if (this.Draw.IsDrawFunction(callItem.Callee.Name) ) { return false; } else if (callItem.Callee.Name==="IFC" && callItem.Draw) { return false; } else { outVar=callItem.Out; if (!Array.isArray(outVar)) outVar=this.SingleDataToArrayData(outVar); } } else { return false; } if (item.Operator=='-') { if (outVar) outVar=this.Algorithm.Subtract(0,outVar); } varInfo.OutVar=outVar; return true; } this.GetOutIconData=function(cond, iconDraw) { if (Array.isArray(cond)) { for(var i=0; i { this.DebugRun_Next(debugCtrl); }); } else { this.DebugRun_End(); debugCtrl.Status=2; this.DebugFilter(debugCtrl,null); } } //debug模式 this.DebugRun=function() { try { if (!this.AST) this.ThrowError(); if (!this.AST.Body) this.ThrowError(); var debugCtrl={ LineCount:this.AST.Body.length, ExeLine:0, Self:this, Status:1 }; this.DebugFilter(debugCtrl, ()=> { this.DebugRun_Next(debugCtrl); }); } catch(error) { if (this.ErrorCallback) { if (this.IndexCtrl) this.IndexCtrl.Status=0; this.ErrorCallback(error, this.CallbackParam); } } } this.VisitNode=function(node) { switch(node.Type) { case Syntax.SequenceExpression: this.VisitSequenceExpression(node); break; case Syntax.ExpressionStatement: this.VisitNode(node.Expression); break; case Syntax.AssignmentExpression: this.VisitAssignmentExpression(node); break; case Syntax.BinaryExpression: case Syntax.LogicalExpression: this.VisitBinaryExpression(node); break; case Syntax.CallExpression: this.VisitCallExpression(node); break; case Syntax.UnaryExpression: this.VisitUnaryExpression(node); break; } } this.VisitUnaryExpression=function(node) { if (node.Operator=='-') { var tempValue=this.GetNodeValueEx(node.Argument); var value=this.Algorithm.Subtract(0,tempValue); } else { var value=node.Argument.Value; } return value; } this.VisitSequenceExpression=function(node) { for(let i in node.Expression) { let item =node.Expression[i]; this.VisitNode(item); } } this.GetDynamicScriptIndex=function(node, args) { var dynamicName=node.Callee.Value; var aryValue=dynamicName.split("."); if (aryValue.length!=2) { this.ThrowUnexpectedNode(node,`调用指标格式'${dynamicName}'错误`); } var name=aryValue[0]; var outName=aryValue[1]; var period=null; var pos=outName.indexOf('#'); if (pos!=-1) { period=outName.slice(pos+1); //周期 outName=outName.slice(0,pos); } var strValue=""; for(var i=0; i0) strValue+=","; strValue+=`${value}`; } var strArgs=`(${strValue})`; var key=`${outName}#${strArgs}`; if (period) key+=`#${period}`; if (!this.VarTable.has(name)) return null; var indexData=this.VarTable.get(name); var value=indexData[key]; return value; } //函数调用 this.VisitCallExpression=function(node) { var funcName=node.Callee.Name; var args=[]; for(var i=0;i=1) break; //IFC先处理第1个条件参数 if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(item); else if (item.Type==Syntax.CallExpression) value=this.VisitCallExpression(item); else value=this.GetNodeValue(item); args.push(value); } if (node.Callee.Type==Syntax.Literal) { node.Out=[]; node.Draw=null; var data=this.GetDynamicScriptIndex(node, args); if (data) node.Out=data; return node.Out; } if (funcName==="IFC") { //IFC(X,A,B)若X不为0则执行A,否则执行B.IFC与IF函数的区别:根据X的值来选择性执行A、B表达式. var bResult=this.Algorithm.IFC(args[0]); var item=bResult? node.Arguments[1] : node.Arguments[2]; var value; if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(item); else if (item.Type==Syntax.CallExpression) value=this.VisitCallExpression(item); else value=this.GetNodeValue(item); node.Out=value; if (item.Draw) node.Draw=item.Draw; return node.Out; } //JSConsole.Complier.Log('[JSExecute::VisitCallExpression]' , funcName, '(', args.toString() ,')'); if (g_JSComplierResource.IsCustomFunction(funcName)) { var data=this.Algorithm.CallCustomFunction(funcName, args, this.SymbolData, node); node.Out=[]; node.Draw=null; if (data) { if (data.Out) node.Out=data.Out; if (data.Draw) node.Draw=data.Draw; } return node.Out; } if (g_JSComplierResource.IsCustomDataFunction(funcName)) { var functionInfo=g_JSComplierResource.CustomDataFunction.Data.get(funcName); node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:functionInfo.ArgCount, Node:node } ); node.Draw=null; return node.Out; } switch(funcName) { case 'DYNAINFO': //行情最新数据 node.Out=this.SymbolData.GetLatestCacheData(args[0]); break; case 'STICKLINE': node.Draw=this.Draw.STICKLINE(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case 'DRAWTEXT': node.Draw=this.Draw.DRAWTEXT(args[0],args[1],args[2]); node.Out=[]; break; case 'DRAWTEXT_FIX': node.Draw=this.Draw.DRAWTEXT_FIX(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case 'SUPERDRAWTEXT': node.Draw=this.Draw.SUPERDRAWTEXT(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case 'DRAWICON': node.Draw=this.Draw.DRAWICON(args[0],args[1],args[2]); node.Out=[]; break; case "ICON": node.Draw=this.Draw.ICON(args[0],args[1]); node.Out=[]; break; case "TIPICON": node.Draw=this.Draw.TIPICON(args[0],args[1],args[2],args[3]); node.Out=[]; break; case "BACKGROUND": node.Draw=this.Draw.BACKGROUND(args[0],args[1],args[2],args[3],args[4],args[5]); node.Out=[]; break; case "CKLINE": node.Draw=this.Draw.CKLINE(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case 'DRAWLINE': node.Draw=this.Draw.DRAWLINE(args[0],args[1],args[2],args[3],args[4]); node.Out=node.Draw.DrawData; break; case 'DRAWBAND': node.Draw=this.Draw.DRAWBAND(args[0],args[1],args[2],args[3]); node.Out=[]; break; case "FILLRGN": if (args.length>=4) node.Draw=this.Draw.FILLRGN2(args); else node.Draw=this.Draw.FILLRGN(args[0],args[1],args[2]); node.Out=[]; break; case "FLOATRGN": node.Draw=this.Draw.FLOATRGN(args); node.Out=[]; break; case "FILLTOPRGN": node.Draw=this.Draw.FILLBGRGN(1, args); node.Out=[]; break; case "FILLBOTTOMRGN": node.Draw=this.Draw.FILLBGRGN(0, args); node.Out=[]; break; case "FILLVERTICALRGN": node.Draw=this.Draw.FILLVERTICALRGN(args); node.Out=[]; break; case 'DRAWKLINE': case "DRAWKLINE1": node.Draw=this.Draw.DRAWKLINE(args[0],args[1],args[2],args[3]); node.Out=[]; break; case 'DRAWKLINE_IF': node.Draw=this.Draw.DRAWKLINE_IF(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case "KLINETYPE": //K线类型 和DRAWKLINE连用 node.Out=this.Draw.KLINETYPE(args[0]); break; case "DRAWOVERLAYKLINE": node.Draw=this.Draw.DRAWOVERLAYKLINE(args[0],args[1],args[2],args[3]); node.Out=[]; break; case "DRAWCOLORKLINE": node.Draw=this.Draw.DRAWCOLORKLINE(args[0],args[1],args[2]); node.Out=[]; break; case 'PLOYLINE': case 'POLYLINE': node.Draw=this.Draw.POLYLINE(args[0],args[1]); node.Out=node.Draw.DrawData; break; case 'DRAWNUMBER': node.Draw=this.Draw.DRAWNUMBER(args[0],args[1],args[2], args[3]); node.Out=node.Draw.DrawData.Value; break; case "DRAWNUMBER_FIX": node.Draw=this.Draw.DRAWNUMBER_FIX(args[0],args[1],args[2],args[3],args[4]); node.Out=node.Draw.DrawData.Value; break; case "DRAWCHANNEL": node.Draw=this.Draw.DRAWCHANNEL(args[0],args[1],args[2],args[3],args[4],args[5],args[6]); node.Out=[]; break; case 'RGB': node.Out=this.Draw.RGB(args[0],args[1],args[2]); break; case "RGBA": node.Out=this.Draw.RGBA(args[0],args[1],args[2],args[3]); break; case "UPCOLOR": node.Out=this.Draw.UPCOLOR(args[0]); break; case "DOWNCOLOR": node.Out=this.Draw.DOWNCOLOR(args[0]); break; case "STICKTYPE": //柱子类型 node.Out=this.Draw.STICKTYPE(args[0]); break; case "XMOVE": node.Out=this.Draw.XMOVE(args[0]); break; case "YMOVE": node.Out=this.Draw.YMOVE(args[0]); break; case "LINEDASH": node.Out=this.Draw.LINEDASH(args); break; case "FIRSTDRAW": node.Out=this.Draw.FIRSTDRAW(args[0]); break; case 'PARTLINE': node.Draw=this.Draw.PARTLINE(args); node.Out=[]; break; case 'DRAWGBK': node.Draw=this.Draw.DRAWGBK(args[0],args[1],args[2],args[3]); node.Out=[]; break; case 'DRAWGBK2': node.Draw=this.Draw.DRAWGBK2(args[0],args[1],args[2],args[3]); node.Out=[]; break; case "DRAWGBK_DIV": node.Draw=this.Draw.DRAWGBK_DIV(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case 'DRAWTEXT_LINE': node.Draw=this.Draw.DRAWTEXT_LINE(args[0],args[1],args[2],args[3],args[4],args[5],args[6]); node.Out=[]; break; case 'DRAWRECTREL': node.Draw=this.Draw.DRAWRECTREL(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case "DRAWTEXTREL": node.Draw=this.Draw.DRAWTEXTREL(args[0],args[1],args[2]); node.Out=[]; break; case "DRAWTEXTABS": node.Draw=this.Draw.DRAWTEXTABS(args[0],args[1],args[2]); node.Out=[]; break; case "DRAWOVERLAYLINE": node.Draw=this.Draw.DRAWOVERLAYLINE(args[0],args[1],args[2]); node.Out=node.Draw.DrawData.Data; break; case "DRAWSL": node.Draw=this.Draw.DRAWSL(args[0],args[1],args[2],args[3],args[4]); node.Out=[]; break; case "VERTLINE": node.Draw=this.Draw.VERTLINE(args[0],args[1]); node.Out=node.Draw.DrawData.Data; break; case "HORLINE": node.Draw=this.Draw.HORLINE(args[0],args[1],args[2],args[3]); node.Out=node.Draw.DrawData.Data; break; case 'CODELIKE': node.Out=this.SymbolData.CODELIKE(args[0]); break; case 'NAMELIKE': case "NAMEINCLUDE": node.Out=this.SymbolData.NAMELIKE(args[1]); break; case 'REFDATE': node.Out=this.SymbolData.REFDATE(args[0],args[1]); break; case 'FINANCE': node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } ); break; case "FINVALUE": node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:1, Node:node } ); break; case "FINONE": node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } ); break; case "GPJYVALUE": case "SCJYVALUE": case "BKJYVALUE": node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:3, Node:node } ); break; case "GPJYONE": case "SCJYONE": case "BKJYONE": node.Out=this.SymbolData.GetStockCacheData( {FunctionName:funcName, Args:args, ArgCount:4, Node:node } ); break; case "MARGIN": node.Out=this.SymbolData.GetMarginCacheData(args[0],node); break; case "HK2SHSZ": node.Out=this.SymbolData.GetHKToSHSZCacheData(args[0],node); break; case "NEWS": node.Out=this.SymbolData.GetNewsAnalysisCacheData(args[0],node); break; case 'UPCOUNT': case 'DOWNCOUNT': node.Out=this.SymbolData.GetIndexIncreaseCacheData(funcName,args[0],node); break; case 'SF': node.Out=this.SymbolData.GetSectionFinanceCacheData(args[0],args[1],args[2],node); break; case 'LOADAPIDATA': node.Out=this.SymbolData.GetCustomApiData(args); break; case "STKINDI": case "CALCSTOCKINDEX": node.Out=this.SymbolData.GetScriptIndexOutData(args,node,funcName); break; case "SOUND": node.Draw=this.Draw.SOUND(args[0]); node.Out=[]; break; case "PLAYSOUND": node.Draw=this.Draw.PLAYSOUND(args[0],args[1]); node.Out=[]; break; case 'CLOSE': case 'C': case 'VOL': case 'V': case 'OPEN': case 'O': case 'HIGH': case 'H': case 'LOW': case 'L': case 'AMOUNT': case 'AMO': node.Out=this.SymbolData.GetOtherSymolCacheData( {FunctionName:funcName, Args:args} ); break; case "INBLOCK": node.Out=this.SymbolData.IsInBlock(args[0],node); break; case 'COVER_C': case 'COVER_O': case 'COVER_H': case 'COVER_L': case 'COVER_A': case 'COVER_V': if (args.length==2) return this.SymbolData.GetSymbolPeriodCacheData2(JSComplierHelper.GetConvertValueName(funcName),args[0],args[1]); return this.SymbolData.GetSymbolPeriodCacheData(JSComplierHelper.GetConvertValueName(funcName),args[0]); case "SYSPARAM": node.Out=this.SymbolData.SysParam(args[0], this); break; case "TESTSKIP": var bExit=this.Algorithm.TESTSKIP(args[0],node); node.Out=null; if (bExit) { this.Interrupt.Exit=true; if (node && node.Marker) { var marker=node.Marker; this.Interrupt.Line=marker.Line; this.Interrupt.Index=marker.Index; this.Interrupt.Column=marker.Column; } } break; //交易函数 case "BUY": node.Draw=this.Draw.BUY(args[0],args[1],args[2],args[3]); node.Out=node.Draw.DrawData.Data; break; case "SELL": node.Draw=this.Draw.SELL(args[0],args[1],args[2],args[3]); node.Out=node.Draw.DrawData.Data; break; case "SELLSHORT": node.Draw=this.Draw.SELLSHORT(args[0],args[1],args[2],args[3]); node.Out=node.Draw.DrawData.Data; break; case "BUYSHORT": node.Draw=this.Draw.BUYSHORT(args[0],args[1],args[2],args[3]); node.Out=node.Draw.DrawData.Data; break; default: node.Out=this.Algorithm.CallFunction(funcName, args, node, this.SymbolData); break; } return node.Out; } //赋值 this.VisitAssignmentExpression=function(node) { let left=node.Left; if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node); let varName=left.Name; let right=node.Right; let value=null, drawValue=null; if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(right); else if (right.Type==Syntax.CallExpression) { value=this.VisitCallExpression(right); if (right.Draw) drawValue=right.Draw; } else if (right.Type==Syntax.Literal) { value=right.Value; if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0) value=this.SymbolData.GetOtherSymolCacheData( {Literal:value} ); } else if (right.Type==Syntax.Identifier) //右值是变量 value=this.ReadVariable(right.Name,right); else if (right.Type==Syntax.MemberExpression) value=this.ReadMemberVariable(right); else if (right.Type==Syntax.UnaryExpression) value=this.VisitUnaryExpression(right); if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitAssignmentExpression]' , varName, ' = ',value); if (drawValue) this.VarDrawTable.set(varName, drawValue); this.VarTable.set(varName,value); } //逻辑运算 this.VisitBinaryExpression=function(node) { let stack=[]; stack.push(node); let temp=null; while(stack.length!=0) { temp=stack[stack.length-1]; if (temp.Left && node!=temp.Left && node!=temp.Right) { stack.push(temp.Left); } else if (temp.Right && node!=temp.Right) { stack.push(temp.Right); } else { let value=stack.pop(); if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以 { let leftValue=this.GetNodeValue(value.Left); let rightValue=this.GetNodeValue(value.Right); if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue); value.Out=null; //保存中间值 switch(value.Operator) { case '-': value.Out=this.Algorithm.Subtract(leftValue,rightValue); break; case '*': value.Out=this.Algorithm.Multiply(leftValue,rightValue); break; case '/': value.Out=this.Algorithm.Divide(leftValue,rightValue) break; case '+': value.Out=this.Algorithm.Add(leftValue,rightValue); break; case '>': value.Out=this.Algorithm.GT(leftValue,rightValue); break; case '>=': value.Out=this.Algorithm.GTE(leftValue,rightValue); break; case '<': value.Out=this.Algorithm.LT(leftValue,rightValue); break; case '<=': value.Out=this.Algorithm.LTE(leftValue,rightValue); break; case '==': case '=': //= 比较 value.Out=this.Algorithm.EQ(leftValue,rightValue); break; case '!=': case '<>': value.Out=this.Algorithm.NEQ(leftValue,rightValue); break; } if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] BinaryExpression',value); } else if (value.Type==Syntax.LogicalExpression) { let leftValue=this.GetNodeValue(value.Left); let rightValue=this.GetNodeValue(value.Right); if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue); value.Out=null; //保存中间值 switch(value.Operator) { case '&&': case 'AND': value.Out=this.Algorithm.And(leftValue,rightValue); break; case '||': case 'OR': value.Out=this.Algorithm.Or(leftValue,rightValue); break; } if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value); } node=temp; } } return node.Out; } //获取节点值,BinaryExpression,LogicalExpression会重新计算 this.GetNodeValueEx=function(item) { var value=null; if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(item); else if (item.Type==Syntax.CallExpression) value=this.VisitCallExpression(item); else value=this.GetNodeValue(item); return value; } this.GetNodeValue=function(node) { switch(node.Type) { case Syntax.Literal: //数字 return node.Value; case Syntax.UnaryExpression: var value=this.VisitUnaryExpression(node); return value; case Syntax.Identifier: var value=this.ReadVariable(node.Name,node); return value; case Syntax.BinaryExpression: case Syntax.LogicalExpression: return node.Out; case Syntax.CallExpression: return this.VisitCallExpression(node); case Syntax.MemberExpression: return this.ReadMemberVariable(node); default: this.ThrowUnexpectedNode(node); } } this.ThrowUnexpectedNode=function(node,message,word) { let marker=node.Marker; let msg=message || "执行异常"; return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg, word); } this.ThrowDownloadSF=function(node,job,message) { let marker=node.Marker; let msg=message; return this.ErrorHandler.ThrowDownloadJob(marker.Index,marker.Line,marker.Column,msg,job); } this.ThrowError=function() { } } //脚本说明 function JSExplainer(ast,option) { this.AST=ast; this.ErrorHandler=new ErrorHandler(); this.ErrorCallback; //执行错误回调 this.UpdateUICallback; this.CallbackParam; this.JobList=[]; //执行的任务队列 this.VarTable=new Map(); //变量表 this.OutVarTable=[]; //输出变量 this.MaxValueLength=150; //最长的字符 //脚本自动变量表, 只读 this.ConstVarTable=new Map( [ //个股数据 ['CLOSE',"收盘价"],['VOL',"成交量"],['OPEN',"开盘价"],['HIGH',"最高价"],['LOW',"最低价"],['AMOUNT',"成交量"], ['C',"收盘价"],['V',"成交量"],['O',"开盘价"],['H',"最高价"],['L',"最低价"],['AMO',"成交量"], ['VOLR',"量比"], ['VOLINSTK',"持仓量"], ["OPI","持仓量"], ["ZSTJJ","均价"], ["QHJSJ","结算价"], ["SETTLE", "结算价"], //日期类 ['DATE',"日期"],['YEAR',"年份"],['MONTH',"月份"],["DAY","日"],['PERIOD', "周期"],['WEEK',"星期"],["TIME","时间"], //大盘数据 ['INDEXA',"大盘成交额"],['INDEXC',"大盘收盘价"],['INDEXH',"大盘最高价"],['INDEXL',"大盘最低价"],['INDEXO',"大盘开盘价"],['INDEXV',"大盘成交量"], ['INDEXADV',"大盘上涨家数"],['INDEXDEC',"´大盘下跌家数"], ["ADVANCE","上涨家数"], ['DECLINE', "下跌家数"], ['FROMOPEN',"当前离开盘分钟数"], ['TOTALFZNUM', "总分钟数"], ['CURRBARSCOUNT',"到最后交易的周期"], //到最后交易日的周期数 ['TOTALBARSCOUNT',"总的周期数"], ['ISLASTBAR',"是否是最后一个周期"], //判断是否为最后一个周期 ['BARSTATUS',"数据位置状态"], //BARSTATUS返回数据位置信息,1表示第一根K线,2表示最后一个数据,0表示中间位置. ['CAPITAL',"当前流通股本(手)"], ["TOTALCAPITAL","当前总股本(手)"], ['EXCHANGE',"换手率"], //换手率 ['SETCODE', "市场类型"], //市场类型 ['CODE',"品种代码"], //品种代码 ['STKNAME',"品种名称"], //品种名称 ["TQFLAG","当前复权状态"], //TQFLAG 当前的复权状态,0:无复权 1:前复权 2:后复权 ['HYBLOCK',"所属行业"], //所属行业板块 ['DYBLOCK',"所属地域"], //所属地域板块 ['GNBLOCK',"所属概念"], //所属概念 ["FGBLOCK","所属风格板块"], ["ZSBLOCK","所属指数板块"], ["ZHBLOCK",'所属组合板块'], ["ZDBLOCK",'所属自定义板块'], ["HYZSCODE","所属行业的板块指数代码"], ["GNBLOCKNUM","所属概念板块的个数"], ["FGBLOCKNUM","所属风格板块的个数"], ["ZSBLOCKNUM","所属指数板块的个数"], ["ZHBLOCKNUM","所属组合板块的个数"], ["ZDBLOCKNUM","所属自定义板块的个数"], ["HYSYL","指数市盈率或个股所属行业的市盈率"], ["HYSJL","指数市净率或个股所属行业的市净率"], ['DRAWNULL',"无效数据"], ["TR", "求真实波幅"], ["LARGEINTRDVOL","逐笔买入大单成交量"], ["LARGEOUTTRDVOL","逐笔卖出大单成交量"], ["TRADENUM", "逐笔成交总单数"], ["TRADEINNUM", "逐笔买入成交单数"], ["TRADEOUTNUM", "逐笔卖出成交单数"], ["LARGETRDINNUM", "逐笔买入大单成交单数"], ["LARGETRDOUTNUM", "逐笔卖出大单成交单数"], ["CUR_BUYORDER", "总委买量"], ["CUR_SELLORDER", "总委卖量"], ["ACTINVOL", "主动买成交量"], ["ACTOUTVOL", "主动卖成交量"], ["BIDORDERVOL", "累计总有效委买量"], ["BIDCANCELVOL", "累计总有效撤买量"], ["AVGBIDPX", "最新委买均价"], ["OFFERORDERVOL", "累计总有效委卖量"], ["OFFERCANCELVOL", "累计总有效撤卖量"], ["AVGOFFERPX", "最新委卖均价"], ]); if (option) { if (option.Callback) this.UpdateUICallback=option.Callback; if (option.CallbackParam) this.CallbackParam=option.CallbackParam; if (option.Arguments) this.Arguments=option.Arguments; } this.Run=function() { try { this.OutVarTable=[]; this.VarTable=new Map(); JSConsole.Complier.Log('[JSExecute::JSExplainer] Load Arguments', this.Arguments); for(let i in this.Arguments) //预定义的变量 { let item =this.Arguments[i]; this.VarTable.set(item.Name,item.Value); } let data=this.RunAST();//执行脚本 JSConsole.Complier.Log('[JSExplainer.Run] explain finish', data); if (this.UpdateUICallback) //回调发送结果, 可以支持异步 { JSConsole.Complier.Log('[JSExplainer.Run] invoke UpdateUICallback.'); this.UpdateUICallback(data); } } catch(error) { JSConsole.Complier.Log('[JSExplainer.Run] throw error ', error); if (this.ErrorCallback) { this.ErrorCallback(error, this.OutVarTable); } } } this.RunAST=function() { if (!this.AST) this.ThrowError(); if (!this.AST.Body) this.ThrowError(); for(var i=0; i0) outVar=this.GetOtherSymbolExplain({ Literal:outVar }, item); varName="__temp_li_"+i+"__"; var type=0; this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`, Type:0, NoneName:true}); } else if (item.Expression.Type==Syntax.BinaryExpression) // CLOSE+OPEN; { var varName="__temp_b_"+i+"__"; let outVar=item.Expression.Out; this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true}); } else if (item.Expression.Type==Syntax.LogicalExpression) //逻辑语句 如 T1 AND T2 { var varName="__temp_l_"+i+"__"; let outVar=item.Expression.Out; this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true}); } else if (item.Expression.Type==Syntax.UnaryExpression) //一元运算 如-C, -7, -(C+10) { var varName="__temp_l_"+i+"__"; var argument=item.Expression.Argument; let outVar=null; if (argument.Type==Syntax.Literal) { outVar=argument.Value; } else if (argument.Type==Syntax.Identifier) { let varName=argument.Name; outVar=this.ReadVariable(varName,item.Expression); } else if (argument.Type==Syntax.BinaryExpression) { outVar=argument.Out; } if (item.Expression.Operator=='-') { outVar=`-${outVar}`; } this.OutVarTable.push({Name:varName, Data:`输出: ${outVar}`,Type:0, NoneName:true}); } else if (item.Expression.Type==Syntax.SequenceExpression) { let varName; let drawName; let draw; let color; let lineWidth; let colorStick=false; let pointDot=false; let circleDot=false; let lineStick=false; let stick=false; let volStick=false; let isShow=true; let isExData=false; let isDotLine=false; let isOverlayLine=false; //叠加线 var isNoneName=false; var fontSize=-1; var drawAlign=-1, drawVAlign=-1; //显示在位置之上,对于DRAWTEXT和DRAWNUMBER等函数有用,放在语句的最后面(不能与LINETHICK等函数共用),比如: //DRAWNUMBER(CLOSE>OPEN,HIGH,CLOSE),DRAWABOVE; var isDrawAbove=false; for(let j in item.Expression.Expression) { let itemExpression=item.Expression.Expression[j]; if (itemExpression.Type==Syntax.AssignmentExpression && itemExpression.Operator==':' && itemExpression.Left) { varName=itemExpression.Left.Name; let varValue=this.VarTable.get(varName); this.VarTable.set(varName,this.ConvertToShortValue(varValue)); //把常量放到变量表里 } else if (itemExpression.Type==Syntax.Identifier) { let value=itemExpression.Name; if (value==='COLORSTICK') colorStick=true; else if (value==='POINTDOT') pointDot=true; else if (value==='CIRCLEDOT') circleDot=true; else if (value==='DOTLINE') isDotLine=true; else if (value==='LINESTICK') lineStick=true; else if (value==='STICK') stick=true; else if (value==='VOLSTICK') volStick=true; else if (value==="DRAWABOVE") isDrawAbove=true; else if (value.indexOf('COLOR')==0) color=value; else if (value.indexOf('LINETHICK')==0) lineWidth=value; else if (value=="ALIGN0") drawAlign=0; else if (value=="ALIGN1") drawAlign=1; else if (value=="ALIGN2") drawAlign=2; else if (value=="VALIGN0") drawVAlign=0; else if (value=="VALIGN1") drawVAlign=1; else if (value=="VALIGN2") drawVAlign=2; else if (value.indexOf('NODRAW')==0) isShow=false; else if (value.indexOf('EXDATA')==0) isExData=true; //扩展数据, 不显示再图形里面 else if (value.indexOf('LINEOVERLAY')==0) isOverlayLine=true; else if (value.indexOf("FONTSIZE")==0) { var strFontSize=value.replace("FONTSIZE",""); fontSize=parseInt(strFontSize); } else { varName=itemExpression.Name; let varValue=this.ReadVariable(varName,itemExpression); varName="__temp_si_"+i+"__"; isNoneName=true; this.VarTable.set(varName,this.ConvertToShortValue(varValue)); //放到变量表里 } } else if(itemExpression.Type==Syntax.Literal) //常量 { let aryValue=itemExpression.Value; varName=itemExpression.Value.toString(); isNoneName=true; this.VarTable.set(varName,aryValue); //把常量放到变量表里 } else if (itemExpression.Type==Syntax.CallExpression) { if (j==0) { if (this.IsDrawFunction(itemExpression.Callee.Name)) { draw=itemExpression.Out; drawName=itemExpression.Callee.Name; } else { let varValue=itemExpression.Out; varName=`__temp_sc_${itemExpression.Callee.Name}_${i}__`; isNoneName=true; this.VarTable.set(varName,varValue); } } } else if (itemExpression.Type==Syntax.BinaryExpression) { varName="__temp_sb_"+i+"__"; let aryValue=itemExpression.Out; isNoneName=true; this.VarTable.set(varName,aryValue); } else if (itemExpression.Type==Syntax.UnaryExpression) { varName="__temp_sb_"+i+"__"; var argument=itemExpression.Argument; let aryValue=null; if (argument.Type==Syntax.Literal) { aryValue=argument.Value; } else if (argument.Type==Syntax.Identifier) { let varName=argument.Name; aryValue=this.ReadVariable(varName,item.Expression); } else if (argument.Type==Syntax.BinaryExpression) { aryValue=argument.Out; } if (itemExpression.Operator=='-') { aryValue=`-${aryValue}`; } isNoneName=true; this.VarTable.set(varName,aryValue); } } var outValue; if (draw) outValue=`输出: ${draw}`; else if (isNoneName) outValue=`输出: ${this.VarTable.get(varName)}`; else outValue=`输出${varName}: ${this.VarTable.get(varName)}`; if (color) outValue+=`,颜色${this.GetColorExplain(color)}`; if (lineWidth) outValue+=`,线段粗细${this.GetLineWidthExplain(lineWidth)}`; if (isShow==false) outValue+=",不显示"; if (isDotLine==true) outValue+=",画虚线"; if (isDrawAbove==true) outValue+=',显示在位置之上'; if (pointDot && varName) //圆点 { outValue+=",画小圆点线"; let value={Name:varName, Draw:outValue, Radius:g_JSChartResource.POINTDOT.Radius, Type:3}; this.OutVarTable.push(value); } else if (circleDot && varName) //圆点 { outValue+=",画小圆圈线"; let value={Name:varName, Draw:outValue, Radius:g_JSChartResource.CIRCLEDOT.Radius, Type:3}; this.OutVarTable.push(value); } else if (lineStick && varName) //LINESTICK 同时画出柱状线和指标线 { outValue+=",画出柱状线和指标线"; let value={Name:varName, Draw:outValue, Type:4}; this.OutVarTable.push(value); } else if (stick && varName) //STICK 画柱状线 { outValue+=",画柱状线"; let value={Name:varName, Draw:outValue, Type:5}; this.OutVarTable.push(value); } else if (volStick && varName) //VOLSTICK 画彩色柱状线 { outValue+=",画成交量柱状线"; let value={Name:varName, Draw:outValue, Type:6}; this.OutVarTable.push(value); } else if (varName && color) { let value={Name:varName, Data:outValue, Color:color, Type:0}; this.OutVarTable.push(value); } else if (draw) //画图函数 { var outVar={ Name:drawName, Draw:outValue, Type:1 }; this.OutVarTable.push(outVar); } else if (colorStick && varName) //CYW: SUM(VAR4,10)/10000, COLORSTICK; 画上下柱子 { outValue+=",画彩色柱状线"; let value={Name:varName, Draw:outValue, Color:color, Type:2}; this.OutVarTable.push(value); } else if (varName) { let value={Name:varName, Data:outValue,Type:0}; this.OutVarTable.push(value); } } } } JSConsole.Complier.Log('[JSExplainer::Run]', this.VarTable); return this.OutVarTable; } this.VisitNode=function(node) { switch(node.Type) { case Syntax.SequenceExpression: this.VisitSequenceExpression(node); break; case Syntax.ExpressionStatement: this.VisitNode(node.Expression); break; case Syntax.AssignmentExpression: this.VisitAssignmentExpression(node); break; case Syntax.BinaryExpression: case Syntax.LogicalExpression: this.VisitBinaryExpression(node); break; case Syntax.CallExpression: this.VisitCallExpression(node); break; case Syntax.UnaryExpression: this.VisitUnaryExpression(node); break; } } this.VisitSequenceExpression=function(node) { for(let i in node.Expression) { let item =node.Expression[i]; this.VisitNode(item); } } this.VisitUnaryExpression=function(node) { if (node.Operator=='-') { let value=this.GetNodeValueEx(node.Argument); return '-'+value; } return node.Argument.Value; } //函数调用 this.VisitCallExpression=function(node) { let funcName=node.Callee.Name; let args=[]; for(let i in node.Arguments) { let item=node.Arguments[i]; let value; if (item.Type==Syntax.BinaryExpression || item.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(item); else if (item.Type==Syntax.CallExpression) value=this.VisitCallExpression(item); else value=this.GetNodeValue(item); args.push(value); } if (node.Callee.Type==Syntax.Literal) { var dynamicName=node.Callee.Value; node.Out=`指标引用'${dynamicName}'`; return node.Out; } if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExplainer::VisitCallExpression]' , funcName, '(', args.toString() ,')'); if (g_JSComplierResource.IsCustomFunction(funcName)) { var functionInfo=g_JSComplierResource.CustomFunction.Data.get(funcName); if (!functionInfo.Description) node.Out=`自定义函数${funcName}`; else node.Out=functionInfo.Description; return node.Out; } node.Out=this.CallFunctionExplain(funcName, args, node); return node.Out; } this.FUNCTION_INFO_LIST=new Map( [ ["REF", { Name:"REF", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日前的${args[0]}`; } } ], ["REFX", { Name:"REFX", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日后的${args[0]}`; } } ], ["REFV", { Name:"REFV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日前的(未作平滑处理)${args[0]}`; } } ], ["REFXV", { Name:"REFXV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日后的(未作平滑处理)${args[0]}`; } } ], ["REFDATE", { Name:"REFDATE", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日${args[0]}`; } } ], ["COUNT", { Name:"COUNT", Param:{ Count:2 }, ToString:function(args) { return `统计${args[1]}日中满足${args[0]}的天数`; } } ], ["BARSLASTCOUNT", { Name:"BARSLASTCOUNT", Param:{ Count:1 }, ToString:function(args) { return `条件${args[0]}连续成立次数`; } } ], ["BARSCOUNT", { Name:"BARSCOUNT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}有效数据周期数`; } } ], ["BARSLAST", { Name:"BARSLAST", Param:{ Count:1 }, ToString:function(args) { return `上次${args[0]}不为0距今天数`; } } ], ["BARSLASTS", { Name:"BARSLASTS", Param:{ Count:2 }, ToString:function(args) { return `倒数第N次成立时距今的周期数`; } } ], ["BARSNEXT", { Name:"BARSNEXT", Param:{ Count:1 }, ToString:function(args) { return `下次${args[0]}不为0距今天数`; } } ], ["BARSSINCEN", { Name:"BARSSINCEN", Param:{ Count:2 }, ToString:function(args) { return `在${args[1]}周期内首次${args[0]}距今天数`; } } ], ["BARSSINCE", { Name:"BARSSINCE", Param:{ Count:1 }, ToString:function(args) { return `首次${args[0]}距今天数`; } } ], ["HHV", { Name:"HHV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的最高值`; } } ], ["LLV", { Name:"LLV", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的最低值`; } } ], ["ZTPRICE", { Name:"ZTPRICE", Param:{ Count:2 }, ToString:function(args) { return '计算涨停价'; } } ], ["DTPRICE", { Name:"DTPRICE", Param:{ Count:2 }, ToString:function(args) { return '计算跌停价'; } } ], ["BACKSET", { Name:"BACKSET", Param:{ Count:2 }, ToString:function(args) { return `若${args[0]}则将最近${args[1]}周期置为1`; } } ], ["HOD", { Name:"HOD", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的高值名次`; } } ], ["LOD", { Name:"LOD", Param:{ Count:2 }, ToString:function(args) { return `${args[1]}日内${args[0]}的低值名次`; } } ], ["REVERSE", { Name:"REVERSE", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的相反数`; } } ], ["FILTER", { Name:"FILTER", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日过滤`; } } ], ["FILTERX", { Name:"FILTERX", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日反向过滤`; } } ], ["TFILTER", { Name:"TFILTER", Param:{Count:3}, ToString:function(args) { return `信号过滤(多头)`; } }], ["SUMBARS", { Name:"SUMBARS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}累加至${args[1]}的天数`; } } ], ["MA", { Name:"MA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日简单移动平均`; } } ], ["SMA", { Name:"SMA", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}的${args[1]}日[${args[2]}日权重]移动平均`; } } ], ["MEMA", { Name:"MEMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日平滑移动平均`; } } ], ["EMA", { Name:"EMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数移动平均`; } } ], ["EXPMA", { Name:"EXPMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数移动平均`; } } ], ["EXPMEMA", { Name:"EXPMEMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日指数平滑移动平均`; } }], ["WMA", { Name:"WMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日加权移动平均`; } } ], ["DMA", { Name:"DMA", Param:{ Count:2 }, ToString:function(args) { return `以${args[1]}为权重${args[0]}的动态移动平均`; } } ], ["XMA", { Name:"XMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日偏移移动平均`; } } ], ["RANGE", { Name:"RANGE", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}位于${args[1]}和${args[2]}之间`; } } ], ["CONST", { Name:"CONST", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的最后一日值`; } } ], ["TOPRANGE", { Name:"TOPRANGE", Param:{ Count:1 }, ToString:function(args) { return `当前值是近${args[0]}周期的最大值`; } } ], ["LOWRANGE", { Name:"LOWRANGE", Param:{ Count:1 }, ToString:function(args) { return `当前值是近${args[0]}周期的最小值`; } } ], ["FINDHIGH", { Name:"FINDHIGH", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最高价`; } } ], ["FINDHIGHBARS", { Name:"FINDHIGHBARS", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最高价到当前周期的周期数`; } } ], ["FINDLOW", { Name:"FINDLOW", Param:{ Count:4 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最低价`; } } ], ["FINDLOWBARS", { Name:"FINDLOWBARS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}在${args[1]}日前的${args[2]}天内第${args[3]}个最低价到当前周期的周期数`; } } ], ["SUM", { Name:"SUM", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}${args[1]}日累加`; } } ], ["MULAR", { Name:"MULAR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}日累乘`; } } ], ["AMA", { Name:"AMA", Param:{ Count:2 }, ToString:function(args) { return `以${args[1]}为权重${args[0]}的自适应均线`; } } ], ["TMA", { Name:"TMA", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}的${args[1]}日[${args[2]}日权重]移动平均`; } } ], ["CROSS", { Name:"CROSS", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}上穿${args[1]}`; } } ], ["LONGCROSS", { Name:"LONGCROSS", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}小于${args[1]}保持${args[2]}个交易日后交叉上穿`; } } ], ["UPNDAY", { Name:"UPNDAY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日${args[0]}连涨`; } } ], ["DOWNNDAY", { Name:"DOWNNDAY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日${args[0]}连跌`; } } ], ["NDAY", { Name:"NDAY", Param:{ Count:3 }, ToString:function(args) { return `最近${args[2]}日${args[0]}一直大于${args[1]}`; } } ], ["EXIST", { Name:"EXIST", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日存在${args[0]}`; } } ], ["EXISTR", { Name:"EXISTR", Param:{ Count:3 }, ToString:function(args) { return `从前${args[1]}日到前${args[2]}日存在${args[0]}`; } } ], ["EVERY", { Name:"EVERY", Param:{ Count:2 }, ToString:function(args) { return `最近${args[1]}日一直存在${args[0]}`; } } ], ["LAST", { Name:"LAST", Param:{ Count:3 }, ToString:function(args) { return `从前${args[1]}日到前${args[2]}日持续${args[0]}`; } } ], ["NOT", { Name:"NOT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}取反`; } } ], ["IF", { Name:"IF", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ], ["IFF", { Name:"IFF", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ], ["IFN", { Name:"IFN", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ], ["IFC", { Name:"IFC", Param:{ Count:3 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回${args[2]}`; } } ], ["TESTSKIP", { Name:"TESTSKIP", Param:{ Count:1 }, ToString:function(args) { return `如果满足条件${args[0]},公式返回`; } } ], ["VALUEWHEN", { Name:"VALUEWHEN", Param:{ Count:2 }, ToString:function(args) { return `如果${args[0]},返回${args[1]},否则返回上个输出值 `; } } ], ["MAX", { Name:"MAX", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}的较大值`; } } ], ["MIN", { Name:"MIN", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}和${args[1]}的较小值`; } } ], ["ACOS", { Name:"ACOS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反余弦`; } } ], ["ASIN", { Name:"ASIN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反正弦`; } } ], ["ATAN", { Name:"ATAN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的反正切`; } } ], ["COS", { Name:"COS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的余弦`; } } ], ["SIN", { Name:"SIN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的正弦`; } } ], ["TAN", { Name:"TAN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的正切`; } } ], ["EXP", { Name:"EXP", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的指数`; } } ], ["LN", { Name:"LN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的自然对数`; } } ], ["LOG", { Name:"LOG", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的对数`; } } ], ["SQRT", { Name:"SQRT", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的开方`; } } ], ["ABS", { Name:"ABS", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的绝对值`; } } ], ["POW", { Name:"POW", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}乘幂`; } } ], ["CEILING", { Name:"CEILING", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的向上舍入`; } } ], ["FLOOR", { Name:"FLOOR", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的向上舍入`; } } ], ["INTPART", { Name:"INTPART", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的整数部分`; } } ], ["BETWEEN", { Name:"BETWEEN", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}位于${args[1]}和${args[2]}之间`; } } ], ["FRACPART", { Name:"FRACPART", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的小数部分`; } } ], ["ROUND", { Name:"ROUND", Param:{ Count:1 }, ToString:function(args) { return `对${args[0]}(进行)四舍五入`; } } ], ["ROUND2", { Name:"ROUND2", Param:{ Count:2 }, ToString:function(args) { return `对${args[0]}(进行)四舍五入`; } } ], ["SIGN", { Name:"SIGN", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}的符号`; } } ], ["MOD", { Name:"MOD", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}关于${args[1]}的模`; } } ], ["RAND", { Name:"RAND", Param:{ Count:1 }, ToString:function(args) { return `随机正整数`; } } ], ["AVEDEV", { Name:"AVEDEV", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日平均绝对偏差`; } } ], ["DEVSQ", { Name:"DEVSQ", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日数据偏差平方和`; } } ], ["FORCAST", { Name:"FORCAST", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日线性回归预测值`; } } ], ["TSMA", { Name:"TSMA", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}在${args[1]}个周期内的时间序列三角移动平均`; } } ], ["SLOPE", { Name:"SLOPE", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日线性回归斜率`; } } ], ["STD", { Name:"STD", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日估算标准差`; } } ], ["STDP", { Name:"STDP", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日总体标准差`; } } ], ["STDDEV", { Name:"STDDEV", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日标准偏差`; } } ], ["VAR", { Name:"VAR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日估算样本方差`; } } ], ["VARP", { Name:"VARP", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}的${args[1]}日总体样本方差`; } } ], ["COVAR", { Name:"COVAR", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[2]}周期的协方差`; } } ], ["RELATE", { Name:"RELATE", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[0]}周期的相关系数`; } } ], ["BETA", { Name:"BETA", Param:{ Count:1 }, ToString:function(args) { return `β(Beta)系数`; } } ], ["BETAEX", { Name:"BETAEX", Param:{ Count:3 }, ToString:function(args) { return `${args[0]}和${args[1]}的${args[2]}周期的相关放大系数`; } } ], ["COST", { Name:"COST", Param:{ Count:1 }, ToString:function(args) { return `获利盘为${args[0]}%的成本分布`; } } ], ["WINNER", { Name:"WINNER", Param:{ Count:1 }, ToString:function(args) { return `以${args[0]}计算的获利盘比例`; } } ], ["LWINNER", { Name:"LWINNER", Param:{ Count:2 }, ToString:function(args) { return `最近${args[0]}日那部分成本以${args[1]}价格卖出的获利盘比例`; } } ], ["PWINNER", { Name:"PWINNER", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}日前那部分成本以${args[1]}价格卖出的获利盘比例`; } } ], ["COSTEX", { Name:"COSTEX", Param:{ Count:2 }, ToString:function(args) { return `位于价格${args[0]}和${args[1]}间的成本`; } } ], ["PPART", { Name:"PPART", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}日前那部分成本占总成本的比例`; } } ], ["SAR", { Name:"SAR", Param:{ Count:3 }, ToString:function(args) { return `步长为${args[1]}极限值为${args[0]}的${args[2]}日抛物转向`; } } ], ["SARTURN", { Name:"SARTURN", Param:{ Count:3 }, ToString:function(args) { return `步长为${args[1]}极限值为${args[0]}的${args[2]}日抛物转向点`; } } ], //字符串函数 ["CON2STR", { Name:"CON2STR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}转为字符串`; } } ], ["VAR2STR", { Name:"VAR2STR", Param:{ Count:2 }, ToString:function(args) { return `${args[0]}转为字符串`; } } ], ["STR2CON", { Name:"STR2CON", Param:{ Count:1 }, ToString:function(args) { return `${args[0]}转为数字`; } } ], ["STRLEN", { Name:"STRLEN", Param:{ Count:1 }, ToString:function(args) { return `得到${args[0]}字符串长度`; } } ], ["STRCAT", { Name:"STRCAT", Param:{ Count:2 }, ToString:function(args) { return `字符串相加`; } } ], ["VARCAT", { Name:"VARCAT", Param:{ Count:2 }, ToString:function(args) { return `字符串相加`; } } ], ["STRSPACE", { Name:"STRSPACE", Param:{ Count:1 }, ToString:function(args) { return `字符串${args[0]}加一空格`; } } ], ["SUBSTR", { Name:"SUBSTR", Param:{ Count:3 }, ToString:function(args) { return `字符串${args[0]}中取一部分`; } } ], ["STRCMP", { Name:"STRCMP", Param:{ Count:2 }, ToString:function(args) { return `字符串${args[0]}和字符串${args[1]}比较`; } } ], ["FINDSTR", { Name:"FINDSTR", Param:{ Count:2 }, ToString:function(args) { return `字符串${args[0]}中查找字符串${args[1]}`; } } ], ["NAMEINCLUDE", { Name:"NAMEINCLUDE", Param:{ Count:1 }, ToString:function(args) { return `查找品种名称中包含${args[0]}`; } } ], ["CODELIKE", { Name:"CODELIKE", Param:{ Count:1 }, ToString:function(args) { return `查找品种名称中包含${args[0]}`; } } ], ["INBLOCK", { Name:"AVEDEV", Param:{ Count:1 }, ToString:function(args) { return `属于${args[0]}板块`; } } ], ["STKINDI",{ Name:"STKINDI", Param:{ Dynamic:true }, ToString:function(args) { return "指标引用"; } }], ["STRFORMAT",{ Name:"STRFORMAT", Param:{ Dynamic:true }, ToString:function(args) { return `格式化${args[0]}字符串`; } }], ["NAMELIKE",{ Name:"NAMELIKE", Param:{ Count:1 }, ToString:function(args) { return `品种名称是否以'${args[0]}'开头`; } }], [ "HHVBARS", { Name:"HHVBARS", Param:{ Count:2 }, ToString:function(args) { if (args[1]==0) return `历史${args[0]}新高距今天数`; return `${args[1]}日内${args[0]}新高距今天数`; } } ], [ "LLVBARS", { Name:"LLVBARS", Param:{ Count:2 }, ToString:function(args) { if (args[1]==0) return `历史${args[0]}新低距今天数`; return `${args[1]}日内${args[0]}新低距今天数`; } } ], ["L2_VOLNUM", { Name:"L2_VOLNUM", Param:{ Count:2 }, ToString:function(args) { return `单数分档`; } }], ["L2_VOL", { Name:"L2_VOL", Param:{ Count:2 }, ToString:function(args) { return `成交量分档`; } }], ["L2_AMO", { Name:"L2_AMO", Param:{ Count:2 }, ToString:function(args) { return `成交额分档`; } }], ] ); this.CallFunctionExplain=function(funcName, args, node) { if (this.FUNCTION_INFO_LIST.has(funcName)) { var item=this.FUNCTION_INFO_LIST.get(funcName); if (item.Param.Dynamic===true) //动态参数 { } else { if (item.Param.Count!=args.length) this.ThrowUnexpectedNode(node,`函数${funcName}参数个数不正确. 需要${item.Param.Count}个参数`); } return item.ToString(args); } switch(funcName) { case "CALCSTOCKINDEX": return `引用${args[0]}的${args[1]}指标第${args[2]}个输出值`; case "PEAK": case "PEAKBARS": case "ZIG": case "ZIGA": case "TROUGH": case "TROUGHBARS": return this.GetZIGExplain(funcName,args); case "FINANCE": return this.GetFinanceExplain(args); case "DYNAINFO": return this.GetDynainfoExplain(args); case 'CLOSE': case 'C': case 'VOL': case 'V': case 'OPEN': case 'O': case 'HIGH': case 'H': case 'LOW': case 'L': case 'AMOUNT': case 'AMO': return this.GetOtherSymbolExplain( {FunctionName:funcName, Args:args} ,node); //绘图函数 case "PLOYLINE": return `当满足条件${args[0]}时以${args[1]}位置为顶点画折线连接`; case "DRAWLINE": return `当满足条件${args[0]}时,在${args[1]}位置画直线起点,当满足条件${args[2]}时,在${args[3]}位置画直线终点,${args[4]}表示是否延长`; case "DRAWSL": return `当满足条件${args[0]}时,在${args[1]}位置画斜线线性回归,${args[2]}斜率,${args[3]}长度,${args[4]}方向`; case "DRAWKLINE": case "DRAWKLINE1": return 'K线'; case "DRAWICON": return `当满足条件${args[0]}时,在${args[1]}位置画${args[2]}号图标`; case "DRAWTEXT": return `当满足条件${args[0]}时,在${args[1]}位置书写文字`; case "DRAWTEXT_FIX": return `当满足条件${args[0]}时,在横轴${args[1]}纵轴${args[2]}位置书写文字`; case "DRAWNUMBER": return `当满足条件${args[0]}时,在${args[1]}位置书写数字`; case "DRAWNUMBER_FIX": return `当满足条件${args[0]}时,在横轴${args[1]}纵轴${args[2]}位置书写数字`; case "RGB": return `自定色[${args[0]},${args[1]},${args[2]}]`; case "RGBA": return `自定色[${args[0]},${args[1]},${args[2]},${args[3]}]`; case "DRAWBAND": return '画带状线'; case "DRAWRECTREL": return "相对位置上画矩形."; case "DRAWGBK": return "填充背景"; case "TIPICON": return `当满足条件${args[0]}时,在${args[1]}位置画${args[2]}号图标`; case "STICKLINE": var barType=""; if (args[4]==-1) barType="虚线空心柱"; else if (args[4]==0) barType="实心柱"; else barType="实线空心柱"; return `当满足条件${args[0]}时, 在${args[1]}和${args[2]}位置之间画柱状线,宽度为${args[3]},${barType}`; case "PARTLINE": return "画折线" case "SELL": return "卖出平仓"; case "BUY": return "买入开仓"; case "SELLSHORT": return "卖出开仓"; case "BUYSHORT": return "买入平仓"; case "YMOVE": return; case "BACKGROUND": return "绘制背景"; case "UPCOLOR": return `上涨颜色${args[0]}`; case "DOWNCOLOR": return `下跌颜色${args[0]}`; case "STICKTYPE": case "FIRSTDRAW": return ""; default: this.ThrowUnexpectedNode(node,`函数${funcName}不存在`); } } this.GetDynainfoExplain=function(args) { const DATA_NAME_MAP=new Map( [ [3,"前收盘价"], [4,"开盘价"], [5,"最高价"], [6,"最低价"], [7,"现价"], [8,'总量'], [9,"现量"], [10,"总金额"], [11,"均价"], [12,"日涨跌"], [13,"振幅"], [14,"涨幅"], [15,"开盘时的成交金额"], [16,"前5日每分钟均量"], [17,"量比"], [18,"上涨家数"], [19,"下跌家数"] ]); var id=args[0]; if (DATA_NAME_MAP.has(id)) return DATA_NAME_MAP.get(id); return `即时行情[${id}]`; } this.GetFinanceExplain=function(args) { const DATA_NAME_MAP=new Map( [ [1,"总股本"], [2,"市场类型"], [3,"沪深品种类型"], [4,"沪深行业代码"], [5,"B股"], [6,"H股"], [7,"流通股本[股]"], [8,"股东人数[户]"], [9,"资产负债率%"], [10,"总资产"], [11,"流动资产"], [12,"固定资产"], [13,"无形资产"], [15,"流动负债"], [16,"少数股东权益"] ]); var id=args[0]; if (DATA_NAME_MAP.has(id)) return DATA_NAME_MAP.get(id); return `财务数据[${id}]`; } this.GetZIGExplain=function(funcName,args) { var value=args[0]; if (value==0) value="开盘价"; else if (value==1) value="最高价"; else if (value==2) value="最低价"; else if (value==3) value="收盘价"; switch(funcName) { case "PEAK": return `${value}的${args[1]}%之字转向的前${args[2]}个波峰值`; case "PEAKBARS": return `${value}的${args[1]}5%之字转向的前${args[2]}个波峰位置`; case "ZIG": return `${value}的${args[1]}的之字转向`; case "ZIGA": return `${value}变化${args[1]}的之字转向`; case "TROUGH": return `${value}的${args[1]}%之字转向的前${args[2]}个波谷值`; case "TROUGHBARS": return `${value}的${args[1]}%之字转向的前${args[2]}个波谷位置`; } } this.GetColorExplain=function(colorName) { const COLOR_MAP=new Map( [ ['COLORBLACK','黑色'],['COLORBLUE','蓝色'],['COLORGREEN','绿色'],['COLORCYAN','青色'],['COLORRED','红色'], ['COLORMAGENTA','洋红色'],['COLORBROWN','棕色'],['COLORLIGRAY','淡灰色'],['COLORGRAY','深灰色'],['COLORLIBLUE','淡蓝色'], ['COLORLIGREEN','淡绿色'],['COLORLICYAN','淡青色'],['COLORLIRED','淡红色'],['COLORLIMAGENTA','淡洋红色'],['COLORWHITE','白色'],['COLORYELLOW','黄色'] ]); if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName); //COLOR 自定义色 //格式为COLOR+“RRGGBB”:RR、GG、BB表示红色、绿色和蓝色的分量,每种颜色的取值范围是00-FF,采用了16进制。 //例如:MA5:MA(CLOSE,5),COLOR00FFFF 表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。 if (colorName.indexOf('COLOR')==0) return '#'+colorName.substr(5); return 'rgb(30,144,255)'; } this.GetLineWidthExplain=function(lineWidth) { var width=parseInt(lineWidth.replace("LINETHICK","")); if (IFrameSplitOperator.IsPlusNumber(width)) return width; return 1; } this.SymbolPeriodExplain=function(valueName,period) { const mapStockDataName=new Map( [ ['CLOSE',"收盘价"],["C","收盘价"],['VOL',"成交量"],['V',"成交量"], ['OPEN',"开盘价"], ['O',"开盘价"], ['HIGH',"最高价"],['H',"最高价"], ['LOW',"最低价"],['L',"最低价"],['AMOUNT',"成交金额"],['AMO',"成交金额"], ['VOLINSTK',"持仓量"] ]); //MIN1,MIN5,MIN15,MIN30,MIN60,DAY,WEEK,MONTH,SEASON,YEAR const mapPeriodName=new Map( [ ["MIN1","1分钟"], ["MIN5", "5分钟"], ["MIN15", "15分钟"], ["MIN30","30分钟"],["MIN60","60分钟"], ["DAY","日"],["WEEK","周"], ["MONTH", "月"], ['SEASON',"季"], ["YEAR", "年"],["WEEK2","双周"], ["HALFYEAR", "半年"] ]); var dataName=valueName; if (mapStockDataName.has(valueName)) dataName=mapStockDataName.get(valueName); var periodName=period; if (mapPeriodName.has(period)) periodName=mapPeriodName.get(period); return `${dataName}[取${periodName}数据]`; } this.GetOtherSymbolExplain=function(obj, node) { const mapStockDataName=new Map( [ ['CLOSE',"收盘价"],["C","收盘价"],['VOL',"成交量"],['V',"成交量"], ['OPEN',"开盘价"], ['O',"开盘价"], ['HIGH',"最高价"],['H',"最高价"], ['LOW',"最低价"],['L',"最低价"],['AMOUNT',"成交金额"],['AMO',"成交金额"], ['VOLINSTK',"持仓量"] ]); if (obj.FunctionName) { var args=obj.Args; var dataName=mapStockDataName.get(obj.FunctionName); return `[${args[0]}]${dataName}`; } else if (obj.Literal) { var value=obj.Literal.toUpperCase(); var args=value.split("$"); if (!mapStockDataName.has(args[1])) return ""; var symbol=args[0]; var dataName=mapStockDataName.get(args[1]); return `[${symbol}]${dataName}`; } } this.IsDrawFunction=function(name) { let setFunctionName=new Set( [ "STICKLINE","DRAWTEXT",'SUPERDRAWTEXT','DRAWLINE','DRAWBAND','DRAWKLINE',"DRAWKLINE1",'DRAWKLINE_IF','PLOYLINE', 'POLYLINE','DRAWNUMBER',"DRAWNUMBER_FIX",'DRAWICON','DRAWCHANNEL','PARTLINE','DRAWTEXT_FIX','DRAWGBK','DRAWTEXT_LINE','DRAWRECTREL',"DRAWTEXTABS", 'DRAWOVERLAYLINE',"FILLRGN", "FILLRGN2","FILLTOPRGN", "FILLBOTTOMRGN", "FILLVERTICALRGN","FLOATRGN","DRAWSL", "DRAWGBK2", "BUY","BUYSHORT","SELL","SELLSHORT", ]); if (setFunctionName.has(name)) return true; return false; } //赋值 this.VisitAssignmentExpression=function(node) { let left=node.Left; if (left.Type!=Syntax.Identifier) this.ThrowUnexpectedNode(node); let varName=left.Name; let right=node.Right; let value=null; if (right.Type==Syntax.BinaryExpression || right.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(right); else if (right.Type==Syntax.CallExpression) value=this.VisitCallExpression(right); else if (right.Type==Syntax.Literal) { value=right.Value; if (IFrameSplitOperator.IsString(value) && right.Value.indexOf("$")>0) value=this.GetOtherSymbolExplain({ Literal:value }, node); } else if (right.Type==Syntax.Identifier) //右值是变量 value=this.ReadVariable(right.Name,right); else if (right.Type==Syntax.MemberExpression) value=this.ReadMemberVariable(right); else if (right.Type==Syntax.UnaryExpression) value=this.VisitUnaryExpression(right); if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExplainer::VisitAssignmentExpression]' , varName, ' = ',value); this.VarTable.set(varName,this.ConvertToShortValue(value)); } this.ConvertToShortValue=function(value) { var maxLength=this.MaxValueLength; if (value && value.length>=maxLength) { var shortValue=value.slice(0, maxLength-10); shortValue+="......"; return shortValue; } return value; } this.ReadMemberVariable=function(node) { var obj=node.Object; var member=node.Property; let maiObj; if (obj.Type==Syntax.BinaryExpression || obj.Type==Syntax.LogicalExpression ) maiObj=this.VisitBinaryExpression(obj); else if (obj.Type==Syntax.CallExpression) maiObj=this.VisitCallExpression(obj); else { if (member.Name.indexOf('#')>0) { var aryValue=member.Name.split("#"); var value=`${obj.Name}的${aryValue[0]}[周期${aryValue[1]}]`; } else { var value=`${obj.Name}的${member.Name}`; } return value; } if (!maiObj) return null; var value=maiObj[member.Name]; if (value) return value; return null; } //逻辑运算 this.VisitBinaryExpression=function(node) { let stack=[]; stack.push(node); let temp=null; while(stack.length!=0) { temp=stack[stack.length-1]; if (temp.Left && node!=temp.Left && node!=temp.Right) { stack.push(temp.Left); } else if (temp.Right && node!=temp.Right) { stack.push(temp.Right); } else { let value=stack.pop(); if (value.Type==Syntax.BinaryExpression) //只遍历操作符就可以 { let leftValue=this.GetNodeValue(value.Left); let rightValue=this.GetNodeValue(value.Right); if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] BinaryExpression',value , leftValue, rightValue); value.Out=null; //保存中间值 value.Out=`(${leftValue} ${value.Operator} ${rightValue})`; if (leftValue=="收盘价" && rightValue=="开盘价") { if (value.Operator==">") value.Out='(收阳线)'; else if (value.Operator=="<") value.Out='(收阴线)'; else if (value.Operator=="=") value.Out='(平盘)'; } else if (leftValue=="开盘价" && rightValue=="收盘价") { if (value.Operator=="<") value.Out='(收阳线)'; else if (value.Operator==">") value.Out='(收阴线)'; else if (value.Operator=="=") value.Out='(平盘)'; } if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] BinaryExpression',value); } else if (value.Type==Syntax.LogicalExpression) { let leftValue=this.GetNodeValue(value.Left); let rightValue=this.GetNodeValue(value.Right); if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExecute::VisitBinaryExpression] LogicalExpression',value , leftValue, rightValue); value.Out=null; //保存中间值 switch(value.Operator) { case '&&': case 'AND': value.Out=`(${leftValue} 并且 ${rightValue})`; break; case '||': case 'OR': value.Out=`(${leftValue} 或者 ${rightValue})`; break; } if (JS_EXECUTE_DEBUG_LOG) JSConsole.Complier.Log('[JSExplainer::VisitBinaryExpression] LogicalExpression',value); } node=temp; } } return node.Out; } this.GetNodeValueEx=function(node) { var value=null; if (node.Type==Syntax.BinaryExpression || node.Type==Syntax.LogicalExpression) value=this.VisitBinaryExpression(node); else if (node.Type==Syntax.CallExpression) value=this.VisitCallExpression(node); else value=this.GetNodeValue(node); return value; } this.GetNodeValue=function(node) { switch(node.Type) { case Syntax.Literal: //数字 return node.Value; case Syntax.UnaryExpression: return this.VisitUnaryExpression(node); case Syntax.Identifier: let value=this.ReadVariable(node.Name,node); return value; case Syntax.BinaryExpression: case Syntax.LogicalExpression: return node.Out; case Syntax.CallExpression: return this.VisitCallExpression(node); default: this.ThrowUnexpectedNode(node); } } //读取变量 this.ReadVariable=function(name,node) { if (this.ConstVarTable.has(name)) { let data=this.ConstVarTable.get(name); return data; } if (g_JSComplierResource.IsCustomVariant(name)) { var variantInfo=g_JSComplierResource.CustomVariant.Data.get(name); //读取自定义变量 if (variantInfo.Description) return variantInfo.Description; else return name; } if (this.VarTable.has(name)) return this.VarTable.get(name); if (name.indexOf('#')>0) { var aryPeriod=name.split('#'); return this.SymbolPeriodExplain(aryPeriod[0],aryPeriod[1]); } if (name=="AUTOFILTER") //信号过滤 { return this.AUTOFILTER(); } this.ThrowUnexpectedNode(node, '变量'+name+'不存在'); return name; } this.AUTOFILTER=function() { //TODO:过滤信号 return null; } this.ThrowUnexpectedNode=function(node,message) { let marker=node.Marker; let msg=message || "执行异常"; return this.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg); } this.ThrowError=function() { } } //对外导出类 function JSComplier() { } //词法分析 JSComplier.Tokenize=function(code) { JSConsole.Complier.Log('[JSComplier.Tokenize]', code); let tokenizer=new Tokenizer(code); let tokens=[]; try { while(true) { let token=tokenizer.GetNextToken(); if (!token) break; tokens.push(token); } } catch(e) { } return tokens; } //语法解析 生成抽象语法树(Abstract Syntax Tree) JSComplier.Parse=function(code) { JSConsole.Complier.Log('[JSComplier.Parse]',code); let parser=new JSParser(code); parser.Initialize(); let program=parser.ParseScript(); let ast=program; return ast; } /* 执行 option.Symbol=股票代码 option.Name=股票名称 option.Data=这个股票的ChartData option.Right=复权 option.MaxRequestDataCount=请求数据的最大个数 */ function timeout(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } JSComplier.Execute=function(code,option,errorCallback) { //异步调用 //var asyncExecute= async function() es5不能执行 去掉异步 var asyncExecute= function() { try { if (option.Self) option.Self.Status=1; JSConsole.Complier.Log('[JSComplier.Execute]',code,option); JSConsole.Complier.Log('[JSComplier.Execute] parser .....'); let parser=new JSParser(code); parser.Initialize(); let program=parser.ParseScript(); let ast=program; JSConsole.Complier.Log('[JSComplier.Execute] parser finish.', ast); if (option.Self) option.Self.Status=2; JSConsole.Complier.Log('[JSComplier.Execute] execute .....'); let execute=new JSExecute(ast,option); execute.ErrorCallback=errorCallback; //执行错误回调 execute.JobList=parser.Node.GetDataJobList(); if (option.ClassName=='ScriptIndexConsole' && !option.Data) execute.JobList.unshift({ID:JS_EXECUTE_JOB_ID.JOB_DOWNLOAD_SYMBOL_DATA}); execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT}); if (option.Self) option.Self.Status=3; let result=execute.Execute(); }catch(error) { JSConsole.Complier.Log(error); if (errorCallback) errorCallback(error, option.CallbackParam); if (option.Self) option.Self.Status=0; } } asyncExecute(); JSConsole.Complier.Log('[JSComplier.Execute] async execute.'); } JSComplier.Explain=function(code,option, errorCallback) { //异步调用 //var asyncExecute= async function() es5不能执行 去掉异步 var asyncExplain= function() { try { JSConsole.Complier.Log('[JSComplier.Explain]',code,option); JSConsole.Complier.Log('[JSComplier.Explain] parser .....'); let parser=new JSParser(code); parser.Initialize(); let program=parser.ParseScript(); let ast=program; JSConsole.Complier.Log('[JSComplier.Explain] parser finish.', ast); JSConsole.Complier.Log('[JSComplier.Explain] explain .....'); let execute=new JSExplainer(ast,option); execute.ErrorCallback=errorCallback; //执行错误回调 execute.JobList=parser.Node.GetDataJobList(); execute.JobList.push({ID:JS_EXECUTE_JOB_ID.JOB_RUN_SCRIPT}); let result=execute.Run(); }catch(error) { JSConsole.Complier.Log(error); if (errorCallback) errorCallback(error, option.CallbackParam); } } asyncExplain(); JSConsole.Complier.Log('[JSComplier.Explain] async explain.'); } JSComplier.SetDomain = function (domain, cacheDomain) //修改API地址 { if (domain) g_JSComplierResource.Domain = domain; if (cacheDomain) g_JSComplierResource.CacheDomain = cacheDomain; } JSComplier.AddIcon=function(obj) //添加一个obj={ID:, Text:, Color, Family: } { g_JSComplierResource.CustomDrawIcon.Data.set(obj.ID, obj); } JSComplier.AddFunction=function(obj) //添加函数 { Name:函数名, Description:描述信息, IsDownload:是否需要下载数据, Invoke:函数执行(可选) } { if (!obj || !obj.Name) return; var ID=obj.Name.toUpperCase(); g_JSComplierResource.CustomFunction.Data.set(ID, obj); } JSComplier.AddVariant=function(obj) //{ Name:变量名, Description:描述信息 } { if (!obj || !obj.Name) return; var ID=obj.Name.toUpperCase(); g_JSComplierResource.CustomVariant.Data.set(ID, obj); } JSComplier.ColorVarToRGB=function(colorName) { let COLOR_MAP=new Map( [ ['COLORBLACK','rgb(0,0,0)'], ['COLORBLUE','rgb(18,95,216)'], ['COLORGREEN','rgb(25,158,0)'], ['COLORCYAN','rgb(0,255,198)'], ['COLORRED','rgb(238,21,21)'], ['COLORMAGENTA','rgb(255,0,222)'], ['COLORBROWN','rgb(149,94,15)'], ['COLORLIGRAY','rgb(218,218,218)'], //画淡灰色 ['COLORGRAY','rgb(133,133,133)'], //画深灰色 ['COLORLIBLUE','rgb(94,204,255)'], //淡蓝色 ['COLORLIGREEN','rgb(183,255,190)'], //淡绿色 ['COLORLICYAN','rgb(154,255,242)'], //淡青色 ['COLORLIRED','rgb(255,172,172)'], //淡红色 ['COLORLIMAGENTA','rgb(255,145,241)'], //淡洋红色 ['COLORWHITE','rgb(255,255,255)'], //白色 ['COLORYELLOW','rgb(255,198,0)'] ]); if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName); //COLOR 自定义色 //格式为COLOR+“BBGGRR”:BB、GG、RR表示蓝色、绿色和红色的分量,每种颜色的取值范围是00-FF,采用了16进制。 //例如:MA5:MA(CLOSE,5),COLOR00FFFF表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。 if (colorName.indexOf('COLOR')==0) { var strColor=colorName.substr(5); if (strColor.length!=6) return null; var value=strColor.substr(0,2); var b=parseInt(value,16); value=strColor.substr(2,2); var g=parseInt(value,16); value=strColor.substr(4,2); var r=parseInt(value,16); return `rgb(${r},${g},${b})`; } //格式为RGBX+“RRGGBB”:RR、GG、BB表示红色、绿色和的蓝色分量,每种颜色的取值范围是00-FF,采用了16进制。 //例如:MA5:MA(CLOSE,5),RGBXFFFF00表示纯红色与纯绿色的混合色:RGBX008080表示淡蓝色和淡绿色的混合色。 if (colorName.indexOf("RGBX")==0) { var strColor=colorName.substr(4); if (strColor.length!=6) return null; var value=strColor.substr(0,2); var r=parseInt(value,16); value=strColor.substr(2,2); var g=parseInt(value,16); value=strColor.substr(4,2); var b=parseInt(value,16); return `rgb(${r},${g},${b})`; } return null; } var HQ_DATA_TYPE= { KLINE_ID:0, //K线 MINUTE_ID:2, //当日走势图 HISTORY_MINUTE_ID:3,//历史分钟走势图 MULTIDAY_MINUTE_ID:4,//多日走势图 }; // 图形指标名字 var SCRIPT_CHART_NAME= { OVERLAY_BARS:"OVERLAY_BARS", //叠加柱子图 KLINE_TABLE:"KLINE_TABLE", SCATTER_PLOT:"SCATTER_PLOT", //散点图 CLIP_COLOR_STICK:"CLIP_COLOR_STICK", //上下柱子 裁剪 } // 外部对接API指标数据及图形 function ScriptIndexChartFactory() { this.DataMap=new Map(); //["图形名字", {} ] this.Add=function(name, option) { this.DataMap.set(name, { MinuteFittingCallback:option.MinuteFittingCallback, KLineFittingCallback:option.KLineFittingCallback, CreateChartCallback:option.CreateChartCallback, FormatTitleCallback:option.FormatTitleCallback, } ); } this.Get=function(name) { if (!this.DataMap.has(name)) return null; return this.DataMap.get(name); } this.Has=function(name) { return this.DataMap.has(name); } } var g_ScriptIndexChartFactory=new ScriptIndexChartFactory(); //脚本指标 //name=指标名字 args=参数名字 参数值 function ScriptIndex(name,script,args,option) { this.newMethod=BaseIndex; //派生 this.newMethod(name); delete this.newMethod; this.ClassName="ScriptIndex"; this.Script=script; this.Arguments=[]; this.OutVar=[]; this.ID; //指标ID this.FloatPrecision=2; //小数位数 this.StringFormat; this.IsShowIndexTitle=true; //是否显示指标标题 this.KLineType=null; //K线显示类型 this.InstructionType; //五彩K线, 交易指标 this.YSpecificMaxMin=null; //最大最小值 this.YSplitScale=null; //固定刻度 this.Condition=null; //限制条件 this.OutName=null; //动态输出指标名字 this.YSplitType; //指标上锁配置信息 this.IsLocked=false; //是否锁住指标 this.LockCallback=null; this.LockID=null; this.LockBG=null; //锁背景色 this.LockTextColor=null; this.LockText=null; this.LockFont=null; this.LockCount=20; this.LockMinWidth=null; this.TitleFont=g_JSChartResource.TitleFont; //标题字体 this.IsShortTitle=false; //是否显示指标参数 this.IsUsePageData=false; //是否使用了K线界面数据 this.YAxis=null; //Y轴刻度设置 { FloatPrecision, StringFormat, EnableRemoveZero } //调试信息 this.Debug; // { Callback:, Count: } this.IsSync=false; //是否是同步计算 (无数据请求) this.IsShow=true; //是否显示图形 this.RunCount=0; //已执行次数 this.MaxRunCount=-1; //最大执行次数 -1=无限 if (option) { if (option.FloatPrecision>=0) this.FloatPrecision=option.FloatPrecision; if (option.StringFormat>0) this.StringFormat=option.StringFormat; if (IFrameSplitOperator.IsBool(option.IsShowIndexTitle)) this.IsShowIndexTitle=option.IsShowIndexTitle; if (option.ID) this.ID=option.ID; if (option.KLineType>=0 || option.KLineType===-1) this.KLineType=option.KLineType; if (option.InstructionType) this.InstructionType=option.InstructionType; if (option.YSpecificMaxMin) this.YSpecificMaxMin=option.YSpecificMaxMin; if (option.YSplitScale) this.YSplitScale=option.YSplitScale; if (option.Condition) this.Condition=option.Condition; if (option.TitleFont) this.TitleFont=option.TitleFont; if (option.IsShortTitle) this.IsShortTitle=option.IsShortTitle; if (option.OutName) this.OutName=option.OutName; if (IFrameSplitOperator.IsNumber(option.YSplitType)) this.YSplitType=option.YSplitType; if (IFrameSplitOperator.IsBool(option.IsSync)) this.IsSync=option.IsSync; if (IFrameSplitOperator.IsNumber(option.MaxRunCount)) this.MaxRunCount=option.MaxRunCount; if (option.Debug) { if (IFrameSplitOperator.IsPlusNumber(option.Debug.Count) && option.Debug.Callback) { this.Debug={ Count:option.Debug.Count, Callback:option.Debug.Callback } } } } if (option && option.Lock) { if (option.Lock.IsLocked==true) this.IsLocked=true; //指标上锁 if (option.Lock.Callback) this.LockCallback=option.Lock.Callback; //锁回调 if (option.Lock.ID) this.LockID=option.Lock.ID; //锁ID if (option.Lock.BG) this.LockBG=option.Lock.BG; if (option.Lock.TextColor) this.LockTextColor=option.Lock.TextColor; if (option.Lock.Text) this.LockText=option.Lock.Text; if (option.Lock.Font) this.LockFont=option.Lock.Font; if (option.Lock.Count) this.LockCount=option.Lock.Count; if (option.Lock.MinWidth) this.LockMinWidth=option.Lock.MinWidth*GetDevicePixelRatio(); } if (option && option.YAxis) { this.YAxis={ }; if (IFrameSplitOperator.IsNumber(option.YAxis.FloatPrecision)) this.YAxis.FloatPrecision=option.YAxis.FloatPrecision; if (IFrameSplitOperator.IsNumber(option.YAxis.StringFormat)) this.YAxis.StringFormat=option.YAxis.StringFormat; if (IFrameSplitOperator.IsBool(option.YAxis.EnableRemoveZero)) this.YAxis.EnableRemoveZero=option.YAxis.EnableRemoveZero; if (IFrameSplitOperator.IsBool(option.YAxis.ExcludeValue)) this.YAxis.ExcludeValue=option.YAxis.ExcludeValue; //不参数Y轴的计算 } if (args) this.Arguments=args; this.CopyTo=function(dest) //赋值到新实例出来 { dest.FloatPrecision=this.FloatPrecision; dest.StringFormat=this.StringFormat; dest.KLineType=this.KLineType; dest.InstructionType=this.InstructionType; dest.Condition=this.Condition; dest.TitleFont=this.TitleFont; dest.IsShortTitle=this.IsShortTitle; dest.OutName=this.OutName; dest.Arguments=this.Arguments; dest.Script=this.Script; dest.Name=this.Name; dest.ID=this.ID; } this.SetLock=function(lockData) { if (lockData.IsLocked==true) { this.IsLocked=true; //指标上锁 if (lockData.Callback) this.LockCallback=lockData.Callback; //锁回调 if (lockData.ID) this.LockID=lockData.ID; //锁ID if (lockData.BG) this.LockBG=lockData.BG; if (lockData.TextColor) this.LockTextColor=lockData.TextColor; if (lockData.Text) this.LockText=lockData.Text; if (lockData.Font) this.LockFont=lockData.Font; if (lockData.Count) this.LockCount=lockData.Count; if (lockData.MinWidth) this.LockMinWidth=lockData.MinWidth*GetDevicePixelRatio(); } else { //清空锁配置信息 this.IsLocked=false; //是否锁住指标 this.LockCallback=null; this.LockID=null; this.LockBG=null; //锁背景色 this.LockTextColor=null; this.LockText=null; this.LockFont=null; this.LockCount=20; } } //是否超出执行的最大次数 this.IsExcessRunCount=function() { if (this.MaxRunCount<0) return false; //没有限制 return this.RunCount>=this.MaxRunCount; } this.ExecuteScript=function(hqChart,windowIndex,hisData) { this.OutVar=[]; let self = this; let param= { HQChart:hqChart, WindowIndex:windowIndex, HistoryData:hisData, Self:this }; //数据类型 let hqDataType=HQ_DATA_TYPE.KLINE_ID; //默认K线 if (hqChart.ClassName==='MinuteChartContainer' || hqChart.ClassName==='MinuteChartHScreenContainer') { if (hqChart.DayCount>1) hqDataType=HQ_DATA_TYPE.MULTIDAY_MINUTE_ID; //多日分钟 else hqDataType=HQ_DATA_TYPE.MINUTE_ID; //分钟数据 } else if (hqChart.ClassName==='HistoryMinuteChartContainer') { hqDataType=HQ_DATA_TYPE.HISTORY_MINUTE_ID; //历史分钟 } let option= { HQDataType:hqDataType, Symbol:hqChart.Symbol, Name:hqChart.Name, Data:hisData, SourceData:hqChart.SourceData, Callback:this.RecvResultData, CallbackParam:param, Async:true, MaxRequestDataCount:hqChart.MaxRequestDataCount, MaxRequestMinuteDayCount:hqChart.MaxRequestMinuteDayCount, Arguments:this.Arguments, Condition:this.Condition, IsBeforeData:hqChart.IsBeforeData, IsApiPeriod:hqChart.IsApiPeriod, DrawInfo:null, Self:this, }; if (this.Debug && IFrameSplitOperator.IsPlusNumber(this.Debug.Count) && this.Debug.Callback) { --this.Debug.Count; option.Debug=1; option.DebugFilter=this.Debug.Callback; } if (hqChart) //当前屏K线信息 { if (hqChart.ChartPaint[0]) { var item=hqChart.ChartPaint[0]; if (item && item.DrawKRange) option.DrawInfo={Start:item.DrawKRange.Start, End:item.DrawKRange.End }; } } if (hqDataType===HQ_DATA_TYPE.HISTORY_MINUTE_ID) option.TrateDate=hqChart.TradeDate; if (hqDataType===HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) option.DayCount=hqChart.DayCount; if (hqChart.NetworkFilter) option.NetworkFilter=hqChart.NetworkFilter; if (this.Condition && !this.IsMeetCondition(param,option)) { this.ShowConditionError(param, this.Condition.Message); return; } ++this.RunCount; let code=this.Script; let run=JSComplier.Execute(code,option,hqChart.ScriptErrorCallback); } //是否符合限制条件 this.IsMeetCondition=function(param,option) { JSConsole.Complier.Log('[ScriptIndex::IsMeetCondition] ', this.Condition); if (this.Condition.Period) //周期是否满足 { if (!this.IsMeetPeriodCondition(param,option)) return false; if (!this.IsMeetIncludeCondition(param,option)) return false; } return true; } //周期是否满足条件 this.IsMeetPeriodCondition=function(param,option) { if (!this.Condition.Period) return true; for(var i in this.Condition.Period) { var item=this.Condition.Period[i]; switch(item) { case CONDITION_PERIOD.MINUTE_ID: if (option.HQDataType==HQ_DATA_TYPE.MINUTE_ID) return true; break; case CONDITION_PERIOD.MULTIDAY_MINUTE_ID: if (option.HQDataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) return true; break; case CONDITION_PERIOD.KLINE_DAY_ID: case CONDITION_PERIOD.KLINE_WEEK_ID: case CONDITION_PERIOD.KLINE_MONTH_ID: case CONDITION_PERIOD.KLINE_YEAR_ID: case CONDITION_PERIOD.KLINE_TWOWEEK_ID: case CONDITION_PERIOD.KLINE_QUARTER_ID: case CONDITION_PERIOD.KLINE_MINUTE_ID: case CONDITION_PERIOD.KLINE_5_MINUTE_ID: case CONDITION_PERIOD.KLINE_15_MINUTE_ID: case CONDITION_PERIOD.KLINE_30_MINUTE_ID: case CONDITION_PERIOD.KLINE_60_MINUTE_ID: if (param.HQChart.Period==item) return true; break; } } return false; } this.IsMeetIncludeCondition=function(param,option) { if (!this.Condition.Include || this.Condition.Include.length<=0) return true; var symbol=param.HQChart.Symbol; if (symbol) symbol=symbol.toUpperCase(); for(var i in this.Condition.Include) { var item=this.Condition.Include[i]; if (symbol==item) return true; } return false; } //显示指标不符合条件 this.ShowConditionError=function(param,msg) { var hqChart=param.HQChart; var windowIndex=param.WindowIndex; hqChart.DeleteIndexPaint(windowIndex); if (windowIndex==0) hqChart.ShowKLine(true); var message='指标不支持当前品种或周期'; if (msg) message=msg; let line=new ChartLine(); line.Canvas=hqChart.Canvas; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; line.NotSupportMessage=message; hqChart.ChartPaint.push(line); hqChart.UpdataDataoffset(); //更新数据偏移 hqChart.UpdateFrameMaxMin(); //调整坐标最大 最小值 hqChart.Draw(); } this.RecvResultData=function(outVar,param) { let hqChart=param.HQChart; let windowIndex=param.WindowIndex; let hisData=param.HistoryData; param.Self.OutVar=outVar; param.Self.BindData(hqChart,windowIndex,hisData); if (param.Self.IsLocked==false) //不上锁 { param.HQChart.Frame.SubFrame[windowIndex].Frame.SetLock(null); } else //上锁 { let lockData={ IsLocked:true,Callback:param.Self.LockCallback,IndexName:param.Self.Name ,ID:param.Self.LockID, BG:param.Self.LockBG,Text:param.Self.LockText,TextColor:param.Self.LockTextColor, Font:param.Self.LockFont, Count:param.Self.LockCount, MinWidth:param.Self.LockMinWidth }; param.HQChart.Frame.SubFrame[windowIndex].Frame.SetLock(lockData); } param.HQChart.UpdataDataoffset(); //更新数据偏移 param.HQChart.UpdateFrameMaxMin(); //调整坐标最大 最小值 if (param.Self.IsSync===false) //异步需要马上刷新,同步主图数据更新的时候会刷新的 param.HQChart.Draw(); if (hqChart.GetIndexEvent) { var event=hqChart.GetIndexEvent(); //指标计算完成回调 if (event) { var self=param.Self; var data={ OutVar:self.OutVar, WindowIndex: windowIndex, Name: self.Name, Arguments: self.Arguments, HistoryData: hisData, Stock: {Symbol:hqChart.Symbol,Name:hqChart.Name} }; event.Callback(event,data,self); } } } //给图形设置指标名字 this.SetChartIndexName=function(chart) { if (this.Name) chart.IndexName=this.Name; else if (this.ID) chart.IndexName==this.ID; if (this.ID) chart.IndexID=this.ID; if (this.YAxis) { if (IFrameSplitOperator.IsBool(this.YAxis.ExcludeValue)) chart.IsExcludeYValue=this.YAxis.ExcludeValue; } chart.Script=this; //指标内容绑定上去 } //设置标题数据 this.SetTitleData=function(titleData, chart) { titleData.ChartClassName=chart.ClassName; titleData.IsVisible=chart.IsVisible; } //自定义图形配色 this.ReloadChartResource=function(hqChart, windowIndex, chart) { var event=hqChart.GetEventCallback(JSCHART_EVENT_ID.ON_RELOAD_INDEX_CHART_RESOURCE); //指标计算完成回调 if (!event || !event.Callback) return; var sendData={ Chart:chart, IndexName:this.Name,IndexID:this.ID, HQChart:hqChart, WindowIndex:windowIndex }; event.Callback(event,sendData,this); } this.CreateLine=function(hqChart,windowIndex,varItem, id, lineType) { if (lineType==7) var line=new ChartStepLine(); else var line=new ChartLine(); line.Canvas=hqChart.Canvas; line.DrawType=1; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; line.Identify=this.Guid; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (lineType==8) { line.DrawType=2; line.BreakPoint=varItem.BreakPoint; } if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) line.LineWidth=width; } if (varItem.IsDotLine) { line.IsDotLine=true; //虚线 line.LineDash=g_JSChartResource.DOTLINE.LineDash.slice(); } //虚线设置 if (IFrameSplitOperator.IsNonEmptyArray(varItem.LineDash)) line.LineDash=varItem.LineDash; if (varItem.IsShow==false) line.IsShow=false; let titleIndex=windowIndex+1; line.Data.Data=varItem.Data; this.ReloadChartResource(hqChart,windowIndex,line); if (varItem.IsShowTitle===false) //NOTEXT 不绘制标题 { } else if (IFrameSplitOperator.IsString(varItem.Name) && varItem.Name.indexOf("NOTEXT")==0) //标题中包含NOTEXT不绘制标题 { } else { if (varItem.NoneName) hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,null,line.Color); else hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); this.SetTitleData(hqChart.TitlePaint[titleIndex].Data[id],line); } this.SetChartIndexName(line); hqChart.ChartPaint.push(line); } this.CreateArea=function(hqChart, windowIndex, varItem, id,) { var line=new ChartArea(); line.Canvas=hqChart.Canvas; line.DrawType=1; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; line.Identify=this.Guid; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (varItem.DownColor) { line.AreaColor=varItem.DownColor; } else if (varItem.UpColor) { line.AreaColor=varItem.UpColor; line.AreaDirection=1; } if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (IFrameSplitOperator.IsPlusNumber(width)) line.LineWidth=width; } if (IFrameSplitOperator.IsNonEmptyArray(varItem.LineDash)) line.LineDash=varItem.LineDash; //虚线 if (varItem.IsShow==false) line.IsShow=false; let titleIndex=windowIndex+1; line.Data.Data=varItem.Data; if (varItem.IsShowTitle===false) //NOTEXT 不绘制标题 { } else if (IFrameSplitOperator.IsString(varItem.Name) && varItem.Name.indexOf("NOTEXT")==0) //标题中包含NOTEXT不绘制标题 { } else { if (varItem.NoneName) hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,null,line.Color); else hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); hqChart.TitlePaint[titleIndex].Data[id].ChartClassName=line.ClassName; } this.SetChartIndexName(line); hqChart.ChartPaint.push(line); } this.CreateOverlayLine=function(hqChart,windowIndex,varItem,id,lineType) { if (lineType==7) var line=new ChartStepLine(); var line=new ChartSubLine(); line.Canvas=hqChart.Canvas; line.DrawType=1; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) line.LineWidth=width; } if (varItem.IsDotLine) line.IsDotLine=true; //虚线 if (varItem.IsShow==false) line.IsShow=false; let titleIndex=windowIndex+1; line.Data.Data=varItem.Data; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); hqChart.TitlePaint[titleIndex].Data[id].ChartClassName=line.ClassName; hqChart.ChartPaint.push(line); } this.CreateSingleLine=function(hqChart,windowIndex,varItem,id,lineType) { var line=new ChartSingleLine(); line.Canvas=hqChart.Canvas; line.DrawType=1; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; line.Identify=this.Guid; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) line.LineWidth=width; } if (varItem.IsDotLine) line.IsDotLine=true; //虚线 if (varItem.IsShow==false) line.IsShow=false; let titleIndex=windowIndex+1; line.Data.Data=varItem.Data; this.ReloadChartResource(hqChart,windowIndex,line); if (varItem.IsShowTitle===false) //NOTEXT 不绘制标题 { } else if (IFrameSplitOperator.IsString(varItem.Name) && varItem.Name.indexOf("NOTEXT")==0) //标题中包含NOTEXT不绘制标题 { } else { if (varItem.NoneName) hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,null,line.Color); else hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); this.SetTitleData(hqChart.TitlePaint[titleIndex].Data[id],line); } this.SetChartIndexName(line); hqChart.ChartPaint.push(line); } //创建柱子 this.CreateBar=function(hqChart,windowIndex,varItem,id) { let bar=new ChartStickLine(); bar.Canvas=hqChart.Canvas; if (varItem.Draw.Width>0) bar.Width=varItem.Draw.Width; else bar.Width=0; bar.Name=varItem.Name; bar.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; bar.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) bar.Color=this.GetColor(varItem.Color); else bar.Color=this.GetDefaultColor(id); let titleIndex=windowIndex+1; bar.Data.Data=varItem.Draw.DrawData; bar.BarType=varItem.Draw.Type; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(bar); hqChart.ChartPaint.push(bar); } //创建文本 this.CreateText=function(hqChart,windowIndex,varItem,id,resource) { let chartText=new ChartSingleText(); chartText.Canvas=hqChart.Canvas; chartText.Name=varItem.Name; chartText.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartText.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chartText.ReloadResource(); if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else chartText.Color=this.GetDefaultColor(id); if (varItem.IsDrawCenter===true) chartText.TextAlign='center'; if (varItem.IsDrawAbove===true) chartText.Direction=1; if (varItem.IsDrawBelow===true) chartText.Direction=2; let titleIndex=windowIndex+1; if (varItem.Draw.Position) chartText.Position=varItem.Draw.Position; //赋值坐标 if (varItem.Draw.DrawData) chartText.Data.Data=varItem.Draw.DrawData; chartText.Text=varItem.Draw.Text; if (varItem.Draw.Direction>0) chartText.Direction=varItem.Draw.Direction; if (varItem.Draw.YOffset>0) chartText.YOffset=varItem.Draw.YOffset; if (varItem.Draw.TextAlign) chartText.TextAlign=varItem.Draw.TextAlign; if (varItem.DrawVAlign>=0) { if (varItem.DrawVAlign==0) chartText.Direction=1; else if (varItem.DrawVAlign==1) chartText.Direction=0; else if (varItem.DrawVAlign==2) chartText.Direction=2; } if (varItem.DrawAlign>=0) { if (varItem.DrawAlign==0) chartText.TextAlign="left"; else if (varItem.DrawAlign==1) chartText.TextAlign="center"; else if (varItem.DrawAlign==2) chartText.TextAlign='right'; } if (varItem.DrawFontSize>0) chartText.FixedFontSize=varItem.DrawFontSize; if (varItem.Background) chartText.TextBG=varItem.Background; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } //DRAWNUMBER this.CreateDrawNumber=function(hqChart,windowIndex,varItem,id) { var chartText=new ChartDrawNumber(); chartText.Canvas=hqChart.Canvas; chartText.Name=varItem.Name; chartText.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartText.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chartText.ReloadResource(); if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else chartText.Color=this.GetDefaultColor(id); if (varItem.IsDrawCenter===true) chartText.TextAlign='center'; if (varItem.IsDrawAbove===true) chartText.TextBaseline='bottom' if (varItem.IsDrawBelow===true) chartText.TextBaseline='top'; chartText.Data.Data=varItem.Draw.DrawData.Value; chartText.Text=varItem.Draw.DrawData.Text; if (varItem.Draw.Direction>0) chartText.Direction=varItem.Draw.Direction; if (varItem.Draw.YOffset>0) chartText.YOffset=varItem.Draw.YOffset; if (varItem.Draw.TextAlign) chartText.TextAlign=varItem.Draw.TextAlign; //指定输出位置 if (varItem.Draw.FixedPosition==="TOP") chartText.FixedPosition=1; else if (varItem.Draw.FixedPosition==="BOTTOM") chartText.FixedPosition=2; if (varItem.DrawVAlign>=0) { if (varItem.DrawVAlign==0) chartText.TextBaseline='top'; else if (varItem.DrawVAlign==1) chartText.TextBaseline='middle'; else if (varItem.DrawVAlign==2) chartText.TextBaseline='bottom'; } if (varItem.DrawAlign>=0) { if (varItem.DrawAlign==0) chartText.TextAlign="left"; else if (varItem.DrawAlign==1) chartText.TextAlign="center"; else if (varItem.DrawAlign==2) chartText.TextAlign='right'; } if (varItem.DrawFontSize>0) chartText.FixedFontSize=varItem.DrawFontSize; if (varItem.Background) chartText.TextBG=varItem.Background; if (varItem.VerticalLine) chartText.VerticalLine=varItem.VerticalLine; let titleIndex=windowIndex+1; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); hqChart.ChartPaint.push(chartText); } //DRAWTEXT this.CreateDrawTextV2=function(hqChart,windowIndex,varItem,id) { var chartText=new ChartDrawText(); chartText.Canvas=hqChart.Canvas; chartText.Name=varItem.Name; chartText.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartText.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chartText.ReloadResource(); if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else chartText.Color=this.GetDefaultColor(id); if (varItem.IsDrawCenter===true) chartText.TextAlign='center'; if (varItem.IsDrawAbove===true) chartText.TextBaseline='bottom' if (varItem.IsDrawBelow===true) chartText.TextBaseline='top'; if (varItem.Draw.DrawData) chartText.Data.Data=varItem.Draw.DrawData; chartText.Text=varItem.Draw.Text; if (varItem.Draw.Direction>0) chartText.Direction=varItem.Draw.Direction; if (varItem.Draw.YOffset>0) chartText.YOffset=varItem.Draw.YOffset; if (varItem.Draw.TextAlign) chartText.TextAlign=varItem.Draw.TextAlign; //指定输出位置 if (varItem.Draw.FixedPosition==="TOP") chartText.FixedPosition=1; else if (varItem.Draw.FixedPosition==="BOTTOM") chartText.FixedPosition=2; if (varItem.DrawVAlign>=0) { if (varItem.DrawVAlign==0) chartText.TextBaseline='top'; else if (varItem.DrawVAlign==1) chartText.TextBaseline='middle'; else if (varItem.DrawVAlign==2) chartText.TextBaseline='bottom'; } if (varItem.DrawAlign>=0) { if (varItem.DrawAlign==0) chartText.TextAlign="left"; else if (varItem.DrawAlign==1) chartText.TextAlign="center"; else if (varItem.DrawAlign==2) chartText.TextAlign='right'; } if (varItem.DrawFontSize>0) chartText.FixedFontSize=varItem.DrawFontSize; if (varItem.Background) chartText.TextBG=varItem.Background; if (varItem.VerticalLine) chartText.VerticalLine=varItem.VerticalLine; if (IFrameSplitOperator.IsNumber(varItem.YOffset)) chartText.ShowOffset.Y=varItem.YOffset; if (IFrameSplitOperator.IsNumber(varItem.XOffset)) chartText.ShowOffset.X=varItem.XOffset; let titleIndex=windowIndex+1; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } //COLORSTICK this.CreateMACD=function(hqChart,windowIndex,varItem,id) { let chartMACD=new ChartMACD(); chartMACD.Canvas=hqChart.Canvas; chartMACD.Identify=this.Guid; chartMACD.Name=varItem.Name; chartMACD.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartMACD.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.LineWidth) { var width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chartMACD.LineWidth=width; } let titleIndex=windowIndex+1; chartMACD.Data.Data=varItem.Data; var clrTitle=this.GetDefaultColor(id); if (varItem.Color) clrTitle=this.GetColor(varItem.Color); if (varItem.UpColor) chartMACD.UpColor=varItem.UpColor; if (varItem.DownColor) chartMACD.DownColor=varItem.DownColor; this.ReloadChartResource(hqChart,windowIndex,chartMACD); hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(chartMACD.Data,varItem.Name,clrTitle); this.SetChartIndexName(chartMACD); hqChart.ChartPaint.push(chartMACD); } this.CreatePointDot=function(hqChart,windowIndex,varItem,id, hisData) { let pointDot=new ChartPointDot(); pointDot.Canvas=hqChart.Canvas; pointDot.Name=varItem.Name; pointDot.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; pointDot.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) pointDot.Color=this.GetColor(varItem.Color); else pointDot.Color=this.GetDefaultColor(id); if (varItem.Radius) pointDot.Radius=varItem.Radius; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) pointDot.Radius=width; } if (IFrameSplitOperator.IsBool(varItem.UpDownDot)) { pointDot.EnableUpDownColor=varItem.UpDownDot; pointDot.HistoryData=hisData; } let titleIndex=windowIndex+1; pointDot.Data.Data=varItem.Data; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(pointDot.Data,varItem.Name,pointDot.Color); this.SetChartIndexName(pointDot); hqChart.ChartPaint.push(pointDot); } this.CreateStick=function(hqChart,windowIndex,varItem,id) { let chart=new ChartStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; this.ReloadChartResource(hqChart,windowIndex,chart); hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateLineStick=function(hqChart,windowIndex,varItem,id) { let chart=new ChartLineStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); hqChart.ChartPaint.push(chart); } this.CreateStraightLine=function(hqChart,windowIndex,varItem,id) { let line=new ChartLine(); line.DrawType=1; line.Canvas=hqChart.Canvas; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) line.LineWidth=width; } let titleIndex=windowIndex+1; line.Data.Data=varItem.Draw.DrawData; if (varItem.Name=="DRAWLINE") hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,null,line.Color); //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); hqChart.ChartPaint.push(line); } this.CreateVolStick=function(hqChart,windowIndex,varItem,id,hisData) { let chart=new ChartVolStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.KLineDrawType=hqChart.KLineDrawType; //设置K线显示类型 chart.Identify=this.Guid; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.UpColor) chart.UpColor=varItem.UpColor; if (varItem.DownColor) chart.DownColor=varItem.DownColor; if (IFrameSplitOperator.IsNumber(varItem.StickType)) chart.BarType=varItem.StickType; if (IFrameSplitOperator.IsNumber(varItem.BarColorType)) chart.BarColorType=varItem.BarColorType; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (IFrameSplitOperator.IsPlusNumber(width)) chart.BarWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; chart.HistoryData=hisData; this.ReloadChartResource(hqChart,windowIndex,chart); if (varItem.IsShowTitle===false) //NOTEXT 不绘制标题 { } else if (IFrameSplitOperator.IsString(varItem.Name) && varItem.Name.indexOf("NOTEXT")==0) //标题中包含NOTEXT不绘制标题 { } else { var titleData=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); hqChart.TitlePaint[titleIndex].Data[id]=titleData; this.SetTitleData(titleData,chart); } this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateBand=function(hqChart,windowIndex,varItem,id) { let chart=new ChartBand(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.FirstColor = varItem.Draw.Color[0]; chart.SecondColor = varItem.Draw.Color[1]; chart.Data.Data=varItem.Draw.DrawData; if (IFrameSplitOperator.IsBool(varItem.IsFirstDraw)) chart.IsDrawFirst=varItem.IsFirstDraw; var titleIndex=windowIndex+1; var titleData=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); titleData.DataType=chart.ClassName; titleData.ExtendData={ Color:[chart.FirstColor, chart.SecondColor] }; hqChart.TitlePaint[titleIndex].Data[id]=titleData; this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateFillRGN=function(hqChart,windowIndex,varItem,id) { let chart=new ChartLineArea(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); hqChart.ChartPaint.push(chart); } this.CreateFillRGN2=function(hqChart,windowIndex,varItem,id) { let chart=new ChartFillRGN(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData; hqChart.ChartPaint.push(chart); } this.CreateFillBGRGN=function(hqChart,windowIndex,varItem,id) { let chart=new ChartFillBGRGN(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData; hqChart.ChartPaint.push(chart); } this.CreateFLOATRGN=function(hqChart,windowIndex,varItem,id) { let chart=new ChartFLOATRGN(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData; hqChart.ChartPaint.push(chart); } //创建K线图 this.CreateKLine=function(hqChart,windowIndex,varItem,id) { let chart=new ChartKLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.Identify=this.Guid; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData; chart.IsShowMaxMinPrice=false; chart.IsShowKTooltip=false; if (IFrameSplitOperator.IsNumber(varItem.KLineType)) chart.DrawType=varItem.KLineType; if (varItem.Color) //如果设置了颜色,使用外面设置的颜色 chart.UnchagneColor=chart.DownColor=chart.UpColor=this.GetColor(varItem.Color); this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateOverlayKLine=function(hqChart,windowIndex,varItem,id) { var chart=null; if (hqChart.IsKLineContainer()) chart=new ChartOverlayKLine(); else if (hqChart.IsMinuteContainer()) chart=new ChartOverlayMinutePriceLine(); else return; chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.Identify=this.Guid; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); //如果设置了颜色,使用外面设置的颜色 else chart.Color=this.GetDefaultColor(id); chart.Data.Data=varItem.Draw.DrawData; chart.MainData=hqChart.ChartPaint[0].Data;//绑定K线 hqChart.ChartPaint.push(chart); } this.CreateDrawColorKLine=function(hqChart,windowIndex,varItem,i) { let chart=new ChartColorKline(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.DrawName="DRAWCOLORKLINE"; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData; if (IFrameSplitOperator.IsBool(varItem.Draw.IsEmptyBar)) chart.IsEmptyBar=varItem.Draw.IsEmptyBar; if (varItem.Draw.Color) chart.Color=varItem.Draw.Color; hqChart.ChartPaint.push(chart); } this.CreatePolyLine=function(hqChart,windowIndex,varItem,id) { let line=new ChartLine(); line.Canvas=hqChart.Canvas; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (varItem.IsDotLine) line.IsDotLine=true; //虚线 if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) line.LineWidth=width; } let titleIndex=windowIndex+1; line.Data.Data=varItem.Draw.DrawData; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,' ',line.Color); //给一个空的标题 hqChart.ChartPaint.push(line); } this.CreateChartSlopeLine=function(hqChart,windowIndex,varItem,id) { let line=new ChartSlopeLine(); line.Canvas=hqChart.Canvas; line.Name=varItem.Name; line.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; line.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) line.Color=this.GetColor(varItem.Color); else line.Color=this.GetDefaultColor(id); if (varItem.IsDotLine) line.IsDotLine=true; //虚线 if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) line.LineWidth=width; } let titleIndex=windowIndex+1; line.Data.Data=varItem.Draw.DrawData.Data; line.Option=varItem.Draw.DrawData.Option; hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,null,line.Color); //给一个空的标题 hqChart.ChartPaint.push(line); } this.CreateChartVericaltLine=function(hqChart,windowIndex,varItem,id) { var chart=new ChartVericaltLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } this.SetChartLineDash(chart,varItem.Draw.DrawData); chart.Data.Data=varItem.Draw.DrawData.Data; hqChart.ChartPaint.push(chart); } this.SetChartLineDash=function(chart, option) { if (IFrameSplitOperator.IsNumber(option.LineType)) { var lineType=option.LineType; var pixelRatio=GetDevicePixelRatio(); switch(lineType) { case 1: chart.LineType=[10*pixelRatio,10*pixelRatio]; break; case 2: chart.LineType=[0,10*pixelRatio]; chart.LineCap="square"; break; case 3: chart.LineType=[10*pixelRatio, 3*pixelRatio, 3*pixelRatio, 3*pixelRatio]; break; case 4: chart.LineType=[10*pixelRatio, 3*pixelRatio, 3*pixelRatio, 3*pixelRatio,3*pixelRatio,3*pixelRatio]; break; } } else if (IFrameSplitOperator.IsString(option.LineType)) { var aryString=option.LineType.split(','); var aryLinType=[]; for(var i=0;i0) chart.LineWidth=width; } this.SetChartLineDash(chart,varItem.Draw.DrawData); chart.ExtendType=varItem.Draw.DrawData.Extend; chart.Data.Data=varItem.Draw.DrawData.Data; hqChart.ChartPaint.push(chart); } this.CreateBackgroud=function(hqChart,windowIndex,varItem,id) { let chart=new ChartBackground(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Draw && varItem.Draw.DrawData) { var drawData=varItem.Draw.DrawData; chart.Color=drawData.Color; chart.ColorAngle=drawData.Angle; if (drawData.Data) chart.Data.Data=drawData.Data; } hqChart.ChartPaint.push(chart); } this.CreateBackgroundDiv=function(hqChart,windowIndex,varItem,id) { var chart=new ChartBackgroundDiv(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Draw && varItem.Draw.DrawData) { var drawData=varItem.Draw.DrawData; chart.AryColor=drawData.AryColor; chart.ColorType=drawData.ColorType; if (drawData.Data) chart.Data.Data=drawData.Data; } hqChart.ChartPaint.push(chart); } this.CreateLineMultiData=function(hqChart,windowIndex,varItem,id) { let chart=new ChartLineMultiData(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Draw && varItem.Draw.DrawData) { var drawData=varItem.Draw.DrawData; chart.Color=drawData.Color; if (drawData.PointColor) chart.PointColor=drawData.PointColor; if (IFrameSplitOperator.IsPlusNumber(drawData.PointRadius)) chart.PointRadius=drawData.PointRadius; if (IFrameSplitOperator.IsPlusNumber(drawData.LineWidth)) chart.LineWidth=drawData.LineWidth; if (drawData.Data) chart.Data.Data=drawData.Data; } let titleIndex=windowIndex+1; var titleData=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); //标题 titleData.DataType="MULTI_POINT_LINE"; hqChart.TitlePaint[titleIndex].Data[id]=titleData; hqChart.ChartPaint.push(chart); } this.CreateTradeIcon=function(hqChart,windowIndex,varItem,id) { var chart=new ChartTradeIcon(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data.Data=varItem.Draw.DrawData.Data; chart.AryIcon=varItem.Draw.DrawData.Icons; chart.TradeType=varItem.Draw.DrawType; //修改颜色 if (varItem.Color && IFrameSplitOperator.IsNonEmptyArray(chart.AryIcon)) { for(var i=0;i0) chart.SVG.Size=varItem.DrawFontSize*GetDevicePixelRatio(); //图标大小 hqChart.ChartPaint.push(chart); } this.CreateTextLine=function(hqChart,windowIndex,varItem,id) { let chart=new ChartTextLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Draw && varItem.Draw.DrawData) { var drawData=varItem.Draw.DrawData; chart.Text=drawData.Text; chart.Line=drawData.Line; chart.Price=drawData.Price; } hqChart.ChartPaint.push(chart); } this.CreateNumberText=function(hqChart,windowIndex,varItem,id) { let chartText=new ChartSingleText(); chartText.Canvas=hqChart.Canvas; chartText.Name=varItem.Name; chartText.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartText.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chartText.ReloadResource(); chartText.TextAlign="center"; if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else chartText.Color=this.GetDefaultColor(id); if (varItem.IsDrawAbove) chartText.Direction=1; else chartText.Direction=2; if (varItem.Draw.Position) chartText.Position=varItem.Draw.Position; //赋值坐标 let titleIndex=windowIndex+1; chartText.Data.Data=varItem.Draw.DrawData.Value; chartText.Text=varItem.Draw.DrawData.Text; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } this.CreateDrawText=function(hqChart,windowIndex,varItem,id) { let chartText=new ChartSingleText(); chartText.Canvas=hqChart.Canvas; chartText.Name=varItem.Name; chartText.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartText.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chartText.ReloadResource(); if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else chartText.Color=this.GetDefaultColor(id); if (varItem.IsDrawAbove) chartText.Direction=1; else chartText.Direction=0; if (varItem.DrawFontSize>0) chartText.TextFont=`${varItem.DrawFontSize*GetDevicePixelRatio()}px 微软雅黑`; //临时用下吧 let titleIndex=windowIndex+1; chartText.DrawData=varItem.Draw.DrawData; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } //创建图标 this.CreateIcon=function(hqChart,windowIndex,varItem,id) { let chartText=new ChartSingleText(); chartText.Canvas=hqChart.Canvas; chartText.TextAlign='center'; chartText.Name=varItem.Name; chartText.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chartText.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chartText.Direction=2; if (varItem.IsDrawAbove) chartText.Direction=1; if (varItem.DrawVAlign>=0) { if (varItem.DrawVAlign==0) chartText.Direction=1; else if (varItem.DrawVAlign==1) chartText.Direction=0; else if (varItem.DrawVAlign==2) chartText.Direction=2; } if (varItem.DrawAlign>=0) { if (varItem.DrawAlign==0) chartText.TextAlign="left"; else if (varItem.DrawAlign==1) chartText.TextAlign="center"; else if (varItem.DrawAlign==2) chartText.TextAlign='right'; } let titleIndex=windowIndex+1; chartText.Data.Data=varItem.Draw.DrawData; var icon=varItem.Draw.Icon; if (icon.IconFont==true) { chartText.IconFont={ Family:icon.Family, Text:icon.Symbol, Color:icon.Color }; if (varItem.Color) chartText.IconFont.Color=this.GetColor(varItem.Color); } else { chartText.Text=icon.Symbol; if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else if (icon.Color) chartText.Color=icon.Color; else chartText.Color='rgb(0,0,0)'; } if (varItem.DrawFontSize>0) chartText.FixedFontSize=varItem.DrawFontSize; if (IFrameSplitOperator.IsNumber(varItem.XOffset)) chartText.ShowOffset.X=varItem.XOffset; if (IFrameSplitOperator.IsNumber(varItem.YOffset)) chartText.ShowOffset.Y=varItem.YOffset; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } this.CreateTipIcon=function(hqChart,windowIndex,varItem,i) { var chart=new ChartDrawSVG(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (hqChart.ChartPaint[0].IsMinuteFrame()) chart.Data=hqChart.SourceData; else chart.Data=hqChart.ChartPaint[0].Data; //绑定K线 chart.Family=varItem.Draw.Icon.Family; chart.TextFont=g_JSChartResource.TIPICON.TextFont; var svgSize=g_JSChartResource.TIPICON.Size; var svgColor=g_JSChartResource.TIPICON.Color; var svgYOffset=0; var svgVAlign=2; //上下对齐方式 if (IFrameSplitOperator.IsNumber(varItem.YOffset)) svgYOffset=varItem.YOffset; if (varItem.Color) svgColor=this.GetColor(varItem.Color); if (varItem.DrawFontSize>0) svgSize=varItem.DrawFontSize; if (varItem.DrawVAlign>=0) svgVAlign=varItem.DrawVAlign; if (varItem.Draw && IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.DrawData) && varItem.Draw.Icon) { var drawData=varItem.Draw.DrawData; var aryData=[]; var isArrayTip=Array.isArray(varItem.Draw.Text); var singleTip=null; if (!isArrayTip && varItem.Draw.Text) singleTip={ Text:varItem.Draw.Text }; for(var j=0;j0) chart.LineWidth=varItem.Draw.Border.Width; //let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData; hqChart.ChartPaint.push(chart); } this.CreatePartLine=function(hqChart,windowIndex,varItem,i) { let chart=new ChartPartLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (IFrameSplitOperator.IsPlusNumber(width)) chart.LineWidth=width; } chart.Data.Data=varItem.Draw.DrawData; this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateMultiLine=function(hqChart,windowIndex,varItem,i) { let chart=new ChartMultiLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Lines=varItem.Draw.DrawData; if (varItem.Draw.Name) chart.Name=varItem.Draw.Name; if (varItem.Draw.LineDash) chart.LineDash=varItem.Draw.LineDash; if (IFrameSplitOperator.IsNumber(varItem.Draw.LineWidth)) chart.LineWidth=varItem.Draw.LineWidth; if (IFrameSplitOperator.IsBool(varItem.Draw.IsFullRangeMaxMin)) chart.IsFullRangeMaxMin=varItem.Draw.IsFullRangeMaxMin; if(varItem.Draw.Arrow) //箭头配置 { var item=varItem.Draw.Arrow; if (item.Start==true) chart.Arrow.Start=true; if (item.End==true) chart.Arrow.End=true; if (IFrameSplitOperator.IsNumber(item.Angle)) chart.ArrawAngle=item.Angle; if (IFrameSplitOperator.IsNumber(item.Length)) chart.ArrawLength=item.Length; if (IFrameSplitOperator.IsNumber(item.LineWidth)) chart.ArrawLineWidth=item.LineWidth; } this.ReloadChartResource(hqChart, windowIndex, chart); this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); var titleIndex=windowIndex+1; if (varItem.IsShowTitle===false) { } else { var titleData=new DynamicTitleData(chart.Data,chart.Name, null); titleData.DataType="ChartMultiLine"; titleData.Lines=chart.Lines; hqChart.TitlePaint[titleIndex].Data[i]=titleData; } } this.CreateMultiPoint=function(hqChart,windowIndex,varItem,i) { let chart=new ChartMultiPoint(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.PointGroup=varItem.Draw.DrawData; if (varItem.Draw.Name) chart.Name=varItem.Draw.Name; this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); var titleIndex=windowIndex+1; var titleData=new DynamicTitleData(chart.Data,chart.Name, null); titleData.DataType="ChartMultiPoint"; titleData.PointGroup=chart.PointGroup; hqChart.TitlePaint[titleIndex].Data[i]=titleData; } this.CreateMultiBar=function(hqChart,windowIndex,varItem,id) { let chart=new ChartMultiBar(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Bars=varItem.Draw.DrawData; var titleIndex=windowIndex+1; var titleData=new DynamicTitleData({ KData:chart.Data, BarData:chart.Bars },varItem.Name,null); titleData.IsShow=false; titleData.DataType="MULTI_BAR"; hqChart.TitlePaint[titleIndex].Data[id]=titleData; this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateMultiText=function(hqChart,windowIndex,varItem,i) { let chart=new ChartMultiText(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Texts=varItem.Draw.DrawData; this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateMultiSVGIcon=function(hqChart,windowIndex,varItem,i) { let chart=new ChartMultiSVGIconV2(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Family=varItem.Draw.DrawData.Family; chart.AryIcon= varItem.Draw.DrawData.Icon; chart.BuildCacheData(); this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } this.CreateChartDrawSVG=function(hqChart,windowIndex,varItem,i) { var chart=new ChartDrawSVG(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (hqChart.ChartPaint[0].IsMinuteFrame()) chart.Data=hqChart.SourceData; else chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 if (IFrameSplitOperator.IsBool(varItem.Draw.DrawData.EnableTooltip)) chart.EnableTooltip=varItem.Draw.DrawData.EnableTooltip; if (IFrameSplitOperator.IsBool(varItem.Draw.DrawData.IsDrawFirst)) chart.IsDrawFirst=varItem.Draw.DrawData.IsDrawFirst; chart.Family=varItem.Draw.DrawData.Family; chart.TextFont=varItem.Draw.DrawData.TextFont; chart.Texts= varItem.Draw.DrawData.Data; hqChart.ChartPaint.push(chart); } this.CreateMulitHtmlDom=function(hqChart,windowIndex,varItem,i) { let chart=new ChartMultiHtmlDom(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.HQChart=hqChart; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Texts=varItem.Draw.DrawData; chart.DrawCallback= varItem.Draw.Callback; hqChart.ChartPaint.push(chart); } this.CreateStackedBar=function(hqChart,windowIndex,varItem,i) { var chart=new ChartStackedBar(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.HQChart=hqChart; chart.Identify=this.Guid; chart.Data.Data=varItem.Draw.DrawData; if (IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.BarColor)) chart.BarColor=varItem.Draw.BarColor; if (IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.BarName)) chart.BarName=varItem.Draw.BarName; if (IFrameSplitOperator.IsNumber(varItem.Draw.LineWidth)) chart.LineWidth=varItem.Draw.LineWidth; if (IFrameSplitOperator.IsNumber(varItem.Draw.BarType)) chart.BarType=varItem.Draw.BarType; hqChart.ChartPaint.push(chart); var titleIndex=windowIndex+1; var titleData=new DynamicTitleData(chart.Data,chart.BarName,chart.BarColor); titleData.DataType="ChartStackedBar"; hqChart.TitlePaint[titleIndex].Data[i]=titleData; } this.CreateKLineTable=function(hqChart,windowIndex,varItem,i) { var chart=new ChartKLineTable(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.HQChart=hqChart; chart.Identify=this.Guid; chart.Data.Data=varItem.Draw.DrawData; if (IFrameSplitOperator.IsNumber(varItem.Draw.RowCount)) chart.RowCount=varItem.Draw.RowCount; if (IFrameSplitOperator.IsBool(varItem.Draw.IsShowRowName)) chart.IsShowRowName=varItem.Draw.IsShowRowName; if (IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.RowName)) chart.RowName=varItem.Draw.RowName; if (varItem.Draw.BGColor) chart.BGColor=varItem.Draw.BGColor; hqChart.ChartPaint.push(chart); var titleIndex=windowIndex+1; var titleData=new DynamicTitleData(chart.Data,chart.BarName,chart.BarColor); titleData.DataType="ChartKLineTable"; hqChart.TitlePaint[titleIndex].Data[i]=titleData; } this.CreateScatterPlot=function(hqChart,windowIndex,varItem,i) { var chart=new ChartScatterPlot(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.HQChart=hqChart; chart.Identify=this.Guid; chart.Data.Data=varItem.Draw.DrawData; chart.Color=varItem.Draw.Color; chart.Radius=varItem.Draw.Radius; hqChart.ChartPaint.push(chart); } this.CreateClipColorStick=function(hqChart,windowIndex,varItem,id) { var chart=new ChartClipColorStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.HQChart=hqChart; chart.Identify=this.Guid; chart.Data.Data=varItem.Draw.DrawData; if (varItem.Option && chart.SetOption) chart.SetOption(varItem.Option); hqChart.ChartPaint.push(chart); var titleIndex=windowIndex+1; if (varItem.IsShowTitle===false) { } else { var clrTitle=this.GetDefaultColor(id); if (varItem.Option && varItem.Option.TitleColor) clrTitle=this.GetColor(varItem.Option.TitleColor); hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(chart.Data,varItem.Name,clrTitle); } } this.CreateColorKLine=function(hqChart,windowIndex,varItem,i) { let chart=new ChartColorKline(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.KLineColor= varItem.Draw.DrawData.KLine; if (varItem.Color) chart.Color=varItem.Color; hqChart.ChartPaint.push(chart); } this.CreateRectangle=function(hqChart,windowIndex,varItem,i) { let chart=new ChartRectangle(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Color=[varItem.Draw.DrawData.Color]; chart.Rect=varItem.Draw.DrawData.Rect; if (varItem.Color) chart.BorderColor=this.GetColor(varItem.Color); hqChart.ChartPaint.push(chart); } this.CreateScriptOverlayLine=function(hqChart,windowIndex,varItem,i) { let chart=new ChartOverlayLine(); chart.Canvas=hqChart.Canvas; chart.DrawType=1; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(i); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } if (varItem.IsDotLine) chart.IsDotLine=true; //虚线 if (varItem.IsShow==false) chart.IsShow=false; let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData.Data; chart.MainData.Data=varItem.Draw.DrawData.MainData; if (varItem.Draw.DrawData.Title) hqChart.TitlePaint[titleIndex].Data[i]=new DynamicTitleData(chart.Data,varItem.Draw.DrawData.Title,chart.Color); hqChart.ChartPaint.push(chart); } //创建K线 this.CreateSelfKLine=function(hqChart,windowIndex,hisData) { let chart=new ChartKLine(); chart.Canvas=hqChart.Canvas; chart.Name="Self Kline"; chart.Identify=this.Guid; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; chart.ChartFrame=hqChart.Frame.SubFrame[windowIndex].Frame; chart.Data=hisData chart.IsShowMaxMinPrice=false; chart.IsShowKTooltip=false; chart.DrawType=this.KLineType; hqChart.ChartPaint.push(chart); } this.BindInstructionData=function(hqChart,windowIndex,hisData) //绑定指示指标 { if (this.OutVar==null || this.OutVar.length<0) return; //参数 var indexParam=''; for(let i in this.Arguments) { let item=this.Arguments[i]; if (indexParam.length>0) indexParam+=','; indexParam+=item.Value.toString(); } if (indexParam.length>0) indexParam='('+indexParam+')'; if (this.InstructionType==2) //五彩K线 { let varItem=this.OutVar[this.OutVar.length-1]; //取最后一组数据作为指示数据 hqChart.SetInstructionData(this.InstructionType, {Data:varItem.Data, Name:this.Name, Param:indexParam, ID:this.ID }); //设置指示数据 return true; } else if (this.InstructionType==1) //交易系统 { var buyData, sellData; for(var i in this.OutVar) { let item=this.OutVar[i]; if (item.Name=='ENTERLONG') buyData=item.Data; else if (item.Name=='EXITLONG') sellData=item.Data; } hqChart.SetInstructionData(this.InstructionType, {Buy:buyData, Sell:sellData, Name:this.Name, Param:indexParam, ID:this.ID}); //设置指示数据 return true; } } this.BindData=function(hqChart,windowIndex,hisData) { if (windowIndex==0 && this.InstructionType) { this.BindInstructionData(hqChart,windowIndex,hisData); return; } //清空主指标图形 hqChart.DeleteIndexPaint(windowIndex); if (windowIndex==0) hqChart.ShowKLine(true); if (this.OutVar==null || this.OutVar.length<0) return; //叠加一个K线背景 if (this.KLineType!=null) { if (this.KLineType===0 || this.KLineType===1 || this.KLineType===2) this.CreateSelfKLine(hqChart,windowIndex,hisData); else if (this.KLineType===-1 && windowIndex==0) hqChart.ShowKLine(false); } if (windowIndex>=1 && hqChart.Frame) { //Y轴刻度格式 默认跟标题栏一致 var ySpliter=hqChart.Frame.SubFrame[windowIndex].Frame.YSplitOperator; if (ySpliter) { ySpliter.Reset(); ySpliter.FloatPrecision=this.FloatPrecision; if (this.YAxis) ySpliter.SetOption(this.YAxis); } if (this.YSpecificMaxMin) hqChart.Frame.SubFrame[windowIndex].Frame.YSpecificMaxMin=this.YSpecificMaxMin; //最大最小值 if (this.YSplitScale) hqChart.Frame.SubFrame[windowIndex].Frame.YSplitScale=this.YSplitScale; //固定刻度 } if (IFrameSplitOperator.IsNumber(this.YSplitType)) hqChart.Frame.SubFrame[windowIndex].Frame.YSplitOperator.SplitType=this.YSplitType; /* if (this.Name=='MA') //测试多线段 { var point1={Point:[{Index:300, Value:15.5}, {Index:301, Value:14.2} , {Index:304, Value:14.05}], Color:'rgb(244,55,50)'}; var point2={Point:[{Index:307, Value:14.5}, {Index:308, Value:14.2} , {Index:309, Value:14.15}], Color:'rgb(0,55,50)'}; var testData={ Name:'MULTI_LINE', Type:1,Draw:{ DrawType:'MULTI_LINE', DrawData:[point1,point2] } }; this.OutVar.push(testData); } */ for(let i=0; i0) titlePaint.Data[i].StringFormat=this.StringFormat; if (this.FloatPrecision>=0) titlePaint.Data[i].FloatPrecision=this.FloatPrecision; if (this.OutName && this.OutName.length>0 && this.Arguments && this.Arguments.length>0) { titlePaint.SetDynamicTitle(this.OutName,this.Arguments); } } } let titleIndex=windowIndex+1; var titlePaint=hqChart.TitlePaint[titleIndex]; titlePaint.Title=this.Name; titlePaint.Identify=this.Guid; //指标ID titlePaint.ArgumentsText=null; titlePaint.Script=this; titlePaint.IsShowMainIndexTitle=this.IsShowIndexTitle; if (!this.IsShortTitle) { let indexParam=''; for(let i=0; i0) indexParam+=','; indexParam+=item.Value.toString(); } if (indexParam.length>0) titlePaint.ArgumentsText=`(${indexParam})`; } if (this.TitleFont) titlePaint.Font=this.TitleFont; return true; } //给一个默认的颜色 this.GetDefaultColor=function(id) { let COLOR_ARRAY=null; //使用全局线段配置 if (g_JSChartResource && g_JSChartResource.Index && g_JSChartResource.Index.LineColor) { COLOR_ARRAY=g_JSChartResource.Index.LineColor; } if (!COLOR_ARRAY || !Array.isArray(COLOR_ARRAY)) { COLOR_ARRAY= [ "rgb(255,174,0)", "rgb(25,199,255)", "rgb(175,95,162)", "rgb(236,105,65)", "rgb(68,114,196)", "rgb(229,0,79)", "rgb(0,128,255)", "rgb(252,96,154)", "rgb(42,230,215)", "rgb(24,71,178)", ]; } let number=parseInt(id); return COLOR_ARRAY[number%(COLOR_ARRAY.length-1)]; } //获取颜色 this.GetColor=function(colorName) { if (colorName.indexOf("RGB(")==0) return colorName.toLowerCase(); if (colorName.indexOf("rgb(")==0) return colorName; if (colorName.indexOf("RGBA(")==0) return colorName.toLowerCase(); if (colorName.indexOf("rgba(")==0) return colorName; var color=JSComplier.ColorVarToRGB(colorName); if (color) return color; return 'rgb(30,144,255)'; /* let COLOR_MAP=new Map([ ['COLORBLACK','rgb(0,0,0)'], ['COLORBLUE','rgb(18,95,216)'], ['COLORGREEN','rgb(25,158,0)'], ['COLORCYAN','rgb(0,255,198)'], ['COLORRED','rgb(238,21,21)'], ['COLORMAGENTA','rgb(255,0,222)'], ['COLORBROWN','rgb(149,94,15)'], ['COLORLIGRAY','rgb(218,218,218)'], //画淡灰色 ['COLORGRAY','rgb(133,133,133)'], //画深灰色 ['COLORLIBLUE','rgb(94,204,255)'], //淡蓝色 ['COLORLIGREEN','rgb(183,255,190)'], //淡绿色 ['COLORLICYAN','rgb(154,255,242)'], //淡青色 ['COLORLIRED','rgb(255,172,172)'], //淡红色 ['COLORLIMAGENTA','rgb(255,145,241)'], //淡洋红色 ['COLORWHITE','rgb(255,255,255)'], //白色 ['COLORYELLOW','rgb(255,198,0)'] ]); if (COLOR_MAP.has(colorName)) return COLOR_MAP.get(colorName); //COLOR 自定义色 //格式为COLOR+“RRGGBB”:RR、GG、BB表示红色、绿色和蓝色的分量,每种颜色的取值范围是00-FF,采用了16进制。 //例如:MA5:MA(CLOSE,5),COLOR00FFFF 表示纯红色与纯绿色的混合色:COLOR808000表示淡蓝色和淡绿色的混合色。 if (colorName.indexOf('COLOR')==0) return '#'+colorName.substr(5); return 'rgb(30,144,255)'; */ } } function OverlayScriptIndex(name,script,args,option) { this.newMethod=ScriptIndex; //派生 this.newMethod(name,script,args,option); delete this.newMethod; this.ClassName="OverlayScriptIndex"; //叠加指标 this.OverlayIndex=null; // { IsOverlay:true, Identify:overlayFrame.Identify, WindowIndex:windowIndex, Frame:overlayFrame } //显示指标不符合条件 this.ShowConditionError=function(param,msg) { var hqChart=param.HQChart; var windowIndex=param.WindowIndex; var message='指标不支持当前品种或周期'; if (msg) message=msg; var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; frame.ChartPaint=[]; var chart=new ChartLine(); chart.Canvas=hqChart.Canvas; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.NotSupportMessage=message; frame.ChartPaint.push(chart); hqChart.Draw(); } this.BindData=function(hqChart,windowIndex,hisData) { if (!this.OverlayIndex || this.OverlayIndex.IsOverlay!=true) return; this.OverlayIndex.Frame.ChartPaint=[]; if (!IFrameSplitOperator.IsNonEmptyArray(this.OutVar)) return; //修改Y轴分割方式 var ySpliter=this.OverlayIndex.Frame.Frame.YSplitOperator; if (ySpliter) { ySpliter.Reset(); ySpliter.FloatPrecision=this.FloatPrecision; if (IFrameSplitOperator.IsNumber(this.YSplitType)) ySpliter.SplitType=this.YSplitType; if (this.YAxis) ySpliter.SetOption(this.YAxis); } //指标名字 var titleInfo={ Data:[], Title:this.Name, Frame:this.OverlayIndex.Frame.Frame, Script:this, IsShowIndexTitle:this.IsShowIndexTitle }; let indexParam=''; for(var i in this.Arguments) { let item=this.Arguments[i]; if (indexParam.length>0) indexParam+=','; indexParam+=item.Value.toString(); } if (indexParam.length>0) titleInfo.Title=this.Name+'('+indexParam+')'; var titleIndex=windowIndex+1; var titlePaint=hqChart.TitlePaint[titleIndex]; titlePaint.OverlayIndex.set(this.OverlayIndex.Identify,titleInfo); if (this.OutName && this.OutName.length>0 && this.Arguments && this.Arguments.length>0) { titlePaint.SetDynamicTitle(this.OutName,this.Arguments, this.OverlayIndex.Identify); } this.OverlayIndex.Frame.Frame.Title=this.Name; //给子框架设置标题 if (hqChart.Frame.SubFrame[windowIndex]) { var mainFrame=hqChart.Frame.SubFrame[windowIndex].Frame; if (mainFrame) this.OverlayIndex.Frame.Frame.XPointCount=mainFrame.XPointCount; //跟主窗口同步下页面显示数据个数 } for(var i=0; i=0) titleData.FloatPrecision=this.FloatPrecision; if (IFrameSplitOperator.IsNumber(this.StringFormat)) titleData.StringFormat=this.StringFormat; } } /* hqChart.TitlePaint[titleIndex].Title=this.Name; let indexParam=''; for(let i in this.Arguments) { let item=this.Arguments[i]; if (indexParam.length>0) indexParam+=','; indexParam+=item.Value.toString(); } if (indexParam.length>0) hqChart.TitlePaint[titleIndex].Title=this.Name+'('+indexParam+')'; */ return true; } //指标执行完成 this.RecvResultData=function(outVar,param) { let hqChart=param.HQChart; let windowIndex=param.WindowIndex; let hisData=param.HistoryData; param.Self.OutVar=outVar; param.Self.BindData(hqChart,windowIndex,hisData); param.HQChart.UpdataDataoffset(); //更新数据偏移 param.HQChart.UpdateFrameMaxMin(); //调整坐标最大 最小值 if (param.Self.IsSync===false) //异步需要马上刷新,同步主图数据更新的时候会刷新的 param.HQChart.Draw(); var event=hqChart.GetOverlayIndexEvent(); //指标计算完成回调 if (event) { var self=param.Self; var data={ OutVar:self.OutVar, WindowIndex: windowIndex, Name: self.Name, Arguments: self.Arguments, HistoryData: hisData, Identify:self.OverlayIndex.Identify, Stock: {Symbol:hqChart.Symbol,Name:hqChart.Name} }; event.Callback(event,data,self); } } //自定义图形配色 this.ReloadChartResource=function(hqChart, windowIndex, chart) { var event=hqChart.GetEventCallback(JSCHART_EVENT_ID.ON_RELOAD_OVERLAY_INDEX_CHART_RESOURCE); //指标计算完成回调 if (!event || !event.Callback) return; var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var script=frame.Script; var sendData={ Chart:chart, IndexName:script.Name,IndexID:script.ID, HQChart:hqChart, WindowIndex:windowIndex, Guid:overlayIndex.Identify }; event.Callback(event,sendData,this); } ////////////////////////////////////////////////////////////////////////////////////// // 图形创建 ///////////////////////////////////////////////////////////////////////////////////// this.CreateLine=function(hqChart,windowIndex,varItem,id,lineType) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; if (lineType==7) var chart=new ChartStepLine(); else var chart=new ChartLine(); chart.Canvas=hqChart.Canvas; chart.DrawType=1; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (lineType==8) { chart.DrawType=2; chart.BreakPoint=varItem.BreakPoint; } if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } if (varItem.IsShow==false) chart.IsShow=false; chart.Data.Data=varItem.Data; this.ReloadChartResource(hqChart, windowIndex, chart); let titleIndex=windowIndex+1; var titlePaint=hqChart.TitlePaint[titleIndex]; var titleData=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); this.SetTitleData(titleData,chart); titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=titleData; this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } //创建柱子 this.CreateBar=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartStickLine(); chart.Canvas=hqChart.Canvas; if (varItem.Draw.Width>0) chart.Width=varItem.Draw.Width; else chart.Width=1; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateDrawText=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var chart=new ChartSingleText(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.ReloadResource(); if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.IsDrawAbove) chart.Direction=1; else chart.Direction=0; chart.DrawData=varItem.Draw.DrawData; if (varItem.DrawFontSize>0) chart.TextFont=`${varItem.DrawFontSize*GetDevicePixelRatio()}px 微软雅黑`; //临时用下吧 frame.ChartPaint.push(chart); } //DRAWTEXT this.CreateDrawTextV2=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var chartText=new ChartDrawText(); chartText.Canvas=hqChart.Canvas; chartText.Name=varItem.Name; chartText.ChartBorder=frame.Frame.ChartBorder; chartText.ChartFrame=frame.Frame; chartText.Identify=overlayIndex.Identify; chartText.ReloadResource(); if (varItem.Color) chartText.Color=this.GetColor(varItem.Color); else chartText.Color=this.GetDefaultColor(id); if (varItem.IsDrawCenter===true) chartText.TextAlign='center'; if (varItem.IsDrawAbove===true) chartText.TextBaseline='bottom' if (varItem.IsDrawBelow===true) chartText.TextBaseline='top'; if (varItem.Draw.DrawData) chartText.Data.Data=varItem.Draw.DrawData; chartText.Text=varItem.Draw.Text; if (varItem.Draw.Direction>0) chartText.Direction=varItem.Draw.Direction; if (varItem.Draw.YOffset>0) chartText.YOffset=varItem.Draw.YOffset; if (varItem.Draw.TextAlign) chartText.TextAlign=varItem.Draw.TextAlign; //指定输出位置 if (varItem.Draw.FixedPosition==="TOP") chartText.FixedPosition=1; else if (varItem.Draw.FixedPosition==="BOTTOM") chartText.FixedPosition=2; if (varItem.DrawVAlign>=0) { if (varItem.DrawVAlign==0) chartText.TextBaseline='top'; else if (varItem.DrawVAlign==1) chartText.TextBaseline='middle'; else if (varItem.DrawVAlign==2) chartText.TextBaseline='bottom'; } if (varItem.DrawAlign>=0) { if (varItem.DrawAlign==0) chartText.TextAlign="left"; else if (varItem.DrawAlign==1) chartText.TextAlign="center"; else if (varItem.DrawAlign==2) chartText.TextAlign='right'; } if (varItem.DrawFontSize>0) chartText.FixedFontSize=varItem.DrawFontSize; if (varItem.Background) chartText.TextBG=varItem.Background; if (varItem.VerticalLine) chartText.VerticalLine=varItem.VerticalLine; if (IFrameSplitOperator.IsNumber(varItem.XOffset)) chartText.ShowOffset.X=varItem.XOffset; if (IFrameSplitOperator.IsNumber(varItem.YOffset)) chartText.ShowOffset.Y=varItem.YOffset; //let titleIndex=windowIndex+1; frame.ChartPaint.push(chartText); } //创建文本 this.CreateText=function(hqChart,windowIndex,varItem,id, drawName) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartSingleText(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.ReloadResource(); if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); let titleIndex=windowIndex+1; if (varItem.Draw.Position) chart.Position=varItem.Draw.Position; //赋值坐标 if (varItem.Draw.DrawData) chart.Data.Data=varItem.Draw.DrawData; chart.Text=varItem.Draw.Text; if (varItem.Draw.Direction>0) chart.Direction=varItem.Draw.Direction; if (varItem.Draw.YOffset>0) chart.YOffset=varItem.Draw.YOffset; if (varItem.Draw.TextAlign) chart.TextAlign=varItem.Draw.TextAlign; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); frame.ChartPaint.push(chart); } //COLORSTICK this.CreateMACD=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMACD(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; var titlePaint=hqChart.TitlePaint[titleIndex]; var clrTitle=this.GetDefaultColor(id); if (varItem.Color) clrTitle=this.GetColor(varItem.Color); if (varItem.UpColor) chart.UpColor=varItem.UpColor; if (varItem.DownColor) chart.DownColor=varItem.DownColor; this.ReloadChartResource(hqChart, windowIndex, chart); titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=new DynamicTitleData(chart.Data,varItem.Name,clrTitle); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreatePointDot=function(hqChart,windowIndex,varItem,id,hisData) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartPointDot(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.Radius) chart.Radius=varItem.Radius; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.Radius=width; } if (IFrameSplitOperator.IsBool(varItem.UpDownDot)) { chart.EnableUpDownColor=varItem.UpDownDot; chart.HistoryData=hisData; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; var titlePaint=hqChart.TitlePaint[titleIndex]; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateStick=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; this.ReloadChartResource(hqChart, windowIndex, chart); var titlePaint=hqChart.TitlePaint[titleIndex]; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); frame.ChartPaint.push(chart); } this.CreateLineStick=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartLineStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; var titlePaint=hqChart.TitlePaint[titleIndex]; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); frame.ChartPaint.push(chart); } this.CreateStraightLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartLine(); chart.DrawType=1; chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(line.Data,varItem.Name,line.Color); frame.ChartPaint.push(chart); } this.CreateVolStick=function(hqChart,windowIndex,varItem,id,hisData) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartVolStick(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.KLineDrawType=hqChart.KLineDrawType; //设置K线显示类型 if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.UpColor) chart.UpColor=varItem.UpColor; if (varItem.DownColor) chart.DownColor=varItem.DownColor; if (IFrameSplitOperator.IsNumber(varItem.StickType)) chart.BarType=varItem.StickType; if (IFrameSplitOperator.IsNumber(varItem.BarColorType)) chart.BarColorType=varItem.BarColorType; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (IFrameSplitOperator.IsPlusNumber(width)) chart.BarWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Data; chart.HistoryData=hisData; this.ReloadChartResource(hqChart, windowIndex, chart); var titlePaint=hqChart.TitlePaint[titleIndex]; var titleData=new DynamicTitleData(chart.Data,varItem.Name,chart.Color); titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=titleData; this.SetTitleData(titleData,chart); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateBand=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartBand(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.FirstColor = varItem.Draw.Color[0]; chart.SecondColor = varItem.Draw.Color[1]; chart.Data.Data=varItem.Draw.DrawData; if (IFrameSplitOperator.IsBool(varItem.IsFirstDraw)) chart.IsDrawFirst=varItem.IsFirstDraw; this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } //创建K线图 this.CreateKLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartKLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data.Data=varItem.Draw.DrawData; chart.IsShowMaxMinPrice=false; chart.IsShowKTooltip=false; if (varItem.Color) //如果设置了颜色,使用外面设置的颜色 chart.UnchagneColor=chart.DownColor=chart.UpColor=this.GetColor(varItem.Color); frame.ChartPaint.push(chart); } this.CreatePolyLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData; var titlePaint=hqChart.TitlePaint[titleIndex]; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=new DynamicTitleData(line.Data,' ',line.Color); //给一个空的标题 frame.ChartPaint.push(chart); } this.CreateNumberText=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartSingleText(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.ReloadResource(); chart.TextAlign="center"; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.IsDrawAbove) chart.Direction=1; else chart.Direction=2; if (varItem.Draw.Position) chart.Position=varItem.Draw.Position; //赋值坐标 let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData.Value; chart.Text=varItem.Draw.DrawData.Text; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateTextLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartTextLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; if (varItem.Draw && varItem.Draw.DrawData) { var drawData=varItem.Draw.DrawData; chart.Text=drawData.Text; chart.Line=drawData.Line; chart.Price=drawData.Price; } frame.ChartPaint.push(chart); } this.CreateStackedBar=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartStackedBar(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.BarColor)) chart.BarColor=varItem.Draw.BarColor; if (IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.BarName)) chart.BarName=varItem.Draw.BarName; if (IFrameSplitOperator.IsNumber(varItem.Draw.LineWidth)) chart.LineWidth=varItem.Draw.LineWidth; if (IFrameSplitOperator.IsNumber(varItem.Draw.BarType)) chart.BarType=varItem.Draw.BarType; chart.Data.Data=varItem.Draw.DrawData; var titleIndex=windowIndex+1; var titlePaint=hqChart.TitlePaint[titleIndex]; var titleData=new DynamicTitleData(chart.Data,chart.BarName,chart.BarColor); titleData.DataType="ChartStackedBar"; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=titleData; frame.ChartPaint.push(chart); } this.CreateDrawColorKLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartColorKline(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.DrawName="DRAWCOLORKLINE"; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data.Data=varItem.Draw.DrawData; if (IFrameSplitOperator.IsBool(varItem.Draw.IsEmptyBar)) chart.IsEmptyBar=varItem.Draw.IsEmptyBar; if (varItem.Draw.Color) chart.Color=varItem.Draw.Color; frame.ChartPaint.push(chart); } //创建图标 this.CreateIcon=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartSingleText(); chart.Canvas=hqChart.Canvas; chart.TextAlign='center'; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.DrawVAlign>=0) { if (varItem.DrawVAlign==0) chart.Direction=1; else if (varItem.DrawVAlign==1) chart.Direction=0; else if (varItem.DrawVAlign==2) chart.Direction=2; } if (varItem.DrawAlign>=0) { if (varItem.DrawAlign==0) chart.TextAlign="left"; else if (varItem.DrawAlign==1) chart.TextAlign="center"; else if (varItem.DrawAlign==2) chart.TextAlign='right'; } if (IFrameSplitOperator.IsNumber(varItem.XOffset)) chart.ShowOffset.X=varItem.XOffset; if (IFrameSplitOperator.IsNumber(varItem.YOffset)) chart.ShowOffset.Y=varItem.YOffset; chart.Data.Data=varItem.Draw.DrawData; var icon=varItem.Draw.Icon; if (icon.IconFont==true) { chart.IconFont={ Family:icon.Family, Text:icon.Symbol, Color:icon.Color }; } else { chart.Text=icon.Symbol; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else if (icon.Color) chart.Color=icon.Color; else chart.Color='rgb(0,0,0)'; } //var titleIndex=windowIndex+1; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateTipIcon=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var chart=new ChartDrawSVG(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (hqChart.ChartPaint[0].IsMinuteFrame()) chart.Data=hqChart.SourceData; else chart.Data=hqChart.ChartPaint[0].Data; //绑定K线 chart.Family=varItem.Draw.Icon.Family; chart.TextFont=g_JSChartResource.TIPICON.TextFont; var svgSize=g_JSChartResource.TIPICON.Size; var svgColor=g_JSChartResource.TIPICON.Color; var svgYOffset=0; var svgVAlign=2; //上下对齐方式 if (IFrameSplitOperator.IsNumber(varItem.YOffset)) svgYOffset=varItem.YOffset; if (varItem.Color) svgColor=this.GetColor(varItem.Color); if (varItem.DrawFontSize>0) svgSize=varItem.DrawFontSize; if (varItem.DrawVAlign>=0) svgVAlign=varItem.DrawVAlign; if (varItem.Draw && IFrameSplitOperator.IsNonEmptyArray(varItem.Draw.DrawData) && varItem.Draw.Icon) { var drawData=varItem.Draw.DrawData; var aryData=[]; var isArrayTip=Array.isArray(varItem.Draw.Text); var singleTip=null; if (!isArrayTip && varItem.Draw.Text) singleTip={ Text:varItem.Draw.Text }; for(var j=0;j0) chart.LineWidth=varItem.Draw.Border.Width; //let titleIndex=windowIndex+1; chart.Data.Data=varItem.Draw.DrawData; frame.ChartPaint.push(chart); } // this.CreatePartLine=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartPartLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (IFrameSplitOperator.IsPlusNumber(width)) chart.LineWidth=width; } chart.Data.Data=varItem.Draw.DrawData; this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateMultiLine=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMultiLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Lines=varItem.Draw.DrawData; if (varItem.Draw.LineDash) chart.LineDash=varItem.Draw.LineDash; if (IFrameSplitOperator.IsNumber(varItem.Draw.LineWidth)) chart.LineWidth=varItem.Draw.LineWidth; if (IFrameSplitOperator.IsBool(varItem.Draw.IsFullRangeMaxMin)) chart.IsFullRangeMaxMin=varItem.Draw.IsFullRangeMaxMin; if(varItem.Draw.Arrow) //箭头配置 { var item=varItem.Draw.Arrow; if (item.Start==true) chart.Arrow.Start=true; if (item.End==true) chart.Arrow.End=true; if (IFrameSplitOperator.IsNumber(item.Angle)) chart.ArrawAngle=item.Angle; if (IFrameSplitOperator.IsNumber(item.Length)) chart.ArrawLength=item.Length; if (IFrameSplitOperator.IsNumber(item.LineWidth)) chart.ArrawLineWidth=item.LineWidth; } this.ReloadChartResource(hqChart, windowIndex, chart); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateMultiPoint=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMultiPoint(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.PointGroup=varItem.Draw.DrawData; frame.ChartPaint.push(chart); } this.CreateBackgroud=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartBackground(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (varItem.Draw && varItem.Draw.DrawData) { var drawData=varItem.Draw.DrawData; chart.Color=drawData.Color; chart.ColorAngle=drawData.Angle; if (drawData.Data) chart.Data.Data=drawData.Data; } frame.ChartPaint.push(chart); } this.CreateMultiBar=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMultiBar(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Bars=varItem.Draw.DrawData; var titleIndex=windowIndex+1; var titlePaint=hqChart.TitlePaint[titleIndex]; var titleData=new DynamicTitleData({ KData:chart.Data, BarData:chart.Bars },varItem.Name,null); titleData.IsShow=false; titleData.DataType="MULTI_BAR"; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=titleData; this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateMultiText=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMultiText(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Texts=varItem.Draw.DrawData; this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateMultiSVGIcon=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMultiSVGIconV2(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Family=varItem.Draw.DrawData.Family; chart.AryIcon= varItem.Draw.DrawData.Icon; chart.BuildCacheData(); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateChartDrawSVG=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var chart=new ChartDrawSVG(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; if (hqChart.ChartPaint[0].IsMinuteFrame()) chart.Data=hqChart.SourceData; else chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 if (IFrameSplitOperator.IsBool(varItem.Draw.DrawData.EnableTooltip)) chart.EnableTooltip=varItem.Draw.DrawData.EnableTooltip; if (IFrameSplitOperator.IsBool(varItem.Draw.DrawData.IsDrawFirst)) chart.IsDrawFirst=varItem.Draw.DrawData.IsDrawFirst; chart.Family=varItem.Draw.DrawData.Family; chart.TextFont=varItem.Draw.DrawData.TextFont; chart.Texts= varItem.Draw.DrawData.Data; if (varItem.Draw.AutoPosition) chart.AutoPosition=varItem.Draw.AutoPosition; this.ReloadChartResource(hqChart, windowIndex, chart); this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } this.CreateMulitHtmlDom=function(hqChart,windowIndex,varItem,i) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartMultiHtmlDom(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.HQChart=hqChart; chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Texts=varItem.Draw.DrawData; chart.DrawCallback= varItem.Draw.Callback; frame.ChartPaint.push(chart); } this.CreateChartVericaltLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var chart=new ChartVericaltLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.HQChart=hqChart; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } this.SetChartLineDash(chart,varItem.Draw.DrawData); chart.Data.Data=varItem.Draw.DrawData.Data; frame.ChartPaint.push(chart); } this.CreateChartHorizontalLine=function(hqChart,windowIndex,varItem,id) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; var chart=new ChartHorizontalLine(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.HQChart=hqChart; if (varItem.Color) chart.Color=this.GetColor(varItem.Color); else chart.Color=this.GetDefaultColor(id); if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); if (!isNaN(width) && width>0) chart.LineWidth=width; } this.SetChartLineDash(chart,varItem.Draw.DrawData); chart.ExtendType=varItem.Draw.DrawData.Extend; chart.Data.Data=varItem.Draw.DrawData.Data; frame.ChartPaint.push(chart); } //创建K线 this.CreateSelfKLine=function(hqChart,windowIndex,hisData) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; let chart=new ChartKLine(); chart.Canvas=hqChart.Canvas; chart.Name="Self Kline" chart.ChartBorder=frame.Frame.ChartBorder; chart.ChartFrame=frame.Frame; chart.Identify=overlayIndex.Identify; chart.Data=hisData chart.IsShowMaxMinPrice=false; chart.IsShowKTooltip=false; chart.DrawType=this.KLineType; frame.ChartPaint.push(chart); } //给一个默认的颜色 this.GetDefaultColor=function(id) { let COLOR_ARRAY= [ "rgb(24,71,178)", "rgb(42,230,215)", "rgb(252,96,154)", "rgb(0,128,255)", "rgb(229,0,79)", "rgb(68,114,196)", "rgb(255,174,0)", "rgb(25,199,255)", "rgb(175,95,162)", "rgb(236,105,65)", ]; let number=parseInt(id); return COLOR_ARRAY[number%(COLOR_ARRAY.length-1)]; } } //后台执行指标 function APIScriptIndex(name,script,args,option, isOverlay) { if (isOverlay) this.newMethod=OverlayScriptIndex; else this.newMethod=ScriptIndex; this.newMethod(name,script,args,option); delete this.newMethod; this.ClassName="APIScriptIndex"; this.IsOverlayIndex=(isOverlay==true); //是否是叠加指标 this.ApiUrl; //指标执行api地址 this.HQDataType; this.Version=1; //1=默认数据格式 1=新的.net数据格式 if (option && option.API) { if (option.API.Url) this.ApiUrl=option.API.Url; if (option.API.Name) this.Name=this.ID=option.API.Name; if (option.API.ID) this.ID=option.API.ID; if (option.API.Version>0) this.Version=option.API.Version; if (option.API.IsUsePageData===true) this.IsUsePageData=option.API.IsUsePageData; } this.Super_CopyTo=this.CopyTo; //父类方法 this.CopyTo=function(dest) //赋值到新实例出来 { this.Super_CopyTo(dest); dest.ApiUrl=this.ApiUrl; dest.Version=this.Version; dest.IsOverlayIndex=this.IsOverlayIndex; } //接收到订阅指标数据 this.RecvSubscribeData=function(data, hqChart, windowIndex, hisData) { if (this.Version==2) this.RecvAPIData2(data,hqChart,windowIndex,hisData); else this.RecvAPIData(data,hqChart,windowIndex,hisData); } this.ExecuteScript=function(hqChart,windowIndex,hisData) { JSConsole.Complier.Log('[APIScriptIndex::ExecuteScript] name, Arguments ', this.Name,this.Arguments ); //数据类型 let hqDataType=HQ_DATA_TYPE.KLINE_ID; //默认K线 var dateRange=null; if (hqChart.ClassName==='MinuteChartContainer' || hqChart.ClassName==='MinuteChartHScreenContainer') { if (hqChart.DayCount>1) hqDataType=HQ_DATA_TYPE.MULTIDAY_MINUTE_ID; //多日分钟 else hqDataType=HQ_DATA_TYPE.MINUTE_ID; //分钟数据 dateRange=hisData.GetDateRange(); } else if (hqChart.ClassName==='HistoryMinuteChartContainer') { hqDataType=HQ_DATA_TYPE.HISTORY_MINUTE_ID; //历史分钟 } else { dateRange=hisData.GetDateRange(); } var args=[]; if (this.Arguments) { for(var i in this.Arguments) { var item=this.Arguments[i]; args.push({name:item.Name, value:item.Value}); } } var requestCount; if (hqChart.GetRequestDataCount) requestCount=hqChart.GetRequestDataCount(); var self=this; var postData = { indexname:this.ID, symbol: hqChart.Symbol, script:this.Script, args:args, period:hqChart.Period, right:hqChart.Right, hqdatatype: hqDataType }; if (dateRange) postData.DateRange=dateRange; if (requestCount) { postData.maxdatacount=requestCount.MaxRequestDataCount; postData.maxminutedaycount=requestCount.MaxRequestMinuteDayCount; } if (hqDataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID || hqDataType==HQ_DATA_TYPE.MINUTE_ID) postData.daycount=hqChart.DayCount; this.HQDataType=hqDataType; ++this.RunCount; if (hqChart.NetworkFilter) { var obj= { Name:'APIScriptIndex::ExecuteScript', //类名:: Explain:'指标计算', Request:{ Url:self.ApiUrl, Type:'POST', Data: postData }, Self:this, HQChart:hqChart, PreventDefault:false }; hqChart.NetworkFilter(obj, function(data) { if (self.Version==2) self.RecvAPIData2(data,hqChart,windowIndex,hisData); else self.RecvAPIData(data,hqChart,windowIndex,hisData); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } JSNetwork.HttpRequest({ url: self.ApiUrl, data: postData, type:"post", dataType: "json", async:true, success: function (recvData) { self.RecvAPIData(recvData,hqChart,windowIndex,hisData); }, error: function(request) { self.RecvError(request); } }); } //py 后台指标计算格式 this.RecvAPIData2=function(data,hqChart,windowIndex,hisData) { JSConsole.Complier.Log('[APIScriptIndex::RecvAPIData2] recv data ', this.Name,data ); //if (data.code!=0) return; if (this.HQDataType==HQ_DATA_TYPE.KLINE_ID) { this.OutVar=this.ConvertToLocalData(data,hqChart); JSConsole.Complier.Log('[APIScriptIndex::RecvAPIData2] conver to OutVar ', this.OutVar); } else if (this.HQDataType==HQ_DATA_TYPE.MINUTE_ID) { this.OutVar=this.ConvertToLocalData(data,hqChart); JSConsole.Complier.Log('[APIScriptIndex::RecvAPIData2] conver to OutVar ', this.OutVar); } else if (this.HQDataType==HQ_DATA_TYPE.MULTIDAY_MINUTE_ID) { this.OutVar=this.ConvertToLocalData(data,hqChart); JSConsole.Complier.Log('[APIScriptIndex::RecvAPIData2] conver to OutVar ', this.OutVar); } this.BindData(hqChart,windowIndex,hisData); hqChart.UpdataDataoffset(); //更新数据偏移 hqChart.UpdateFrameMaxMin(); //调整坐标最大 最小值 hqChart.Draw(); if (hqChart.GetIndexEvent) { var event=hqChart.GetIndexEvent(); //指标计算完成回调 if (event) { var data={ OutVar:this.OutVar, WindowIndex: windowIndex, Name: this.Name, Arguments: this.Arguments, HistoryData: hisData, Stock: {Symbol:hqChart.Symbol,Name:hqChart.Name} }; event.Callback(event,data,this); } } } this.ConvertToLocalData=function(jsonData, hqChart) { var outVar=jsonData.OutVar; if (hqChart.ClassName=="MinuteChartContainer" || hqChart.ClassName=="MinuteChartHScreenContainer") { var kdata=hqChart.SourceData; var aryDataIndex=kdata.GetAPIDataIndex(jsonData.Date,jsonData.Time); } else { var kdata=hqChart.ChartPaint[0].Data; if (ChartData.IsDayPeriod(jsonData.Period,true)) var aryDataIndex=kdata.GetAPIDataIndex(jsonData.Date); else var aryDataIndex=kdata.GetAPIDataIndex(jsonData.Date,jsonData.Time); } var localOutVar=[]; for(var i in outVar) { var item=outVar[i]; var outItem={ Type:item.Type, Name:item.Name }; if (item.Type==0) { outItem.Data=[]; for(var j=0;j=0) outItem.Name=outItem.Name.replace("@NODRAW@",""); } else if (item.Type==1) //绘图函数 { outItem.Name=item.DrawType; outItem.Draw={ DrawType:item.DrawType }; var draw=item.Draw; switch(item.DrawType) { case "STICKLINE": { var drawData=[]; for(var j=0;j=kData.Data.length) continue; var valueName=item.Value.toUpperCase(); var kItem=kData.Data[item.Index]; switch(valueName) { case "HIGH": case "H": item.Value=kItem.High; break; case "L": case "LOW": item.Value=kItem.Low; break; case "C": case "CLOSE": item.Value=kItem.Close; break; } } } this.FittingKLineBG=function(data, hqChart) { var kData=hqChart.ChartPaint[0].Data; //K线 var result=[]; if (ChartData.IsDayPeriod(hqChart.Period,true)) //日线 { var bFill=false; for(var i=0,j=0;i=data.length) { ++i; continue; } var dataItem=data[j]; if (dataItem.DatekItem.Date) { ++i; } else { bFill=true; result[i]=1; ++j; ++i; } } if (bFill) return result; } else if (ChartData.IsMinutePeriod(hqChart.Period,true)) //分钟线 { var bFill=false; for(var i=0,j=0;i=data.length) { ++i; continue; } var dataItem=data[j]; if (dataItem.DatekItem.Date || (dataItem.Date==kItem.Date && dataItem.Time>kItem.Time)) { ++i; } else { bFill=true; result[i]=1; ++j; ++i; } } if (bFill) return result; } return null; } this.FittingKLineBG_V2=function(data, hqChart) //2.0版本通过 [{ Start:, End: }, .....]来填充背景色 { var kData=hqChart.ChartPaint[0].Data; //K线 var result=[]; if (ChartData.IsDayPeriod(hqChart.Period,true)) //日线 { var bFill=false; for(var i=0,j=0;i=rangeItem.Start.Date && date<=rangeItem.End.Date) { result[i]=1; bFill=true; break; } } } if (bFill) return result; } else if (ChartData.IsMinutePeriod(hqChart.Period,true)) //分钟线 { var aryRange=[]; for(var i=0;i=rangeItem.Start && date<=rangeItem.End) { result[i]=1; bFill=true; break; } } } if (bFill) return result; } return null; } this.FittingMinuteData=function(jsonData, hqChart) { var outVar=jsonData.outvar; var date=jsonData.date; var time=jsonData.time; var result=[]; for(var i=0;i=1) outVarItem.LineWidth=item.linewidth; if (item.isshow==false) outVarItem.IsShow = false; if (item.isexdata==true) outVarItem.IsExData = true; if (item.BreakPoint) outVarItem.BreakPoint=item.BreakPoint; if (item.UpColor) outVarItem.UpColor=item.UpColor; if (item.DownColor) outVarItem.DownColor=item.DownColor; if (IFrameSplitOperator.IsBool(item.isDotLine)) outVarItem.IsDotLine = item.isDotLine; if (IFrameSplitOperator.IsNonEmptyArray(item.lineDash)) outVarItem.LineDash=item.lineDash; if (IFrameSplitOperator.IsBool(item.isSingleLine)) outVarItem.IsSingleLine=item.isSingleLine; result.push(outVarItem); } else if (item.Draw) { var draw=item.Draw; var drawItem={}; if (draw.DrawType=='DRAWICON') //图标 { drawItem.Icon=draw.Icon; drawItem.Name=draw.Name; drawItem.DrawType=draw.DrawType; drawItem.DrawData=this.FittingMinuteArray(draw.DrawData,date,time,hqChart); outVarItem.Draw=drawItem; result.push(outVarItem); } else if (draw.DrawType=='DRAWTEXT') //文本 { drawItem.Text=draw.Text; drawItem.Name=draw.Name; drawItem.DrawType=draw.DrawType; drawItem.DrawData=this.FittingMinuteArray(draw.DrawData,date,time,hqChart); outVarItem.Draw=drawItem; result.push(outVarItem); } else if (draw.DrawType=='STICKLINE') //柱子 { drawItem.Name=draw.Name; drawItem.Type=draw.Type; drawItem.Width=draw.Width; drawItem.DrawType=draw.DrawType; drawItem.DrawData=this.FittingMinuteArray(draw.DrawData,date,time,hqChart,1); outVarItem.Draw=drawItem; result.push(outVarItem); } else if (draw.DrawType==SCRIPT_CHART_NAME.OVERLAY_BARS) { drawItem.Name=draw.Name; drawItem.Type=draw.Type; drawItem.DrawType=draw.DrawType; drawItem.BarName=draw.BarName; drawItem.BarColor=draw.BarColor; drawItem.LineWidth=draw.LineWidth; drawItem.DrawData=this.FittingMinuteArray(draw.DrawData,date,time,hqChart,1); outVarItem.Draw=drawItem; result.push(outVarItem); } else if (draw.DrawType==SCRIPT_CHART_NAME.CLIP_COLOR_STICK) { drawItem.Name=draw.Name; drawItem.Type=draw.Type; drawItem.DrawType=draw.DrawType; drawItem.DrawData=this.FittingMinuteArray(draw.Data,date,time,hqChart); outVarItem.Draw=drawItem; if (draw.Option) outVarItem.Option=draw.Option; result.push(outVarItem); } else if (draw.DrawType=='MULTI_LINE') { drawItem.Text=draw.Text; drawItem.Name=draw.Name; drawItem.DrawType=draw.DrawType; drawItem.DrawData=this.FittingMultiLine(draw.DrawData,date,time,hqChart); for(var k in drawItem.DrawData) { this.GetKLineData(drawItem.DrawData[k].Point, hqChart); } outVarItem.Draw=drawItem; if (draw.LineDash) drawItem.LineDash=draw.LineDash; if (draw.Arrow) drawItem.Arrow=draw.Arrow; result.push(outVarItem); } else if (draw.DrawType=='MULTI_POINT') { drawItem.Text=draw.Text; drawItem.Name=draw.Name; drawItem.DrawType=draw.DrawType; drawItem.DrawData=this.FittingMultiLine(draw.DrawData,date,time,hqChart); if (IFrameSplitOperator.IsNonEmptyArray(drawItem.DrawData)) { for(var k=0; k { return a.Date-b.Date}); var firstItem=arySrouceData[0]; var kdata=hqChart.ChartPaint[0].Data; //K线 var firstKItem=kdata.Data[0]; var kIndex=0, dataIndex=0; if (firstItem.Date>firstKItem.Date) { var preIndex=0; for(kIndex=0;kIndexfirstItem.Date) { kIndex=preIndex; break; } preIndex=kIndex; } } else { for(dataIndex=0;dataIndex=firstKItem.Date) break; } } var preItem=null; for(var i=kIndex, j=dataIndex; i0) value+=' '; value+=item.name; } } return { Value:value }; } } /* 测试例子 var code1='VARHIGH:IF(VAR1<=REF(HH,-1),REF(H,BARSLAST(VAR1>=REF(HH,1))),DRAWNULL),COLORYELLOW;'; var code2='VAR1=((SMA(MAX((CLOSE - LC),0),3,1) / SMA(ABS((CLOSE - LC)),3,1)) * 100);'; var code3='mm1=1-2*-9+20;'; JSConsole.Complier.Log(code1+code2) var tokens=JSComplier.Tokenize(code1+code2); var ast=JSComplier.Parse(code2+code1); JSConsole.Complier.Log(ast); */ //外部通达信的变量 这些需要外部自己计算 JSComplier.AddVariant({ Name:'DHIGH', Description:'不定周期最高价' } ); JSComplier.AddVariant({ Name:'DOPEN', Description:'不定周期开盘价' } ); JSComplier.AddVariant({ Name:'DLOW', Description:'不定周期最低价' } ); JSComplier.AddVariant({ Name:'DCLOSE', Description:'不定周期收盘价' } ); JSComplier.AddVariant({ Name:'DVOL', Description:'不定周期成交量价' } ); /* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 配色 */ /* 不同风格行情配置文件 !!手机上字体大小需要*分辨率比 */ /* umychart.js 里面已经有了 function GetDevicePixelRatio() { return window.devicePixelRatio || 1; } */ //黑色风格 function GetBlackStyle() { var BLACK_STYLE= { BGColor:'rgb(0,0,0)', //背景色 TooltipBGColor: "rgb(255, 255, 255)", //背景色 TooltipAlpha: 0.92, //透明度 SelectRectBGColor: "rgba(1,130,212,0.06)", //背景色 // SelectRectAlpha: 0.06; //透明度 //K线颜色 UpBarColor: "rgb(238,21,21)", //上涨 DownBarColor: "rgb(25,158,0)", //下跌 UnchagneBarColor: "rgb(228,228,228)", //平盘 EmptyBarBGColor:'rgb(0,0,0)', //空心柱子背景色 SplashScreen: { BGColor:"rgba(112,128,144,0.5)", TextColor:"rgb(230,230,230)", }, HLCArea: { HighLineColor:'rgb(238,21,21)', LowLineColor:"rgb(25,158,0)", CloseLineColor:"rgb(156,156,156)", LineWidth:2*GetDevicePixelRatio(), UpAreaColor:"rgba(238,21,21, 0.3)", DownAreaColor:"rgba(25,158,0, 0.3)", }, Minute: { VolBarColor: null, PriceColor: "rgb(25,180,231)", AreaPriceColor:"rgba(63,158,255,.3)", AvPriceColor: "rgb(255,236,0)", PositionColor:'rgb(218,165,32)', VolTitleColor:"rgb(190,190,190)", Before: { BGColor:"rgba(105,105,105,0.5)", AvPriceColor:'rgb(248,248,255)', //均线 CloseIcon: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" } }, After: { BGColor:"rgba(105,105,105,0.5)", AvPriceColor:'rgb(248,248,255)' //均线 }, NightDay: { NightBGColor:"rgb(22,22,22)", Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, Day: { Color:"rgb(153,153,153)", BGColor:"rgb(51,51,51)", BorderColor:"rgb(51,51,51)", Margin:{ Left:5, Top:2, Bottom:2, Right:5 } }, Night: { Color:"rgb(153,153,153)", BGColor:"rgb(51,51,51)", BorderColor:"rgb(51,51,51)", Margin:{ Left:5, Top:2, Bottom:2, Right:5 } }, } }, PopMinuteChart: { BGColor:"rgba(0,0,0,0.95)", BorderColor:"rgb(230,230,230)", }, DefaultTextColor: "rgb(101,104,112)", DefaultTextFont: 14*GetDevicePixelRatio() +'px 微软雅黑', TitleFont: 13*GetDevicePixelRatio() +'px 微软雅黑', //标题字体(动态标题 K线及指标的动态信息字体) IndexTitleColor:"rgb(190, 190 ,190)", //指标名字颜色 IndexTitleBGColor:'rgb(0,0,0)', //指标名字背景色 IndexTitleBorderColor:'rgb(211, 211, 211)', //指标名字边框颜色 IndexTitleBorderMoveOnColor:'rgb(30,144,255)', //指标名字边框颜色(鼠标在上面) UpTextColor: "rgb(238,21,21)", DownTextColor: "rgb(25,158,0)", UnchagneTextColor: "rgb(190, 190 ,190)", CloseLineColor: 'rgb(250,250,250)', IndexTitle: { UpDownArrow: //数值涨跌箭头 { UpColor:"rgb(238,21,21)", //上涨 DownColor:"rgb(25,158,0)", //下跌 UnchangeColor:"rgb(190, 190 ,190)" //不变 }, NameArrow:{ Color:"rgb(190, 190 ,190)", Space:2, Symbol:'▼' }, }, Title: { TradeIndexColor:'rgb(105,105,105)', //交易指标颜色 ColorIndexColor:'rgb(112,128,144)', //五彩K线颜色 VolColor:"rgb(190, 190 ,190)", //标题成交量 AmountColor:"rgb(190, 190 ,190)", //成交金额 DateTimeColor:"rgb(190, 190 ,190)", //时间,日期 SettingColor:"rgb(190, 190 ,190)", //周期,复权 NameColor:"rgb(190, 190 ,190)" , //股票名称 TurnoverRateColor:'rgb(101,104,112)', //换手率 PositionColor:"rgb(101,104,112)" //持仓 }, FrameBorderPen: "rgb(47,51,62)", //边框 MultiDayBorderPen:"rgba(236,236,236,0.5)", FrameSplitPen: "rgba(236,236,236,0.13)", //分割线 FrameSplitTextColor: "rgb(220,220,220)", //刻度文字颜色 FrameSplitTextFont: 12*GetDevicePixelRatio() +"px 微软雅黑", //坐标刻度文字字体 FrameTitleBGColor: "rgb(0,0,0)", //标题栏背景色 OverlayIndexTitleBGColor:'rgba(0,0,0,0.7)', //叠加指标背景色 Frame: { XBottomOffset:2*GetDevicePixelRatio(), //X轴文字向下偏移 PercentageText: //百分比坐标文字颜色 { PriceColor:'rgb(101,104,112)', PercentageColor:"rgb(101,104,112)", SplitColor:"rgb(101,104,112)", Font:14*GetDevicePixelRatio() +"px 微软雅黑" } }, //叠加指标框架 OverlayFrame: { BolderPen:'rgb(130,130,130)', //指标边框线 TitleColor:'rgb(181,181,181)', //指标名字颜色 TitleFont:11*GetDevicePixelRatio() +'px arial', //指标名字字体 }, FrameLatestPrice : { TextColor:'rgb(255,255,255)', //最新价格文字颜色 UpBarColor:"rgb(238,21,21)", //上涨 DownBarColor:"rgb(25,158,0)", //下跌 UnchagneBarColor:"rgb(190,190,190)", //平盘 BGAlpha:0.6, EmptyBGColor:"rgb(0,0,0)" }, CorssCursorBGColor: "rgb(43,54,69)", //十字光标背景 CorssCursorTextColor: "rgb(255,255,255)", CorssCursorTextFont: 12*GetDevicePixelRatio() +"px 微软雅黑", CorssCursorHPenColor: "rgb(130,130,130)", //十字光标线段颜色 CorssCursorVPenColor: "rgb(130,130,130)", //十字光标线段颜色 CorssCursor: { RightButton : { BGColor:'rgb(43,54,69)', PenColor:'rgb(255,255,255)', Icon: { Text:'\ue6a3', Color:'rgb(255,255,255)', Family:"iconfont", Size:18 } } }, //订单流配置 OrderFlow: { UpColor:{BG:'rgb(223,191,180)', Border:"rgb(196,84,86)" }, //阳线 DownColor:{ BG:"rgb(176,212,184)", Border:'rgb(66,94,74)' }, //阴线 UnchagneColor: {BG:"rgb(216,221,177)", Border:"rgb(209,172,129)"}, //平盘 Text:{ Color: "rgb(248,248,255)" , Family:'Arial', FontMaxSize:16, MaxValue:"8888" }, //文字 Line:{ UpDownColor: "rgb(220,220,220)", MiddleColor:"rgb(211,211,211)" } //最大, 最低,中间 竖线 }, KLine: { MaxMin: { Font: 12*GetDevicePixelRatio() +'px 微软雅黑', Color: 'rgb(255,250,240)', RightArrow:"→", LeftArrow:"←", HighYOffset:0, LowYOffset:0 }, //K线最大最小值显示 Info: //信息地雷 { Investor: { ApiUrl:'/API/NewsInteract', //互动易 IconFont: { Family:'iconfont', Text:'\ue631' , HScreenText:'\ue684', Color:'#1c65db'} //SVG 文本 }, Announcement: //公告 { ApiUrl:'/API/ReportList', IconFont: { Family:'iconfont', Text:'\ue633', HScreenText:'\ue685', Color:'#f5a521' }, //SVG 文本 IconFont2: { Family:'iconfont', Text:'\ue634', HScreenText:'\ue686', Color:'#ed7520' } //SVG 文本 //季报 }, Pforecast: //业绩预告 { ApiUrl:'/API/StockHistoryDay', IconFont: { Family:'iconfont', Text:'\ue62e', HScreenText:'\ue687', Color:'#986cad' } //SVG 文本 }, Research: //调研 { ApiUrl:'/API/InvestorRelationsList', IconFont: { Family:'iconfont', Text:'\ue632', HScreenText:'\ue688', Color:'#19b1b7' } //SVG 文本 }, BlockTrading: //大宗交易 { ApiUrl:'/API/StockHistoryDay', IconFont: { Family:'iconfont', Text:'\ue630', HScreenText:'\ue689', Color:'#f39f7c' } //SVG 文本 }, TradeDetail: //龙虎榜 { ApiUrl:'/API/StockHistoryDay', IconFont: { Family:'iconfont', Text:'\ue62f', HScreenText:'\ue68a' ,Color:'#b22626' } //SVG 文本 } }, NumIcon: { Color:'rgb(251,80,80)',Family:'iconfont', Text:[ '\ue649', '\ue63b','\ue640','\ue63d','\ue63f','\ue645','\ue641','\ue647','\ue648','\ue646','\ue636', '\ue635','\ue637','\ue638','\ue639','\ue63a','\ue63c','\ue63e','\ue642','\ue644','\ue643' ] }, TradeIcon: //交易指标 图标 { Family:'iconfont', Buy: { Color:'rgb(255,15,4)', Text:'\ue683', HScreenText:'\ue682'}, Sell: { Color:'rgb(64,122,22)', Text:'\ue681',HScreenText:'\ue680'}, } }, VirtualKLine: { Color:'rgb(119,136,153)', LineDash:[2,2] }, PriceGapStyple: { Line:{ Color:"rgb(128,128,128)" }, Text:{ Color:"rgb(219,220,220)", Font:`${12*GetDevicePixelRatio()}px 微软雅黑` } }, Index: { LineColor: //指标线段颜色 [ "rgb(255,189,09)", "rgb(22,198,255)", "rgb(174,35,161)", "rgb(236,105,65)", "rgb(68,114,196)", "rgb(229,0,79)", "rgb(0,128,255)", "rgb(252,96,154)", "rgb(42,230,215)", "rgb(24,71,178)", ], NotSupport: { Font: `${14*GetDevicePixelRatio()}px 微软雅黑`, TextColor: "rgb(250,250,250)" } }, ColorArray: //自定义指标默认颜色 [ "rgb(255,174,0)", "rgb(25,199,255)", "rgb(175,95,162)", "rgb(236,105,65)", "rgb(68,114,196)", "rgb(229,0,79)", "rgb(0,128,255)", "rgb(252,96,154)", "rgb(42,230,215)", "rgb(24,71,178)", ], //按钮 Buttons: { CloseOverlayIndex: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, CloseWindow: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, ChangeIndex: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, OverlayIndex: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, ModifyIndexParam: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, //最大化, 最小化 MaxMinWindow: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, TitleWindow: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, ExportData: { MoveOnColor:"rgb(255,255,255)", Color:"rgb(156,156,156)" }, Tooltip: { //Font:12*GetDevicePixelRatio() +"px 微软雅黑", Color:'rgb(204,204,204)', ColorBG:'rgb(32,32,32)', ColorBorder:'rgb(69,69,69)', //BorderRadius:4, //Mergin:{ Left:4, Right:4, Top:2, Bottom:4 }, } }, DrawPicture: //画图工具 { LineColor: [ "rgb(41,98,255)" ], PointColor: [ "rgb(41,98,255)", //选中颜色 "rgb(89,135,255)", //moveon颜色 "rgb(0,0,0)" //空心点背景色 ], }, TooltipPaint : { BGColor:'rgba(20,20,20,0.8)', //背景色 BorderColor:'rgb(210,210,210)', //边框颜色 TitleColor:'rgb(210,210,210)', //标题颜色 TitleFont:13*GetDevicePixelRatio() +'px 微软雅黑', //字体 DateTimeColor:'rgb(210,210,210)', VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(210,210,210)", //成交金额 PositionColor:"rgb(255,215,0)", //持仓量 }, PCTooltipPaint: { BGColor:'rgba(20,20,20,0.8)', //背景色 BorderColor:'rgb(210,210,210)', //边框颜色 TitleColor:'rgb(210,210,210)', //标题颜色 TitleFont:12*GetDevicePixelRatio() +'px 微软雅黑', //字体 DateTimeColor:'rgb(210,210,210)', VolColor:"rgb(161,154,3)", //标题成交量 AmountColor:"rgb(161,154,3)", //成交金额 }, DialogTooltip: { BGColor:'rgb(20,20,20)', //背景色 BorderColor:'rgb(170,170,170)', //边框颜色 TitleColor:'rgb(250,250,250)', //标题颜色 VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(210,210,210)", //成交金额 DateTimeColor:'rgb(210,210,210)', TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(255,0,255)", //持仓 TextColor:"rgb(210,210,210)", //数值名称 ValueColor:"rgb(210,210,210)", //数值 TitleBGColor:"rgb(200, 66, 69)", }, FloatTooltip: { BGColor:'rgb(20,20,20)', //背景色 BorderColor:'rgb(170,170,170)', //边框颜色 VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(210,210,210)", //成交金额 DateTimeColor:'rgb(210,210,210)', TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(255,0,255)", //持仓 TextColor:"rgb(210,210,210)", //数值名称 ValueColor:"rgb(210,210,210)", //数值 }, DialogSelectRect: { BGColor:'rgb(20,20,20)', //背景色 BorderColor:'rgb(170,170,170)', //边框颜色 TitleColor:'rgb(210,210,210)', //标题颜色 VolColor:"rgb(255, 185, 15)", //标题成交量 AmountColor:"rgb(210,210,210)", //成交金额 TextColor:"rgb(210,210,210)", //数值名称 ValueColor:"rgb(210,210,210)", //数值 TurnoverRateColor:'rgb(43,54,69)', //换手率 PositionColor:"rgb(255,0,255)" //持仓 }, DialogSearchIndex: { BGColor:'rgb(20,20,20)', //背景色 BorderColor:'rgb(170,170,170)', //边框颜色 TitleColor:'rgb(230,230,230)', //标题颜色 IndexNameColor:"rgb(210,210,210)", GroupNameColor:"rgb(210,210,210)", InputTextColor:"rgb(210,210,210)", }, DialogPopKeyboard: { BGColor:'rgb(20,20,20)', //背景色 BorderColor:'rgb(170,170,170)', //边框颜色 TitleColor:'rgb(240,240,240)', //标题颜色 Input: { BGColor:"rgb(20,20,20)", TextColor:"rgb(250,250,250)", } }, //走势图 信息地雷 MinuteInfo: { TextColor: 'rgb(84,143,255)', Font: 14*GetDevicePixelRatio() +'px 微软雅黑', PointColor:'rgb(38,113,254)', LineColor:'rgb(120,167,255)', TextBGColor:'rgba(255,255,255,1)' }, DepthMapPaint: { LineColor:"rgba(255,185,15)", AreaColor:"rgba(255,185,15,0.8)", TextColor:"rgba(255,255,255)", TextBGColor:'rgb(43,54,69)' }, KLineYAxisBGPaint: { Font:12*GetDevicePixelRatio() +'px 微软雅黑', TextColor:"rgb(255,255,255)", LineColor:"rgb(255,255,255)" }, //筹码分布图 StockChip: { InfoColor:'rgb(255,255,255)', //文字颜色 DayInfoColor:'rgb(0,0,0)' //周期颜色内文字颜色 }, //深度图 DepthChart: { BidColor: { Line:"rgb(82,176,123)", Area:"rgba(82,176,123,0.5)"}, //卖 AskColor: { Line:"rgb(207,76,89)", Area:"rgba(207,76,89, 0.5)"}, //买 LineWidth:4 }, DepthCorss: { BidColor: { Line:"rgb(82,176,123)" }, //卖 AskColor: { Line:"rgb(207,76,89)" }, //买 LineWidth:2, //线段宽度 LineDash:[3,3], Tooltip: { BGColor:'rgba(54,54,54, 0.8)', TextColor:"rgb(203,215,224)", Border:{ Top:5, Left:20, Bottom:5, Center: 5}, Font:14*GetDevicePixelRatio() +"px 微软雅黑", LineHeight:16 //单行高度 } }, ChartDrawVolProfile: { BGColor:"rgba(244,250,254,0.3)", BorderColor:"rgba(255,255,255)", VolLineColor:"rgb(232,5,9)", UpVolColor:"rgba(103,179,238, 0.24)", DownVolColor:"rgba(237,208,105,0.24)", AreaUpColor:"rgb(103,179,238,0.7)", AreaDonwColor:"rgba(237,208,105,0.7)", Text:{ Color: "rgb(0,0,0)" , Family:'Arial', FontMaxSize:18, FontMinSize:6 }, //文字 }, //区间选择 RectSelect: { LineColor:"rgb(115,83,64)", //竖线 LineWidth:1*GetDevicePixelRatio(), LineDotted:[3,3], AreaColor:"rgba(26,13,7,0.5)", //面积 }, RectDrag: { LineColor:"rgb(220,220,220)", LineWidth:1*GetDevicePixelRatio(), BGColor:"rgba(220,220,220,0.2)", //面积 }, SelectedChart: { LineWidth:1, LineColor:'rgb(55,100,100)', Radius:4, MinSpace:200, //点和点间最小间距 BGColor:"rgb(255,255,255)" }, DragMovePaint: { TextColor:"rgb(255,255,255)", //Font:14*GetDevicePixelRatio() +"px 微软雅黑" }, SessionBreaksPaint: { BGColor:[null, "rgb(42,46,57)"], SplitLine:{ Color:'rgb(73,133,231)', Width:1*GetDevicePixelRatio(), Dash:[5*GetDevicePixelRatio(),5*GetDevicePixelRatio()] } }, //成交明细 DealList: { BorderColor:'rgb(38,38,41)', //边框线 Header: { Color:"RGB(245,245,245)", Mergin:{ Left:5, Right:5, Top:4, Bottom:2 }, Font:{ Size:12, Name:"微软雅黑" } }, Row: { Mergin:{ Top:2, Bottom:2 }, Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:3, Right:3, Bottom:2 } }, FieldColor: { Vol:"rgb(192,192,0)", //成交量 Time:"rgb(245,245,245)", //时间 Deal:"rgb(111,128,112)", //成交笔数 Index:"rgb(245,245,245)", //序号 BarTitle:'rgb(245,245,245)', //柱子文字 Text:"rgb(245,245,245)", //默认文本 }, UpTextColor:"rgb(238,21,21)", //上涨文字颜色 DownTextColor:"rgb(25,158,0)", //下跌文字颜色 UnchagneTextColor:"rgb(228,228,228)" //平盘文字颜色 }, //报价列表 Report: { BorderColor:'rgb(38,38,41)', //边框线 SelectedColor:"rgb(49,48,56)", //选中行 Header: { Color:"RGB(245,245,245)", SortColor:"rgb(255,0,0)", //Mergin:{ Left:5, Right:5, Top:4, Bottom:2 }, Font:{ Size:12, Name:"微软雅黑" } }, Item: { Mergin:{ Top:2, Bottom:4,Left:5, Right:5 }, Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:3, Right:3, Bottom:2 }, NameFont:{ Size:14, Name:"微软雅黑" }, SymbolFont:{ Size:12, Name:"微软雅黑" } }, //固定行 FixedItem: { Font:{ Size:15, Name:"微软雅黑"}, }, LimitBorder: { Color:"rgb(64,64,64)", Mergin:{ Top:1, Bottom:1,Left:0, Right:0 }, }, FieldColor: { Index:"rgb(245,245,245)", //序号 Symbol:"rgb(255,255,255)", Name:"rgb(255,255,255)", Amount:"rgb(2,226,244)", //成交金额 Vol:"rgb(192,192,0)", //成交量 BarTitle:'rgb(245,245,245)', //柱子文字 Text:"rgb(245,245,245)", //默认文本 }, NameSymbolV2: { Name:{ Size:14, Name:"微软雅黑", Color: "rgb(250,250,250)"}, Symbol:{ Size:12, Name:"微软雅黑", Color: "rgb(190, 190, 190)"}, }, CloseLine: { CloseColor:"rgb(30,144,255)", YCloseColor:"rgba(220,220,220,0.5)", //昨收线 AreaColor:'rgba(220,220,220,0.2)', }, KLine: { UpColor:"rgb(255,0,0)", DownColor:"rgb(0,128,0)", UnchagneColor:'rgb(240,240,240)', DataWidth:16, DistanceWidth:3 }, UpTextColor:"rgb(238,21,21)", //上涨文字颜色 DownTextColor:"rgb(25,158,0)", //下跌文字颜色 UnchagneTextColor:"rgb(228,228,228)", //平盘文字颜色 Tab: { Font:{ Size:12, Name:"微软雅黑" }, ScrollBarWidth:100, ButtonColor:"rgb(13,12,15)", BarColor:"rgb(48,48,48)", BorderColor:'rgb(48,48,48)', TabTitleColor:'rgb(153,153,153)', TabSelectedTitleColor:'rgb(255,255,255)', TabSelectedBGColor:"rgb(234,85,4)", TabMoveOnTitleColor:"rgb(255,255,255)", TabBGColor:"rgb(28,28,31)" }, PageInfo: { Font:{ Size:15, Name:"微软雅黑"}, TextColor:"rgb(255,255,255)", BGColor:"rgba(49,48,56,0.8)", Mergin:{ Left:5, Right:5, Top:4, Bottom:2 }, }, DragRow: { Color:"rgba(255,250, 250,0.8)", TextColor:'rgba(0,0, 0, 0.8)', MoveRowColor:'rgb(135,206,250)', SrcRowColor:'rgb(49,48,56)', }, VScrollbar: { BarWidth:40, ScrollBarHeight:60, ButtonColor:"rgba(13,12,15,0.8)", BarColor:"rgba(48,48,48,0.9)", BorderColor:'rgba(48,48,48,0.9)', BGColor:"rgba(211,211,211,0.5)", }, CheckBox: { Family:"iconfont", Size:15, Checked:{ Color:"rgb(69,147,238)", Symbol:"\ue6b3", DisableColor:"rgb(120,120,120)", MouseOnColor:"rgb(69,147,238)" }, Unchecked:{ Color:"rgb(210,210,210)", Symbol:"\ue6b4", DisableColor:"rgb(120,120,120)", MouseOnColor:"rgb(69,147,238)" }, }, Link: { Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextColor:"rgb(0,144,255)", Disable:{ TextColor:"rgb(211,211,211)" }, MouseOn:{ TextColor:"rgb(0,144,255)" }, }, ProgressBar: { BGColor:"rgb(20,24,28)", BarColor:"rgb(47,124,197)", Margin:{ Left:2, Right:2, Bottom:2, Top:2 }, BarMargin:{ Left:2, Right:2, Bottom:2, Top:2 }, TextColor:"rgb(230,230,230)", Font:`${12*GetDevicePixelRatio()}px 微软雅黑`, TextMargin:{ Left:40, Right:2, Bottom:2, Top:2}, Disable:{ BGColor:"rgb(61,61,61)", BarColor:"rgb(131,131,131)", TextColor:"rgb(159,161,159)"} } }, //T型报价 TReport: { BorderColor:'rgb(38,38,41)', //边框线 SelectedColor:"rgb(180,180,180)", //选中行 Header: { Color:"rgb(187,187,187)", //表头文字颜色 SortColor:"rgb(255,0,0)", //排序箭头颜色 Mergin:{ Left:5, Right:5, Top:4, Bottom:2}, //表头四周间距 Font:{ Size:14, Name:"微软雅黑" } //表头字体 }, Item: { Mergin:{ Top:2, Bottom:0,Left:5, Right:5 }, //单元格四周间距 Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:3, Right:3, Bottom:2 },//单元格字体 NameFont:{ Size:14, Name:"微软雅黑" }, SymbolFont:{ Size:12, Name:"微软雅黑" } }, CenterItem: { TextColor:"rgb(16,226,217)", BaseTextColor:"rgb(60,60,83)", BGColor:"rgb(65,65,65)" }, FieldColor: { Index:"rgb(250,250,250)", //序号 Symbol:"rgb(60,60,60)", Name:"rgb(250,250,250)", Vol:"rgb(192,165,3)", //成交量 Position:"rgb(250,250,250)", //持仓量 Amount:"rgb(16,226,217)", //成交金额 Text:"rgb(250,250,250)", //默认文本 }, UpTextColor:"rgb(238,21,21)", //上涨文字颜色 DownTextColor:"rgb(25,158,0)", //下跌文字颜色 UnchangeTextColor:"rgb(187,187,187)", //平盘文字颜色 UpBGColor:"rgb(35,5,5)", DownBGColor:"rgb(5,35,5)", MarkBorder: { MaxPositionColor:"rgb(192,192,0)" }, }, //键盘精灵 Keyboard: { BorderColor:'rgb(38,38,41)', //边框线 SelectedColor:"rgb(49,48,56)", //选中行 TextColor:"rgb(245,245,245)", Item: { Mergin:{ Top:2, Bottom:0,Left:1, Right:1 }, //单元格四周间距 Font:{ Size:15, Name:"微软雅黑"}, BarMergin:{ Top:2, Left:0, Right:0, Bottom:2 },//单元格字体 NameFont:{ Size:14, Name:"微软雅黑" }, SymbolFont:{ Size:12, Name:"微软雅黑" } }, VScrollbar: { ScrollBarHeight:50, ButtonColor:"rgba(13,12,15,0.8)", BarColor:"rgba(48,48,48,0.9)", BorderColor:'rgba(48,48,48,0.9)', BGColor:"rgba(211,211,211,0.5)", BarWidth:{ Size:8 } }, }, ScrollBar: { BorderColor:'rgb(38,38,41)', //边框线 XSplitTextColor:"rgb(240,240,240)", XSplitLineColor:'rgb(38,38,41)', Slider: { DateFont:`${14*GetDevicePixelRatio()}px 微软雅黑`, DateColor:'rgb(240,240,240)', BarColor:"rgb(105,105,105)", BarAreaColor:"rgba(128,128,128,0.65)" }, BGChart: { Color:"rgb(105,113,125)", LineWidth:1, AreaColor:"rgba(24,28,42,0.5)", }, }, FrameButtomToolbar: { BGColor:"rgb(25,25,25)", BorderColor:"rgb(60,60,60)", Button: { Font:{ Family:"微软雅黑" }, TitleColor: { Selected:"rgb(255,255,255)", Default:"rgb(140,140,140)", MoveOn:"rgb(255,255,255)" }, BGColor: { Selected:"rgb(234,85,4)", Default:"rgb(25,25,25)", MoveOn:"rgb(59,59,59)" }, BorderColor:"rgb(60,60,60)", } } }; return BLACK_STYLE; } var STYLE_TYPE_ID= { BLACK_ID:1, //黑色风格 WHITE_ID:0, //白色风格 } function HQChartStyle() { } HQChartStyle.GetStyleConfig=function(styleid) //获取一个风格的配置变量 { switch (styleid) { case STYLE_TYPE_ID.BLACK_ID: return GetBlackStyle(); case STYLE_TYPE_ID.WHITE_ID: return new JSChartResource(); default: return null; } } /* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装成交明细表格控件 (H5版本) */ function JSDealChart(divElement) { this.DivElement=divElement; this.JSChartContainer; //表格控件 //h5 canvas this.CanvasElement=document.createElement("canvas"); this.CanvasElement.className='jsdeallist-drawing'; this.CanvasElement.id=Guid(); this.CanvasElement.setAttribute("tabindex",0); if (this.CanvasElement.style) this.CanvasElement.style.outline='none'; if(divElement.hasChildNodes()) { JSConsole.Chart.Log("[JSDealChart::JSDealList] divElement hasChildNodes", divElement.childNodes); } divElement.appendChild(this.CanvasElement); this.OnSize=function() { //画布大小通过div获取 var height=parseInt(this.DivElement.style.height.replace("px","")); this.CanvasElement.height=height; this.CanvasElement.width=parseInt(this.DivElement.style.width.replace("px","")); this.CanvasElement.style.width=this.CanvasElement.width+'px'; this.CanvasElement.style.height=this.CanvasElement.height+'px'; var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.CanvasElement.height*=pixelTatio; this.CanvasElement.width*=pixelTatio; JSConsole.Chart.Log(`[JSDealChart::OnSize] devicePixelRatio=${window.devicePixelRatio}, height=${this.CanvasElement.height}, width=${this.CanvasElement.width}`); if (this.JSChartContainer && this.JSChartContainer.OnSize) { this.JSChartContainer.OnSize(); } } this.SetOption=function(option) { var chart=this.CreateJSDealChartContainer(option); if (!chart) return false; if (option.OnCreatedCallback) option.OnCreatedCallback(chart); this.JSChartContainer=chart; this.DivElement.JSChart=this; //div中保存一份 if (!option.Symbol) { chart.Draw(); } else { chart.ChangeSymbol(option.Symbol); } } this.CreateJSDealChartContainer=function(option) { var chart=new JSDealChartContainer(this.CanvasElement); chart.Create(option); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) chart.SetColumn(option.Column); if (IFrameSplitOperator.IsNumber(option.ShowOrder)) chart.ChartPaint[0].ShowOrder=option.ShowOrder; this.SetChartBorder(chart, option); //是否自动更新 if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate; if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; if (IFrameSplitOperator.IsBool(option.EnableFilter)) chart.EnableFilter=option.EnableFilter; //注册事件 if (option.EventCallback) { for(var i=0;i { return this.GetEventCallback(id); } this.ChartPaint[0]=chart; if (option) { if (IFrameSplitOperator.IsBool(option.IsSingleTable)) chart.IsSingleTable=option.IsSingleTable; //单表模式 if (IFrameSplitOperator.IsBool(option.IsShowHeader)) chart.IsShowHeader=option.IsShowHeader; //是否显示表头 if (IFrameSplitOperator.IsBool(option.IsShowLastPage)) this.IsShowLastPage=option.IsShowLastPage; //是否显示最后一页 if (IFrameSplitOperator.IsNumber(option.BorderLine)) this.Frame.BorderLine=option.BorderLine; //边框 } var bRegisterKeydown=true; var bRegisterWheel=true; if (option) { if (option.KeyDown===false) { bRegisterKeydown=false; JSConsole.Chart.Log('[JSDealChartContainer::Create] not register keydown event.'); } if (option.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[JSDealChartContainer::Create] not register wheel event.'); } } if (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 } this.Draw=function() { if (this.UIElement.width<=0 || this.UIElement.height<=0) return; this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度 if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) { this.Frame.Draw( { IsEnableSplash:this.ChartSplashPaint.IsEnableSplash} ); this.ChartSplashPaint.Draw(); return; } this.Frame.Draw(); this.Frame.DrawLogo(); //框架内图形 for(var i=0;i= this.Data.Data.length) this.Data.DataOffset=0; } else { this.AddDealData(this.SourceData, aryDeal); this.AddDealData(this.Data,this.FilterData(aryDeal)); } this.Draw(); } this.AddDealData=function(dealData, aryNewData) { if (!dealData.Data) //原来是空的 { dealData.Data=aryNewData; } else { var pageSize=0; var chart=this.ChartPaint[0]; if (chart) pageSize=chart.GetPageSize(); for(var i=0;i0 && IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { var pageSize=chart.GetPageSize(true); if (pageSize+this.Data.DataOffset>=this.Data.Data.length) //当前屏不能显示满,调整 this.GotoLastPage(); } this.Draw(); } this.SetSizeChange=function(bChanged) { var chart=this.ChartPaint[0]; if (chart) chart.SizeChange=bChanged; } this.OnWheel=function(e) //滚轴 { JSConsole.Chart.Log('[JSDealChartContainer::OnWheel]',e); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; var x = e.clientX-this.UIElement.getBoundingClientRect().left; var y = e.clientY-this.UIElement.getBoundingClientRect().top; var isInClient=false; this.Canvas.beginPath(); this.Canvas.rect(this.Frame.ChartBorder.GetLeft(),this.Frame.ChartBorder.GetTop(),this.Frame.ChartBorder.GetWidth(),this.Frame.ChartBorder.GetHeight()); isInClient=this.Canvas.isPointInPath(x,y); if (!isInClient) return; var chart=this.ChartPaint[0]; if (!chart) return; var wheelValue=e.wheelDelta; if (!IFrameSplitOperator.IsObjectExist(e.wheelDelta)) wheelValue=e.deltaY* -0.01; if (wheelValue<0) //下一页 { if (this.GotoNextPage()) this.Draw(); } else if (wheelValue>0) //上一页 { if (this.GotoPreviousPage()) this.Draw(); } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnKeyDown=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var keyID = e.keyCode ? e.keyCode :e.which; switch(keyID) { case 38: //up if (this.GotoPreviousPage()) this.Draw(); break; case 40: //down if (this.GotoNextPage()) this.Draw(); break; } //不让滚动条滚动 if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.GotoNextPage=function() { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageSize=chart.GetPageSize(); if (pageSize>this.Data.Data.length) return false; var offset=this.Data.DataOffset+pageSize; if (offset+pageSize==this.Data.Data.length-1) return false; if (offset+pageSize>this.Data.Data.length) //最后一页不够一屏调整到满屏 { this.Data.DataOffset=this.Data.Data.length-pageSize; } else { this.Data.DataOffset=offset; } return true; } this.GotoPreviousPage=function() { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; if (this.Data.DataOffset<=0) return false; var pageSize=chart.GetPageSize(); var offset=this.Data.DataOffset; offset-=pageSize; if (offset<0) offset=0; this.Data.DataOffset=offset; return true; } this.GotoLastPage=function() { var chart=this.ChartPaint[0]; if (!chart) return; //显示最后一屏 var pageSize=chart.GetPageSize(true); var offset=this.Data.Data.length-pageSize; if (offset<0) offset=0; this.Data.DataOffset=offset; } this.SetColumn=function(aryColunm, option) { var chart=this.ChartPaint[0]; if (chart) { chart.SetColumn(aryColunm); chart.SizeChange=true; if (option && option.Redraw) this.Draw(); } } this.ReloadResource=function(option) { this.Frame.ReloadResource(option); for(var i=0;i0) //上 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(right,top); } if ((this.BorderLine&2)>0) //下 { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } if ((this.BorderLine&4)>0) //左 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(left,bottom); } if ((this.BorderLine&8)>0) //右 { this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); } this.Canvas.stroke(); } } this.DrawLogo=function() { var text=g_JSChartResource.FrameLogo.Text; if (!IFrameSplitOperator.IsString(text)) return; this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.font=this.LogoTextFont; this.Canvas.textAlign = 'left'; this.Canvas.textBaseline = 'bottom'; var x=this.ChartBorder.GetLeft()+5; var y=this.ChartBorder.GetBottom()-5; this.Canvas.fillText(text,x,y); } } var DEAL_COLUMN_ID= { TIME_ID:0, //时间 PRICE_ID:1, //成交价格 VOL_ID:2, //成交量 DEAL_ID:3, //成交笔数 BS_ID:4, UPDOWN_ID:5, //涨跌 STRING_TIME_ID:6, //字符串时间 INDEX_ID:7, //序号 从1开始 MULTI_BAR_ID:8, //多颜色柱子 CENTER_BAR_ID:9, //中心柱子 CUSTOM_TEXT_ID:10 //自定义文本 } function ChartDealList() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartDealList'; //类名 this.IsDrawFirst=false; this.GetEventCallback; this.Data; //数据 { Data:[ { Time:, Price:, Vol:, BS:, StrTime } ], Offset: } //this.Data={Offset:0, Data:[ {Time:925, Price:20.1, Vol:10000050, BS:1, Deal:45 }, {Time:925, Price:18.2, Vol:1150, BS:1, Deal:5 }] }; this.Symbol; this.YClose; //昨收 this.Open; //开盘价 this.Decimal=2; //小数位数 this.IsSingleTable=false; //单表模式 this.IsShowHeader=true; //是否显示表头 this.ShowOrder=1; //0=顺序 1=倒序 this.SizeChange=true; //涨跌颜色 this.UpColor=g_JSChartResource.DealList.UpTextColor; this.DownColor=g_JSChartResource.DealList.DownTextColor; this.UnchagneColor=g_JSChartResource.DealList.UnchagneTextColor; this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.DealList.Header.Font.Size, Name:g_JSChartResource.DealList.Header.Font.Name }; this.HeaderColor=g_JSChartResource.DealList.Header.Color; this.HeaderMergin= { Left:g_JSChartResource.DealList.Header.Mergin.Left, Right:g_JSChartResource.DealList.Header.Mergin.Right, Top:g_JSChartResource.DealList.Header.Mergin.Top, Bottom:g_JSChartResource.DealList.Header.Mergin.Bottom }; //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.DealList.Row.Font.Size, Name:g_JSChartResource.DealList.Row.Font.Name }; this.RowMergin={ Top:g_JSChartResource.DealList.Row.Mergin.Top, Bottom:g_JSChartResource.DealList.Row.Mergin.Bottom }; this.BarMergin= { Top:g_JSChartResource.DealList.Row.BarMergin.Top, Left:g_JSChartResource.DealList.Row.BarMergin.Left, Right:g_JSChartResource.DealList.Row.BarMergin.Right, Bottom:g_JSChartResource.DealList.Row.BarMergin.Bottom }; //缓存 this.HeaderFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.RowCount=0; this.TableWidth=0; this.TableCount=0; this.HeaderHeight=0; this.Column= [ { Type:DEAL_COLUMN_ID.TIME_ID, Title:"时间", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.Time, MaxText:"88:88:88" , Foramt:"HH:MM:SS"}, { Type:DEAL_COLUMN_ID.PRICE_ID, Title:"价格", TextAlign:"center", Width:null, MaxText:"888888.88"}, { Type:DEAL_COLUMN_ID.VOL_ID, Title:"成交", TextAlign:"right", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.Vol, MaxText:"888888"}, { Type:DEAL_COLUMN_ID.BS_ID, Title:"", TextAlign:"right", Width:null, MaxText:"擎" } ]; this.RectClient={}; this.ReloadResource=function(resource) { this.UpColor=g_JSChartResource.DealList.UpTextColor; this.DownColor=g_JSChartResource.DealList.DownTextColor; this.UnchagneColor=g_JSChartResource.DealList.UnchagneTextColor; this.BorderColor=g_JSChartResource.DealList.BorderColor; //边框线 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.DealList.Header.Font.Size, Name:g_JSChartResource.DealList.Header.Font.Name }; this.HeaderColor=g_JSChartResource.DealList.Header.Color; this.HeaderMergin= { Left:g_JSChartResource.DealList.Header.Mergin.Left, Right:g_JSChartResource.DealList.Header.Mergin.Right, Top:g_JSChartResource.DealList.Header.Mergin.Top, Bottom:g_JSChartResource.DealList.Header.Mergin.Bottom }; //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.DealList.Row.Font.Size, Name:g_JSChartResource.DealList.Row.Font.Name }; this.RowMergin={ Top:g_JSChartResource.DealList.Row.Mergin.Top, Bottom:g_JSChartResource.DealList.Row.Mergin.Bottom }; for(var i=0;i=dataCount) index=dataCount-1; for(var i=0,j=0;i=0;++j, --index) { var dataItem=this.Data.Data[index]; this.DrawRow(dataItem, textLeft, textTop, index); textTop+=this.RowHeight; } } } else { for(var i=0,j=0;itableRight) break; if (i==this.Column.length-1) itemWidth=this.TableWidth-(left-tableLeft)-this.HeaderMergin.Right-this.HeaderMergin.Left; if (item.Type==DEAL_COLUMN_ID.TIME_ID) { text=IFrameSplitOperator.FormatTimeString(data.Time,item.Foramt); } else if (item.Type==DEAL_COLUMN_ID.STRING_TIME_ID) { text=data.StrTime; } else if (item.Type==DEAL_COLUMN_ID.PRICE_ID) { if (data.Price>this.YClose) textColor=this.UpColor; else if (data.Price0) textColor=this.UpColor; else if (value<0) textColor=this.DownColor; else textColor=this.UnchagneColor; } } else if (item.Type==DEAL_COLUMN_ID.INDEX_ID) { text=(dataIndex+1).toString(); } else if (item.Type==DEAL_COLUMN_ID.MULTI_BAR_ID) { var rtItem={Left:left, Top:top, Width:itemWidth, Height:this.RowHeight}; this.DrawMultiBar(item, data, rtItem); } else if (item.Type==DEAL_COLUMN_ID.CENTER_BAR_ID) { var rtItem={Left:left, Top:top, Width:itemWidth, Height:this.RowHeight}; this.DrawCenterBar(item, data, rtItem); } else if (item.Type==DEAL_COLUMN_ID.CUSTOM_TEXT_ID) { var out={ Text:null, TextColor:null, TextAlign:null }; //输出 var rtItem={Left:left, Top:top, Width:itemWidth, Height:this.RowHeight}; if (this.DrawCustomText(item, data, rtItem, dataIndex, i, out)) { if (out.Text) text=out.Text; if (out.TextColor) textColor=out.TextColor; if (out.TextAlign) textAlign=out.TextAlign; } } this.DrawItemText(text, textColor, textAlign, left, top, itemWidth); left+=item.Width; } } this.DrawItemText=function(text, textColor, textAlign, left, top, width) { var x=left; if (textAlign=='center') { x=left+width/2; this.Canvas.textAlign="center"; } else if (textAlign=='right') { x=left+width; this.Canvas.textAlign="right"; } else { this.Canvas.textAlign="left"; } this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=textColor; if (text) this.Canvas.fillText(text,x,top+this.RowHeight/2); } this.DrawMultiBar=function(colunmInfo, data, rtItem) { if (!data.Source || !IFrameSplitOperator.IsNonEmptyArray(data.Source)) return false; var barData=data.Source[colunmInfo.DataIndex]; //{ Value:[0.4,0,2], Color:[0,1] }; if (!barData) return false; if (!IFrameSplitOperator.IsNonEmptyArray(barData.Value)) return false; var width=rtItem.Width-this.BarMergin.Left-this.BarMergin.Right; var left=rtItem.Left+this.BarMergin.Left; var top=rtItem.Top+this.RowMergin.Top+this.BarMergin.Top; var height=rtItem.Height-this.RowMergin.Top-this.RowMergin.Bottom-this.BarMergin.Top-this.BarMergin.Bottom; var right=left+width; for(var i=0;i=right) break; var barWidth=width*value; if (barWidth<1) barWidth=1; if (left+barWidth>right) barWidth=right-left; var colorIndex=i; if (IFrameSplitOperator.IsNonEmptyArray(barData.Color) && i1) value=1; var barWidth=width*value; if (barWidth<1) barWidth=1; var colorIndex=i; if (IFrameSplitOperator.IsNonEmptyArray(barData.Color) && i{ return this.GetExtraCanvas(name); } chart.Create(option); if (option.NetworkFilter) chart.NetworkFilter=option.NetworkFilter; if (IFrameSplitOperator.IsNonEmptyArray(option.Column)) chart.SetColumn(option.Column); if (IFrameSplitOperator.IsNonEmptyArray(option.Tab)) chart.SetTab(option.Tab); if (IFrameSplitOperator.IsNumber(option.TabSelected)) chart.SetSelectedTab(option.TabSelected); if (IFrameSplitOperator.IsBool(option.EnableDragRow)) chart.EnableDragRow=option.EnableDragRow; if (IFrameSplitOperator.IsNumber(option.DragRowType)) chart.DragRowType=option.DragRowType; if (IFrameSplitOperator.IsBool(option.EnableDragHeader)) chart.EnableDragHeader=option.EnableDragHeader; if (IFrameSplitOperator.IsNumber(option.WheelPageType)) chart.WheelPageType=option.WheelPageType; if (IFrameSplitOperator.IsBool(option.PageUpDownCycle)) chart.PageUpDownCycle=option.PageUpDownCycle; if (option.VScrollbar) chart.SetVScrollbar(option.VScrollbar); if (option.SortInfo) { var item=option.SortInfo; if (IFrameSplitOperator.IsNumber(item.Field)) chart.SortInfo.Field=item.Field; if (IFrameSplitOperator.IsNumber(item.Sort)) chart.SortInfo.Sort=item.Sort; } if (option.VirtualTable) { var item=option.VirtualTable; if (IFrameSplitOperator.IsBool(item.Enable)) chart.Data.Virtual.Enable=item.Enable; } var reportChart=chart.GetReportChart(); if (reportChart) { if (IFrameSplitOperator.IsNumber(option.TextOverflowStyle)) reportChart.TextOverflowStyle=option.TextOverflowStyle; if (IFrameSplitOperator.IsNumber(option.MultiSelectModel)) reportChart.MultiSelectModel=option.MultiSelectModel; } this.SetChartBorder(chart, option); //是否自动更新 if (option.IsAutoUpdate!=null) chart.IsAutoUpdate=option.IsAutoUpdate; if (option.AutoUpdateFrequency>0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; if (IFrameSplitOperator.IsBool(option.EnableFilter)) chart.EnableFilter=option.EnableFilter; //注册事件 if (option.EventCallback) { for(var i=0;i{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } this.OnDivResize=function(entries) { JSConsole.Chart.Log("[JSReportChart::OnDivResize] entries=", entries); this.OnSize(); } ///////////////////////////////////////////////////////////////////////////// //对外接口 //切换股票代码接口 this.ChangeSymbol=function(symbol, option) { if (this.JSChartContainer) this.JSChartContainer.ChangeSymbol(symbol,option); } this.SetColumn=function(aryColumn, option) { if (this.JSChartContainer) this.JSChartContainer.SetColumn(aryColumn,option); } this.SetSelectedRow=function(option) { if (this.JSChartContainer) this.JSChartContainer.SetSelectedRow(option); } this.EnableFilter=function(bEnable, option) //启动|关闭筛选 { if (this.JSChartContainer) this.JSChartContainer.EnableFilter(bEnable, option); } //事件回调 this.AddEventCallback=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function') { JSConsole.Chart.Log('[JSReportChart:AddEventCallback] obj=', obj); this.JSChartContainer.AddEventCallback(obj); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSReportChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } this.ChartDestory=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestory) == 'function') { this.JSChartContainer.ChartDestory(); } } this.Draw=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.Draw)=='function') { JSConsole.Chart.Log('[JSReportChart:Draw] '); this.JSChartContainer.Draw(); } } } JSReportChart.TooltipCursorCanvasKey="hq_report_tooltip"; //提示信息 JSReportChart.Init=function(divElement) { var jsChartControl=new JSReportChart(divElement); jsChartControl.OnSize(); return jsChartControl; } //自定义风格 JSReportChart.SetStyle=function(option) { if (option) g_JSChartResource.SetStyle(option); } //获取颜色配置 (设置配必须啊在JSChart.Init()之前) JSReportChart.GetResource=function() { return g_JSChartResource; } function HQReportItem() { this.OriginalSymbol; //原始代码 this.Symbol; this.Name; this.YClose; this.Open; this.Price; this.High; this.Low; this.Amount; this.Vol; this.Increase; //涨幅 this.UpDown; //涨跌 this.Exchange; //换手 this.Amplitude; //振幅 this.BuyPrice; //买价/量 this.BuyVol; this.SellPrice; //卖价/量 this.SellVol; this.AvPrice; //均价 this.LimitHigh; //涨停价 this.LimitLow; //跌停价 this.VolIn; //内盘 this.VolOut; //外盘 this.DealNum; //现量 this.OutShares; //流通股本 this.TotalShares; //总股本 this.MarketValue; //总市值 this.CircMarketValue;//流通市值 this.CloseLine; //{Data:[], Max:, Min:, Count: } this.ExtendData; //扩展数据 this.Time; this.Date; } function JSReportChartContainer(uielement) { this.ClassName='JSReportChartContainer'; this.Frame; //框架画法 this.ChartPaint=[]; //图形画法 this.ChartSplashPaint=null; //等待提示 this.LoadDataSplashTitle="数据加载中"; //下载数据提示信息 this.SplashTitle={ StockList:"下载码表中.....", MemberList:"下载成分中....." } ; this.Canvas=uielement.getContext("2d"); //画布 this.TooltipCanvas; this.ChartTooltip; this.Tooltip=document.createElement("div"); this.Tooltip.className='jsreport-tooltip'; this.Tooltip.style.background=g_JSChartResource.TooltipBGColor; this.Tooltip.style.opacity=g_JSChartResource.TooltipAlpha; this.Tooltip.style["pointer-events"]="none"; this.Tooltip.id=Guid(); uielement.parentNode.appendChild(this.Tooltip); this.Symbol; //板块代码 this.Name; //板块名称 this.NetworkFilter; //数据回调接口 this.Data={ XOffset:0, YOffset:0, Data:[], Virtual:{ Enable:false, Count:0 } }; //股票列表 (Virtual 虚拟表) this.SourceData={ Data:[] } ; //原始股票顺序(排序还原用) this.BlockData=new Map(); //当前板块数据 this.MapStockData=new Map(); //原始股票数据 this.FixedRowData={ Data:[], Type:0, Symbol:[] }; //顶部固定行Data:[{ Value:, Text:, Color:, TextAgiln: }], Type:0=自定义数据, 1 =(股票数据) Symbol:[], this.FlashBG=new Map(); this.FlashBGTimer=null; //闪烁背景 Value:{ LastTime:数据最后的时间, Data: { Key:ID, BGColor:, Time: , Count: 次数 } }; this.GlobalOption={ FlashBGCount:0 }; //this.FixedRowData.Data=[ [null, {Value:11, Text:"11" }], [null, null, null, {Value:12, Text:"ddddd", Color:"rgb(45,200,4)"}]]; this.SortInfo={ Field:-1, Sort:0 }; //排序信息 {Field:排序字段id, Sort:0 不排序 1升序 2降序 } //行拖拽 this.DragRow; this.DragColumnWidth; //列宽拖动 this.EnableDragRow=false; this.DragRowType=0; //0=插入 1=交换 this.AutoDragScrollTimer=null; this.EnablePageScroll=false; this.DragMove; //={ Click:{ 点击的点}, Move:{最后移动的点}, PreMove:{上一个点的位置} }; //表头拖拽 this.DragHeader; this.EnableDragHeader=false; //事件回调 this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} this.AutoUpdateTimer=null; this.AutoUpdateFrequency=15000; //15秒更新一次数据 this.DelayUpdateTimer=null; //延迟更新 this.DelayUpdateFrequency=500; //延迟更新时间 this.UIElement=uielement; this.LastPoint=new Point(); //鼠标位置 this.IsOnTouch=false; this.TouchDrag; this.TouchMoveMinAngle=70; //左右移动最小角度 this.YStepPixel=5*GetDevicePixelRatio(); this.XStepPixel=10*GetDevicePixelRatio(); this.PageUpDownCycle=true; //翻页循环 this.DragPageCycle=true; //手机翻页循环 this.WheelPageType=0; //鼠标滚轴翻页模式 0=一页一页翻 1=一条一条翻 //拖拽滚动条 this.DragXScroll=null; //{Start:{x,y}, End:{x, y}} this.DragYScroll=null; this.IsShowVScrollbar=false; this.IsDestroy=false; //是否已经销毁了 this.JSPopMenu; //内置菜单 this.IsShowRightMenu=true; //MouseOnStatus:{ RowIndex:行, ColumnIndex:列} this.LastMouseStatus={ MoveStatus:null, TooltipStatus:null, MouseOnStatus:null }; this.ChartDestory=function() //销毁 { this.IsDestroy=true; this.StopAutoUpdate(); } this.StopAutoDragScrollTimer=function() { JSConsole.Chart.Log("[JSReportChartContainer::StopAutoDragScrollTimer] stop "); this.EnablePageScroll=false; if (this.AutoDragScrollTimer!=null) { clearTimeout(this.AutoDragScrollTimer); this.AutoDragScrollTimer = null; } } this.InitalPopMenu=function() //初始化弹出窗口 { if (this.JSPopMenu) return; this.JSPopMenu=new JSPopMenu(); //内置菜单 this.JSPopMenu.Inital(); } this.AutoScrollPage=function(step) { this.AutoDragScrollTimer=setTimeout(() => { this.ChartOperator_Temp_ScrollPage(step); },300); } this.ChartOperator_Temp_ScrollPage=function(moveSetp) { if (!this.EnablePageScroll) return; var reportChart=this.GetReportChart() if (!reportChart) return; if (moveSetp>0) { var pageStatus=reportChart.GetCurrentPageStatus(); if (pageStatus.IsEnd) return; this.MoveYOffset(moveSetp, false); ++moveSetp; } else if (moveSetp<0) { if (this.Data.YOffset<=0) return; this.MoveYOffset(moveSetp, false); --moveSetp; } else { return; } this.Draw(); if (!this.EnablePageScroll) return; this.AutoScrollPage(moveSetp); return; } //清空画布 this.ClearCanvas=function(canvas) { if (!canvas) return; if (!this.UIElement) return; canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); } //清空固定行数据 this.ClearFixedRowData=function() { this.FixedRowData.Data=[]; this.FixedRowData.Symbol=[]; } //设置固定行 this.SetFixedRowCount=function(value) { var chart=this.GetReportChart(); if (!chart) return; chart.FixedRowCount=value; } //创建 this.Create=function(option) { this.UIElement.JSChartContainer=this; //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.IsEnableSplash=true; //创建框架 this.Frame=new JSReportFrame(); this.Frame.ChartBorder=new ChartBorder(); this.Frame.ChartBorder.UIElement=this.UIElement; this.Frame.ChartBorder.Top=30; this.Frame.ChartBorder.Left=5; this.Frame.ChartBorder.Bottom=20; this.Frame.Canvas=this.Canvas; this.ChartSplashPaint.Frame = this.Frame; //创建表格 var chart=new ChartReport(); chart.Frame=this.Frame; chart.ChartBorder=this.Frame.ChartBorder; chart.Canvas=this.Canvas; chart.UIElement=this.UIElement; chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); } chart.GetStockDataCallback=(symbol)=>{ return this.GetStockData(symbol);} chart.GetBlockDataCallback=(symbol)=>{ return this.GetBlockData(symbol);} chart.GetFlashBGDataCallback=(symbol, time)=>{ return this.GetFlashBGData(symbol, time); } chart.Data=this.Data; chart.GlobalOption=this.GlobalOption; chart.FixedRowData=this.FixedRowData; chart.SortInfo=this.SortInfo; chart.Tab=new ChartReportTab(); chart.Tab.Frame=this.Frame; chart.Tab.Canvas=this.Canvas; chart.Tab.ChartBorder=this.Frame.ChartBorder; chart.Tab.Report=chart; chart.VScrollbar=new ChartVScrollbar(); chart.VScrollbar.Frame=this.Frame; chart.VScrollbar.Canvas=this.Canvas; chart.VScrollbar.ChartBorder=this.Frame.ChartBorder; chart.VScrollbar.Report=chart; chart.VScrollbar.IsShowCallback=()=> { if (this.DragYScroll) return true; return this.IsShowVScrollbar; } this.ChartPaint[0]=chart; //提示信息 var chartTooltip=new ChartCellTooltip(); chartTooltip.Frame=this.Frame; chartTooltip.ChartBorder=this.Frame.ChartBorder; this.ChartTooltip=chartTooltip; //页脚 if (option && option.PageInfo===true) { var pageInfoChart=new ChartReportPageInfo(); pageInfoChart.Frame=this.Frame; pageInfoChart.ChartBorder=this.Frame.ChartBorder; pageInfoChart.Canvas=this.Canvas; pageInfoChart.Report=chart; this.ChartPaint[1]=pageInfoChart; } if (option) { if (IFrameSplitOperator.IsBool(option.IsShowHeader)) chart.IsShowHeader=option.IsShowHeader; //是否显示表头 if (IFrameSplitOperator.IsNumber(option.FixedColumn)) chart.FixedColumn=option.FixedColumn; //固定列 if (IFrameSplitOperator.IsNumber(option.BorderLine)) this.Frame.BorderLine=option.BorderLine; //边框 if (IFrameSplitOperator.IsBool(option.TabShow)) chart.Tab.IsShow=option.TabShow; if (IFrameSplitOperator.IsNumber(option.FixedRowCount)) chart.FixedRowCount=option.FixedRowCount; //固定行 if (IFrameSplitOperator.IsBool(option.ItemBorder)) chart.IsDrawBorder=option.ItemBorder; //单元格边框 if (IFrameSplitOperator.IsNumber(option.SelectedModel)) chart.SelectedModel=option.SelectedModel; if (IFrameSplitOperator.IsNonEmptyArray(option.FixedSymbol)) { chart.FixedRowCount=0; this.FixedRowData.Type=1; this.FixedRowData.Symbol=[]; var aryData=option.FixedSymbol; for(var i=0; i{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 this.UIElement.ondblclick=(e)=>{ this.UIOnDblClick(e); } this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); } this.UIElement.onmouseup=(e)=>{ this.UIOnMounseUp(e); } this.UIElement.oncontextmenu=(e)=> { this.UIOnContextMenu(e); } this.UIElement.onmousemove=(e)=>{ this.UIOnMouseMove(e);} this.UIElement.onmouseout=(e)=>{ this.UIOnMounseOut(e); } this.UIElement.onmouseleave=(e)=>{ this.UIOnMouseleave(e); } //手机拖拽 this.UIElement.ontouchstart=(e)=> { this.OnTouchStart(e); } this.UIElement.ontouchmove=(e)=> {this.OnTouchMove(e); } this.UIElement.ontouchend=(e)=> {this.OnTouchEnd(e); } } this.Draw=function() { if (this.UIElement.width<=0 || this.UIElement.height<=0) return; this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度 this.LastMouseStatus.MouseOnStatus=null; if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) { this.Frame.Draw( { IsEnableSplash:this.ChartSplashPaint.IsEnableSplash} ); this.ChartSplashPaint.Draw(); return; } this.Frame.Draw(); this.Frame.DrawLogo(); //框架内图形 for(var i=0;i0) { this.DelayDraw(500); } this.DrawTooltip(this.LastMouseStatus.TooltipStatus); } this.DelayDraw=function(frequency) { if (typeof (this.FlashBGTimer) == 'number') { clearTimeout(this.FlashBGTimer); this.FlashBGTimer = null; } this.FlashBGTimer=setTimeout(()=> { this.Draw(); },frequency); } this.ResetReportStatus=function() { this.Data.XOffset=0; this.Data.YOffset=0; } this.ResetReportSelectStatus=function() { var chart=this.GetReportChart(); if (chart) { chart.SelectedRow=-1; chart.SelectedFixedRow=-1; chart.MultiSelectedRow=[]; } } this.ClearData=function() { this.SourceData.Data=[]; this.Data.Data=[]; this.Data.Virtual.Count=0; this.BlockData=new Map(); } this.ClearMapStockData=function() { this.MapStockData=new Map(); } this.ResetSortStatus=function() { this.SortInfo.Field=-1; this.SortInfo.Sort=0; } this.SetSelectedRow=function(option) { var reportChart=this.GetReportChart(); if (!reportChart) return false; if (!reportChart.SetSelectedRow(option)) return false; this.Draw(); } //设置股票列表 this.SetSymbolList=function(arySymbol, option) { this.ClearData(); this.ResetReportStatus(); this.ResetSortStatus(); if (IFrameSplitOperator.IsNonEmptyArray(arySymbol)) { for(var i=0;i{ this.RequestMemberListData(); }; this.MapStockData=new Map(); this.RequestStockListData(requestOption); return; } } this.RequestMemberListData(); } //更新数据 this.UpdateFullData=function(data) { var arySymbol=[]; if (IFrameSplitOperator.IsNonEmptyArray(data.data)) { //0=证券代码 1=股票名称 for(var i=0;i=0 && this.SortInfo.Sort>0) { var reportChart=this.GetReportChart(); if (reportChart) { var column=reportChart.Column[this.SortInfo.Field]; obj.Sort={ Column:column, Field:this.SortInfo.Field, Sort:this.SortInfo.Sort} ; } } this.NetworkFilter(obj, function(data) { self.ChartSplashPaint.EnableSplash(false); self.RecvMemberListData(data); }); if (obj.PreventDefault==true) return; //已被上层替换,不调用默认的网络请求 } //throw { Name:'JSReportChartContainer::RequestMemberListData', Error:'(板块成分数据)不提供内置测试数据' }; } this.RecvMemberListData=function(recvData) { this.ClearData(); if (IFrameSplitOperator.IsNonEmptyArray(recvData.data)) { for(var i=0;i=timeDiff) //超时的删除 { this.FlashBG.delete(symbol); return null; } if (!stockItem.Data || stockItem.Data.size<=0) { this.FlashBG.delete(symbol); return null; } var aryDelID=[]; //超时需要参数的 for(var mapItem of stockItem.Data) { var item=mapItem[1]; if (time-item.Time>=timeDiff || item.Count<=0) aryDelID.push(item.ID); } if (IFrameSplitOperator.IsNonEmptyArray(aryDelID)) { for(var i=0; i { this.UpdateStockData(); },frequency); } this.UpdateStockData=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; var chart=this.ChartPaint[0]; if (!chart) return; if (this.Data.Virtual && this.Data.Virtual.Enable) { this.RequestVirtualStockData(); //虚拟表格 全部取后台 return; } if (this.SortInfo && this.SortInfo.Field>=0 && this.SortInfo.Sort>0) { var column=chart.Column[this.SortInfo.Field]; if (column.Sort==2) { this.RequestStockSortData(column, this.SortInfo.Field, this.SortInfo.Sort); //远程排序 return; } } var arySymbol=chart.ShowSymbol; if (!IFrameSplitOperator.IsNonEmptyArray(arySymbol)) return; this.RequestStockData(arySymbol); } //下载股票数据 this.RequestStockData=function(arySymbol) { var self=this; if (this.NetworkFilter) { var obj= { Name:'JSDealChartContainer::RequestStockData', //类名::函数名 Explain:'报价列表股票数据', Request:{ Data: { stocks: arySymbol } , symbol:this.Symbol, name:this.Name }, Self:this, PreventDefault:false }; this.NetworkFilter(obj, function(data) { self.RecvStockData(data); self.AutoUpdate(); }); if (obj.PreventDefault==true) return; } //throw { Name:'JSReportChartContainer::RequestStockData', Error:'(报价列表股票数据)不提供内置测试数据' }; } this.RecvStockData=function(data) { var setUpdateSymbol=new Set(); //更新的股票列表 if (IFrameSplitOperator.IsNonEmptyArray(data.data)) { //0=证券代码 1=股票名称 2=昨收 3=开 4=高 5=低 6=收 7=成交量 8=成交金额, 9=买价 10=买量 11=卖价 12=卖量 13=均价 14=流通股 15=总股本 for(var i=0;i=0) { var column=chart.Column[this.SortInfo.Field]; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_LOCAL_SORT); if (event && event.Callback) { var sendData={ Column:column, SortInfo:this.SortInfo, SymbolList:this.Data.Data, Result:null }; event.Callback (event, sendData, this); if (Array.isArray(sendData.Result)) this.Data.Data=sendData.Result; } else { this.Data.Data.sort((left, right)=> { return this.LocalSort(left, right, column, this.SortInfo.Sort); }); } bUpdate=true; //排序暂时每次都刷新 } else { //更新的股票在当前页面,需要重绘 var aryStock=chart.ShowSymbol; for(var i=0;i0) stock.Exchange=stock.Vol/stock.OutShares*100; } if (!IFrameSplitOperator.IsNumber(item[24])) //振幅% { if (IFrameSplitOperator.IsNumber(stock.High) && IFrameSplitOperator.IsNumber(stock.Low) && IFrameSplitOperator.IsNumber(stock.YClose) && stock.YClose!=0) stock.Amplitude=(stock.High-stock.Low)/stock.YClose*100; } if (!IFrameSplitOperator.IsNumber(item[25])) //流通市值 { if (IFrameSplitOperator.IsNumber(stock.OutShares) && IFrameSplitOperator.IsNumber(stock.Price)) stock.CircMarketValue=stock.OutShares*stock.Price; } if (!IFrameSplitOperator.IsNumber(item[26])) //总市值 { if (IFrameSplitOperator.IsNumber(stock.TotalShares) && IFrameSplitOperator.IsNumber(stock.Price)) stock.MarketValue=stock.TotalShares*stock.Price; } if (item[30]) stock.ExtendData=item[30]; //30=全局扩展数据 if (item[31]) this.BlockData.set(stock.OriginalSymbol,item[31]); //31=当前板块数据 if (item[32]) stock.CloseLine=item[32]; //32=收盘价线 if (item[33]) stock.KLine=item[33]; //33=K线 if (IFrameSplitOperator.IsNumber(item[35])) stock.Time=item[35]; //时间 hhmm / hhmmss / hhmmss.fff if (IFrameSplitOperator.IsNumber(item[36])) stock.Date=item[36]; //日期 if (IFrameSplitOperator.IsBool(item[37])) stock.Checked=item[37]; if (IFrameSplitOperator.IsNumber(item[38])) stock.Position=item[38]; //持仓量 if (IFrameSplitOperator.IsNumber(item[39])) stock.FClose=item[39]; //结算价 if (IFrameSplitOperator.IsNumber(item[40])) stock.YFClose=item[40]; //昨结算价 if (IFrameSplitOperator.IsNumber(item[41])) stock.OpenPosition=item[41]; //开仓量 if (IFrameSplitOperator.IsNumber(item[42])) stock.ClosePosition=item[42]; //平仓量 //1,3,5,10,15 涨速% if (IFrameSplitOperator.IsNumber(item[43])) stock.RSpeed1M=item[43]; if (IFrameSplitOperator.IsNumber(item[44])) stock.RSpeed3M=item[44]; if (IFrameSplitOperator.IsNumber(item[45])) stock.RSpeed5M=item[45]; if (IFrameSplitOperator.IsNumber(item[46])) stock.RSpeed10M=item[46]; if (IFrameSplitOperator.IsNumber(item[47])) stock.RSpeed15M=item[47]; //10个数值型 101-199 if (IFrameSplitOperator.IsNumber(item[101])) stock.ReserveNumber1=item[101]; if (IFrameSplitOperator.IsNumber(item[102])) stock.ReserveNumber2=item[102]; if (IFrameSplitOperator.IsNumber(item[103])) stock.ReserveNumber3=item[103]; if (IFrameSplitOperator.IsNumber(item[104])) stock.ReserveNumber4=item[104]; if (IFrameSplitOperator.IsNumber(item[105])) stock.ReserveNumber5=item[105]; if (IFrameSplitOperator.IsNumber(item[106])) stock.ReserveNumber6=item[106]; if (IFrameSplitOperator.IsNumber(item[107])) stock.ReserveNumber7=item[107]; if (IFrameSplitOperator.IsNumber(item[108])) stock.ReserveNumber8=item[108]; if (IFrameSplitOperator.IsNumber(item[109])) stock.ReserveNumber9=item[109]; if (IFrameSplitOperator.IsNumber(item[110])) stock.ReserveNumber10=item[110]; //10个字符型 201-299 if (IFrameSplitOperator.IsString(item[201])) stock.ReserveString1=item[201]; if (IFrameSplitOperator.IsString(item[202])) stock.ReserveString2=item[202]; if (IFrameSplitOperator.IsString(item[203])) stock.ReserveString3=item[203]; if (IFrameSplitOperator.IsString(item[204])) stock.ReserveString4=item[204]; if (IFrameSplitOperator.IsString(item[205])) stock.ReserveString5=item[205]; if (IFrameSplitOperator.IsString(item[206])) stock.ReserveString6=item[206]; if (IFrameSplitOperator.IsString(item[207])) stock.ReserveString7=item[207]; if (IFrameSplitOperator.IsString(item[208])) stock.ReserveString8=item[208]; if (IFrameSplitOperator.IsString(item[209])) stock.ReserveString9=item[209]; if (IFrameSplitOperator.IsString(item[210])) stock.ReserveString10=item[210]; //10个进度条 301-350 { Value:, BGColor: } if (IFrameSplitOperator.IsNumber(item[301]) || IFrameSplitOperator.IsObject(item[301])) stock.ReserveProgressBar1=item[301]; if (IFrameSplitOperator.IsNumber(item[302]) || IFrameSplitOperator.IsObject(item[302])) stock.ReserveProgressBar2=item[302]; if (IFrameSplitOperator.IsNumber(item[303]) || IFrameSplitOperator.IsObject(item[303])) stock.ReserveProgressBar3=item[303]; if (IFrameSplitOperator.IsNumber(item[304]) || IFrameSplitOperator.IsObject(item[304])) stock.ReserveProgressBar4=item[304]; if (IFrameSplitOperator.IsNumber(item[305]) || IFrameSplitOperator.IsObject(item[305])) stock.ReserveProgressBar5=item[305]; if (IFrameSplitOperator.IsNumber(item[306]) || IFrameSplitOperator.IsObject(item[306])) stock.ReserveProgressBar6=item[306]; if (IFrameSplitOperator.IsNumber(item[307]) || IFrameSplitOperator.IsObject(item[307])) stock.ReserveProgressBar7=item[307]; if (IFrameSplitOperator.IsNumber(item[308]) || IFrameSplitOperator.IsObject(item[308])) stock.ReserveProgressBar8=item[308]; if (IFrameSplitOperator.IsNumber(item[309]) || IFrameSplitOperator.IsObject(item[309])) stock.ReserveProgressBar9=item[309]; if (IFrameSplitOperator.IsNumber(item[310]) || IFrameSplitOperator.IsObject(item[310])) stock.ReserveProgressBar10=item[310]; } this.GetSymbolNoSuffix=function(symbol) { var index=symbol.lastIndexOf("."); if (index>0) return symbol.substring(0,index); else return symbol; } this.CancelAutoUpdate=function() //关闭停止更新 { if (typeof (this.AutoUpdateTimer) == 'number') { clearTimeout(this.AutoUpdateTimer); this.AutoUpdateTimer = null; } } this.AutoUpdate=function(waitTime) //waitTime 更新时间 { this.CancelAutoUpdate(); if (!this.IsAutoUpdate) return; var self = this; var marketStatus=2; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_MARKET_STATUS); if (event && event.Callback) { var sendData={ MarketStatus:2 }; event.Callback(event, sendData, this); if (IFrameSplitOperator.IsNumber(sendData.MarketStatus)) marketStatus=sendData.MarketStatus; } 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.UpdateStockData(); },frequency); } } this.StopAutoUpdate=function() { this.CancelAutoUpdate(); this.AutoUpdateEvent(false,'JSDealChartContainer::StopAutoUpdate'); if (!this.IsAutoUpdate) return; this.IsAutoUpdate=false; } //设置事件回调 //{event:事件id, callback:回调函数} this.AddEventCallback=function(object) { if (!object || !object.event || !object.callback) return; var data={Callback:object.callback, Source:object}; this.mapEvent.set(object.event,data); } this.RemoveEventCallback=function(eventid) { if (!this.mapEvent.has(eventid)) return; this.mapEvent.delete(eventid); } this.GetEventCallback=function(id) //获取事件回调 { if (!this.mapEvent.has(id)) return null; var item=this.mapEvent.get(id); return item; } this.OnSize=function() { if (!this.Frame) return; this.SetSizeChange(true); this.Draw(); this.DelayUpdateStockData(); } this.SetSizeChange=function(bChanged) { for(var i=0;i0) //上 { this.LastMouseStatus.TooltipStatus=null; if (this.GotoNextItem(-1)) { this.Draw(); this.DelayUpdateStockData(); } } } else { if (wheelValue<0) //下一页 { this.LastMouseStatus.TooltipStatus=null; if (this.GotoNextPage(this.PageUpDownCycle)) { this.Draw(); this.DelayUpdateStockData(); } } else if (wheelValue>0) //上一页 { this.LastMouseStatus.TooltipStatus=null; if (this.GotoPreviousPage(this.PageUpDownCycle)) { this.Draw(); this.DelayUpdateStockData(); } } } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnKeyDown=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var reportChart=this.GetReportChart(); if (!reportChart) return; var keyID = e.keyCode ? e.keyCode :e.which; if (keyID==116) return; //F15刷新不处理 switch(keyID) { case 33: //page up if (this.GotoPreviousPage(this.PageUpDownCycle)) { this.Draw(); this.DelayUpdateStockData(); } break; case 34: //page down if (this.GotoNextPage(this.PageUpDownCycle)) { this.Draw(); this.DelayUpdateStockData(); } break; case 38: //up var result=this.MoveSelectedRow(-1); if (result) { if (result.Redraw) this.Draw(); if (result.Update) this.DelayUpdateStockData(); } break; case 40: //down var result=this.MoveSelectedRow(1) if (result) { if (result.Redraw) this.Draw(); if (result.Update) this.DelayUpdateStockData(); } break; case 37: //left if (this.MoveXOffset(-1)) this.Draw(); break case 39: //right if (this.MoveXOffset(1)) this.Draw(); break; } //不让滚动条滚动 if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.UIOnDblClick=function(e) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var chart=this.ChartPaint[0]; if (chart) chart.OnDblClick(x,y,e); } this.UIOnMouseDown=function(e) { this.DragXScroll=null; this.DragYScroll=null; this.DragHeader=null; this.DragColumnWidth=null; this.DragMove={ Click:{ X:e.clientX, Y:e.clientY }, Move:{X:e.clientX, Y:e.clientY}, PreMove:{X:e.clientX, Y:e.clientY } }; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var chart=this.ChartPaint[0]; if (chart) { var dragColumnWidth=chart.PtInHeaderDragBorder(x,y) if (dragColumnWidth) { this.DragColumnWidth= { ClickPoint:{ X:x, Y:y }, LastPoint:{ X:x, Y:y }, //Click:{ X:e.clientX, Y:e.clientY }, //LastMove:{ X:e.clientX, Y:e.clientY}, ClickData:dragColumnWidth, ColumnWidth:dragColumnWidth.Column.Width }; } else { var clickData=chart.OnMouseDown(x,y,e); if (!clickData) return; //if (e.button!=0) return; if ((clickData.Type==2 || clickData.Type==4) && (e.button==0 || e.button==2)) //点击行|固定行 { if (e.button==0 && clickData.Type==2) { if (this.EnableDragRow && this.SortInfo.Sort<=0) { this.DragRow={ Click:{ X:e.clientX, Y:e.clientY }, LastMove:{ X:e.clientX, Y:e.clientY} , Data:clickData }; } } if (clickData.Redraw==true) this.Draw(); } else if (clickData.Type==3 && e.button==0) //表头 { this.DragHeader={ ClickPoint:{ X:x, Y:y }, Click:{ X:e.clientX, Y:e.clientY }, ClickData:clickData, LastMove:{ X:e.clientX, Y:e.clientY}, MovePoint:null, MoveToData:null }; } else if (clickData.Type==1 && e.button==0) //底部工具栏 { var tabData=clickData.Tab; if (tabData.Type==1) //左按钮 { if (this.MoveXOffset(-1)) this.Draw(); } else if (tabData.Type==2) //右按钮 { if (this.MoveXOffset(1)) this.Draw(); } else if (tabData.Type==3) //滚动条 { this.DragXScroll={ Click:{X:x, Y:y}, LastMove:{X:x, Y:y} }; } else if (tabData.Type==4) //滚动条内部 { if (this.SetXOffset(tabData.Pos)) this.Draw(); } else if (tabData.Type==5) //标签 { this.OnClickTab(tabData, e); } } else if (clickData.Type==5 && e.button==0) //右侧滚动条 { var scroll=clickData.VScrollbar; if (scroll.Type==1) //顶部按钮 { if (this.MoveYOffset(-1)) { this.Draw(); this.DelayUpdateStockData(); } } else if (scroll.Type==2) //底部按钮 { if (this.MoveYOffset(1)) { this.Draw(); this.DelayUpdateStockData(); } } else if (scroll.Type==3) //滚动条 { this.DragYScroll={ Click:{X:x, Y:y}, LastMove:{X:x, Y:y} }; } else if (scroll.Type==4) //滚动条内部 { if (this.SetYOffset(scroll.Pos)) { this.Draw(); this.DelayUpdateStockData(); } } } } } document.onmousemove=(e)=>{ this.DocOnMouseMove(e); } document.onmouseup=(e)=> { this.DocOnMouseUp(e); } } this.UIOnMounseUp=function(e) { console.log('"UIOnMounseUp'); } //去掉右键菜单 this.UIOnContextMenu=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; if (!this.IsShowRightMenu) return; var x = e.clientX-this.UIElement.getBoundingClientRect().left; var y = e.clientY-this.UIElement.getBoundingClientRect().top; if(typeof(this.OnRightMenu)=='function') this.OnRightMenu(x,y,e); //右键菜单事件 } this.OnRightMenu=function(x,y,e) { e.preventDefault(); } this.UIOnMouseMove=function(e) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var oldMouseOnStatus=this.LastMouseStatus.MouseOnStatus; this.LastMouseStatus.OnMouseMove=null; var bDrawTooltip=false; if (this.LastMouseStatus.TooltipStatus) bDrawTooltip=true; this.LastMouseStatus.TooltipStatus=null; if (this.DragRow) return; if (this.DrawHeader) return; if (this.DragColumnWidth) return; var tabChart=this.GetTabChart(); var bDrawTab=false; if (tabChart) { var tabData=tabChart.PtInTab(x,y); if (tabData) { var index=tabData.Index; if (tabChart.MoveOnTabIndex!=index) { tabChart.MoveOnTabIndex=index; bDrawTab=true; } } else { if (tabChart.MoveOnTabIndex>=0) { tabChart.MoveOnTabIndex=-1; bDrawTab=true; } } } this.LastMouseStatus.OnMouseMove={ X:x, Y:y }; var mouseStatus={ Cursor:"default", Name:"Default"};; //鼠标状态 var report=this.GetReportChart(); var bDraw=false; if (report) { var dragHeaderWidth=report.PtInHeaderDragBorder(x,y); if (dragHeaderWidth) { mouseStatus={ Cursor:"col-resize", Name:"DragHeaderWidth"}; JSConsole.Chart.Log("[JSReportChartContainer::UIOnMouseMove] drag column width ",dragHeaderWidth); } else { var buttonData=report.GetButtonData(x,y); var mouseOnStatus=null; if (buttonData) { mouseStatus={ Cursor:"pointer", Name:"Botton"}; if (buttonData.Type==1 || buttonData.Type==0 || buttonData.Type==2) { mouseOnStatus={ Index:buttonData.Index, ColumnIndex:buttonData.ColumnIndex }; } } //console.log("[UIOnMouseMove] ", oldMouseOnStatus, mouseOnStatus) if ((!oldMouseOnStatus && mouseOnStatus) || (oldMouseOnStatus && !mouseOnStatus)) { bDraw=true; } else if (oldMouseOnStatus && mouseOnStatus) { if (oldMouseOnStatus.Index!=mouseOnStatus.Index || oldMouseOnStatus.ColumnIndex!=mouseOnStatus.ColumnIndex) bDraw=true; } var tooltipData=report.GetTooltipData(x,y); //单元格提示信息 if (tooltipData) { this.LastMouseStatus.TooltipStatus={ X:e.clientX, Y:e.clientY, Data:tooltipData }; bDrawTooltip=true; } } var scrollbar=report.VScrollbar; if (scrollbar.Enable) { var bShowScrollbar=report.PtInClient(x,y); this.IsShowVScrollbar=bShowScrollbar; if (!this.DragYScroll) { if (bShowScrollbar && !scrollbar.LastStatus.Draw) bDraw=true; else if (!bShowScrollbar && scrollbar.LastStatus.Draw) bDraw=true; } } } /* 目前没有用到 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_MOUSE_MOVE); if (event) { var sendData={X:x, Y:y, Cell:cell }; event.Callback(event,sendData,this); } */ if (mouseStatus) this.UIElement.style.cursor=mouseStatus.Cursor; if (bDraw || bDrawTab) this.Draw(); else if (bDrawTooltip) this.DrawTooltip(this.LastMouseStatus.TooltipStatus); } this.UIOnMounseOut=function(e) { var bDraw=false; var tabChart=this.GetTabChart(); if (tabChart && tabChart.MoveOnTabIndex>=0) { tabChart.MoveOnTabIndex=-1; bDraw=true; this.Draw(); } var scrollbar=this.GetVScrollbarChart(); if (scrollbar.Enable) { this.IsShowVScrollbar=false; if (!this.DragYScroll) { if (scrollbar.LastStatus.Draw) bDraw=true; } } if (bDraw) this.Draw(); } this.UIOnMouseleave=function(e) { var tabChart=this.GetTabChart(); if (tabChart && tabChart.MoveOnTabIndex>=0) { tabChart.MoveOnTabIndex=-1; this.Draw(); } } this.DocOnMouseMove=function(e) { this.DragMove.PreMove.X=this.DragMove.Move.X; this.DragMove.PreMove.Y=this.DragMove.Move.Y; this.DragMove.Move.X=e.clientX; this.DragMove.Move.Y=e.clientX; if (this.DragMove.Move.X!=this.DragMove.PreMove.X || this.DragMove.Move.Y!=this.DragMove.PreMove.Y) this.StopAutoDragScrollTimer(); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; //JSConsole.Chart.Log(`[JSReportChartContainer::DocOnMouseMove] x=${x}, y=${y}`); if (this.DragRow) { var drag=this.DragRow; var moveSetpY=drag.LastMove.Y-e.clientY; if (Math.abs(moveSetpY)<2) return; var reportChart=this.GetReportChart(); drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; drag.Inside={X:x, Y:y}; if (reportChart) { var moveRow=reportChart.OnDrawgRow(x,y,e); if (moveRow ) { if (moveRow.Type==2) { if (moveRow.Data.DataIndex!=drag.Data.Row.DataIndex) { drag.MoveRow=moveRow; } } else if (moveRow.Type==7) { var pageStatus=reportChart.GetCurrentPageStatus(); if (!pageStatus.IsEnd) { this.MoveYOffset(1, false); drag.MoveRow=null; this.EnablePageScroll=true; this.AutoScrollPage(2); } } else if (moveRow.Type==5) { if (this.Data.YOffset>0) { this.MoveYOffset(-1, false); drag.MoveRow=null; this.EnablePageScroll=true; this.AutoScrollPage(-2); } } } reportChart.DragRow=drag; } this.Draw(); } else if (this.DragXScroll) { var chart=this.ChartPaint[0]; if (!chart || !chart.Tab) return; this.DragXScroll.LastMove.X=x; this.DragXScroll.LastMove.Y=y; var pos=chart.Tab.GetScrollPostionByPoint(x,y); if (this.SetXOffset(pos)) this.Draw(); } else if (this.DragYScroll) { var chart=this.ChartPaint[0]; if (!chart || !chart.VScrollbar) return; this.DragYScroll.LastMove.X=x; this.DragYScroll.LastMove.Y=y; var pos=chart.VScrollbar.GetScrollPostionByPoint(x,y); if (this.SetYOffset(pos)) { this.Draw(); this.DelayUpdateStockData(); } } else if (this.DragHeader && this.DragHeader.ClickData) //表头拖拽 { if (this.DragHeader.ClickData.Header.IsFixed) return; if (!this.EnableDragHeader) return; var xMove=e.clientX-this.DragHeader.Click.X; var yMove=e.clientY-this.DragHeader.Click.Y; if ( Math.abs(yMove)<=1 && Math.abs(xMove)<=1) return; this.DragHeader.LastMove.X=e.clientX; this.DragHeader.LastMove.Y=e.clientY; if (!this.DragHeader.MovePoint) { this.DragHeader.MovePoint={ X:x, Y:y }; } else { this.DragHeader.MovePoint.X=x; this.DragHeader.MovePoint.Y=y; } this.OnMoveDragHeader(x,y,e); this.ShowDragHeaderTooltip(x,y,e); } else if (this.DragColumnWidth && this.DragColumnWidth.ClickData) //列宽度拖拽 { var xMove=x-this.DragColumnWidth.ClickPoint.X; if (Math.abs(xMove)<1) return; var fixedWidth=this.DragColumnWidth.ColumnWidth+xMove; if (fixedWidth<=10) return; var index=this.DragColumnWidth.ClickData.Index; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_DRAG_COLUMN_WIDTH); if (event && event.Callback) { var sendData={ Index:index, Width:fixedWidth, PreventDefault:false }; if (this.DragColumnWidth && this.DragColumnWidth.ClickData) sendData.Column=this.DragColumnWidth.ClickData.Column event.Callback(event, sendData, this); if (sendData.PreventDefault) return; } this.SetColumnFixedWidth(index, fixedWidth); this.DragColumnWidth.LastPoint.X=x; this.DragColumnWidth.LastPoint.Y=y; } } this.SetColumnFixedWidth=function(index, width) { var chart=this.ChartPaint[0]; if (!chart) return; var item=chart.Column[index]; if (!item) return; item.FixedWidth=width; this.SetSizeChange(true); this.Draw(); } this.OnMoveDragHeader=function(x, y,e) { var chart=this.ChartPaint[0]; if (!chart) return; var clickData=this.DragHeader.ClickData; this.DragHeader.MoveToData=null; if (!clickData.Header.IsFixed) //固定列不能拖 { var yHeader=this.DragHeader.ClickPoint.Y; var moveData=chart.OnMouseDown(x,yHeader,e); if (!moveData || !moveData.Header) return; if (moveData.Header.IsFixed) return; if (moveData.Header.Index== clickData.Header.Index) return; this.DragHeader.MoveToData=moveData; console.log(`[JSReportChartContainer::OnMoveDragHeader] Click[Index=${clickData.Header.Index}, Title=${clickData.Header.Column.Title}] => Move[Index=${moveData.Header.Index}, Title=${moveData.Header.Column.Title}]`); } } this.ShowDragHeaderTooltip=function(x,y,e) { if (!this.DragHeader) return; var drag=this.DragHeader; if (!drag.ClickData || !drag.MovePoint) return; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_DRAG_HEADER_TOOLTIP); if (event) { var sendData={ PreventDefault:false, e, X:x, Y:y, DragHeader:this.DragHeader, Tooltip:this.Tooltip }; event.Callback(event,sendData,this); if (sendData.PreventDefault) return; } var title=drag.ClickData.Header.Column.Title; this.Tooltip.className='jchart-chartdrawsvg-tooltip'; //ChartDrawSVG指标数据 this.Tooltip.style.position = "absolute"; this.Tooltip.style.left = e.clientX + "px"; this.Tooltip.style.top = e.clientY+ "px"; this.Tooltip.style.width = 100+"px"; this.Tooltip.style.height =null; this.Tooltip.innerHTML=title; this.Tooltip.style.display = "block"; } this.HideTooltip=function() { if (this.Tooltip.style.display!="none") this.Tooltip.style.display = "none"; } this.DocOnMouseUp=function(e) { //清空事件 document.onmousemove=null; document.onmouseup=null; this.StopAutoDragScrollTimer(); this.HideTooltip(); var reportChart=this.GetReportChart(); var mouseStatus={ Cursor:"default", Name:"Default"};; //鼠标状态 var bRedraw=false; if (this.DragRow) { if (reportChart) { this.OnDragRow(); reportChart.DragRow=null; } bRedraw=true; } var dragHeader=this.DragHeader; this.DragHeader=null; this.DragXScroll=null; if (this.DragYScroll) { bRedraw=true; this.DragYScroll=null; } this.DragRow=null; this.DragMove=null; this.DragColumnWidth=null; if (bRedraw) this.Draw(); if (dragHeader) { var clickData=dragHeader.ClickData; var moveToData=dragHeader.MoveToData; if (clickData && moveToData) { this.SwapColumn(clickData.Header.Index, moveToData.Header.Index, { Redraw:true }); } else { this.OnClickHeader(clickData, e); } } if (mouseStatus) this.UIElement.style.cursor=mouseStatus.Cursor; } this.OnDragRow=function() { if (!this.SourceData || !IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) return; if (!this.DragRow || !this.DragRow.MoveRow) return; var drag=this.DragRow; var srcIndex=drag.Data.Row.DataIndex; var moveIndex=drag.MoveRow.Data.DataIndex; if (srcIndex==moveIndex || srcIndex<0 || moveIndex<0) return; var data=this.SourceData.Data; if (srcIndex>=data.length || moveIndex>=data.length) return; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_DRAG_ROW); if (event) { var sendData= { Symbol:this.Symbol, Src:{ Index:srcIndex, Symbol:data[srcIndex] }, To:{ Index:moveIndex, Symbol:data[moveIndex] }, PreventDefault:false //PreventDefault 是否阻止内置的点击处理 }; event.Callback(event,sendData,this); if (sendData.PreventDefault) return; } if (this.DragRowType==1) { //原始数据交换顺序 var temp=data[srcIndex]; data[srcIndex]=data[moveIndex]; data[moveIndex]=temp; this.Data.Data=data.slice(0); } else { //插入模式 var srcItem=data[srcIndex]; data.splice(srcIndex,1); data.splice(moveIndex, 0, srcItem); this.Data.Data=data.slice(0); } //更新选中行 var reportChart=this.GetReportChart(); if (reportChart) { if (reportChart.SelectedModel==0) reportChart.SelectedRow=drag.MoveRow.Data.Index; else reportChart.SelectedRow=drag.MoveRow.Data.DataIndex; } } //判断是单个手指 this.IsPhoneDragging=function(e) { // JSConsole.Chart.Log(e); var changed=e.changedTouches.length; var touching=e.touches.length; return changed==1 && touching==1; } this.GetTouchData=function(e) { var touches=[]; var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 for(var i=0; i0 && moveAngle0 && moveAngle>=this.TouchMoveMinAngle) { if (!this.OnDragXOffset(drag, touches,moveLeftRight, e)) return; } else { return; } drag.LastMove.X=touches[0].clientX; drag.LastMove.Y=touches[0].clientY; } } } this.OnTouchEnd=function(e) { JSConsole.Chart.Log('[JSReportChartContainer:OnTouchEnd]',e); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; this.ShowPageInfo(false); this.OnTouchClick(this.TouchInfo, e); this.IsOnTouch=false; this.TouchDrag=null; this.TouchInfo=null; } this.OnTouchClick=function(touchInfo, e) { if (!touchInfo || !touchInfo.Click) return false; if (touchInfo.Move) return false; var clickPoint=touchInfo.InsideClick; var reportChart=this.GetReportChart(); if (!reportChart) return false; var clickData=reportChart.OnMouseDown(clickPoint.X,clickPoint.Y,e); if (!clickData) return false; if (clickData.Type==2 || clickData.Type==4) //点击行 { if (clickData.Redraw==true) this.Draw(); } else if (clickData.Type==3) //表头 { this.OnClickHeader(clickData, e); } JSConsole.Chart.Log('[JSReportChartContainer:OnTouchClick] clickData', clickData); } this.GetTabChart=function() { var chart=this.ChartPaint[0]; if (!chart) return null; return chart.Tab; } this.GetVScrollbarChart=function() { var chart=this.ChartPaint[0]; if (!chart) return null; return chart.VScrollbar; } this.GetReportChart=function() { var chart=this.ChartPaint[0]; return chart; } this.GotoNextItem=function(step) { if (step==0) return false; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageSize=chart.GetPageSize(); if (pageSize>this.Data.Data.length) return false; var moveCount=0; if (step>0) { for(var i=0;i=this.Data.Data.length) break; ++this.Data.YOffset; ++moveCount; } } else if (step<0) { step=Math.abs(step); for(var i=0;i0 } this.GotoNextPage=function(bCycle) //bCycle 是否循环 { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageSize=chart.GetPageSize(); var dataCount=chart.GetAllRowCount(); if (pageSize>dataCount) return false; if (this.Data.YOffset+pageSize>=dataCount) { if (bCycle===true) { this.Data.YOffset=0; //循环到第1页 return true; } else { return false; } } this.Data.YOffset+=pageSize; var showDataCount=dataCount-this.Data.YOffset; if (chart.SelectedModel==0) { if (chart.SelectedRow>showDataCount-1) chart.SelectedRow=showDataCount-1; } return true; } this.GotoPreviousPage=function(bCycle) //bCycle 是否循环 { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageSize=chart.GetPageSize(); var dataCount=chart.GetAllRowCount(); if (pageSize>dataCount) return false; if (this.Data.YOffset<=0) { if (bCycle===true) { this.Data.YOffset=dataCount-pageSize; //循环到最后一页 return true; } else { return false; } } var offset=this.Data.YOffset; offset-=pageSize; if (offset<0) offset=0; this.Data.YOffset=offset; return true; } this.MoveYOffset=function(setp, bCycle) //bCycle 是否循环 { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageStatus=chart.GetCurrentPageStatus(); if (pageStatus.IsSinglePage) return false; if (setp>0) //向上 { var count=this.Data.Data.length; var pageSize=pageStatus.PageSize; var offset=this.Data.YOffset; if (bCycle) { for(var i=0;icount) offset=0; } } else { if (offset+pageSize>=count) return false; for(var i=0;icount) break; ++offset; } } this.Data.YOffset=offset; return true; } else if (setp<0) //向下 { setp=Math.abs(setp); var offset=this.Data.YOffset; if (bCycle) { var pageSize=pageStatus.PageSize; for(var i=0;i0) { if (selected==this.Data.Data.length-1) return result; if (selected<0 || selectedpageStatus.End) { chart.MultiSelectedRow=[pageStatus.Start]; result.Redraw=true; return result; } var offset=this.Data.YOffset; for(var i=0;ipageStatus.End) ++offset; if (selected>=this.Data.Data.length) { selected=0; offset=0; } } result.Redraw=true; result.Update=(offset!=this.Data.YOffset); chart.MultiSelectedRow=[selected]; this.Data.YOffset=offset; return result; } else if (step<0) { if (selected==0) return result; if (selected<0 || selectedpageStatus.End) { chart.MultiSelectedRow=[pageStatus.End]; result.Redraw=true; return result; } step=Math.abs(step); var offset=this.Data.YOffset; for(var i=0;i0) selected=pageStatus.Start; else if (step<0) selected=pageStatus.End; else return null; chart.MultiSelectedRow=[selected]; result.Redraw=true; } return result; } if (chart.SelectedModel==0) //不可翻页模式, 只能在当前页移动 { var pageStatus=chart.GetCurrentPageStatus(); var pageSize=pageStatus.End-pageStatus.Start+1; var selected=pageStatus.SelectedRow; if (step>0) { selected+=step; selected=selected%pageSize; chart.SelectedRow=selected; chart.SelectedFixedRow=-1; result.Redraw=true; return result; } else if (step<0) { selected+=step; if (selected<0) { selected=selected%pageSize; selected=pageSize+selected; } chart.SelectedRow=selected; chart.SelectedFixedRow=-1; result.Redraw=true; return result; } } else if (chart.SelectedModel==1) //可翻页模式 { var pageStatus=chart.GetCurrentPageStatus(); var pageSize=pageStatus.PageSize; var selected=pageStatus.SelectedRow; if (step>0) { if (selected<0 || selectedpageStatus.End) { chart.SelectedRow=pageStatus.Start; result.Redraw=true; return result; } var offset=this.Data.YOffset; for(var i=0;ipageStatus.End) ++offset; if (selected>=this.Data.Data.length) { selected=0; offset=0; } } result.Redraw=true; result.Update=(offset!=this.Data.YOffset); chart.SelectedRow=selected; this.Data.YOffset=offset; return result; } else if (step<0) { if (selected<0 || selectedpageStatus.End) { chart.SelectedRow=pageStatus.End; result.Redraw=true; return result; } step=Math.abs(step); var offset=this.Data.YOffset; for(var i=0;i0) { if (this.Data.XOffset>=maxOffset) return false; for(var i=0;i=maxOffset) break; ++this.Data.XOffset; } return true; } else if (step<0) { if (this.Data.XOffset<=0) return false; step=Math.abs(step); for(var i=0;imaxOffset) pos=maxOffset; this.Data.XOffset=pos; return true; } this.SetYOffset=function(pos) { if (!IFrameSplitOperator.IsNumber(pos)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var maxOffset=chart.GetYScrollRange(); if (pos<0) pos=0; if (pos>maxOffset) pos=maxOffset; this.Data.YOffset=pos; return true; } this.GotoLastPage=function() { var chart=this.ChartPaint[0]; if (!chart) return; //显示最后一屏 var pageSize=chart.GetPageSize(true); var offset=this.Data.Data.length-pageSize; if (offset<0) offset=0; this.Data.DataOffset=offset; } this.SetColumn=function(aryColunm, option) { var chart=this.ChartPaint[0]; if (!chart) return; chart.SetColumn(aryColunm); chart.SizeChange=true; if (option && option.Redraw) this.Draw(); } this.SetTab=function(aryTab, option) { var chart=this.ChartPaint[0];; if (!chart) return; var chartTab=chart.Tab; if (!chartTab) return; chartTab.SetTabList(aryTab); if (option && option.Redraw) this.Draw(); } this.SetVScrollbar=function(option) { var chart=this.GetReportChart(); if (!chart) return; var scrollbar=chart.VScrollbar; if (!scrollbar) return; scrollbar.SetOption(option); } this.SetSelectedTab=function(index, opiton) { var chart=this.ChartPaint[0];; if (!chart) return; var chartTab=chart.Tab; if (!chartTab) return; chartTab.SelectedTabIndex=index; } this.ReloadResource=function(option) { this.Frame.ReloadResource(option); for(var i=0;i { return this.LocalSort(left, right, column, sortInfo.Sort); }); } } else if (column.Sort==2) //远程排序 { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; this.SortInfo.Field=sortInfo.Field; this.SortInfo.Sort=sortInfo.Sort; this.Data.YOffset=0; this.ResetReportSelectStatus(); this.RequestStockSortData(column, sortInfo.Field, sortInfo.Sort); //远程排序 return true; } } this.Data.YOffset=0; this.ResetReportSelectStatus(); this.SortInfo.Field=sortInfo.Field; this.SortInfo.Sort=sortInfo.Sort; this.Draw(); this.DelayUpdateStockData(); return true; } //点表头 this.OnClickHeader=function(clickData, e) { var header=clickData.Header; if (header.Column && header.Column.EnablePopupHeaderMenu) { this.PopupHeaderMenu(clickData, e); return; } if (header.Column && (header.Column.Sort==1 || header.Column.Sort==2)) { var index=header.Index; var sortInfo={Field:this.SortInfo.Field, Sort:this.SortInfo.Sort }; var arySortType=header.Column.SortType; if (sortInfo.Field!=index) { sortInfo.Field=index; sortInfo.Sort=arySortType[0] } else { if (arySortType.length==1) { sortInfo.Sort=arySortType[0]; } else { for(var i=0;i { return this.LocalSort(left, right, header.Column, sortInfo.Sort); }); } } else if (header.Column.Sort==2) //远程排序 { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; this.SortInfo.Field=sortInfo.Field; this.SortInfo.Sort=sortInfo.Sort; this.Data.YOffset=0; this.ResetReportSelectStatus(); this.RequestStockSortData(header.Column, sortInfo.Field, sortInfo.Sort); //远程排序 return; } } this.Data.YOffset=0; this.ResetReportSelectStatus(); this.SortInfo.Field=sortInfo.Field; this.SortInfo.Sort=sortInfo.Sort; this.Draw(); this.DelayUpdateStockData(); } } } this.PopupHeaderMenu=function(clickData, e) { if (!this.JSPopMenu) return; if (!this.GetEventCallback) return; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CREATE_REPORT_HEADER_MENU); if (!event || !event.Callback) return; var header=clickData.Header; var column=header.Column; var menuData={ Menu:null, Position:JSPopMenu.POSITION_ID.DROPDOWN_MENU_ID }; menuData.ClickCallback=(data)=>{ this.OnClickHeaderMenu(column, data); } var sendData={ MenuData:menuData, Column:column, Index:header.Index, PreventDefault:false, e:e }; event.Callback(event, sendData, this); if (sendData.PreventDefault==true) return; if (!menuData.Menu) return; this.PopupMenuByDrapdown(menuData, header.Rect); } //下拉菜单 this.PopupMenuByDrapdown=function(menuData, rtButton) { if (!this.JSPopMenu) return; var pixelRatio=GetDevicePixelRatio(); var rtCell={ Left:rtButton.Left/pixelRatio, Right:rtButton.Right/pixelRatio, Bottom:rtButton.Bottom/pixelRatio, Top:rtButton.Top/pixelRatio }; rtCell.Width=rtCell.Right-rtCell.Left; rtCell.Height=rtCell.Bottom-rtCell.Top; var rtClient=this.UIElement.getBoundingClientRect(); var rtScroll=GetScrollPosition(); var offsetLeft=rtClient.left+rtScroll.Left; var offsetTop=rtClient.top+rtScroll.Top; rtCell.Left+=offsetLeft; rtCell.Right+=offsetLeft; rtCell.Top+=offsetTop; rtCell.Bottom+=offsetTop; this.JSPopMenu.CreatePopMenu(menuData); this.JSPopMenu.PopupMenuByDrapdown(rtCell); } this.GetTabPopMenu=function(tabItem) { var aryMenu=[ ]; if (IFrameSplitOperator.IsNonEmptyArray(tabItem.ArySubMenu)) { for(var i=0;i{ this.OnClickTabPopMenu(tabData, data); } var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_REPORT_TABMENU); if (event && event.Callback) { var sendData={ MenuData:menuData, Tab:tabData, PreventDefault:false, e:e }; event.Callback(event, sendData, this); if (sendData.PreventDefault==true) return; } this.PopupTabMenu(menuData, tabData.Tab, e); } else { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_REPORT_TAB); if (event && event.Callback) { var sendData={ Data:tabData, IsSide:{X:x, Y:x}, UIElement:uiElement, e:e , Redraw:redraw, PreventDefault:false }; event.Callback(event, sendData, this); if (IFrameSplitOperator.IsBool(sendData.Redraw)) redraw=sendData.Redraw; if (sendData.PreventDefault==true) return; } if (tabData.Tab.CommandID==JSCHART_MENU_ID.CMD_REPORT_CHANGE_BLOCK_ID) { this.ExecuteMenuCommand(tabData.Tab.CommandID, [tabData.Tab.ID]); this.SetSelectedTab(tabData.Index); redraw=true; } } if (redraw) this.Draw(); } this.OnClickTabPopMenu=function(tabData, data) { JSConsole.Chart.Log('[JSReportChartContainer::OnClickTabPopMenu] ',tabData, data); var cmdID=data.Data.ID; //命令ID var aryArgs=data.Data.Args; //参数 var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_MENU_COMMAND); //回调通知外部 if (event && event.Callback) { var data={ PreventDefault:false, CommandID:cmdID, Args:aryArgs, SrcData:data, TabData:tabData }; event.Callback(event,data,this); if (data.PreventDefault) return; } this.ExecuteMenuCommand(cmdID,aryArgs); this.SetSelectedTab(tabData.Index); this.Draw(); } this.OnClickHeaderMenu=function(menuData, data) { JSConsole.Chart.Log('[JSReportChartContainer::OnClickHeaderMenu] ',menuData, data); var cmdID=data.Data.ID; var aryArgs=data.Data.Args; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_MENU_COMMAND); //回调通知外部 if (event && event.Callback) { var data={ PreventDefault:false, CommandID:cmdID, Args:aryArgs, SrcData:data, MenuData:menuData }; event.Callback(event,data,this); if (data.PreventDefault) return; } this.ExecuteMenuCommand(cmdID,aryArgs); } this.ExecuteMenuCommand=function(cmdID, aryArgs) { JSConsole.Chart.Log('[JSReportChartContainer::ExecuteMenuCommand] cmdID=, aryArgs=', cmdID,aryArgs); var param=null, srcParam=null; //原始值 if (IFrameSplitOperator.IsNonEmptyArray(aryArgs)) { srcParam=aryArgs[0]; if (IFrameSplitOperator.IsNumber(aryArgs[0])) param=aryArgs[0]; } switch(cmdID) { case JSCHART_MENU_ID.CMD_REPORT_CHANGE_BLOCK_ID: if (srcParam) this.ChangeSymbol(srcParam); break; case JSCHART_MENU_ID.CMD_REPORT_COLUMN_SORT_ID: if (IFrameSplitOperator.IsNumber(param) && IFrameSplitOperator.IsNumber(aryArgs[1])) this.SortColumn(param, aryArgs[1]); break; case JSCHART_MENU_ID.CMD_REPORT_COLUMN_MOVE_ID: if (IFrameSplitOperator.IsNumber(param) && IFrameSplitOperator.IsNumber(aryArgs[1])) { var leftIndex=param; var rightIndex=param+aryArgs[1]; this.SwapColumn(leftIndex, rightIndex, {Redraw:true}); } break; case JSCHART_MENU_ID.CMD_REPORT_COLUMN_DEL_ID: if (IFrameSplitOperator.IsNumber(param)) this.DeleteColumn(param, {Redraw:true}); break; } } this.SwapColumn=function(leftIndex, rightIndex, option) { var reportChart=this.GetReportChart(); if (!reportChart) return; if (!reportChart.SwapColumn(leftIndex, rightIndex)) return; if (option && option.Redraw) { this.SetSizeChange(true); this.Draw(); } } this.DeleteColumn=function(index, option) { var reportChart=this.GetReportChart(); if (!reportChart) return; if (!reportChart.DeleteColumn(index)) return; if (option && option.Redraw) { this.SetSizeChange(true); this.Draw(); } } //本地排序 this.LocalSort=function(left, right, column, sortType) { switch(column.Type) { case REPORT_COLUMN_ID.SYMBOL_ID: case REPORT_COLUMN_ID.NAME_ID: return this.LocalStringSort(left, right, column, sortType); case REPORT_COLUMN_ID.NAME_EX_ID: return this.LocalNameExSort(left, right, column, sortType); case REPORT_COLUMN_ID.PRICE_ID: case REPORT_COLUMN_ID.VOL_ID: case REPORT_COLUMN_ID.INCREASE_ID: case REPORT_COLUMN_ID.UPDOWN_ID: case REPORT_COLUMN_ID.BUY_PRICE_ID: case REPORT_COLUMN_ID.SELL_PRICE_ID: case REPORT_COLUMN_ID.AMOUNT_ID: case REPORT_COLUMN_ID.BUY_VOL_ID: case REPORT_COLUMN_ID.SELL_VOL_ID: case REPORT_COLUMN_ID.YCLOSE_ID: case REPORT_COLUMN_ID.OPEN_ID: case REPORT_COLUMN_ID.HIGH_ID: case REPORT_COLUMN_ID.LOW_ID: case REPORT_COLUMN_ID.AVERAGE_PRICE_ID: case REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID: case REPORT_COLUMN_ID.TOTAL_SHARES_ID: case REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID: case REPORT_COLUMN_ID.MARKET_VALUE_ID: case REPORT_COLUMN_ID.EXCHANGE_RATE_ID: case REPORT_COLUMN_ID.AMPLITUDE_ID: case REPORT_COLUMN_ID.LIMIT_HIGH_ID: case REPORT_COLUMN_ID.LIMIT_LOW_ID: //期货字段 case REPORT_COLUMN_ID.FUTURES_POSITION_ID: case REPORT_COLUMN_ID.FUTURES_CLOSE_ID: case REPORT_COLUMN_ID.FUTURES_YCLOSE_ID: case REPORT_COLUMN_ID.FUTURES_OPEN_POSITION_ID: case REPORT_COLUMN_ID.FUTURES_CLOSE_POSITION_ID: case REPORT_COLUMN_ID.VOL_IN_ID: case REPORT_COLUMN_ID.VOL_OUT_ID: case REPORT_COLUMN_ID.DATE_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER1_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER2_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER3_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER4_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER5_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER6_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER7_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER8_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER9_ID: case TREPORT_COLUMN_ID.RESERVE_NUMBER10_ID: return this.LocalNumberSort(left, right, column, sortType); case REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID: //自定义数值字段 return this.LoacCustomNumberSort(left, right, column, sortType); case REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID: //自定义字符串字段 return this.LoacCustomStringSort(left, right, column, sortType); case REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID: return this.LoacCustomDateTimeSort(left, right, column, sortType); default: return 0; } } this.GetStockExtendData=function(symbol,column) { if (IFrameSplitOperator.IsNumber(column.DataIndex)) { if (column.DataIndex<0) return null; var stock=this.GetStockData(symbol); if (!stock || !stock.ExtendData) return null; return stock.ExtendData[column.DataIndex]; } if (IFrameSplitOperator.IsNumber(column.BlockIndex)) { if (column.BlockIndex<0) return null; var stock=this.GetBlockData(symbol); if (!stock) return null; return stock[column.BlockIndex]; } return null; } this.LocalNameExSort=function(left, right, column, sortType) { var leftStock=this.GetStockData(left); var rightStock=this.GetStockData(right); var leftValue="", rightValue=""; if (sortType==2) { leftValue="啊啊啊啊啊"; rightValue="啊啊啊啊啊"; } if (leftStock && leftStock.Name) leftValue=leftStock.Name; if (rightStock && rightStock.Name) rightValue=rightStock.Name; if (sortType==1) { if (rightValuerightValue) return 1; else return 0; } } this.LocalStringSort=function(left, right, column, sortType) { var leftStock=this.GetStockData(left); var rightStock=this.GetStockData(right); var leftValue="", rightValue=""; if (sortType==2) { leftValue="啊啊啊啊啊"; rightValue="啊啊啊啊啊"; } var filedName=MAP_COLUMN_FIELD.get(column.Type); if (leftStock && leftStock[filedName]) leftValue=leftStock[filedName]; if (rightStock && rightStock[filedName]) rightValue=rightStock[filedName]; if (sortType==1) { if (rightValuerightValue) return 1; else return 0; } } this.LocalNumberSort=function(left, right, column, sortType) { var leftStock=this.GetStockData(left); var rightStock=this.GetStockData(right); var leftValue=-99999999999999, rightValue=-99999999999999; if (sortType==2) leftValue=rightValue=99999999999999; var filedName=MAP_COLUMN_FIELD.get(column.Type); if (leftStock && IFrameSplitOperator.IsNumber(leftStock[filedName])) leftValue=leftStock[filedName]; if (rightStock && IFrameSplitOperator.IsNumber(rightStock[filedName])) rightValue=rightStock[filedName]; if (sortType==1) { if (rightValuerightValue) return 1; else return 0; } } this.LoacCustomNumberSort=function(left, right, column, sortType) { var leftValue=-99999999999999, rightValue=-99999999999999; if (sortType==2) leftValue=rightValue=99999999999999; var value=this.GetStockExtendData(left, column); if (IFrameSplitOperator.IsNumber(value)) leftValue=value; var value=this.GetStockExtendData(right, column); if (IFrameSplitOperator.IsNumber(value)) rightValue=value; if (sortType==1) { if (rightValuerightValue) return 1; else return 0; } } this.LoacCustomDateTimeSort=function(left, right, column, sortType) { var leftValue=-99999999999999, rightValue=-99999999999999; if (sortType==2) leftValue=rightValue=99999999999999; var value=this.GetStockExtendData(left, column); if (IFrameSplitOperator.IsNumber(value)) leftValue=value; var value=this.GetStockExtendData(right, column); if (IFrameSplitOperator.IsNumber(value)) rightValue=value; if (sortType==1) { if (rightValuerightValue) return 1; else return 0; } } this.LoacCustomStringSort=function(left, right, column, sortType) { var leftValue="", rightValue=""; if (sortType==2) rightValue=leftValue="啊啊啊啊啊"; var value=this.GetStockExtendData(left, column); if (IFrameSplitOperator.IsString(value)) leftValue=value; var value=this.GetStockExtendData(right, column); if (IFrameSplitOperator.IsString(value)) rightValue=value; if (sortType==1) { if (rightValuerightValue) return 1; else return 0; } } this.RequestStockSortData=function(column, filedid, sortType) { var chart=this.ChartPaint[0]; if (!chart) return; var self=this; var startIndex=this.Data.YOffset; var pageSize=chart.GetPageSize(); var endIndex=startIndex+pageSize; if (endIndex>=this.Data.Data.length) endIndex=this.Data.Data.length-1; if (this.NetworkFilter) { var obj= { Name:'JSDealChartContainer::RequestStockSortData', //类名::函数名 Explain:'报价列表股票排序数据', Request: { Data: { range:{ start:startIndex, end:endIndex, count:this.Data.Data.length }, column:{ name: column.Title, type: column.Type, index:filedid, ID:column.ID }, sort:sortType, symbol:this.Symbol, name:this.Name, pageSize:pageSize } }, Self:this, PreventDefault:false }; if (chart.FixedRowCount>0 && chart.FixedRowData.Type==1) { var arySymbol=[]; for(var i=0;i=dataCount) endIndex=dataCount-1; if (!this.NetworkFilter) return; var requestData= { range:{ start:startIndex, end:endIndex, count:chart.GetAllRowCount() }, column:null, sort:0, symbol:this.Symbol, name:this.Name, pageSize:pageSize } if (this.SortInfo && this.SortInfo.Field>=0 && this.SortInfo.Sort>0) //排序 { var column=chart.Column[this.SortInfo.Field]; requestData.column={ name: column.Title, type: column.Type, index:this.SortInfo.Field, ID:column.ID }; requestData.sort=this.SortInfo.Sort; } var obj= { Name:'JSDealChartContainer::RequestVirtualStockData', //类名::函数名 Explain:'报价列表股票数据(虚拟表格)', Request: { Data: requestData }, Self:this, PreventDefault:false }; if (chart.FixedRowCount>0 && chart.FixedRowData.Type==1) { var arySymbol=[]; for(var i=0;i0) //上 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(right,top); } if ((this.BorderLine&2)>0) //下 { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } if ((this.BorderLine&4)>0) //左 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(left,bottom); } if ((this.BorderLine&8)>0) //右 { this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); } this.Canvas.stroke(); } } this.DrawLogo=function() { var text=g_JSChartResource.FrameLogo.Text; if (!IFrameSplitOperator.IsString(text)) return; this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.font=this.LogoTextFont; this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'bottom'; var x=this.ChartBorder.GetRight()-30; var y=this.ChartBorder.GetBottom()-5; this.Canvas.fillText(text,x,y); } } var REPORT_COLUMN_ID= { SYMBOL_ID:0, NAME_ID:1, PRICE_ID:2, //成交价格 VOL_ID:3, //成交量 INCREASE_ID:4, //涨幅 UPDOWN_ID:5, //涨跌 BUY_PRICE_ID:6, //买价 SELL_PRICE_ID:7, //卖价 AMOUNT_ID:8, //总金额 BUY_VOL_ID:9, //买量 SELL_VOL_ID:10, //卖量 YCLOSE_ID:11, //昨收 OPEN_ID:12, HIGH_ID:13, LOW_ID:14, AVERAGE_PRICE_ID:15,//均价 INDEX_ID:16, //序号 从1开始 OUTSTANDING_SHARES_ID:17, //流通股本 TOTAL_SHARES_ID:18, //总股本 CIRC_MARKET_VALUE_ID:19, //流通市值 MARKET_VALUE_ID:20, //总市值 EXCHANGE_RATE_ID:21, //换手率 成交量/流通股本 AMPLITUDE_ID:22, //振幅 LIMIT_HIGH_ID:23, //涨停价 LIMIT_LOW_ID:24, //跌停价 VOL_IN_ID:25, //内盘 VOL_OUT_ID:26, //外盘 NAME_EX_ID:27, //扩展名字 CLOSE_LINE_ID:28, //收盘价线 KLINE_ID:29, //K线 TIME_ID:31, //时间 hhmmss / hhmm / hhmmss.fff DATE_ID:32, //日期 CHECKBOX_ID:33, //单选框 FUTURES_POSITION_ID:34, //期货持仓量 FUTURES_CLOSE_ID:35, //期货结算价 FUTURES_YCLOSE_ID:36, //期货昨结算 FUTURES_OPEN_POSITION_ID:37, //期货开仓量 FUTURES_CLOSE_POSITION_ID:38, //期货平仓量 //1,3,5,10,15分钟涨速 RISING_SPEED_1M_ID:60, RISING_SPEED_3M_ID:61, RISING_SPEED_5M_ID:62, RISING_SPEED_10M_ID:63, RISING_SPEED_15M_ID:64, SYMBOL_NAME_V2_ID:98, //单行 SYMBOL_NAME_ID:99, //两行 CUSTOM_STRING_TEXT_ID:100, //自定义字符串文本 CUSTOM_NUMBER_TEXT_ID:101, //自定义数值型 CUSTOM_DATETIME_TEXT_ID:102, //自定义日期类型 CUSTOM_ICON_ID:103, //自定义图标 CUSTOM_CHECKBOX_ID:104, //自定义checkbox CUSTOM_BUTTON_ID:105, //自定义按钮 CUSTOM_PROGRESS_ID:106, //进度条 CUSTOM_LINK_ID:107, //链接 //预留数值类型 10个 RESERVE_NUMBER1_ID:201, //ReserveNumber1: RESERVE_NUMBER2_ID:202, RESERVE_NUMBER3_ID:203, RESERVE_NUMBER4_ID:204, RESERVE_NUMBER5_ID:205, RESERVE_NUMBER6_ID:206, RESERVE_NUMBER7_ID:207, RESERVE_NUMBER8_ID:208, RESERVE_NUMBER9_ID:209, RESERVE_NUMBER10_ID:210, //预留字符串类型 10个 301-399 RESERVE_STRING1_ID:301, //ReserveString1: RESERVE_STRING2_ID:302, RESERVE_STRING3_ID:303, RESERVE_STRING4_ID:304, RESERVE_STRING5_ID:305, RESERVE_STRING6_ID:306, RESERVE_STRING7_ID:307, RESERVE_STRING8_ID:308, RESERVE_STRING9_ID:309, RESERVE_STRING10_ID:310, //预留进度条类型 10个 401-450 RESERVE_PROGRESS_BAR1_ID:401, //ReserveProgressBar1: RESERVE_PROGRESS_BAR2_ID:402, RESERVE_PROGRESS_BAR3_ID:403, RESERVE_PROGRESS_BAR4_ID:404, RESERVE_PROGRESS_BAR5_ID:405, RESERVE_PROGRESS_BAR6_ID:406, RESERVE_PROGRESS_BAR7_ID:407, RESERVE_PROGRESS_BAR8_ID:408, RESERVE_PROGRESS_BAR9_ID:409, RESERVE_PROGRESS_BAR10_ID:410, } //数据对应字段名对照表 var MAP_COLUMN_FIELD=new Map([ [REPORT_COLUMN_ID.SYMBOL_ID, "Symbol"], [REPORT_COLUMN_ID.NAME_ID, "Name"], [REPORT_COLUMN_ID.PRICE_ID, "Price"], [REPORT_COLUMN_ID.INCREASE_ID, "Increase"], [REPORT_COLUMN_ID.UPDOWN_ID, "UpDown"], [REPORT_COLUMN_ID.VOL_ID, "Vol"], [REPORT_COLUMN_ID.BUY_PRICE_ID, "BuyPrice"], [REPORT_COLUMN_ID.SELL_PRICE_ID, "SellPrice"], [REPORT_COLUMN_ID.AMOUNT_ID, "Amount"], [REPORT_COLUMN_ID.BUY_VOL_ID, "BuyVol"], [REPORT_COLUMN_ID.SELL_VOL_ID, "SellVol"], [REPORT_COLUMN_ID.YCLOSE_ID, "YClose"], [REPORT_COLUMN_ID.OPEN_ID, "Open"], [REPORT_COLUMN_ID.HIGH_ID, "High"], [REPORT_COLUMN_ID.LOW_ID, "Low"], [REPORT_COLUMN_ID.AVERAGE_PRICE_ID,"AvPrice"], [REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID,"OutShares"], [REPORT_COLUMN_ID.TOTAL_SHARES_ID,"TotalShares"], [REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID,"CircMarketValue"], [REPORT_COLUMN_ID.MARKET_VALUE_ID,"MarketValue"], [REPORT_COLUMN_ID.EXCHANGE_RATE_ID, "Exchange"], [REPORT_COLUMN_ID.AMPLITUDE_ID, "Amplitude"], [REPORT_COLUMN_ID.LIMIT_HIGH_ID, "LimitHigh"], [REPORT_COLUMN_ID.LIMIT_LOW_ID,"LimitLow"], [REPORT_COLUMN_ID.VOL_IN_ID, "VolIn"], [REPORT_COLUMN_ID.VOL_OUT_ID,"VolOut"], [REPORT_COLUMN_ID.NAME_EX_ID, "NameEx"], [REPORT_COLUMN_ID.DATE_ID, "Date"], [REPORT_COLUMN_ID.FUTURES_POSITION_ID, "Position"], [REPORT_COLUMN_ID.FUTURES_CLOSE_ID, "FClose"], [REPORT_COLUMN_ID.FUTURES_YCLOSE_ID, "YFClose"], [REPORT_COLUMN_ID.FUTURES_OPEN_POSITION_ID, "OpenPosition"], [REPORT_COLUMN_ID.FUTURES_CLOSE_POSITION_ID, "ClosePosition"], [REPORT_COLUMN_ID.RISING_SPEED_1M_ID, "RSpeed1M"], [REPORT_COLUMN_ID.RISING_SPEED_3M_ID, "RSpeed3M"], [REPORT_COLUMN_ID.RISING_SPEED_5M_ID, "RSpeed5M"], [REPORT_COLUMN_ID.RISING_SPEED_10M_ID, "RSpeed10M"], [REPORT_COLUMN_ID.RISING_SPEED_15M_ID, "RSpeed15M"], [REPORT_COLUMN_ID.RESERVE_NUMBER1_ID,"ReserveNumber1"], [REPORT_COLUMN_ID.RESERVE_NUMBER2_ID,"ReserveNumber2"], [REPORT_COLUMN_ID.RESERVE_NUMBER3_ID,"ReserveNumber3"], [REPORT_COLUMN_ID.RESERVE_NUMBER4_ID,"ReserveNumber4"], [REPORT_COLUMN_ID.RESERVE_NUMBER5_ID,"ReserveNumber5"], [REPORT_COLUMN_ID.RESERVE_NUMBER6_ID,"ReserveNumber6"], [REPORT_COLUMN_ID.RESERVE_NUMBER7_ID,"ReserveNumber7"], [REPORT_COLUMN_ID.RESERVE_NUMBER8_ID,"ReserveNumber8"], [REPORT_COLUMN_ID.RESERVE_NUMBER9_ID,"ReserveNumber9"], [REPORT_COLUMN_ID.RESERVE_NUMBER10_ID,"ReserveNumber10"], [REPORT_COLUMN_ID.RESERVE_STRING1_ID,"ReserveString1"], [REPORT_COLUMN_ID.RESERVE_STRING2_ID,"ReserveString2"], [REPORT_COLUMN_ID.RESERVE_STRING3_ID,"ReserveString3"], [REPORT_COLUMN_ID.RESERVE_STRING4_ID,"ReserveString4"], [REPORT_COLUMN_ID.RESERVE_STRING5_ID,"ReserveString5"], [REPORT_COLUMN_ID.RESERVE_STRING6_ID,"ReserveString6"], [REPORT_COLUMN_ID.RESERVE_STRING7_ID,"ReserveString7"], [REPORT_COLUMN_ID.RESERVE_STRING8_ID,"ReserveString8"], [REPORT_COLUMN_ID.RESERVE_STRING9_ID,"ReserveString9"], [REPORT_COLUMN_ID.RESERVE_STRING10_ID,"ReserveString10"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR1_ID,"ReserveProgressBar1"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR2_ID,"ReserveProgressBar2"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR3_ID,"ReserveProgressBar3"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR4_ID,"ReserveProgressBar4"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR5_ID,"ReserveProgressBar5"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR6_ID,"ReserveProgressBar6"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR7_ID,"ReserveProgressBar7"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR8_ID,"ReserveProgressBar8"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR9_ID,"ReserveProgressBar9"], [REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR10_ID,"ReserveProgressBar10"], ]); function ChartReport() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartReport'; //类名 this.UIElement; this.IsDrawFirst=false; this.GetEventCallback; //获取事件 this.GetStockDataCallback; //获取股票数据 this.GetFlashBGDataCallback; //获取闪烁背景 this.GetBlockDataCallback; //获取当前板块的数据 this.Data; //数据 { XOffset:0, YOffset:0, Data:['600000.sh', '000001.sz'] } this.FixedRowData; //固定行 this.SortInfo; //排序信息 {Field:排序字段id, Sort:0 不排序 1升序 2降序 } this.FixedColumn=2; //固定列 this.FixedRowCount=0; //固定行 this.IsShowHeader=true; //是否显示表头 this.SizeChange=true; this.SelectedModel=0; //选中模式 0=SelectedRow表示当前屏索引 this.SelectedRow=-1; //选中行ID this.SelectedFixedRow=-1; //选中固定行ID this.IsDrawBorder=1; //是否绘制单元格边框 //多选模式 this.MultiSelectModel=0; //0=禁用 1=开启 this.MultiSelectedRow=[]; //选中行 this.ShowSymbol=[]; //显示的股票列表 { Index:序号(排序用), Symbol:股票代码 } this.DragRow; //拖拽行 this.Tab; this.VScrollbar; this.GlobalOption; this.TextOverflowStyle=0; //输出内容比单元格长度大 0=裁剪 1=输出"####" //涨跌颜色 this.UpColor=g_JSChartResource.Report.UpTextColor; this.DownColor=g_JSChartResource.Report.DownTextColor; this.UnchagneColor=g_JSChartResource.Report.UnchagneTextColor; this.BorderColor=g_JSChartResource.Report.BorderColor; //边框线 this.SelectedColor=g_JSChartResource.Report.SelectedColor; //选中行 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.Report.Header.Font.Size, Name:g_JSChartResource.Report.Header.Font.Name }; this.HeaderColor=g_JSChartResource.Report.Header.Color; this.HeaderMergin= { Left:g_JSChartResource.Report.Header.Mergin.Left, Right:g_JSChartResource.Report.Header.Mergin.Right, Top:g_JSChartResource.Report.Header.Mergin.Top, Bottom:g_JSChartResource.Report.Header.Mergin.Bottom }; //排序图标 this.SortConfig= { Size:g_JSChartResource.Report.SortIcon.Size, Family:g_JSChartResource.Report.SortIcon.Family, Arrow:g_JSChartResource.Report.SortIcon.Arrow.slice(), Color:g_JSChartResource.Report.SortIcon.Color.slice(), Margin: { Left:g_JSChartResource.Report.SortIcon.Margin.Left, Bottom:g_JSChartResource.Report.SortIcon.Margin.Bottom } } //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.Report.Item.Font.Size, Name:g_JSChartResource.Report.Item.Font.Name }; this.ItemFixedFontConfg={ Size:g_JSChartResource.Report.FixedItem.Font.Size, Name:g_JSChartResource.Report.FixedItem.Font.Name }; //固定行 this.ItemMergin= { Left:g_JSChartResource.Report.Item.Mergin.Left, Right:g_JSChartResource.Report.Item.Mergin.Right, Top:g_JSChartResource.Report.Item.Mergin.Top, Bottom:g_JSChartResource.Report.Item.Mergin.Bottom, }; this.BarMergin= { Top:g_JSChartResource.Report.Item.BarMergin.Top, Left:g_JSChartResource.Report.Item.BarMergin.Left, Right:g_JSChartResource.Report.Item.BarMergin.Right, Bottom:g_JSChartResource.Report.Item.BarMergin.Bottom, }; this.LimitDrawType=0; //0=绘制边框 1=背景色 this.LimitBorderColor=g_JSChartResource.Report.LimitBorder.Color; this.LimitUpBGColor=g_JSChartResource.Report.LimitColor.UpColor; this.LimitDownBGColor=g_JSChartResource.Report.LimitColor.DownColor; this.LimitTextColor=g_JSChartResource.Report.LimitColor.TextColor; this.LimitMergin= { Top:g_JSChartResource.Report.LimitBorder.Mergin.Top, Left:g_JSChartResource.Report.LimitBorder.Mergin.Left, Right:g_JSChartResource.Report.LimitBorder.Mergin.Right, Bottom:g_JSChartResource.Report.LimitBorder.Mergin.Bottom } this.DragRowColor=g_JSChartResource.Report.DragRow.Color; this.DragRowTextColor=g_JSChartResource.Report.DragRow.TextColor; this.DragMoveRowColor=g_JSChartResource.Report.DragRow.MoveRowColor; this.DragSrcRowColor=g_JSChartResource.Report.DragRow.SrcRowColor; //走势图 this.CloseLineConfig= { CloseColor:g_JSChartResource.Report.CloseLine.CloseColor, YCloseColor:g_JSChartResource.Report.CloseLine.YCloseColor, AreaColor:g_JSChartResource.Report.CloseLine.AreaColor } //K线配置 this.KLineConfig= { UpColor:g_JSChartResource.Report.KLine.UpColor, DownColor:g_JSChartResource.Report.KLine.DownColor, UnchagneColor:g_JSChartResource.Report.KLine.UnchagneColor, DataWidth:g_JSChartResource.Report.KLine.DataWidth, DistanceWidth:g_JSChartResource.Report.KLine.DistanceWidth } this.CheckBoxConfig=CloneData(g_JSChartResource.Report.CheckBox); this.LinkConfig=CloneData(g_JSChartResource.Report.Link); this.ProgressBarConfig=CloneData(g_JSChartResource.Report.ProgressBar); this.ButtonConfig=CloneData(g_JSChartResource.Report.Button); //股票代码+股票名称 this.ItemSymbolFontConfig={Size:g_JSChartResource.Report.Item.SymbolFont.Size, Name:g_JSChartResource.Report.Item.SymbolFont.Name}; this.ItemNameFontConfg={Size:g_JSChartResource.Report.Item.NameFont.Size, Name:g_JSChartResource.Report.Item.NameFont.Name}; //名称+代码 this.NameSymbolV2Config=CloneData(g_JSChartResource.Report.NameSymbolV2); //缓存 this.HeaderFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.SortFont=null, this.ItemFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemFontHeight=0; this.ItemFixedFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemSymbolFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemNameFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemNameHeight=0; this.ItemSymbolHeight=0; this.NameSymbolFont={ Symbol:null, Name:null }; this.RowCount=0; //一屏显示行数 this.HeaderHeight=0; //表头高度 this.FixedRowHeight=0; //固定行高度 this.RowHeight=0; //行高度 this.ItemTextLines=1; //单元格输出行数 this.BottomToolbarHeight=0; //底部工具条高度 this.IsShowAllColumn=false; //是否已显示所有列 this.DevicePixelRatio=GetDevicePixelRatio(); //分辨率 //{ // Type:列id, Title:标题, TextAlign:文字对齐方式, MaxText:文字最大宽度 , TextColor:文字颜色, Sort:0=不支持排序 1=本地排序 0=远程排序, // Icon:{ Family:"iconfont", Size:12, Symbol:"", Margin: { Left:, Bottom }} //} this.Column= [ { Type:REPORT_COLUMN_ID.INDEX_ID, Title:"序号", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Index, MaxText:"8888"}, { Type:REPORT_COLUMN_ID.SYMBOL_ID, Title:"代码", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Symbol, MaxText:"888888"}, { Type:REPORT_COLUMN_ID.NAME_ID, Title:"名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎" }, { Type:REPORT_COLUMN_ID.INCREASE_ID, Title:"涨幅%", TextAlign:"right", Width:null, MaxText:"-888.88" }, ]; this.RectClient={}; //{ Rect:rtItem, Stock:stock, Index:index, Column:column, RowType:rowType, Type:drawInfo.Tooltip.Type, Data:{ AryText:[ {Text:xx} ]} }; //Type:1=数据截断 // { Text, Color, Title:, TitleColor, Space, Margin:{ Left, Top, Right, Bottom }} this.TooltipRect=[]; //{ Rect:rtItem, Type: 0=checkedbox, 1=button, 2=link , Stock, Index:index, Column:column } this.ButtonRect=[]; this.LastMouseStatus; this.ReloadResource=function(resource) { this.DevicePixelRatio=GetDevicePixelRatio() this.UpColor=g_JSChartResource.Report.UpTextColor; this.DownColor=g_JSChartResource.Report.DownTextColor; this.UnchagneColor=g_JSChartResource.Report.UnchagneTextColor; this.BorderColor=g_JSChartResource.Report.BorderColor; //边框线 this.SelectedColor=g_JSChartResource.Report.SelectedColor; //选中行 //表头配置 this.HeaderFontConfig={ Size:g_JSChartResource.Report.Header.Font.Size, Name:g_JSChartResource.Report.Header.Font.Name }; this.HeaderColor=g_JSChartResource.Report.Header.Color; this.HeaderMergin= { Left:g_JSChartResource.Report.Header.Mergin.Left, Right:g_JSChartResource.Report.Header.Mergin.Right, Top:g_JSChartResource.Report.Header.Mergin.Top, Bottom:g_JSChartResource.Report.Header.Mergin.Bottom }; //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.Report.Item.Font.Size, Name:g_JSChartResource.Report.Item.Font.Name }; this.ItemMergin= { Left:g_JSChartResource.Report.Item.Mergin.Left, Right:g_JSChartResource.Report.Item.Mergin.Right, Top:g_JSChartResource.Report.Item.Mergin.Top, Bottom:g_JSChartResource.Report.Item.Mergin.Bottom }; this.BarMergin= { Top:g_JSChartResource.Report.Item.BarMergin.Top, Left:g_JSChartResource.Report.Item.BarMergin.Left, Right:g_JSChartResource.Report.Item.BarMergin.Right, Bottom:g_JSChartResource.Report.Item.BarMergin.Bottom }; this.LimitBorderColor=g_JSChartResource.Report.LimitBorder.Color; this.LimitMergin= { Top:g_JSChartResource.Report.LimitBorder.Mergin.Top, Left:g_JSChartResource.Report.LimitBorder.Mergin.Left, Right:g_JSChartResource.Report.LimitBorder.Mergin.Right, Bottom:g_JSChartResource.Report.LimitBorder.Mergin.Bottom } //排序图标 this.SortConfig= { Size:g_JSChartResource.Report.SortIcon.Size, Family:g_JSChartResource.Report.SortIcon.Family, Arrow:g_JSChartResource.Report.SortIcon.Arrow.slice(), Color:g_JSChartResource.Report.SortIcon.Color.slice(), Margin: { Left:g_JSChartResource.Report.SortIcon.Margin.Left, Bottom:g_JSChartResource.Report.SortIcon.Margin.Bottom } } for(var i=0;i0, =0, <0) 2=(>=0, <0) else colItem.IsDrawCallback=false; if (item.Icon) colItem.Icon=item.Icon; //点击表头弹出菜单 if (IFrameSplitOperator.IsBool(item.EnablePopupHeaderMenu)) colItem.EnablePopupHeaderMenu=item.EnablePopupHeaderMenu; if (item.Sort==1 || item.Sort==2) //1本地排序 2=远程排序 { colItem.SortType=[1,2]; //默认 降序 ,升序 if (IFrameSplitOperator.IsNonEmptyArray(item.SortType)) colItem.SortType=item.SortType.slice(); } if (item.Type==REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; colItem.FormatType=0; //0=默认格式 1=长度不够使用... if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; if (IFrameSplitOperator.IsNumber(item.FormatType)) colItem.FormatType=item.FormatType; //输出样式 } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; colItem.Decimal=2; colItem.FormatType=0; //0=默认格式化 1=原始输出 2=科学计数 3=成交量格式化 colItem.ColorType=0; //0=默认使用TextColor, 1=(>0涨,<0跌)2=(>昨收涨,<昨收跌) if (IFrameSplitOperator.IsNumber(item.Decimal)) colItem.Decimal=item.Decimal; //小数位数 if (IFrameSplitOperator.IsNumber(item.FormatType)) colItem.FormatType=item.FormatType; //输出样式 if (IFrameSplitOperator.IsNumber(item.ColorType)) colItem.ColorType=item.ColorType; //颜色属性 } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; colItem.FormatType=0; //0=yyyy-mm-dd 1=YYYY/MM/DD colItem.ValueType=0; //0=yyyymmdd 1=hhmmss if (IFrameSplitOperator.IsNumber(item.FormatType)) colItem.FormatType=item.FormatType; //输出样式 if (IFrameSplitOperator.IsNumber(item.ValueType)) colItem.FormatType=item.ValueType; //输出样式 } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_CHECKBOX_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; if (item.CheckBox) colItem.CheckBox=CloneData(item.CheckBox); else colItem.CheckBox=this.CheckBoxConfig; } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_BUTTON_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; if (item.Button) colItem.Button=CloneData(item.Button); else colItem.Button=this.ButtonConfig; } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_PROGRESS_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; if (item.ProgressBar) colItem.ProgressBar=CloneData(item.ProgressBar); else colItem.ProgressBar=this.ProgressBarConfig; } else if (this.IsReserveProgressBarColumn(item.Type)) { if (item.ProgressBar) colItem.ProgressBar=CloneData(item.ProgressBar); else colItem.ProgressBar=this.ProgressBarConfig; } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_LINK_ID) { if (!IFrameSplitOperator.IsNumber(item.DataIndex) && !IFrameSplitOperator.IsNumber(item.BlockIndex)) continue; if (IFrameSplitOperator.IsNumber(item.DataIndex)) colItem.DataIndex=item.DataIndex; //数据在扩展数据索引列 if (IFrameSplitOperator.IsNumber(item.BlockIndex)) colItem.BlockIndex=item.BlockIndex; if (item.Link) colItem.Link=CloneData(item.Link); else colItem.Link=this.LinkConfig; } else if (item.Type==REPORT_COLUMN_ID.CUSTOM_ICON_ID) { } else if (item.Type==REPORT_COLUMN_ID.CLOSE_LINE_ID) { if (IFrameSplitOperator.IsBool(item.IsDrawArea)) colItem.IsDrawArea=item.IsDrawArea; } else if(item.Type==REPORT_COLUMN_ID.TIME_ID) { if (IFrameSplitOperator.IsNumber(item.ValueType)) colItem.ValueType=item.ValueType; } else if (item.Type==REPORT_COLUMN_ID.DATE_ID) { if (IFrameSplitOperator.IsNumber(item.FormatType)) colItem.FormatType=item.FormatType; } this.Column.push(colItem); } } this.SwapColumn=function(leftIndex, rightIndex) { if (!IFrameSplitOperator.IsNumber(leftIndex) || !IFrameSplitOperator.IsNumber(rightIndex)) return false; var count=this.Column.length; if (leftIndex<0 || leftIndex>=count) return false; if (rightIndex<0 || rightIndex>=count) return false; if (leftIndex==rightIndex) return; var tempItem=this.Column[leftIndex]; this.Column[leftIndex]=this.Column[rightIndex]; this.Column[rightIndex]=tempItem; return true; } this.DeleteColumn=function(index) { if (!IFrameSplitOperator.IsNonEmptyArray(this.Column)) return false; if (index<0 || index>=this.Column.length) return false; this.Column.splice(index,1); return true; } this.GetXScrollPos=function() { return this.Data.XOffset; } this.GetXScrollRange=function() { var maxOffset=this.Column.length-this.FixedColumn-3; if (maxOffset<0) return 0; return maxOffset; } this.GetYScrollRange=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return 0; var dataCount=this.GetAllRowCount(); var maxOffset=dataCount-this.RowCount; return maxOffset; } this.GetDefaultColunm=function(id) { var DEFAULT_COLUMN= [ { Type:REPORT_COLUMN_ID.INDEX_ID, Title:"序号", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Index, MaxText:"8888"}, { Type:REPORT_COLUMN_ID.SYMBOL_ID, Title:"代码", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Symbol, MaxText:"888888"}, { Type:REPORT_COLUMN_ID.NAME_ID, Title:"名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎0" }, { Type:REPORT_COLUMN_ID.NAME_EX_ID, Title:"名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.SYMBOL_NAME_ID, Title:"股票名称", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Name, MaxText:"擎擎擎擎0"}, { Type:REPORT_COLUMN_ID.SYMBOL_NAME_V2_ID, Title:"名称/代码", TextAlign:"left", Width:null, TextColor:g_JSChartResource.Report.NameSymbolV2.Name.Color, MaxText:"擎擎擎擎*", MaxText2:"999999", Space:5, TextColor2:g_JSChartResource.Report.NameSymbolV2.Symbol.Color }, { Type:REPORT_COLUMN_ID.INCREASE_ID, Title:"涨幅%", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.PRICE_ID, Title:"现价", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.UPDOWN_ID, Title:"涨跌", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.AMPLITUDE_ID, Title:"振幅%", TextAlign:"right", Width:null, MaxText:"888.88" }, { Type:REPORT_COLUMN_ID.BUY_PRICE_ID, Title:"买价", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.SELL_PRICE_ID, Title:"卖价", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.AVERAGE_PRICE_ID, Title:"均价", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.OPEN_ID, Title:"今开", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.HIGH_ID, Title:"最高", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.LOW_ID, Title:"最低", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.YCLOSE_ID, Title:"昨收", TextAlign:"right", Width:null, MaxText:"88888.88" }, { Type:REPORT_COLUMN_ID.VOL_ID, Title:"总量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.AMOUNT_ID, Title:"总金额", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Amount, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.EXCHANGE_RATE_ID, Title:"换手%", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"88.88擎" }, { Type:REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID, Title:"流通股本", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.TOTAL_SHARES_ID, Title:"总股本", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID, Title:"流通市值", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.MARKET_VALUE_ID, Title:"总市值", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.VOL_IN_ID, Title:"内盘", TextAlign:"right", TextColor:g_JSChartResource.Report.DownTextColor, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.VOL_OUT_ID, Title:"外盘", TextAlign:"right", TextColor:g_JSChartResource.Report.UpTextColor, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.CLOSE_LINE_ID, Title:"走势", TextAlign:"center", TextColor:g_JSChartResource.Report.CloseLineColor, Width:null, MaxText:"88888.88888" }, { Type:REPORT_COLUMN_ID.BUY_VOL_ID, Title:"买量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888.8擎" }, { Type:REPORT_COLUMN_ID.SELL_VOL_ID, Title:"卖量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888.8擎" }, //{ Type:REPORT_COLUMN_ID.MULTI_BAR_ID, Title:"柱子", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.BarTitle, MaxText:"888888" }, //{ Type:REPORT_COLUMN_ID.CENTER_BAR_ID, Title:"柱子2", TextAlign:"center", Width:null, TextColor:g_JSChartResource.DealList.FieldColor.BarTitle, MaxText:"888888" }, { Type:REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID, Title:"自定义", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID, Title:"自定义", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID, Title:"自定义", TextAlign:"center", Width:null, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999-99-99" }, { Type:REPORT_COLUMN_ID.CUSTOM_ICON_ID, Title:" ", TextAlign:"left", FixedWidth:20, TextColor:g_JSChartResource.Report.FieldColor.Text }, { Type:REPORT_COLUMN_ID.KLINE_ID, Title:"K线", TextAlign:"left", FixedWidth:50, TextColor:g_JSChartResource.Report.FieldColor.Text }, { Type:REPORT_COLUMN_ID.TIME_ID, Title:"时间", TextAlign:"left", ValueType:0, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"99:99:99.999" }, { Type:REPORT_COLUMN_ID.DATE_ID, Title:"日期", TextAlign:"left", FormatType:0, TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999-99-99" }, { Type:REPORT_COLUMN_ID.CHECKBOX_ID, Title:"", TextAlign:"center", FixedWidth:20*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.CUSTOM_CHECKBOX_ID, Title:"", TextAlign:"center", FixedWidth:20*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.CUSTOM_BUTTON_ID, Title:"", TextAlign:"center", FixedWidth:50*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.CUSTOM_PROGRESS_ID, Title:"进度条", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.CUSTOM_LINK_ID, Title:"链接地址", TextAlign:"center", MaxText:"擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.FUTURES_POSITION_ID, Title:"持仓量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Vol, Width:null, MaxText:"8888888" }, { Type:REPORT_COLUMN_ID.FUTURES_CLOSE_ID, Title:"结算价", TextAlign:"right", Width:null, MaxText:"8888888" }, { Type:REPORT_COLUMN_ID.FUTURES_YCLOSE_ID, Title:"昨结算价", TextAlign:"right", Width:null, MaxText:"8888888" }, { Type:REPORT_COLUMN_ID.FUTURES_OPEN_POSITION_ID, Title:"开仓量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888888" }, { Type:REPORT_COLUMN_ID.FUTURES_CLOSE_POSITION_ID, Title:"平仓量", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, Width:null, MaxText:"8888888" }, { Type:REPORT_COLUMN_ID.RISING_SPEED_1M_ID, Title:"涨速%", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.RISING_SPEED_3M_ID, Title:"3分涨速%", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.RISING_SPEED_5M_ID, Title:"5分涨速%", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.RISING_SPEED_10M_ID, Title:"10分涨速%", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.RISING_SPEED_15M_ID, Title:"15分涨速%", TextAlign:"right", Width:null, MaxText:"-888.88" }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER1_ID, Title:"数值1", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER2_ID, Title:"数值2", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER3_ID, Title:"数值3", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER4_ID, Title:"数值4", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER5_ID, Title:"数值5", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER6_ID, Title:"数值6", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER7_ID, Title:"数值7", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER8_ID, Title:"数值8", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER9_ID, Title:"数值9", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_NUMBER10_ID, Title:"数值10", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"9999.99", FloatPrecision:2 }, { Type:REPORT_COLUMN_ID.RESERVE_STRING1_ID, Title:"文字1", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING2_ID, Title:"文字2", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING3_ID, Title:"文字3", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING4_ID, Title:"文字4", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING5_ID, Title:"文字5", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING6_ID, Title:"文字6", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING7_ID, Title:"文字7", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING8_ID, Title:"文字8", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING9_ID, Title:"文字9", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_STRING10_ID, Title:"文字10", TextAlign:"right", TextColor:g_JSChartResource.Report.FieldColor.Text, MaxText:"擎擎擎擎擎擎" }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR1_ID, Title:"进度条1", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR2_ID, Title:"进度条2", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR3_ID, Title:"进度条3", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR4_ID, Title:"进度条4", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR5_ID, Title:"进度条5", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR6_ID, Title:"进度条6", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR7_ID, Title:"进度条7", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR8_ID, Title:"进度条8", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR9_ID, Title:"进度条9", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, { Type:REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR10_ID, Title:"进度条10", TextAlign:"center", FixedWidth:100*GetDevicePixelRatio() }, ]; for(var i=0;i0) { var bottom=this.ChartBorder.GetBottom(); this.Tab.DrawTab(this.RectClient.Left,bottom-this.BottomToolbarHeight, this.RectClient.Right, bottom) this.Tab.DrawScrollbar(this.RectClient.Left,bottom-this.BottomToolbarHeight, this.RectClient.Right, bottom); } this.ClipClient(); this.DrawBorder(); this.Canvas.restore(); this.DrawDragRow(); if (this.VScrollbar) { var bottom=this.ChartBorder.GetBottom(); this.VScrollbar.DrawScrollbar(this.RectClient.Left,this.RectClient.Top+this.HeaderHeight, this.RectClient.Right, bottom-this.BottomToolbarHeight-4); } this.LastMouseStatus=null; this.SizeChange=false; } //更新缓存变量 this.UpdateCacheData=function() { this.RectClient.Left=this.ChartBorder.GetLeft(); this.RectClient.Right=this.ChartBorder.GetRight(); this.RectClient.Top=this.ChartBorder.GetTop(); this.RectClient.Bottom=this.ChartBorder.GetBottom()-this.BottomToolbarHeight; } this.GetPageSize=function(recalculate) //recalculate 是否重新计算 { if (recalculate) this.CalculateSize(); var size=this.RowCount; return size; } this.GetCurrentPageStatus=function() //{ Start:起始索引, End:结束索引(数据), PageSize:页面可以显示几条记录, IsEnd:是否是最后一页, IsSinglePage:是否只有一页数据} { var result={ Start:this.Data.YOffset, PageSize:this.RowCount, IsEnd:false, SelectedRow:this.SelectedRow, IsSinglePage:false, DataCount:0, MultiSelectModel:this.MultiSelectModel }; if (this.MultiSelectModel==1) { result.SelectedRow=-1; result.MultiSelectedRow=this.MultiSelectedRow.slice(); result.MultiSelectedRow.sort((left, right)=>{ return left>right; }); } if (IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) { result.End=this.Data.YOffset+this.RowCount-1; result.IsSinglePage=this.Data.Data.length<=this.RowCount; result.DataCount=this.Data.Data.length; if (result.End>=this.Data.Data.length-1) result.IsEnd=true; if (result.End>=this.Data.Data.length) result.End=this.Data.Data.length-1; } else { result.Start=0; result.End=0; result.IsEnd=true; result.IsSinglePage=true; } return result; } this.CalculateSize=function() //计算大小 { if (this.Tab && this.Tab.IsShow) { this.Tab.CalculateSize(); this.BottomToolbarHeight=this.Tab.Height; } else { this.BottomToolbarHeight=0; } if (this.VScrollbar && this.VScrollbar.Enable) this.VScrollbar.CalculateSize(); this.UpdateCacheData(); var pixelRatio=GetDevicePixelRatio(); this.HeaderFont=`${this.HeaderFontConfig.Size*pixelRatio}px ${ this.HeaderFontConfig.Name}`; this.ItemFont=`${this.ItemFontConfig.Size*pixelRatio}px ${ this.ItemFontConfig.Name}`; this.ItemFixedFont=`${this.ItemFixedFontConfg.Size*pixelRatio}px ${ this.ItemFixedFontConfg.Name}`; this.ItemSymbolFont=`${this.ItemSymbolFontConfig.Size*pixelRatio}px ${ this.ItemSymbolFontConfig.Name}`; this.ItemNameFont=`${this.ItemNameFontConfg.Size*pixelRatio}px ${ this.ItemNameFontConfg.Name}`; this.NameSymbolFont.Symbol=`${this.NameSymbolV2Config.Symbol.Size*pixelRatio}px ${this.NameSymbolV2Config.Symbol.Name}`; this.NameSymbolFont.Name=`${this.ItemSymbolFontConfig.Name.Size*pixelRatio}px ${this.NameSymbolV2Config.Name.Name}`; this.ItemFontHeight=this.GetFontHeight(this.ItemFont,"擎"); this.RowHeight=this.ItemFontHeight+ this.ItemMergin.Top+ this.ItemMergin.Bottom; this.ItemTextLines=1; this.FixedRowHeight=this.GetFontHeight(this.ItemFixedFont,"擎")+ this.ItemMergin.Top+ this.ItemMergin.Bottom; this.SortFont=`${this.SortConfig.Size*pixelRatio}px ${ this.SortConfig.Family}`; this.Canvas.font=this.ItemFont; var itemWidth=0; for(var i=0;ithis.RowHeight) this.RowHeight=rowHeight; if (rowHeight>this.FixedRowHeight) this.FixedRowHeight=rowHeight; } else if (item.Type==REPORT_COLUMN_ID.SYMBOL_NAME_V2_ID) //单行显示 { this.Canvas.font==this.NameSymbolFont.Name; var nameWidth=this.Canvas.measureText(item.MaxText).width; var nameHeight=this.GetFontHeight(this.ItemNameFont,"擎"); this.Canvas.font==this.NameSymbolFont.Symbol; var symbolWidth=this.Canvas.measureText(item.MaxText2).width; var symboHeight=this.GetFontHeight(this.ItemSymbolFont,"擎"); this.ItemNameHeight=Math.abs(nameHeight,symboHeight); var space=2; if (IFrameSplitOperator.IsNumber(item.Space)) space=item.Space; itemWidth=nameWidth+symbolWidth+space; item.Width=itemWidth+4+this.ItemMergin.Left+this.ItemMergin.Right; } else { if (IFrameSplitOperator.IsNumber(item.FixedWidth)) itemWidth=item.FixedWidth; else itemWidth=this.Canvas.measureText(item.MaxText).width; item.Width=itemWidth+4+this.ItemMergin.Left+this.ItemMergin.Right; } if (item.Icon && item.Icon.Symbol) { item.Width+=item.Icon.Size; if (item.Icon.Margin) { var margin=item.Icon.Margin; if (IFrameSplitOperator.IsNumber(margin.Left)) item.Width+=margin.Left; if (IFrameSplitOperator.IsNumber(margin.Right)) item.Width+=margin.Right; } } } this.Canvas.font=this.HeaderFont; for(var i=0;i0) itemWidth+this.SortConfig.Size*pixelRatio; itemWidth+=(4+this.HeaderMergin.Left+this.HeaderMergin.Right); if (item.Width0) { this.DrawSortHeader(item.Title,item.TextAlign,x,yBottom,textWidth,this.SortInfo.Sort, textSize); } else { this.DrawText(item.Title,item.TextAlign,x,yBottom,textWidth,textSize); } if (iconWidth>0) { this.DrawHeaderIcon(item.Icon, textSize.Right, yBottom, i, item); this.Canvas.font=this.HeaderFont; } this.Canvas.fillStyle=this.HeaderColor; textLeft+=item.Width; } for(var i=this.FixedColumn+this.Data.XOffset;i0) { this.DrawSortHeader(item.Title,item.TextAlign,x,yBottom,textWidth,this.SortInfo.Sort,textSize); } else { this.DrawText(item.Title,item.TextAlign,x,yBottom,textWidth,textSize); } if (iconWidth>0) { this.DrawHeaderIcon(item.Icon, textSize.Right, yBottom, i, item); this.Canvas.font=this.HeaderFont; } textLeft+=item.Width; } } this.DrawText=function(text, textAlign, x, yBottom, cellWidth, textSize) { var textWidth=this.Canvas.measureText(text).width; if (textAlign=='center') { x=x+(cellWidth-textWidth)/2; } else if (textAlign=='right') { x=x+cellWidth-textWidth; } this.Canvas.textAlign="left"; this.Canvas.textBaseline="bottom"; this.Canvas.fillText(text,x,yBottom-this.HeaderMergin.Bottom); if (textSize) { textSize.Right=x+textWidth; textSize.Width=textWidth; } } this.DrawHeaderIcon=function(icon, x, yBottom, index, column) { var iconFont=`${icon.Size}px ${icon.Family}`; this.Canvas.font=iconFont; this.Canvas.textAlign="left"; if (icon.Color) this.Canvas.fillStyle=icon.Color; var xIcon=x; var yIcon=yBottom; if (icon.Margin && IFrameSplitOperator.IsNumber(icon.Margin.Left)) xIcon+=icon.Margin.Left; if (icon.Margin && IFrameSplitOperator.IsNumber(icon.Margin.Bottom)) yIcon-=icon.Margin.Bottom; this.Canvas.fillText(icon.Symbol, xIcon, yIcon); if (icon.Tooltip) { var rtIcon={ Left:xIcon, Bottom:yIcon, Width:icon.Size, Height:icon.Size }; rtIcon.Right=rtIcon.Left+rtIcon.Width; rtIcon.Top=rtIcon.Bottom-rtIcon.Height; var tooltipData={ Rect:rtIcon, Type:2, Column:column, Index:index, Data:icon.Tooltip.Data }; this.TooltipRect.push(tooltipData); } } this.DrawSortHeader=function(text, textAlign, x, yBottom, width, sortType,textSize) { var pixelRatio=GetDevicePixelRatio(); var sortText=this.SortConfig.Arrow[sortType]; this.Canvas.font=this.HeaderFont; var textWidth=this.Canvas.measureText(text).width; var sortTextWidth=this.SortConfig.Size*pixelRatio+this.SortConfig.Margin.Left; if (textAlign=='center') { x=x+width/2-(sortTextWidth+textWidth)/2; } else if (textAlign=='right') { x=(x+width)-sortTextWidth-textWidth; } this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; var xText=x; this.Canvas.font=this.HeaderFont; this.Canvas.fillStyle=this.HeaderColor; this.Canvas.fillText(text,xText,yBottom-this.HeaderMergin.Bottom); xText+=(textWidth+this.SortConfig.Margin.Left); this.Canvas.font=this.SortFont; this.Canvas.fillStyle=this.SortConfig.Color[sortType]; this.Canvas.fillText(sortText,xText,yBottom-this.SortConfig.Margin.Bottom); this.Canvas.font=this.HeaderFont; this.Canvas.fillStyle=this.HeaderColor; if (textSize) { textSize.Right=x+textWidth+sortTextWidth; textSize.Width=textWidth+sortTextWidth; } } this.DrawBorder=function() { if (!this.IsDrawBorder) return; var left=this.RectClient.Left; var right=this.RectClient.Right; var top=this.RectClient.Top; var bottom=this.RectClient.Bottom; this.Canvas.strokeStyle=this.BorderColor; this.Canvas.beginPath(); this.Canvas.moveTo(left,ToFixedPoint(top+this.HeaderHeight)); this.Canvas.lineTo(right,ToFixedPoint(top+this.HeaderHeight)); var rowTop=top+this.HeaderHeight+this.RowHeight; var rotBottom=rowTop; for(var i=0;i=chartRight) break; } for(var i=this.FixedColumn+this.Data.XOffset;i=chartRight) break; } } this.DrawFixedItem=function(dataIndex, colIndex, column, left, top) { var x=left+this.ItemMergin.Left; var textWidth=column.Width-this.ItemMergin.Left-this.ItemMergin.Right; var drawInfo={ Text:null, TextColor:column.TextColor , TextAlign:column.TextAlign }; if (this.GetFixedRowTextDrawInfo(dataIndex, colIndex, column, drawInfo)) { this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth); return; } if (!this.FixedRowData || !IFrameSplitOperator.IsNonEmptyArray(this.FixedRowData.Data)) return; var data=this.FixedRowData.Data; var rowData=data[dataIndex]; if (!IFrameSplitOperator.IsNonEmptyArray(rowData)) return; var itemData=rowData[colIndex]; if (!itemData || !itemData.Text) return; drawInfo.Text=itemData.Text; if (itemData.Color) drawInfo.TextColor=itemData.Color; if (itemData.TextAlign) drawInfo.TextAlign=itemData.TextAlign; this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth); } this.DrawRow=function(symbol, top, dataIndex, rowType) //rowType 0=表格行 1=顶部固定行 2=拖拽行 { var left=this.RectClient.Left; var chartRight=this.RectClient.Right; var data= { Symbol:symbol , Stock:null, Block:null }; if (this.GetStockDataCallback) data.Stock=this.GetStockDataCallback(symbol); if (this.GetBlockDataCallback) data.Block=this.GetBlockDataCallback(symbol); if (this.GetFlashBGDataCallback) data.FlashBG=this.GetFlashBGDataCallback(symbol, Date.now()); data.Decimal=GetfloatPrecision(symbol); //小数位数 for(var i=0;i=chartRight) break; } for(var i=this.FixedColumn+this.Data.XOffset;i=chartRight) break; } } this.DrawItem=function(index, data, column, left, top, rowType, columnIndex) { var itemWidth=column.Width; var x=left+this.ItemMergin.Left; var textWidth=column.Width-this.ItemMergin.Left-this.ItemMergin.Right; var stock=data.Stock; var drawInfo= { Text:null, TextColor:column.TextColor , TextAlign:column.TextAlign, Tooltip:null, Index:index, ColumnIndex:columnIndex }; var rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; drawInfo.Rect=rtItem; if (column.FullColBGColor) { this.DrawItemBG({ Rect:rtItem, BGColor:column.FullColBGColor }); } if (column.Type==REPORT_COLUMN_ID.INDEX_ID) { if (rowType==1) return; //固定行序号空 drawInfo.Text=(index+1).toString(); } else if (column.Type==REPORT_COLUMN_ID.SYMBOL_ID) { if (stock && stock.Symbol) drawInfo.Text=stock.Symbol; else drawInfo.Text=data.Symbol; this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.SYMBOL_NAME_ID) { this.DrawSymbolName(data, column, left, top, rowType); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.SYMBOL_NAME_V2_ID) { this.DrawSymbolNameV2(data, column, left, top, rowType); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.NAME_ID) { if (stock && stock.Name) { if (IFrameSplitOperator.IsString(stock.Name)) { drawInfo.Text=this.TextEllipsis(stock.Name, textWidth, column.MaxText); drawInfo.TextColor=this.GetNameColor(column,data.Symbol, rowType); } } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.NAME_EX_ID) { //复杂格式 { Text:, Symbol:{ Family:'iconfont', Size:, Data:[ { Text:'\ue631', Color:'#1c65db'}, ...] } ]} if (stock && stock.NameEx) { var nameEx=stock.NameEx; drawInfo.Text=this.TextEllipsis(nameEx.Text, textWidth, column.MaxText); drawInfo.TextColor=this.GetNameColor(column,data.Symbol, rowType); if (nameEx.Symbol) drawInfo.Symbol=nameEx.Symbol; } } else if (column.Type==REPORT_COLUMN_ID.PRICE_ID) { if (stock) this.GetPriceDrawInfo(stock.Price, stock, data, drawInfo, { LimitBG:true }); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.OPEN_ID) { //如果行情开盘价为涨停价或跌停价,则对内容加灰框 if (stock) { this.DrawLimitPriceBorder(stock.Open, stock, left, top, column.Width); this.GetPriceDrawInfo(stock.Open, stock, data, drawInfo, { LimitBG:true }); } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.HIGH_ID) { //如果行情最高价为涨停价,则对内容加灰框 if (stock) { this.DrawLimitPriceBorder(stock.High, stock, left, top, column.Width); this.GetPriceDrawInfo(stock.High, stock, data, drawInfo, { LimitBG:true }); } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.LOW_ID) { //如果行情最低价为跌停价,则对内容加灰框 if (stock) { this.DrawLimitPriceBorder(stock.Low, stock, left, top, column.Width); this.GetPriceDrawInfo(stock.Low, stock, data, drawInfo, { LimitBG:true }); } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.YCLOSE_ID) { if (stock) this.GetPriceDrawInfo(stock.YClose, stock, data, drawInfo); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.BUY_PRICE_ID) { if (stock) this.GetPriceDrawInfo(stock.BuyPrice, stock, data, drawInfo); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.FUTURES_CLOSE_ID || column.Type==REPORT_COLUMN_ID.FUTURES_YCLOSE_ID) { var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (stock && IFrameSplitOperator.IsNumber(stock[fieldName])) { var value=stock[fieldName]; this.GetPriceDrawInfo(value, stock, data, drawInfo); } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.SELL_PRICE_ID) { if (stock) this.GetPriceDrawInfo(stock.SellPrice, stock, data, drawInfo); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.AVERAGE_PRICE_ID) { if (stock) this.GetPriceDrawInfo(stock.AvPrice, stock, data, drawInfo); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.EXCHANGE_RATE_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.Exchange)) drawInfo.Text=stock.Exchange.toFixed(2); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.BUY_VOL_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.BuyVol)) drawInfo.Text=this.FormatVolString(stock.BuyVol); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.SELL_VOL_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.SellVol)) drawInfo.Text=this.FormatVolString(stock.SellVol); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.VOL_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.Vol)) drawInfo.Text=this.FormatVolString(stock.Vol); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.VOL_IN_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.VolIn)) drawInfo.Text=this.FormatVolString(stock.VolIn); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.VOL_OUT_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.VolOut)) drawInfo.Text=this.FormatVolString(stock.VolOut); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.TOTAL_SHARES_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.TotalShares)) drawInfo.Text=this.FormatVolString(stock.TotalShares); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.OUTSTANDING_SHARES_ID) { if (stock && IFrameSplitOperator.IsNumber(stock.OutShares)) drawInfo.Text=this.FormatVolString(stock.OutShares); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.CIRC_MARKET_VALUE_ID || column.Type==REPORT_COLUMN_ID.MARKET_VALUE_ID || column.Type==REPORT_COLUMN_ID.AMOUNT_ID) { var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (stock && IFrameSplitOperator.IsNumber(stock[fieldName])) drawInfo.Text=this.FormatVolString(stock[fieldName]); this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.INCREASE_ID || column.Type==REPORT_COLUMN_ID.AMPLITUDE_ID || column.Type==REPORT_COLUMN_ID.UPDOWN_ID || column.Type==REPORT_COLUMN_ID.RISING_SPEED_1M_ID || column.Type==REPORT_COLUMN_ID.RISING_SPEED_3M_ID || column.Type==REPORT_COLUMN_ID.RISING_SPEED_5M_ID || column.Type==REPORT_COLUMN_ID.RISING_SPEED_10M_ID || column.Type==REPORT_COLUMN_ID.RISING_SPEED_15M_ID ) { var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (stock && IFrameSplitOperator.IsNumber(stock[fieldName])) { var value=stock[fieldName]; drawInfo.Text=value.toFixed(2); drawInfo.TextColor=this.GetUpDownColor(value,0); } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.FUTURES_POSITION_ID || column.Type==REPORT_COLUMN_ID.FUTURES_OPEN_POSITION_ID || column.Type==REPORT_COLUMN_ID.FUTURES_CLOSE_POSITION_ID) { //持仓量原始值输出 var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (stock && IFrameSplitOperator.IsNumber(stock[fieldName])) { var value=stock[fieldName]; drawInfo.Text=value.toFixed(0); } this.FormatDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID) { this.GetCustomStringDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_NUMBER_TEXT_ID) { this.GetCustomNumberDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_DATETIME_TEXT_ID) { this.GetCustomDateTimeDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_ICON_ID) { this.GetCustomIconDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CLOSE_LINE_ID) { var rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; if (stock) this.DrawLine(stock.CloseLine, column, rtItem); } else if (column.Type==REPORT_COLUMN_ID.KLINE_ID) { var rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; this.DrawKLine(stock.KLine, column, rtItem, data); } else if (column.Type==REPORT_COLUMN_ID.TIME_ID) { this.FormaTimeDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.DATE_ID) { this.FormaDateDrawInfo(column, stock, drawInfo, data); } else if (column.Type==REPORT_COLUMN_ID.CHECKBOX_ID) { rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; drawInfo.Rect=rtItem; drawInfo.Checked=false; drawInfo.Enable=true; drawInfo.CheckBox=this.CheckBoxConfig; drawInfo.Data=stock; if (stock && IFrameSplitOperator.IsBool(stock.Checked)) drawInfo.Checked=stock.Checked; } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_CHECKBOX_ID) { rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; drawInfo.Rect=rtItem; this.GetCustomCheckBoxDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_BUTTON_ID) { rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; drawInfo.Rect=rtItem; this.GetCustomButtonDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_PROGRESS_ID) { rtItem={ Left:left, Top:top, Width:column.Width, Height:this.RowHeight }; rtItem.Right=rtItem.Left+rtItem.Width; rtItem.Bottom=rtItem.Top+rtItem.Height; drawInfo.Rect=rtItem; this.GetCustomProgressBarDrawInfo(data, column, drawInfo); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_LINK_ID) { this.GetCustomLinkDrawInfo(data, column, drawInfo); } else if ([REPORT_COLUMN_ID.RESERVE_NUMBER1_ID,REPORT_COLUMN_ID.RESERVE_NUMBER2_ID,REPORT_COLUMN_ID.RESERVE_NUMBER3_ID, REPORT_COLUMN_ID.RESERVE_NUMBER4_ID,REPORT_COLUMN_ID.RESERVE_NUMBER5_ID,REPORT_COLUMN_ID.RESERVE_NUMBER6_ID,REPORT_COLUMN_ID.RESERVE_NUMBER7_ID, REPORT_COLUMN_ID.RESERVE_NUMBER8_ID,REPORT_COLUMN_ID.RESERVE_NUMBER9_ID,REPORT_COLUMN_ID.RESERVE_NUMBER10_ID].includes(column.Type)) { this.FormatReserveNumber(column, stock, drawInfo); } else if ([REPORT_COLUMN_ID.RESERVE_STRING1_ID,REPORT_COLUMN_ID.RESERVE_STRING2_ID,REPORT_COLUMN_ID.RESERVE_STRING3_ID,REPORT_COLUMN_ID.RESERVE_STRING4_ID, REPORT_COLUMN_ID.RESERVE_STRING5_ID,REPORT_COLUMN_ID.RESERVE_STRING6_ID,REPORT_COLUMN_ID.RESERVE_STRING7_ID,REPORT_COLUMN_ID.RESERVE_STRING8_ID, REPORT_COLUMN_ID.RESERVE_STRING9_ID,REPORT_COLUMN_ID.RESERVE_STRING10_ID].includes(column.Type)) { this.FormatReserveString(column, stock, drawInfo); } else if (this.IsReserveProgressBarColumn(column.Type)) { this.FormatReserveProgressBar(column, stock, drawInfo); } //拖拽行颜色 if (rowType==3) drawInfo.TextColor=this.DragRowTextColor; if (drawInfo.Symbol) { this.DrawItemTextEx(drawInfo, x, top, textWidth); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_ICON_ID) { this.DrawIconItem(drawInfo, x, top, textWidth); } else if (column.Type==REPORT_COLUMN_ID.CHECKBOX_ID || column.Type==REPORT_COLUMN_ID.CUSTOM_CHECKBOX_ID) { this.DrawCheckbox(drawInfo, left, top, itemWidth); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_BUTTON_ID) { this.DrawButton(drawInfo, left, top, itemWidth); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_PROGRESS_ID || this.IsReserveProgressBarColumn(column.Type)) { this.DrawProgressBar(drawInfo, left, top, itemWidth); } else if (column.Type==REPORT_COLUMN_ID.CUSTOM_LINK_ID) { this.DrawLinkText(drawInfo, x, top, textWidth); } else { if (data.FlashBG && data.FlashBG.Data && column.ID!=undefined) { if (data.FlashBG.Data.has(column.ID)) { var flashItem=data.FlashBG.Data.get(column.ID); var drawBG={ Rect:drawInfo.Rect , BGColor:flashItem.Color }; --flashItem.Count; this.DrawItemBG(drawBG); if (this.GlobalOption) ++this.GlobalOption.FlashBGCount; } } this.DrawItemBG(drawInfo); if (column.Type==REPORT_COLUMN_ID.CUSTOM_STRING_TEXT_ID) this.DrawCustomText(drawInfo,column, x, top, textWidth); else this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth, drawInfo.BGColor); } //tooltip提示 if (drawInfo.Tooltip) { //Type:1=数据截断 var tooltipData={ Rect:rtItem, Stock:stock, Index:index, Column:column, RowType:rowType, Type:drawInfo.Tooltip.Type, Data:drawInfo.Tooltip.Data }; this.TooltipRect.push(tooltipData); } if (drawInfo.Botton) { var buttonData={ Stock:stock, Index:index, ColumnIndex:columnIndex, Column:column, Rect:drawInfo.Botton.Rect, Type:drawInfo.Botton.Type, Data:drawInfo.Data }; this.ButtonRect.push(buttonData); } } this.IsReserveProgressBarColumn=function(value) { var ARARY_TYPE= [ REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR1_ID, REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR2_ID,REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR3_ID, REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR4_ID,REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR5_ID,REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR6_ID,REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR7_ID, REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR8_ID,REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR9_ID,REPORT_COLUMN_ID.RESERVE_PROGRESS_BAR10_ID ]; return ARARY_TYPE.includes(value); } this.DrawCustomText=function(drawInfo, column, left, top, cellWidth) { if (!drawInfo.Text) return; var text=drawInfo.Text; var x=left; if (drawInfo.TextAlign=='center') { x=left+cellWidth/2; this.Canvas.textAlign="center"; } else if (drawInfo.TextAlign=='right') { x=left+cellWidth-2; this.Canvas.textAlign="right"; } else { x+=2; this.Canvas.textAlign="left"; } var textWidth=this.Canvas.measureText(text).width+1; var bClip=false; if (textWidth>=cellWidth) //长度超过单元格 裁剪 { if (column.FormatType==2) { var count=text.length+5; text=""; for(var i=0;i=stock.LimitHigh) bDraw=true; } if (IFrameSplitOperator.IsNumber(stock.LimitLow)) { if (value<=stock.LimitLow) bDraw=true; } if (!bDraw) return; var x=left+this.ItemMergin.Left+this.LimitMergin.Left; var width=itemWidth-this.ItemMergin.Left-this.ItemMergin.Right-this.LimitMergin.Left-this.LimitMergin.Right; var y=top+this.ItemMergin.Top+this.LimitMergin.Top; var height=this.RowHeight-this.ItemMergin.Top-this.ItemMergin.Bottom-this.LimitMergin.Top-this.LimitMergin.Bottom; this.Canvas.strokeStyle=this.LimitBorderColor; this.Canvas.strokeRect(ToFixedPoint(x),ToFixedPoint(y),ToFixedRect(width),ToFixedRect(height)); } this.GetExtendData=function(data, column) { if (IFrameSplitOperator.IsNumber(column.DataIndex)) { if (!data.Stock || !data.Stock.ExtendData) return null; if (column.DataIndex<0) return; return data.Stock.ExtendData[column.DataIndex]; } if (IFrameSplitOperator.IsNumber(column.BlockIndex)) { if (!data.Block) return; if (column.BlockIndex<0) return; return data.Block[column.BlockIndex]; } return null; } this.GetCustomStringDrawInfo=function(data, column, drawInfo) { var value=this.GetExtendData(data, column); if (column.IsDrawCallback) //外部处理输出格式 { this.GetCustomTextDrawInfo(column, data.Symbol, value, drawInfo, data); return; } if (!IFrameSplitOperator.IsString(value)) return; drawInfo.Text=value; } this.GetCustomNumberDrawInfo=function(data, column, drawInfo) { var value=this.GetExtendData(data, column); if (column.IsDrawCallback) //外部处理输出格式 { this.GetCustomTextDrawInfo(column, data.Symbol, value, drawInfo, data); return; } if (!IFrameSplitOperator.IsNumber(value)) return; //格式化输出 switch(column.FormatType) { case 1: drawInfo.Text=value.toFixed(column.Decimal); break; case 2: drawInfo.Text=IFrameSplitOperator.FormatValueThousandsString(value, column.Decimal); break; case 3: drawInfo.Text=this.FormatVolString(value); break; default: drawInfo.Text=IFrameSplitOperator.FormatValueString(value, column.Decimal); break; } //颜色 switch(column.ColorType) { case 1: drawInfo.TextColor=this.GetUpDownColor(value,0); break; case 2: if (!IFrameSplitOperator.IsNumber(data.Stock.YClose)) drawInfo.TextColor=this.UnchagneColor; else drawInfo.TextColor=this.GetUpDownColor(value, data.Stock.YClose); break; default: break; } } this.GetCustomDateTimeDrawInfo=function(data, column, drawInfo) { var value=this.GetExtendData(data, column); if (!IFrameSplitOperator.IsNumber(value)) return; if (column.IsDrawCallback) //外部处理输出格式 { this.GetCustomTextDrawInfo(column, data.Symbol, value, drawInfo, data); return; } if (column.ValueType==0) { if (column.FormatType==1) drawInfo.Text=IFrameSplitOperator.FormatDateString(value,"YYYY/MM/DD"); else drawInfo.Text=IFrameSplitOperator.FormatDateString(value); } } this.GetCustomIconDrawInfo=function(data, column, drawInfo) { if (column.IsDrawCallback) //外部处理输出格式 { this.GetCustomIconData(column, data.Symbol, drawInfo, data); return; } } this.GetCustomCheckBoxDrawInfo=function(data, column, drawInfo) { var checkData=this.GetExtendData(data, column); if (!checkData) return; if (!IFrameSplitOperator.IsBool(checkData.Checked)) return; drawInfo.Checked=checkData.Checked; drawInfo.Enable=true; drawInfo.Data=checkData; if (IFrameSplitOperator.IsBool(checkData.DisableCheckBox)) drawInfo.Enable=!checkData.DisableCheckBox; drawInfo.CheckBox=column.CheckBox; } this.GetCustomButtonDrawInfo=function(data, column, drawInfo) { var buttonData=this.GetExtendData(data, column); if (!buttonData) return; drawInfo.Text=buttonData.Title; drawInfo.Button=column.Button; drawInfo.Font=column.Button.Font; drawInfo.Enable=true; drawInfo.Data=buttonData; if (IFrameSplitOperator.IsBool(buttonData.Enable)) drawInfo.Enable=buttonData.Enable; } this.GetCustomProgressBarDrawInfo=function(data, column, drawInfo) { var barData=this.GetExtendData(data, column); if (!barData) return; drawInfo.Text=barData.Title; drawInfo.ProgressBar=column.ProgressBar; drawInfo.Enable=true; drawInfo.Value=barData.Value; //占比 drawInfo.Data=barData; if (IFrameSplitOperator.IsBool(barData.Enable)) drawInfo.Enable=barData.Enable; if (barData.TextColor) drawInfo.TextColor=barData.TextColor; if (barData.BarColor) drawInfo.BarColor=barData.BarColor; if (barData.BGColor) drawInfo.BGColor=barData.BGColor; } this.GetCustomLinkDrawInfo=function(data, column, drawInfo) { var linkData=this.GetExtendData(data, column); if (!linkData) return; drawInfo.Text=linkData.Title; drawInfo.Link=column.Link; drawInfo.Enable=true; drawInfo.Data=linkData; drawInfo.MaxText=column.MaxText; if (IFrameSplitOperator.IsBool(linkData.Enable)) drawInfo.Enable=linkData.Enable; if (linkData.TextColor) drawInfo.TextColor=linkData.TextColor; } this.FormatReserveNumber=function(column, data, drawInfo) { if (column.DefaultText) drawInfo.Text=column.DefaultText; var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (!data || !fieldName) return; var value=data[fieldName]; if (!IFrameSplitOperator.IsNumber(value)) return; if (IFrameSplitOperator.IsNumber(column.ColorType)) { if (column.ColorType==1) { drawInfo.TextColor=this.GetUpDownColor(value,0); } else if (column.ColorType==2) { drawInfo.TextColor=this.GetUpDownColorV2(value,0); } } //TODO: 不同类型的 格式化输出 drawInfo.Text=value.toFixed(column.FloatPrecision); } this.FormatReserveString=function(column, data, drawInfo) { if (column.DefaultText) drawInfo.Text=column.DefaultText; var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (!data || !fieldName) return; var item=data[fieldName]; if (IFrameSplitOperator.IsObject(item)) { if (item.Text) drawInfo.Text=item.Text; if (item.TextColor) drawInfo.TextColor=item.TextColor; if (item.BGColor) drawInfo.BGColor=item.BGColor; } else if (IFrameSplitOperator.IsString(item)) { drawInfo.Text=item; } } this.FormatReserveProgressBar=function(column, data, drawInfo) { var fieldName=MAP_COLUMN_FIELD.get(column.Type); if (!data || !fieldName) return; var item=data[fieldName]; if (IFrameSplitOperator.IsNumber(item)) { drawInfo.ProgressBar=column.ProgressBar; drawInfo.Enable=true; drawInfo.Value=item; //占比 drawInfo.Data={ Value:item }; } else if (IFrameSplitOperator.IsObject(item)) { if (item.Title) drawInfo.Text=item.Title; drawInfo.ProgressBar=column.ProgressBar; drawInfo.Enable=true; drawInfo.Value=item.Value; //占比 drawInfo.Data=item; if (IFrameSplitOperator.IsBool(item.Enable)) drawInfo.Enable=item.Enable; if (item.TextColor) drawInfo.TextColor=item.TextColor; if (item.BarColor) drawInfo.BarColor=item.BarColor; if (item.BGColor) drawInfo.BGColor=item.BGColor; } } this.FormaTimeDrawInfo=function(column, stock, drawInfo, data) { if (!IFrameSplitOperator.IsNumber(stock.Time)) return; if (column.ValueType==0) //0=hhmm 1=hhmmss 2=hhmmss.fff { drawInfo.Text=IFrameSplitOperator.FormatTimeString(stock.Time,"HH:MM"); } else if (column.ValueType==1) { drawInfo.Text=IFrameSplitOperator.FormatTimeString(stock.Time,"HH:MM:SS"); } else if (column.ValueType==2) { drawInfo.Text=IFrameSplitOperator.FormatTimeString(stock.Time,"HH:MM:SS.fff"); } } this.FormaDateDrawInfo=function(column, stock, drawInfo, data) { if (!IFrameSplitOperator.IsNumber(stock.Date)) return; if (column.FormatType==0) drawInfo.Text=IFrameSplitOperator.FormatDateString(stock.Date,"YYYY-MM-DD"); else if (column.FormatType==1) drawInfo.Text=IFrameSplitOperator.FormatDateString(stock.Date,"YYYY/MM/DD"); else if (column.FormatType==2) drawInfo.Text=IFrameSplitOperator.FormatDateString(stock.Date,"YYYY/MM/DD/W"); else if (column.FormatType==3) drawInfo.Text=IFrameSplitOperator.FormatDateString(stock.Date,"YYYY-MM"); else if (column.FormatType==4) drawInfo.Text=IFrameSplitOperator.FormatDateString(stock.Date,"MM/DD"); else if (column.FormatType==4) drawInfo.Text=IFrameSplitOperator.FormatDateString(stock.Date,"MM-DD"); } //自定义图标 this.GetCustomIconData=function(columnInfo, symbol, drawInfo, data) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_DRAW_CUSTOM_ICON); if (!event || !event.Callback) return false; var sendData= { Symbol:symbol, Column:columnInfo, Data:data, Out:{ Text:null, TextColor:null, TextAlign:null, Font:null } }; event.Callback(event,sendData,this); if (sendData.Out.Text) drawInfo.Text=sendData.Out.Text; if (sendData.Out.TextColor) drawInfo.TextColor=sendData.Out.TextColor; if (sendData.Out.TextAlign) drawInfo.TextAlign=sendData.Out.TextAlign; if (sendData.Out.BGColor) drawInfo.BGColor=sendData.Out.BGColor; if (sendData.Out.Font) drawInfo.Font=sendData.Out.Font; return true; } this.GetPriceDrawInfo=function(price, stock, data, drawInfo, option) { if (!IFrameSplitOperator.IsNumber(price)) return false; drawInfo.Text=price.toFixed(data.Decimal); var yClose=null; if (stock.PriceColorType===1) //昨结算价 计算颜色 { if (IFrameSplitOperator.IsNumber(stock.YFClose)) yClose=stock.YFClose; } else //昨收价 计算颜色 { if (IFrameSplitOperator.IsNumber(stock.YClose)) yClose=stock.YClose; } if (!IFrameSplitOperator.IsNumber(yClose)) drawInfo.TextColor=this.UnchagneColor; else drawInfo.TextColor=this.GetUpDownColor(price, yClose); if (option && option.LimitBG) { if (IFrameSplitOperator.IsNumber(stock.LimitHigh)) { if (price>=stock.LimitHigh) { drawInfo.BGColor=this.LimitUpBGColor; drawInfo.TextColor=this.LimitTextColor; } } if (IFrameSplitOperator.IsNumber(stock.LimitLow)) { if (price<=stock.LimitLow) { drawInfo.BGColor=this.LimitDownBGColor; drawInfo.TextColor=this.LimitTextColor; } } } } this.GetUpDownColor=function(price, price2) { if (price>price2) return this.UpColor; else if (price=price2) return this.UpColor; else return this.DownColor; } //单独处理成交量显示 this.FormatVolString=function(value,languageID) { return IFrameSplitOperator.FormatVolString(value, languageID); } this.DrawItemBG=function(drawInfo) { if (drawInfo.BGColor && drawInfo.Rect)//绘制背景色 { var rtItem=drawInfo.Rect; this.Canvas.fillStyle=drawInfo.BGColor; this.Canvas.fillRect(rtItem.Left,rtItem.Top,rtItem.Width,rtItem.Height); //画一个背景色, 不然是一个黑的背景 } } this.DrawItemText=function(text, textColor, textAlign, left, top, width, bgColor) { if (!text) return; var x=left; if (textAlign=='center') { x=left+width/2; this.Canvas.textAlign="center"; } else if (textAlign=='right') { x=left+width-2; this.Canvas.textAlign="right"; } else { x+=2; this.Canvas.textAlign="left"; } var textWidth=this.Canvas.measureText(text).width+1; var bClip=false; if (textWidth>=width) //长度超过单元格 裁剪 { this.Canvas.save(); bClip=true; var rtCell={ Left:left, Top:top+this.ItemMergin.Top, Width:width, Height:this.RowHeight }; this.Canvas.beginPath(); this.Canvas.rect(rtCell.Left, rtCell.Top, rtCell.Width, rtCell.Height); //this.Canvas.stroke(); //调试用 this.Canvas.clip(); if (this.TextOverflowStyle==1) { var count=text.length+5; text=""; for(var i=0;i1) //多行模式要上下居中 { var yOffset=(this.RowHeight-this.ItemMergin.Bottom-this.ItemMergin.Top-this.ItemFontHeight)/2; var yBottom=top+this.RowHeight-this.ItemMergin.Bottom-yOffset; this.Canvas.fillText(text,x,yBottom); } else { this.Canvas.fillText(text,x,top+this.RowHeight-this.ItemMergin.Bottom); } if (bClip) this.Canvas.restore(); } //{ Text:, Symbol:{ Family:'iconfont', Size:, Data:[ { Text:'\ue631', Color:'#1c65db'}, ...] } ]} this.DrawItemTextEx=function(drawInfo, left, top, width) { var text=drawInfo.Text; var clrText=drawInfo.TextColor; var symbol=drawInfo.Symbol; //符号 var textAlign=drawInfo.TextAlign; var textWidth=this.Canvas.measureText(text).width+1;; var totalWidth=textWidth; var font= `${symbol.Size*GetDevicePixelRatio()}px ${symbol.Family}`; this.Canvas.font=font; var aryIconWidth=[]; for(var i=0;iwidth) break; totalWidth+=iconWidth; aryIconWidth[i]=iconWidth; } var x=left; var y=top+this.ItemMergin.Top+this.RowHeight/2; if (textAlign=='center') { x=left+(width-totalWidth)/2; } else if (textAlign=='right') { x=left+(width-totalWidth); } else { x+=2; } this.Canvas.textBaseline="middle"; this.Canvas.textAlign="left"; this.Canvas.font=this.ItemFont; this.Canvas.fillStyle=clrText; this.Canvas.fillText(text,x,y); x+=textWidth; this.Canvas.font=font; for(var i=0;irtBox.Left && xMousertBox.Top && yMousertBG.Left && xrtBG.Top && y0) { if (value>1) value=1; rtBar.Width=fullBarWidth*value; rtBar.Height=rtBar.Bottom-rtBar.Top; if (rtBar.Width<1) rtBG.Width=1; this.Canvas.fillStyle=barColor; this.Canvas.fillRect(rtBar.Left, rtBar.Top,rtBar.Width,rtBar.Height); } if (textColor && drawInfo.Text) { this.Canvas.font=config.Font; this.Canvas.textBaseline="bottom"; this.Canvas.textAlign="left"; this.Canvas.fillStyle=textColor; var xText=rtBar.Left+config.TextMargin.Left; var yText=rtBar.Bottom-config.TextMargin.Bottom; this.Canvas.fillText(drawInfo.Text, xText, yText); } } this.DrawLinkText=function(drawInfo, left, top, width) { if (!drawInfo.Link || !drawInfo.Text) return; var config=drawInfo.Link; var text=drawInfo.Text; var textAlign=drawInfo.TextAlign; var font=config.Font; var color=config.TextColor; this.Canvas.font=font; var textWidth=this.Canvas.measureText(text).width; var textHeight=this.Canvas.measureText("擎").width; var x=left; if (width>=textWidth) { if (textAlign=='center') x=left+(width-textWidth)/2; else if (textAlign=='right') x=left+width-textWidth; } else { text=this.TextEllipsis(text, width, drawInfo.MaxText); textWidth=this.Canvas.measureText(text).width; //数据截断提示信息 drawInfo.Tooltip= { Type:2, Data:{ AryText:[ {Text:drawInfo.Text} ] } } } var rtText={Left:x, Bottom:top+this.RowHeight-this.ItemMergin.Bottom, Height:textHeight, Width:textWidth }; rtText.Right=rtText.Left+rtText.Width; rtText.Top=rtText.Bottom-rtText.Height; var drawLine=false; //下划线 if (drawInfo.Enable===false) { color=config.Disable.TextColor; } else if (this.LastMouseStatus && this.LastMouseStatus.OnMouseMove && config.MouseOn) { var x=this.LastMouseStatus.OnMouseMove.X; var y=this.LastMouseStatus.OnMouseMove.Y; if (x>rtText.Left && xrtText.Top && ymaxWidth) { newText+="..."; break; } newText+=text[i]; } return newText; } this.DrawMultiBar=function(colunmInfo, data, rtItem) { if (!data.Source || !IFrameSplitOperator.IsNonEmptyArray(data.Source)) return false; var barData=data.Source[colunmInfo.DataIndex]; //{ Value:[0.4,0,2], Color:[0,1] }; if (!barData) return false; if (!IFrameSplitOperator.IsNonEmptyArray(barData.Value)) return false; var width=rtItem.Width-this.BarMergin.Left-this.BarMergin.Right; var left=rtItem.Left+this.BarMergin.Left; var top=rtItem.Top+this.RowMergin.Top+this.BarMergin.Top; var height=rtItem.Height-this.RowMergin.Top-this.RowMergin.Bottom-this.BarMergin.Top-this.BarMergin.Bottom; var right=left+width; for(var i=0;i=right) break; var barWidth=width*value; if (barWidth<1) barWidth=1; if (left+barWidth>right) barWidth=right-left; var colorIndex=i; if (IFrameSplitOperator.IsNonEmptyArray(barData.Color) && i1) value=1; var barWidth=width*value; if (barWidth<1) barWidth=1; var colorIndex=i; if (IFrameSplitOperator.IsNonEmptyArray(barData.Color) && i=count) { return right; } else { var offset=left+width*index/count; return offset; } } var priceMax=lineData.Max, priceMin=lineData.Min; if (IFrameSplitOperator.IsNumber(lineData.YClose)) //前收盘价 { if (lineData.YClose==priceMax && lineData.YClose==priceMin) { priceMax=lineData.YClose+lineData.YClose*0.1; priceMin=lineData.YClose-lineData.YClose*0.1 } else { var distanceValue=Math.max(Math.abs(lineData.YClose-priceMax),Math.abs(lineData.YClose-priceMin)); priceMax=lineData.YClose+distanceValue; priceMin=lineData.YClose-distanceValue; } } var Temp_GetYFromData=function(value) { if(value<=priceMin) return bottom; if(value>=priceMax) return top; var value=height*(value-priceMin)/(priceMax-priceMin); return bottom-value; } this.Canvas.save(); var yCenter=null; if (IFrameSplitOperator.IsNumber(lineData.YClose)) { var y=Temp_GetYFromData(lineData.YClose); y=ToFixedPoint(y); yCenter=y; this.Canvas.setLineDash([2,2]); this.Canvas.strokeStyle=this.CloseLineConfig.YCloseColor; this.Canvas.beginPath(); this.Canvas.moveTo(left,y); this.Canvas.lineTo(right,y); this.Canvas.stroke(); this.Canvas.setLineDash([]); } if (lineData.Color) this.Canvas.strokeStyle=lineData.Color; else this.Canvas.strokeStyle=this.CloseLineConfig.CloseColor; var bFirstPoint=true; var ptFirst={}; //第1个点 var drawCount=0, x,y; for(var i=0; i0) { this.Canvas.stroke(); if (column.IsDrawArea && IFrameSplitOperator.IsNumber(yCenter)) { this.Canvas.lineTo(x,yCenter); this.Canvas.lineTo(ptFirst.X,yCenter); this.Canvas.closePath(); this.SetFillStyle(this.CloseLineConfig.AreaColor,left,top, left,bottom); this.Canvas.fill(); } } this.Canvas.restore(); } //klineData={ Data:[ open, high, low, close ] } this.DrawKLine=function(klineData, column, rtItem, data) { if (column.IsDrawCallback) //外部处理输出格式 { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_REPORT_DRAW_KLINE); if (event || event.Callback) { var sendData= { Column:column, Data:data, KLineData:klineData, Rect:rtItem, PreventDefault:false }; event.Callback(event,sendData,this); if (sendData.PreventDefault) return; } } if (!klineData) return; if (!IFrameSplitOperator.IsNonEmptyArray(klineData.Data)) return; var high=klineData.Data[1]; var low=klineData.Data[2]; var aryKLine= [ { Open:klineData.Data[0], High:high, Low:low, Close:klineData.Data[3]}, //{ Open:klineData.Data[0], High:high, Low:low, Close:klineData.Data[3]} ]; this.DrawKLineBar(aryKLine, high, low, rtItem); } this.DrawKLineBar=function(aryKLine, high, low, rtItem) { var yMergin=4; var left=rtItem.Left+this.ItemMergin.Left; var width=rtItem.Width-this.ItemMergin.Left-this.ItemMergin.Right; var left=rtItem.Left+this.ItemMergin.Left; var top=rtItem.Top+this.ItemMergin.Top+yMergin; var height=rtItem.Height-this.ItemMergin.Top-this.ItemMergin.Bottom-yMergin*2; var right=left+width; var bottom=top+height; var Temp_GetYFromData=function(value) { if(value<=low) return bottom; if(value>=high) return top; var value=height*(value-low)/(high-low); return bottom-value; } var dataWidth=this.KLineConfig.DataWidth; var distanceWidth=this.KLineConfig.DistanceWidth; var xOffset=left; var x, xLeft, xRight; for(var i=0;iright) break; var yLow=Temp_GetYFromData(item.Low, false); var yHigh=Temp_GetYFromData(item.High, false); var yOpen=Temp_GetYFromData(item.Open, false); var yClose=Temp_GetYFromData(item.Close, false); var y=yHigh; if (item.Openitem.Close) //阴线 { this.DrawKBarItem(item,dataWidth, this.KLineConfig.DownColor, 0, xLeft, xRight, yLow, yHigh, yOpen, yClose); } else //平线 { this.DrawKBarItem(item,dataWidth, this.KLineConfig.UnchagneColor, 0, xLeft, xRight, yLow, yHigh, yOpen, yClose); } } } this.DrawKBarItem=function(data, dataWidth, barColor, drawType, left, right, yLow, yHigh, yOpen, yClose) { var isEmptyBar=false; if (drawType==1) isEmptyBar=true; var yBarTop=Math.min(yOpen, yClose); var yBarBottom=Math.max(yOpen, yClose); var barTopValue=Math.max(data.Open, data.Close); var barBottomValue=Math.min(data.Open, data.Close); this.Canvas.fillStyle=barColor; this.Canvas.strokeStyle=barColor; var x=left+(right-left)/2; if (isEmptyBar) { if ((dataWidth%2)!=0) dataWidth-=1; } if (dataWidth>=4) { if (data.High>barTopValue) { this.Canvas.beginPath(); var xBar=x; if (isEmptyBar) xBar=left+dataWidth/2; this.Canvas.moveTo(ToFixedPoint(xBar),ToFixedPoint(yBarTop)); this.Canvas.lineTo(ToFixedPoint(xBar),ToFixedPoint(yHigh)); this.Canvas.stroke(); } if (Math.abs(yBarBottom-yBarTop)<1) { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(yBarTop),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 } else { if (isEmptyBar) { this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarBottom-yBarTop)); this.Canvas.stroke(); } else { this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarBottom-yBarTop)); } } if (data.Low=0) this.MultiSelectedRow.splice(pos,1); else this.MultiSelectedRow.push(row.DataIndex); } else if (e && e.shiftKey) //批量多选 { this.OnShiftClickRow(row); } else { if (this.MultiSelectedRow.length==1 && this.MultiSelectedRow[0]==row.DataIndex) bRedraw=false; else this.MultiSelectedRow=[row.DataIndex]; } this.SelectedFixedRow=-1; } else { if (this.SelectedModel==0) { if (this.SelectedRow==row.Index) bRedraw=false; this.SelectedRow=row.Index; this.SelectedFixedRow=-1; } else { if (this.SelectedRow==row.DataIndex) bRedraw=false; this.SelectedRow=row.DataIndex; this.SelectedFixedRow=-1; } } var eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_ROW; if (e.button==2) eventID=JSCHART_EVENT_ID.ON_RCLICK_REPORT_ROW; this.SendClickEvent(eventID, { Data:row, X:x, Y:y, e:e, Inside:insidePoint, UIElement:uiElement }); return { Type:2, Redraw:bRedraw || btnStatus.Redraw, Row:row }; //行 } var header=this.PtInHeader(x,y); if (header) { var eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_HEADER; if (e.button==2) { eventID=JSCHART_EVENT_ID.ON_RCLICK_REPORT_HEADER; } else if (e.button==0) { eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_HEADER; } this.SendClickEvent(eventID, { Data:row, X:x, Y:y , e:e, Inside:insidePoint, UIElement:uiElement}); return { Type:3, Redraw:bRedraw, Header:header }; //表头 } return null; } this.OnShiftClickRow=function(row) { if (this.MultiSelectedRow.length<=0) { this.MultiSelectedRow.push(row.DataIndex); return; } var max=null, min=null; for(var i=0;ivalue) min=value; if (value==row.DataIndex) //移除 { this.MultiSelectedRow.splice(i,1); return; } } if (max==min) { var start=row.DataIndex, end=max; if (start>end) { start=max; end=row.DataIndex; } this.MultiSelectedRow=[]; for(var i=start;i<=end;++i) { this.MultiSelectedRow.push(i); } } else { if (row.DataIndex<=max && row.DataIndex>=min) { this.MultiSelectedRow.push(row.DataIndex); } else { var start=Math.min(row.DataIndex, min); var end=Math.max(row.DataIndex, max); this.MultiSelectedRow=[]; for(var i=start;i<=end;++i) { this.MultiSelectedRow.push(i); } } } } this.OnDrawgRow=function(x, y, e) //Type: 5=顶部 6=空白行 2=行 7=底部 { if (!this.Data) return null; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null; var topOffset=this.RowHeight/2; var top=this.RectClient.Top+this.HeaderHeight; var right=this.ChartBorder.GetChartWidth(); var textTop=top+this.FixedRowHeight*this.FixedRowCount; if (y=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom) { var data={ DataIndex:i, Index:j , Symbol:symbol, Pos:0 }; if (j==0) data.Pos=1; else if (j==this.RowCount-1) data.Pos=2; return { Type: 2, Data:data }; } textTop+=this.RowHeight; } if (jthis.RectClient.Left && xthis.RectClient.Top && y=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom) { var data={ Rect:rtRow, DataIndex:i, Index:j , Symbol:symbol }; data.Item=this.PtInItem(x,y, rtRow.Top, rtRow.Bottom); return data; } textTop+=this.RowHeight; } return null; } this.PtInFixedBody=function(x,y) { if (this.FixedRowCount<=0) return null; var top=this.RectClient.Top+this.HeaderHeight; var left=this.RectClient.Left; var right=this.RectClient.Right; var rowWidth=this.RectClient.Right-this.RectClient.Left; var textTop=top; for(var i=0; i=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom) { var data={ Rect:rtRow, Index:i}; data.Item=this.PtInItem(x,y, rtRow.Top, rtRow.Bottom); return data; } textTop+=this.FixedRowHeight; } return null; } this.PtInItem=function(x,y, top, bottom) { var left=this.RectClient.Left; var right=this.RectClient.Right; var textLeft=left; //固定列 for(var i=0;i=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom) { return { Rect:header, Column:item, Index:i, IsFixed:true }; } textLeft+=item.Width; } for(var i=this.FixedColumn+this.Data.XOffset;i=right) break; var header={Left:textLeft, Right:textLeft+item.Width, Top:top, Bottom:bottom }; if (x>=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom) { return { Rect:header, Column:item, Index:i, IsFixed:false }; } textLeft+=item.Width; } return null; } this.PtInHeader=function(x,y) { if (!this.IsShowHeader) return null; var left=this.RectClient.Left; var right=this.RectClient.Right; var top=this.RectClient.Top; var bottom=top+this.HeaderHeight; if (!(x>=left && x<=right && y>=top && y<=bottom)) return null; return this.PtInItem(x,y,top,bottom); } this.IsPtInBody=function(x,y) { var top=this.RectClient.Top+this.HeaderHeight; var left=this.RectClient.Left; var right=this.RectClient.Right; var bottom=this.RectClient.Bottom; if (x>=left && x<=right && y>=top && y<=bottom) return true; return false; } this.IsPtInHeader=function(x,y) { if (!this.IsShowHeader) return false; var left=this.RectClient.Left; var right=this.RectClient.Right; var top=this.RectClient.Top; var bottom=top+this.HeaderHeight; if (x>=left && x<=right && y>=top && y<=bottom) return true; return false; } this.SendClickEvent=function(id, data) { var event=this.GetEventCallback(id); if (event && event.Callback) { event.Callback(event,data,this); } } this.DrawDragRow=function() { if (!this.DragRow) return; var drag=this.DragRow; if (!drag.Data || !drag.Inside || !drag.Data.Row) return; var dataIndex=drag.Data.Row.DataIndex; if (!IFrameSplitOperator.IsNumber(dataIndex) || dataIndex<0) return; var textTop=drag.Inside.Y-(this.RowHeight/2); var top=textTop; var left=this.RectClient.Left; var rowWidth=this.RectClient.Right-this.RectClient.Left; //背景 this.Canvas.fillStyle=this.DragRowColor; this.Canvas.fillRect(left,textTop,rowWidth,this.RowHeight); var symbol=this.Data.Data[dataIndex]; var data= { Symbol:symbol , Stock:null, Block:null }; if (this.GetStockDataCallback) data.Stock=this.GetStockDataCallback(symbol); if (this.GetBlockDataCallback) data.Block=this.GetBlockDataCallback(symbol); data.Decimal=GetfloatPrecision(symbol); //小数位数 var chartRight=this.RectClient.Right; this.Canvas.font=this.ItemFont; for(var i=0;i=chartRight) break; } for(var i=this.FixedColumn+this.Data.XOffset;i=chartRight) break; } } this.GetTooltipData=function(x,y) { if (!IFrameSplitOperator.IsNonEmptyArray(this.TooltipRect)) return null; for(var i=0;i=rt.Left && x<=rt.Right && y>=rt.Top && y<=rt.Bottom) { return { Rect:item.Rect, Stock:item.Stock, Column:item.Column, Index:item.Index, Type:item.Type, Data:item.Data }; } } return null; } this.GetButtonData=function(x,y) { if (!IFrameSplitOperator.IsNonEmptyArray(this.ButtonRect)) return null; for(var i=0;i=rt.Left && x<=rt.Right && y>=rt.Top && y<=rt.Bottom) { return { Rect:item.Rect, Stock:item.Stock, Column:item.Column, Index:item.Index, Type:item.Type, Data:item.Data, ColumnIndex:item.ColumnIndex }; } } } this.PtInHeaderDragBorder=function(x, y) { if (!this.IsShowHeader) return null; var left=this.RectClient.Left; var right=this.RectClient.Right; var top=this.RectClient.Top; var bottom=top+this.HeaderHeight; if (!(x>=left && x<=right && y>=top && y<=bottom)) return null; var textLeft=left; var dragBarWidth=5*GetDevicePixelRatio(); //固定列 for(var i=0;i=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom) { return { Rect:header, Column:item, Index:i, IsFixed:true }; } } textLeft+=item.Width; } for(var i=this.FixedColumn+this.Data.XOffset;i=right) break; if (item.EnableDragWidth===true) { var header={ Right:textLeft+item.Width, Top:top, Bottom:bottom }; header.Left=header.Right-dragBarWidth; if (x>=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom) { return { Rect:header, Column:item, Index:i, IsFixed:false }; } } textLeft+=item.Width; } return null; } //设置选中行 data={ Symbol:, AutoYScroll:true/false Y滚动条自定定位 } this.SetSelectedRow=function(option) { if (!option) return false; if (this.SelectedModel===0) return false; if (option.Symbol) { var symbol=option.Symbol; var bFinder=false; for(var i=0;i=pageStatus.Start && selectedRow<=pageStatus.End) return; this.Data.YOffset=selectedRow; //选中行不在当前屏 设置为第1行 } } //报价列表底部tab和横向滚动条 function ChartReportTab() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartReportTab'; //类名 this.IsDrawFirst=false; this.GetEventCallback; //获取事件 this.Report; this.IsShow=true; //是否显示 //Tab this.TabList=[]; //{ Title:标题, ID:, IsMenu: 是否菜单, ArySubMenu:[ { Title:, ID: }] } this.SelectedTabIndex=-1; this.MoveOnTabIndex=-1; //滚动条信息 this.MaxPos=15; //滚动条可移动长度 this.CurrentPos=15; //当前滚动条移动位置 this.Step=1; //滚动条移动步长 this.ScrollBarWidth=g_JSChartResource.Report.Tab.ScrollBarWidth; this.ButtonColor=g_JSChartResource.Report.Tab.ButtonColor; this.BarColor=g_JSChartResource.Report.Tab.BarColor; this.BorderColor=g_JSChartResource.Report.Tab.BorderColor; this.Mergin={ Left:2, Right:2, Top:2, Bottom:2 }; this.TabFontConfig={ Size:g_JSChartResource.Report.Tab.Font.Size, Name:g_JSChartResource.Report.Tab.Font.Name }; this.TabFont; this.TabTitleColor=g_JSChartResource.Report.Tab.TabTitleColor; this.TabSelectedTitleColor=g_JSChartResource.Report.Tab.TabSelectedTitleColor; this.TabSelectedBGColor=g_JSChartResource.Report.Tab.TabSelectedBGColor; this.TabMoveOnTitleColor=g_JSChartResource.Report.Tab.TabMoveOnTitleColor; this.TabBGColor=g_JSChartResource.Report.Tab.TabBGColor; this.TabMergin= { Top:g_JSChartResource.Report.Tab.Mergin.Top, Left:g_JSChartResource.Report.Tab.Mergin.Left, Right:g_JSChartResource.Report.Tab.Mergin.Right, Bottom:g_JSChartResource.Report.Tab.Mergin.Bottom }; this.Height; this.ButtonSize=25; this.TabWidth=0; this.RectScroll={ Left:null, Right:null, Bar:null, Client:null }; //滚动条区域 this.ReloadResource=function(resource) { //滚动条 this.ScrollBarWidth=g_JSChartResource.Report.Tab.ScrollBarWidth; this.ButtonColor=g_JSChartResource.Report.Tab.ButtonColor; this.BarColor=g_JSChartResource.Report.Tab.BarColor; this.BorderColor=g_JSChartResource.Report.Tab.BorderColor; //tab this.TabFontConfig={ Size:g_JSChartResource.Report.Tab.Font.Size, Name:g_JSChartResource.Report.Tab.Font.Name }; this.TabTitleColor=g_JSChartResource.Report.Tab.TabTitleColor; this.TabSelectedTitleColor=g_JSChartResource.Report.Tab.TabSelectedTitleColor; this.TabSelectedBGColor=g_JSChartResource.Report.Tab.TabSelectedBGColor; this.TabMoveOnTitleColor=g_JSChartResource.Report.Tab.TabMoveOnTitleColor; this.TabBGColor=g_JSChartResource.Report.Tab.TabBGColor; this.TabMergin= { Top:g_JSChartResource.Report.Tab.Mergin.Top, Left:g_JSChartResource.Report.Tab.Mergin.Left, Right:g_JSChartResource.Report.Tab.Mergin.Right, Bottom:g_JSChartResource.Report.Tab.Mergin.Bottom }; } this.SetTabList=function(aryTab) { this.TabList=[]; for(var i=0;iright) return; this.MaxPos=clolumCount; this.CurrentPos=columnOffset; var buttonSize=this.ButtonSize; var rtLeft={ Left:left+this.Mergin.Left, Top:bottom-buttonSize-this.Mergin.Bottom, Width:buttonSize, Height:buttonSize }; rtLeft.Right=rtLeft.Left+buttonSize; rtLeft.Bottom=rtLeft.Top+buttonSize; var rtRight={ Left:right-buttonSize-this.Mergin.Right, Top:rtLeft.Top, Width:buttonSize, Height:buttonSize }; rtRight.Right=rtRight.Left+buttonSize; rtRight.Bottom=rtRight.Top+buttonSize; this.Canvas.fillStyle=this.ButtonColor; this.Canvas.fillRect(rtLeft.Left,rtLeft.Top,rtLeft.Width,rtLeft.Height); this.Canvas.fillRect(rtRight.Left,rtRight.Top,rtRight.Width,rtRight.Height); this.Canvas.strokeStyle=this.BorderColor; this.Canvas.strokeRect(rtLeft.Left,rtLeft.Top,rtLeft.Width,rtLeft.Height); this.Canvas.strokeRect(rtRight.Left,rtRight.Top,rtRight.Width,rtRight.Height); var centerWidth = (rtRight.Left - 2) - (rtLeft.Right + 2); var value = centerWidth - this.ScrollBarWidth; var xOffset = (value * this.CurrentPos) / this.MaxPos; var x = rtLeft.Right + 2 + xOffset; var rtBar = {Left:x, Top:rtLeft.Top, Width:this.ScrollBarWidth, Height: rtLeft.Height }; rtBar.Right=rtBar.Left+this.ScrollBarWidth; rtBar.Bottom=rtLeft.Bottom; this.Canvas.fillStyle=this.BarColor; this.Canvas.fillRect(rtBar.Left,rtBar.Top,rtBar.Width,rtBar.Height); this.RectScroll.Left=rtLeft; this.RectScroll.Right=rtRight; this.RectScroll.Bar=rtBar; this.RectScroll.Client={ Left:rtLeft.Right, Right: rtRight.Left, Top:rtLeft.Top, Bottom:rtLeft.Bottom }; } this.DrawTab=function(left, top, right, bottom) { this.TabWidth=0; this.Canvas.font=this.TabFont; this.Canvas.textBaseline="bottom"; var tabHeight=bottom-top; var itemLeft=left+1; var y=bottom-this.TabMergin.Bottom, x=0; var text; var itemWidth=0; var i=0; for(i=0;iright) break; var bgColor=this.TabBGColor; if (i==this.SelectedTabIndex) bgColor=this.TabSelectedBGColor this.Canvas.fillStyle=bgColor; this.Canvas.fillRect(rtItem.Left,rtItem.Top,rtItem.Width,rtItem.Height); this.Canvas.textAlign="left"; var textColor=this.TabTitleColor; if (i==this.MoveOnTabIndex) textColor=this.TabMoveOnTitleColor; if (i==this.SelectedTabIndex) textColor=this.TabSelectedTitleColor; this.Canvas.fillStyle=textColor; this.Canvas.fillText(text,x,y); item.Rect=rtItem; itemLeft+=rtItem.Width+1; this.TabWidth+=rtItem.Width+1; } for(;i=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) return { Type: 1, Rect: rtItem }; } if (this.RectScroll.Right) { var rtItem=this.RectScroll.Right; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) return { Type: 2, Rect: rtItem }; } if (this.RectScroll.Bar) { var rtItem=this.RectScroll.Bar; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) return { Type: 3, Rect: rtItem }; } if (this.RectScroll.Client) { var rtItem=this.RectScroll.Client; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) { return { Type: 4, Rect: rtItem , Pos: this.GetScrollPostionByPoint(x,y) }; } } return null; } // Type=5 标签 6=标签菜单 this.PtInTab=function(x,y) { for(var i=0;i=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) { var result= { Type: 5, Rect: rtItem, Tab:item, Index:i }; if (item.IsMenu==true) result.Type==6; return result; } } return null; } this.GetFontHeight=function(font,word) { return GetFontHeight(this.Canvas, font, word); } this.GetScrollPostionByPoint=function(x,y) { var rtItem=this.RectScroll.Client; var value=rtItem.Right-rtItem.Left-this.ScrollBarWidth; var pos =parseInt((this.MaxPos * (x - rtItem.Left)) / value); return pos; } } //页脚信息 function ChartReportPageInfo() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartPageInfo'; //类名 this.IsDrawFirst=false; this.IsShow=false; //是否显示 this.SizeChange=true; this.Report; this.FontConfig={ Size:g_JSChartResource.Report.PageInfo.Font.Size, Name:g_JSChartResource.Report.PageInfo.Font.Name }; this.TextColor=g_JSChartResource.Report.PageInfo.TextColor; this.BGColor=g_JSChartResource.Report.PageInfo.BGColor; this.Mergin= { Top:g_JSChartResource.Report.PageInfo.Mergin.Top, Left:g_JSChartResource.Report.PageInfo.Mergin.Left, Right:g_JSChartResource.Report.PageInfo.Mergin.Right, Bottom:g_JSChartResource.Report.PageInfo.Mergin.Bottom } this.Font; this.TextHeight=0; this.ReloadResource=function(resource) { this.FontConfig={ Size:g_JSChartResource.Report.PageInfo.Font.Size, Name:g_JSChartResource.Report.PageInfo.Font.Name }; this.TextColor=g_JSChartResource.Report.PageInfo.TextColor; this.BGColor=g_JSChartResource.Report.PageInfo.BGColor; this.Mergin= { Top:g_JSChartResource.Report.PageInfo.Mergin.Top, Left:g_JSChartResource.Report.PageInfo.Mergin.Left, Right:g_JSChartResource.Report.PageInfo.Mergin.Right, Bottom:g_JSChartResource.Report.PageInfo.Mergin.Bottom } } this.Draw=function() { if (!this.IsShow) return; if (!this.Report) return; var pageStatus=this.Report.GetCurrentPageStatus(); if (pageStatus.IsSinglePage) return; if (this.SizeChange) { var pixelRatio=GetDevicePixelRatio(); this.Font=`${this.FontConfig.Size*pixelRatio}px ${ this.FontConfig.Name}`; this.TextHeight=GetFontHeight(this.Canvas, this.Font, "擎")+this.Mergin.Top+this.Mergin.Bottom; } var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); var bottom=this.ChartBorder.GetBottom()-2; var center=left+(right-left)/2; var text=`${pageStatus.DataCount}/${pageStatus.DataCount}`; this.Canvas.font=this.Font; var textWidth=this.Canvas.measureText(text).width+4; var bgLeft=center-textWidth/2-this.Mergin.Left; var bgTop=bottom-this.TextHeight; this.Canvas.fillStyle=this.BGColor;; this.Canvas.fillRect(bgLeft,bgTop,textWidth+(this.Mergin.Left+this.Mergin.Right),this.TextHeight); text=`${pageStatus.Start+1}/${pageStatus.DataCount}`; this.Canvas.textAlign="center"; this.Canvas.textBaseline="bottom"; this.Canvas.fillStyle=this.TextColor; this.Canvas.fillText(text,center,bottom-this.Mergin.Bottom); this.SizeChange=false; } } function ChartVScrollbar() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartVScrollbar'; //类名 this.IsDrawFirst=false; this.GetEventCallback; //获取事件 this.Report; this.MaxPos=15; //滚动条可移动长度 this.CurrentPos=15; //当前滚动条移动位置 this.Step=1; //滚动条移动步长 this.ButtonSize=25; this.Enable=false; this.LastStatus={ Draw:false, }; this.GlobalOption; this.Style=0; //0=滚动条+按钮 1=滚动条 this.ScrollBarHeight=g_JSChartResource.Report.VScrollbar.ScrollBarHeight; this.ButtonColor=g_JSChartResource.Report.VScrollbar.ButtonColor; this.BarColor=g_JSChartResource.Report.VScrollbar.BarColor; this.BorderColor=g_JSChartResource.Report.VScrollbar.BorderColor; this.BGColor=g_JSChartResource.Report.VScrollbar.BGColor; this.Margin={ Left:2, Right:2, Top:2, Bottom:2 }; this.BarWithConfig={ Size:g_JSChartResource.Report.VScrollbar.BarWidth.Size }; this.RectScroll={ Top:null, Bottom:null, Bar:null, Client:null }; //滚动条区域 //this.BarWithConfig.Size=2; //this.Mergin={ Left:1, Right:1, Top:1, Bottom:1 }; this.SetOption=function(option) { if (!option) return; if (IFrameSplitOperator.IsBool(option.Enable)) this.Enable=option.Enable; if (IFrameSplitOperator.IsNumber(option.Style)) this.Style=option.Style; if (IFrameSplitOperator.IsNumber(option.BarWidth)) this.BarWithConfig.Size=option.BarWidth; if (option.Margin) { var item=option.Margin; if (IFrameSplitOperator.IsNumber(item.Top)) this.Margin.Top=item.Top; if (IFrameSplitOperator.IsNumber(item.Bottom)) this.Margin.Bottom=item.Bottom; if (IFrameSplitOperator.IsNumber(item.Left)) this.Margin.Left=item.Left; if (IFrameSplitOperator.IsNumber(item.Right)) this.Margin.Right=item.Right; } } this.ReloadResource=function(resource) { this.ScrollBarHeight=g_JSChartResource.Report.VScrollbar.ScrollBarHeight; this.ButtonColor=g_JSChartResource.Report.VScrollbar.ButtonColor; this.BarColor=g_JSChartResource.Report.VScrollbar.BarColor; this.BorderColor=g_JSChartResource.Report.VScrollbar.BorderColor; this.BGColor=g_JSChartResource.Report.VScrollbar.BGColor; this.BarWithConfig={ Size:g_JSChartResource.Report.VScrollbar.BarWidth.Size }; } this.CalculateSize=function() { var pixelRatio=GetDevicePixelRatio(); var width=this.BarWithConfig.Size*pixelRatio+this.Margin.Left+this.Margin.Right; this.ButtonSize=Math.min(25, width); } //不带上下按钮的滚动条样式 this.DrawScrollbarStyle2=function(left, top, right, bottom) { this.LastStatus.Draw=false; this.RectScroll={ Left:null, Right:null, Bar:null, Client:null }; if (!this.Enable) return; var isShow=this.IsShowCallback(); if (!isShow) return; var pageInfo=this.Report.GetCurrentPageStatus(); if (pageInfo.IsSinglePage) return; var xOffset=pageInfo.Start; var dataCount=pageInfo.DataCount-pageInfo.PageSize; var buttonSize=this.ButtonSize; this.MaxPos=dataCount; this.CurrentPos=xOffset; var scrollTop=top+this.Margin.Top+2; var scrollBottom=bottom-this.Margin.Bottom-2; var centerHeight=scrollBottom-scrollTop; var value = centerHeight - this.ScrollBarHeight; var yOffset = (value * this.CurrentPos) / this.MaxPos; var y = scrollTop + 2 + yOffset; var rtBar = {Right:right-this.Margin.Right, Top:y, Width:buttonSize, Height: this.ScrollBarHeight }; rtBar.Left=rtBar.Right-buttonSize; rtBar.Bottom=rtBar.Top+rtBar.Height; if (rtBar.Bottom>scrollBottom-2) { rtBar.Bottom=scrollBottom-2; rtBar.Top=rtBar.Bottom-rtBar.Height; } this.RectScroll.Bar=rtBar; this.RectScroll.Client={ Left:rtBar.Left, Right: rtBar.Right, Top:scrollTop, Bottom:scrollBottom }; var rtBG={ Right:right, Top:top, Bottom:bottom, Width:buttonSize+this.Margin.Right+this.Margin.Left }; rtBG.Left=rtBG.Right-rtBG.Width; rtBG.Height=rtBG.Bottom-rtBG.Top; this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); this.Canvas.fillStyle=this.BarColor; this.Canvas.fillRect(rtBar.Left,rtBar.Top,rtBar.Width,rtBar.Height); this.LastStatus.Draw=true; } this.DrawScrollbarStyle=function(left, top, right, bottom) { this.LastStatus.Draw=false; this.RectScroll={ Left:null, Right:null, Bar:null, Client:null }; if (!this.Enable) return; var isShow=this.IsShowCallback(); if (!isShow) return; var pageInfo=this.Report.GetCurrentPageStatus(); if (pageInfo.IsSinglePage) return; var xOffset=pageInfo.Start; var dataCount=pageInfo.DataCount-pageInfo.PageSize; var buttonSize=this.ButtonSize; this.MaxPos=dataCount; this.CurrentPos=xOffset; var rtTop={ Right:right-this.Margin.Right, Top:top+this.Margin.Top, Width:buttonSize, Height:buttonSize }; rtTop.Left=rtTop.Right-buttonSize; rtTop.Bottom=rtTop.Top+buttonSize; var rtBottom={ Right:right-this.Margin.Right, Bottom:bottom-this.Margin.Bottom, Width:buttonSize, Height:buttonSize }; rtBottom.Left=rtBottom.Right-buttonSize; rtBottom.Top=rtBottom.Bottom-buttonSize; var centerHeight=(rtBottom.Top-2)-(rtTop.Bottom+2); var value = centerHeight - this.ScrollBarHeight; var yOffset = (value * this.CurrentPos) / this.MaxPos; var y = rtTop.Bottom + 2 + yOffset; var rtBar = {Right:right-this.Margin.Right, Top:y, Width:buttonSize, Height: this.ScrollBarHeight }; rtBar.Left=rtBar.Right-buttonSize; rtBar.Bottom=rtBar.Top+rtBar.Height; if (rtBar.Bottom>rtBottom.Top-2) { rtBar.Bottom=rtBottom.Top-2; rtBar.Top=rtBar.Bottom-rtBar.Height; } this.RectScroll.Top=rtTop; this.RectScroll.Bottom=rtBottom; this.RectScroll.Bar=rtBar; this.RectScroll.Client={ Left:rtTop.Left, Right: rtTop.Right, Top:rtTop.Bottom, Bottom:rtBottom.Top }; var rtBG={ Right:right, Top:top, Bottom:bottom, Width:buttonSize+this.Margin.Right+this.Margin.Left }; rtBG.Left=rtBG.Right-rtBG.Width; rtBG.Height=rtBG.Bottom-rtBG.Top; this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height); this.Canvas.fillStyle=this.ButtonColor; this.Canvas.fillRect(rtTop.Left,rtTop.Top,rtTop.Width,rtTop.Height); this.Canvas.fillRect(rtBottom.Left,rtBottom.Top,rtBottom.Width,rtBottom.Height); this.Canvas.strokeStyle=this.BorderColor; this.Canvas.strokeRect(rtTop.Left,rtTop.Top,rtTop.Width,rtTop.Height); this.Canvas.strokeRect(rtBottom.Left,rtBottom.Top,rtBottom.Width,rtBottom.Height); this.Canvas.fillStyle=this.BarColor; this.Canvas.fillRect(rtBar.Left,rtBar.Top,rtBar.Width,rtBar.Height); this.LastStatus.Draw=true; } this.DrawScrollbar=function(left, top, right, bottom) { if (this.Style==1) this.DrawScrollbarStyle2(left, top, right, bottom); else this.DrawScrollbarStyle(left, top, right, bottom); } this.OnMouseDown=function(x,y, e) { return this.PtInScroll(x,y); } // Type 1-4 滚动条 this.PtInScroll=function(x,y) { if (!this.RectScroll) return null; if (this.RectScroll.Top) { var rtItem=this.RectScroll.Top; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) return { Type: 1, Rect: rtItem }; } if (this.RectScroll.Bottom) { var rtItem=this.RectScroll.Bottom; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) return { Type: 2, Rect: rtItem }; } if (this.RectScroll.Bar) { var rtItem=this.RectScroll.Bar; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) return { Type: 3, Rect: rtItem }; } if (this.RectScroll.Client) { var rtItem=this.RectScroll.Client; if (x>=rtItem.Left && x<=rtItem.Right && y>=rtItem.Top && y<=rtItem.Bottom) { return { Type: 4, Rect: rtItem , Pos: this.GetScrollPostionByPoint(x,y) }; } } return null; } this.GetScrollPostionByPoint=function(x,y) { var rtItem=this.RectScroll.Client; var value=rtItem.Bottom-rtItem.Top-this.ScrollBarHeight; var pos =parseInt((this.MaxPos * (y - rtItem.Top)) / value); return pos; } } function ChartCellTooltip() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartCellTooltip'; //类名 this.BGColor="rgba(255,255,225, 0.9)"; this.BorderColor="rgb(0,0,0)"; this.Margin={ Left:5, Right:5, Top:4, Bottom:5 }; this.Font=`${13*GetDevicePixelRatio()}px 微软雅黑`; this.TextColor="rgb(0,0,0)"; this.YOffset=20; this.XOffset=5; this.Point; //{ X, Y} this.Data; //{ AryText:[ { Text, Color, Title:, TitleColor, Space, Margin:{ Left, Top, Right, Bottom }} ]} this.Draw=function() { if (!this.Canvas) return; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.AryText)) return; if (!this.Point) return; var size={ Width:0, Height:0, Text:[] }; this.CalculateTextSize(this.Data.AryText, size); if (!IFrameSplitOperator.IsNonEmptyArray(size.Text)) return; this.DrawTooltip(this.Data.AryText, size); } this.CalculateTextSize=function(aryText, size) { var width=0, height=0; for(var i=0;iborder.ChartHeight) { rtBG.Bottom=this.Point.Y; rtBG.Top=rtBG.Bottom-rtBG.Height; } if (rtBG.Right>border.ChartWidth) { rtBG.Right=this.Point.X; rtBG.Left=rtBG.Right-rtBG.Width; } if (this.BGColor) { this.Canvas.fillStyle=this.BGColor; this.Canvas.fillRect(ToFixedPoint(rtBG.Left),ToFixedPoint(rtBG.Top),ToFixedRect(rtBG.Width),ToFixedRect(rtBG.Height)); } if (this.BorderColor) { this.Canvas.strokeStyle=this.BorderColor; this.Canvas.strokeRect(ToFixedPoint(rtBG.Left),ToFixedPoint(rtBG.Top),ToFixedRect(rtBG.Width),ToFixedRect(rtBG.Height)); } var left=rtBG.Left; var top=rtBG.Top; if (this.Margin && IFrameSplitOperator.IsNumber(this.Margin.Left)) left+=this.Margin.Left; if (this.Margin && IFrameSplitOperator.IsNumber(this.Margin.Top)) top+=this.Margin.Top; var xText, yText=top; for(var i=0;i{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } this.OnDivResize=function(entries) { JSConsole.Chart.Log("[JSKeyboardChart::OnDivResize] entries=", entries); this.OnSize(); } ///////////////////////////////////////////////////////////////////////////// //对外接口 this.SetColumn=function(aryColumn, option) { if (this.JSChartContainer) this.JSChartContainer.SetColumn(aryColumn,option); } //事件回调 this.AddEventCallback=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:AddEventCallback] obj=', obj); this.JSChartContainer.AddEventCallback(obj); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } this.ChartDestory=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestory) == 'function') { this.JSChartContainer.ChartDestory(); } } this.Draw=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.Draw)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:Draw] '); this.JSChartContainer.Draw(); } } this.SetSymbolData=function(arySymbol) { if(this.JSChartContainer && typeof(this.JSChartContainer.Draw)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:SetSymbolData] ', arySymbol); this.JSChartContainer.SetSymbolData(arySymbol); } } this.Search=function(strText) { if(this.JSChartContainer && typeof(this.JSChartContainer.Search)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:Search] ', strText); this.JSChartContainer.Search(strText); } } this.OnKeyDown=function(event) { if(this.JSChartContainer && typeof(this.JSChartContainer.OnKeyDown)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:OnKeyDown] ', event); this.JSChartContainer.OnKeyDown(event); } } this.ClearSearch=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ClearSearch)=='function') { JSConsole.Chart.Log('[JSKeyboardChart:ClearSearch] ', option); this.JSChartContainer.ClearSearch(option); } } } JSKeyboardChart.Init=function(divElement) { var jsChartControl=new JSKeyboardChart(divElement); jsChartControl.OnSize(); return jsChartControl; } //自定义风格 JSKeyboardChart.SetStyle=function(option) { if (option) g_JSChartResource.SetStyle(option); } function JSKeyboardChartContainer(uielement) { this.ClassName='JSKeyboardChartContainer'; this.Frame; //框架画法 this.ChartPaint=[]; //图形画法 this.Canvas=uielement.getContext("2d"); //画布 this.ShowCanvas=null; this.NetworkFilter; //数据回调接口 this.Data={ XOffset:0, YOffset:0, Data:[] }; //股票列表 this.MapSymbol=new Map(); this.SourceData={ Data:[] } //码表数据 Data:[ { Symbol:, Spell, Name:, Color: TypeName:, TypeID } ] this.FunctionKeyData=[]; //功能键 { Priority:, Data:[ { Symbol:, Spell, Name:, Color:, TypeName:, TypeID } ] //事件回调 this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} this.UIElement=uielement; this.LastPoint=new Point(); //鼠标位置 //拖拽滚动条 this.DragYScroll=null; //{Start:{x,y}, End:{x, y}} this.IsDestroy=false; //是否已经销毁了 this.ChartDestory=function() //销毁 { this.IsDestroy=true; } this.ClearSearch=function(option) { this.Data.Data=[]; this.Data.XOffset=0; this.Data.YOffset=0; if (option && option.Redraw==true) this.Draw(); } this.SearchFunctionKeyData=function(strSearch) { if (strSearch.length<=0) return null; if (!IFrameSplitOperator.IsNonEmptyArray(this.FunctionKeyData)) return null; var aryData=[]; for(var i=0; i0) return aryData; return null; } this.Search=function(strText) { var aryExactQuery=[]; //精确查询 var aryFuzzyQuery=[]; //模糊查询 var aryEqualQuery=[]; //相等 var aryFuncKeyQuery=null; this.MapSymbol.clear(); this.Data.Data=[]; this.Data.XOffset=0; this.Data.YOffset=0; var strSearch=strText.trim(); if (strSearch.length>0) { aryFuncKeyQuery=this.SearchFunctionKeyData(strSearch); for(var i=0;i { return this.GetEventCallback(id); } chart.GetStockDataCallback=(symbol)=>{ return this.GetStockData(symbol);} chart.Data=this.Data; this.ChartPaint[0]=chart; chart.VScrollbar=new ChartKeyboardVScrollbar(); chart.VScrollbar.Frame=this.Frame; chart.VScrollbar.Canvas=this.Canvas; chart.VScrollbar.ChartBorder=this.Frame.ChartBorder; chart.VScrollbar.Report=chart; if (option) { } var bRegisterKeydown=true; var bRegisterWheel=true; if (option) { if (option.KeyDown===false) { bRegisterKeydown=false; JSConsole.Chart.Log('[JSKeyboardChartContainer::Create] not register keydown event.'); } if (option.Wheel===false) { bRegisterWheel=false; JSConsole.Chart.Log('[JSKeyboardChartContainer::Create] not register wheel event.'); } } if (bRegisterKeydown) this.UIElement.addEventListener("keydown", (e)=>{ this.OnKeyDown(e); }, true); //键盘消息 if (bRegisterWheel) this.UIElement.addEventListener("wheel", (e)=>{ this.OnWheel(e); }, true); //上下滚动消息 this.UIElement.ondblclick=(e)=>{ this.UIOnDblClick(e); } this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); } this.UIElement.oncontextmenu=(e)=> { this.UIOnContextMenu(e); } this.UIElement.onmousemove=(e)=>{ this.UIOnMouseMove(e);} this.UIElement.onmouseout=(e)=>{ this.UIOnMounseOut(e); } this.UIElement.onmouseleave=(e)=>{ this.UIOnMouseleave(e); } } this.Draw=function() { if (this.UIElement.width<=0 || this.UIElement.height<=0) return; this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度 this.Frame.Draw(); this.Frame.DrawLogo(); //框架内图形 for(var i=0;i0) //上一页 { if (this.GotoPreviousPage(this.PageUpDownCycle)) { this.Draw(); } } if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnKeyDown=function(e) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var reportChart=this.GetReportChart(); if (!reportChart) return; var keyID = e.keyCode ? e.keyCode :e.which; switch(keyID) { case 33: //page up if (this.GotoPreviousPage(this.PageUpDownCycle)) { this.Draw(); } break; case 34: //page down if (this.GotoNextPage(this.PageUpDownCycle)) { this.Draw(); } break; case 38: //up var result=this.MoveSelectedRow(-1); if (result) { if (result.Redraw) this.Draw(); } break; case 40: //down var result=this.MoveSelectedRow(1) if (result) { if (result.Redraw) this.Draw(); } break; case 37: //left if (this.MoveXOffset(-1)) this.Draw(); break case 39: //right if (this.MoveXOffset(1)) this.Draw(); break; case 13: //Enter this.OnSelectedSymbol(); break; } //不让滚动条滚动 if(e.preventDefault) e.preventDefault(); else e.returnValue = false; } this.OnSelectedSymbol=function() { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var data=chart.GetSelectedSymbol(); var selItem=this.MapSymbol.get(data.Symbol); if (!selItem) return false; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYBOARD_SELECTED) if (event && event.Callback) { event.Callback(event, { Data:data, RowData:selItem }, this); } } this.UIOnDblClick=function(e) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var chart=this.ChartPaint[0]; if (chart) { if (chart.OnDblClick(x,y,e)) this.OnSelectedSymbol(); } } this.UIOnMouseDown=function(e) { this.DragYScroll=null; this.DragMove={ Click:{ X:e.clientX, Y:e.clientY }, Move:{X:e.clientX, Y:e.clientY}, PreMove:{X:e.clientX, Y:e.clientY } }; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; var chart=this.ChartPaint[0]; if (chart) { var clickData=chart.OnMouseDown(x,y,e); if (!clickData) return; //if (e.button!=0) return; if ((clickData.Type==2) && (e.button==0 || e.button==2)) //点击行 { if (clickData.Redraw==true) this.Draw(); } else if (clickData.Type==5 && e.button==0) //右侧滚动条 { var scroll=clickData.VScrollbar; if (scroll.Type==1) //顶部按钮 { if (this.MoveYOffset(-1)) this.Draw(); } else if (scroll.Type==2) //底部按钮 { if (this.MoveYOffset(1)) this.Draw(); } else if (scroll.Type==3) //滚动条 { this.DragYScroll={ Click:{X:x, Y:y}, LastMove:{X:x, Y:y} }; } else if (scroll.Type==4) //滚动条内部 { if (this.SetYOffset(scroll.Pos)) this.Draw(); } } } document.onmousemove=(e)=>{ this.DocOnMouseMove(e); } document.onmouseup=(e)=> { this.DocOnMouseUp(e); } } //去掉右键菜单 this.UIOnContextMenu=function(e) { e.preventDefault(); } this.UIOnMouseMove=function(e) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; } this.UIOnMounseOut=function(e) { } this.UIOnMouseleave=function(e) { } this.DocOnMouseMove=function(e) { this.DragMove.PreMove.X=this.DragMove.Move.X; this.DragMove.PreMove.Y=this.DragMove.Move.Y; this.DragMove.Move.X=e.clientX; this.DragMove.Move.Y=e.clientX; //if (this.DragMove.Move.X!=this.DragMove.PreMove.X || this.DragMove.Move.Y!=this.DragMove.PreMove.Y) // this.StopAutoDragScrollTimer(); if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.DragYScroll) { var chart=this.ChartPaint[0]; if (!chart || !chart.VScrollbar) return; this.DragYScroll.LastMove.X=x; this.DragYScroll.LastMove.Y=y; var pos=chart.VScrollbar.GetScrollPostionByPoint(x,y); if (this.SetYOffset(pos)) this.Draw(); } } this.DocOnMouseUp=function(e) { //清空事件 document.onmousemove=null; document.onmouseup=null; this.DragYScroll=null; var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_KEYBOARD_MOUSEUP) if (event && event.Callback) { event.Callback(event, { }, this); } } this.GetMoveAngle=function(pt,pt2) //计算角度 { var xMove=Math.abs(pt.X-pt2.X); var yMove=Math.abs(pt.Y-pt2.Y); var angle=Math.atan(xMove/yMove)*180/Math.PI; return angle; } this.PreventTouchEvent=function(e) { if (e.cancelable) e.preventDefault(); e.stopPropagation(); } this.OnDragYOffset=function(drag, touches, moveUpDown, e) { if (moveUpDown<5) return false var isUp=true; if (drag.LastMove.Ythis.Data.Data.length) return false; if (this.Data.YOffset+pageSize>=this.Data.Data.length) { if (bCycle===true) { this.Data.YOffset=0; //循环到第1页 return true; } else { return false; } } this.Data.YOffset+=pageSize; var showDataCount=this.Data.Data.length-this.Data.YOffset; chart.SelectedRow=this.Data.YOffset; return true; } this.GotoPreviousPage=function(bCycle) //bCycle 是否循环 { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageSize=chart.GetPageSize(); if (pageSize>this.Data.Data.length) return false; if (this.Data.YOffset<=0) { if (bCycle===true) { this.Data.YOffset=this.Data.Data.length-pageSize; //循环到最后一页 return true; } else { return false; } } var offset=this.Data.YOffset; offset-=pageSize; if (offset<0) offset=0; this.Data.YOffset=offset; chart.SelectedRow=this.Data.YOffset; return true; } this.MoveYOffset=function(setp, bCycle) //bCycle 是否循环 { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; var chart=this.ChartPaint[0]; if (!chart) return false; var pageStatus=chart.GetCurrentPageStatus(); if (pageStatus.IsSinglePage) return false; if (setp>0) //向上 { var count=this.Data.Data.length; var pageSize=pageStatus.PageSize; var offset=this.Data.YOffset; if (bCycle) { for(var i=0;icount) offset=0; } } else { if (offset+pageSize>=count) return false; for(var i=0;icount) break; ++offset; } } this.Data.YOffset=offset; return true; } else if (setp<0) //向下 { setp=Math.abs(setp); var offset=this.Data.YOffset; if (bCycle) { var pageSize=pageStatus.PageSize; for(var i=0;i0) { if (selected<0 || selectedpageStatus.End) { chart.SelectedRow=pageStatus.Start; result.Redraw=true; return result; } var offset=this.Data.YOffset; for(var i=0;ipageStatus.End) ++offset; if (selected>=this.Data.Data.length) break; result.Redraw=true; chart.SelectedRow=selected; this.Data.YOffset=offset; } return result; } else if (step<0) { if (selected<0 || selectedpageStatus.End) { chart.SelectedRow=pageStatus.End; result.Redraw=true; return result; } step=Math.abs(step); var offset=this.Data.YOffset; for(var i=0;imaxOffset) pos=maxOffset; this.Data.YOffset=pos; return true; } } function JSKeyboardFrame() { this.ChartBorder; this.Canvas; //画布 this.BorderLine=null; //1=上 2=下 4=左 8=右 this.BorderColor=g_JSChartResource.Keyboard.BorderColor; //边框线 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; this.ReloadResource=function(option) { this.BorderColor=g_JSChartResource.Keyboard.BorderColor; //边框线 this.LogoTextColor=g_JSChartResource.FrameLogo.TextColor; this.LogoTextFont=g_JSChartResource.FrameLogo.Font; } this.Draw=function() { var left=ToFixedPoint(this.ChartBorder.GetLeft()); var top=ToFixedPoint(this.ChartBorder.GetTop()); var right=ToFixedPoint(this.ChartBorder.GetRight()); var bottom=ToFixedPoint(this.ChartBorder.GetBottom()); var width=right-left; var height=bottom-top; if (!IFrameSplitOperator.IsNumber(this.BorderLine)) { this.Canvas.strokeStyle=this.BorderColor; this.Canvas.strokeRect(left,top,width,height); } else { this.Canvas.strokeStyle=this.BorderColor; this.Canvas.beginPath(); if ((this.BorderLine&1)>0) //上 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(right,top); } if ((this.BorderLine&2)>0) //下 { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } if ((this.BorderLine&4)>0) //左 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(left,bottom); } if ((this.BorderLine&8)>0) //右 { this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); } this.Canvas.stroke(); } } this.DrawLogo=function() { var text=g_JSChartResource.FrameLogo.Text; if (!IFrameSplitOperator.IsString(text)) return; this.Canvas.fillStyle=this.LogoTextColor; this.Canvas.font=this.LogoTextFont; this.Canvas.textAlign = 'right'; this.Canvas.textBaseline = 'bottom'; var x=this.ChartBorder.GetRight()-30; var y=this.ChartBorder.GetBottom()-5; this.Canvas.fillText(text,x,y); } } var KEYBOARD_COLUMN_ID= { SHORT_SYMBOL_ID:0, //不带后缀代码 SYMBOL_ID:1, NAME_ID:2, //简称 TYPE_ID:3, //类型 TYPE_NAME_ID:4, //类型中文名字 } function ChartSymbolList() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ChartSymbolList'; //类名 this.UIElement; this.IsDrawFirst=false; this.GetEventCallback; //获取事件 this.Data; //数据 { XOffset:0, YOffset:0, Data:['600000.sh', '000001.sz'] } this.SizeChange=true; this.SelectedRow=-1; //选中行ID this.IsDrawBorder=false; //是否绘制单元格边框 this.ShowSymbol=[]; //显示的股票列表 { Index:序号(排序用), Symbol:股票代码 } this.VScrollbar; //竖向滚动条 this.BorderColor=g_JSChartResource.Keyboard.BorderColor; //边框线 this.SelectedColor=g_JSChartResource.Keyboard.SelectedColor; //选中行 this.TextColor=g_JSChartResource.Keyboard.TextColor; //文字颜色 //表格内容配置 this.ItemFontConfig={ Size:g_JSChartResource.Keyboard.Item.Font.Size, Name:g_JSChartResource.Keyboard.Item.Font.Name }; this.ItemMergin= { Left:g_JSChartResource.Keyboard.Item.Mergin.Left, Right:g_JSChartResource.Keyboard.Item.Mergin.Right, Top:g_JSChartResource.Keyboard.Item.Mergin.Top, Bottom:g_JSChartResource.Keyboard.Item.Mergin.Bottom }; //缓存 this.ItemFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemSymbolFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemNameFont=15*GetDevicePixelRatio() +"px 微软雅黑"; this.ItemNameHeight=0; this.RowCount=0; //一屏显示行数 this.RowHeight=0; //行高度 this.Column= //{ Type:列id, Title:标题, TextAlign:文字对齐方式, MaxText:文字最大宽度 , TextColor:文字颜色, Sort:0=不支持排序 1=本地排序 0=远程排序 } [ { Type:KEYBOARD_COLUMN_ID.SHORT_SYMBOL_ID, Title:"代码", TextAlign:"left", Width:null, MaxText:"888888" }, { Type:KEYBOARD_COLUMN_ID.NAME_ID, Title:"名称", TextAlign:"left", Width:null, MaxText:"擎擎擎擎擎擎" }, //{ Type:KEYBOARD_COLUMN_ID.TYPE_ID, Title:"类型", TextAlign:"right", Width:null, MaxText:"擎擎擎擎" }, { Type:KEYBOARD_COLUMN_ID.TYPE_NAME_ID, Title:"类型", TextAlign:"right", Width:null, MaxText:"擎擎擎擎" }, ]; this.RectClient={ }; this.ReloadResource=function(resource) { this.BorderColor=g_JSChartResource.Keyboard.BorderColor; //边框线 this.SelectedColor=g_JSChartResource.Keyboard.SelectedColor; //选中行 this.TextColor=g_JSChartResource.Keyboard.TextColor; //文字颜色 if (this.VScrollbar) this.VScrollbar.ReloadResource(resource); } this.SetColumn=function(aryColumn) { if (!IFrameSplitOperator.IsNonEmptyArray(aryColumn)) return; this.Column=[]; for(var i=0;i=this.Data.Data.length-1) result.IsEnd=true; if (result.End>=this.Data.Data.length) result.End=this.Data.Data.length-1; } else { result.Star=0; result.End=0; result.IsEnd=true; result.IsSinglePage=true; } return result; } this.CalculateSize=function() //计算大小 { if (this.VScrollbar && this.VScrollbar.Enable) this.VScrollbar.CalculateSize(); this.UpdateCacheData(); var pixelRatio=GetDevicePixelRatio(); this.ItemFont=`${this.ItemFontConfig.Size*pixelRatio}px ${ this.ItemFontConfig.Name}`; this.RowHeight=this.GetFontHeight(this.ItemFont,"擎")+ this.ItemMergin.Top+ this.ItemMergin.Bottom; var left=this.RectClient.Left; var right=this.RectClient.Right; this.Canvas.font=this.ItemFont; var itemWidth=0; for(var i=0;i=this.Data.Data.length) return null; return { Symbol: this.Data.Data[this.SelectedRow], RowID: this.SelectedRow }; } this.DrawBody=function() { if (!this.Data) return; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; this.Canvas.font=this.ItemFont; var top=this.RectClient.Top; var left=this.RectClient.Left; var rowWidth=this.RectClient.Right-this.RectClient.Left; var textTop=top; this.Canvas.font=this.ItemFont; for(var i=this.Data.YOffset, j=0; i=chartRight) break; } } this.DrawItem=function(index, data, column, left, top, rowType) { var itemWidth=column.Width; var x=left+this.ItemMergin.Left; var textWidth=column.Width-this.ItemMergin.Left-this.ItemMergin.Right; var stock=data.Stock; var drawInfo={ Text:null, TextColor:this.TextColor , TextAlign:column.TextAlign }; if (column.Type==KEYBOARD_COLUMN_ID.SHORT_SYMBOL_ID) { if (stock && stock.ShortSymbol) drawInfo.Text=stock.ShortSymbol; else drawInfo.Text=data.Symbol; if (stock.Color) drawInfo.TextColor=stock.Color; } else if (column.Type==KEYBOARD_COLUMN_ID.NAME_ID) { if (stock && stock.Name) { drawInfo.Text=this.TextEllipsis(stock.Name, textWidth, column.MaxText); if (stock.Color) drawInfo.TextColor=stock.Color; } } else if (column.Type==KEYBOARD_COLUMN_ID.TYPE_NAME_ID) { if (stock && stock.TypeName) { drawInfo.Text=this.TextEllipsis(stock.TypeName, textWidth, column.MaxText); if (stock.Color) drawInfo.TextColor=stock.Color; } } this.DrawItemText(drawInfo.Text, drawInfo.TextColor, drawInfo.TextAlign, x, top, textWidth); } this.DrawItemText=function(text, textColor, textAlign, left, top, width) { if (!text) return; var x=left; if (textAlign=='center') { x=left+width/2; this.Canvas.textAlign="center"; } else if (textAlign=='right') { x=left+width-2; if (left+width-2>this.RectClient.Right) x=this.RectClient.Right-2; this.Canvas.textAlign="right"; } else { x+=2; this.Canvas.textAlign="left"; } this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=textColor; this.Canvas.fillText(text,x,top+this.ItemMergin.Top+this.RowHeight/2); } //字体由外面设置 this.TextEllipsis=function(text, maxWidth, maxText) { if (!text) return null; if (text.lengthmaxWidth) { newText+="..."; break; } newText+=text[i]; } return newText; } this.GetFontHeight=function(font,word) { return GetFontHeight(this.Canvas, font, word); } this.OnMouseDown=function(x,y,e) //Type: 2=行 { if (!this.Data) return null; var pixelTatio = GetDevicePixelRatio(); var insidePoint={X:x/pixelTatio, Y:y/pixelTatio}; if (this.UIElement) var uiElement={Left:this.UIElement.getBoundingClientRect().left, Top:this.UIElement.getBoundingClientRect().top}; else var uiElement={Left:null, Top:null}; if (this.VScrollbar) { var item=this.VScrollbar.OnMouseDown(x,y,e); if (item) return { Type:5, VScrollbar:item }; //右侧滚动条 } var row=this.PtInBody(x,y); if (row) { var bRedraw=true; if (this.SelectedModel==0) { if (this.SelectedRow==row.Index) bRedraw=false; this.SelectedRow=row.Index; this.SelectedFixedRow=-1; } else { if (this.SelectedRow==row.DataIndex) bRedraw=false; this.SelectedRow=row.DataIndex; this.SelectedFixedRow=-1; } var eventID=JSCHART_EVENT_ID.ON_CLICK_REPORT_ROW; if (e.button==2) eventID=JSCHART_EVENT_ID.ON_RCLICK_REPORT_ROW; this.SendClickEvent(eventID, { Data:row, X:x, Y:y, e:e, Inside:insidePoint, UIElement:uiElement }); return { Type:2, Redraw:bRedraw, Row:row }; //行 } return null; } this.OnDrawgRow=function(x, y, e) //Type: 5=顶部 6=空白行 2=行 7=底部 { if (!this.Data) return null; if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return null; var topOffset=this.RowHeight/2; var top=this.RectClient.Top+this.HeaderHeight; var right=this.ChartBorder.GetChartWidth(); var textTop=top; if (y=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom) { var data={ DataIndex:i, Index:j , Symbol:symbol, Pos:0 }; if (j==0) data.Pos=1; else if (j==this.RowCount-1) data.Pos=2; return { Type: 2, Data:data }; } textTop+=this.RowHeight; } if (j=rtRow.Left && x<=rtRow.Right && y>=rtRow.Top && y<=rtRow.Bottom) { var data={ Rect:rtRow, DataIndex:i, Index:j , Symbol:symbol }; data.Item=this.PtInItem(x,y, rtRow.Top, rtRow.Bottom); return data; } textTop+=this.RowHeight; } return null; } this.PtInItem=function(x,y, top, bottom) { var left=this.RectClient.Left; var right=this.RectClient.Right; var textLeft=left; //固定列 for(var i=0;i=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom) { return { Rect:header, Column:item, Index:i }; } textLeft+=item.Width; } for(var i=this.FixedColumn+this.Data.XOffset;i=right) break; var header={Left:textLeft, Right:textLeft+item.Width, Top:top, Bottom:bottom }; if (x>=header.Left && x<=header.Right && y>=header.Top && y<=header.Bottom) { return { Rect:header, Column:item, Index:i }; } textLeft+=item.Width; } return null; } this.IsPtInBody=function(x,y) { var top=this.RectClient.Top; var left=this.RectClient.Left; var right=this.RectClient.Right; var bottom=this.RectClient.Bottom; if (x>=left && x<=right && y>=top && y<=bottom) return true; return false; } this.SendClickEvent=function(id, data) { var event=this.GetEventCallback(id); if (event && event.Callback) { event.Callback(event,data,this); } } this.GetYScrollRange=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return 0; var maxOffset=this.Data.Data.length-this.RowCount; return maxOffset; } //大于1屏数据 显示滚动条 this.IsShowVScrollbar=function() { if (!IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return false; return this.Data.Data.length>this.RowCount; } } //纵向滚动条 function ChartKeyboardVScrollbar() { this.newMethod=ChartVScrollbar; //派生 this.newMethod(); delete this.newMethod; this.ClassName='ChartKeyboardVScrollbar'; this.Enable=true; this.ScrollBarHeight=g_JSChartResource.Keyboard.VScrollbar.ScrollBarHeight; this.ButtonColor=g_JSChartResource.Keyboard.VScrollbar.ButtonColor; this.BarColor=g_JSChartResource.Keyboard.VScrollbar.BarColor; this.BorderColor=g_JSChartResource.Keyboard.VScrollbar.BorderColor; this.BGColor=g_JSChartResource.Keyboard.VScrollbar.BGColor; this.Mergin={ Left:2, Right:2, Top:2, Bottom:2 }; this.BarWithConfig={ Size:g_JSChartResource.Keyboard.VScrollbar.BarWidth.Size }; this.ReloadResource=function(resource) { this.ScrollBarHeight=g_JSChartResource.Keyboard.VScrollbar.ScrollBarHeight; this.ButtonColor=g_JSChartResource.Keyboard.VScrollbar.ButtonColor; this.BarColor=g_JSChartResource.Keyboard.VScrollbar.BarColor; this.BorderColor=g_JSChartResource.Keyboard.VScrollbar.BorderColor; this.BGColor=g_JSChartResource.Keyboard.VScrollbar.BGColor; this.BarWithConfig={ Size:g_JSChartResource.Keyboard.VScrollbar.BarWidth.Size }; } this.IsShowCallback=function() { return true; } } /* Copyright (c) 2018 jones http://www.apache.org/licenses/LICENSE-2.0 开源项目 https://github.com/jones2000/HQChart jones_2000@163.com 封装滚动条控件 (H5版本) */ function JSScrollBarChart(divElement) { this.DivElement=divElement; this.JSChartContainer; //表格控件 this.ResizeListener; //h5 canvas this.CanvasElement=document.createElement("canvas"); this.CanvasElement.className='jsscrollbar-drawing'; this.CanvasElement.id=Guid(); this.CanvasElement.setAttribute("tabindex",0); if (this.CanvasElement.style) this.CanvasElement.style.outline='none'; if(divElement.hasChildNodes()) { JSConsole.Chart.Log("[JSScrollBarChart::JSScrollBarChart] divElement hasChildNodes", divElement.childNodes); } divElement.appendChild(this.CanvasElement); this.OnSize=function() { //画布大小通过div获取 var height=this.DivElement.offsetHeight; var width=this.DivElement.offsetWidth; if (this.DivElement.style.height && this.DivElement.style.width) { if (this.DivElement.style.height.includes("px")) height=parseInt(this.DivElement.style.height.replace("px","")); if (this.DivElement.style.width.includes("px")) width=parseInt(this.DivElement.style.width.replace("px","")); } this.CanvasElement.height=height; this.CanvasElement.width=width; this.CanvasElement.style.width=this.CanvasElement.width+'px'; this.CanvasElement.style.height=this.CanvasElement.height+'px'; var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率 this.CanvasElement.height*=pixelTatio; this.CanvasElement.width*=pixelTatio; JSConsole.Chart.Log(`[JSScrollBarChart::OnSize] devicePixelRatio=${window.devicePixelRatio}, height=${this.CanvasElement.height}, width=${this.CanvasElement.width}`); if (this.JSChartContainer && this.JSChartContainer.OnSize) { this.JSChartContainer.OnSize(); } } this.SetOption=function(option) { var chart=this.CreateJSScrollBarChartContainer(option); if (!chart) return false; this.JSChartContainer=chart; this.DivElement.JSChart=this; //div中保存一份 if (option.EnableResize==true) this.CreateResizeListener(); if (option.OnCreatedCallback) option.OnCreatedCallback(chart); chart.Draw(); } this.CreateJSScrollBarChartContainer=function(option) { var chart=new JSScrollBarChartContainer(this.CanvasElement); chart.Create(option); if (IFrameSplitOperator.IsNumber(option.DelayDragFrequency)) chart.DelayDragFrequency=option.DelayDragFrequency; this.SetChartBorder(chart, option); //注册事件 if (option.EventCallback) { for(var i=0;i{ this.OnDivResize(entries); }); this.ResizeListener.observe(this.DivElement); } this.OnDivResize=function(entries) { JSConsole.Chart.Log("[JSScrollBarChart::OnDivResize] entries=", entries); this.OnSize( ); } ///////////////////////////////////////////////////////////////////////////// //对外接口 //事件回调 this.AddEventCallback=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.AddEventCallback)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:AddEventCallback] obj=', obj); this.JSChartContainer.AddEventCallback(obj); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } this.ChartDestory=function() { if (this.JSChartContainer && typeof (this.JSChartContainer.ChartDestory) == 'function') { this.JSChartContainer.ChartDestory(); } } this.Draw=function() { if(this.JSChartContainer && typeof(this.JSChartContainer.Draw)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:Draw] '); this.JSChartContainer.Draw(); } } this.RecvData=function(data, option) { if(this.JSChartContainer && typeof(this.JSChartContainer.RecvData)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:RecvData] '); this.JSChartContainer.RecvData(data,option); } } this.UpdateSlider=function(obj) { if(this.JSChartContainer && typeof(this.JSChartContainer.UpdateSlider)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:UpdateSlider] '); this.JSChartContainer.UpdateSlider(obj); } } this.Reset=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.Reset)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:Reset] '); this.JSChartContainer.Reset(option); } } //重新加载配置 this.ReloadResource=function(option) { if(this.JSChartContainer && typeof(this.JSChartContainer.ReloadResource)=='function') { JSConsole.Chart.Log('[JSScrollBarChart:ReloadResource] '); this.JSChartContainer.ReloadResource(option); } } } JSScrollBarChart.Init=function(divElement) { var jsChartControl=new JSScrollBarChart(divElement); jsChartControl.OnSize(); return jsChartControl; } //自定义风格 JSScrollBarChart.SetStyle=function(option) { if (option) g_JSChartResource.SetStyle(option); } //获取颜色配置 (设置配必须啊在JSChart.Init()之前) JSScrollBarChart.GetResource=function() { return g_JSChartResource; } ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////// function JSScrollBarChartContainer(uielement) { this.ClassName='JSScrollBarChartContainer'; this.Frame; //框架画法 this.ChartPaint=[]; //图形画法 this.ChartSplashPaint=null; //等待提示 this.LoadDataSplashTitle="无数据"; //下载数据提示信息 this.Canvas=uielement.getContext("2d"); //画布 this.ShowCanvas=null; this.XOffsetData={ Start:-1, End:-1, Count:0 }; //Count:一共的数据个数 this.SourceData// new ChartData(); //K线数据 this.SliderChart; //滑块 this.DragMove; //={ Click:{ 点击的点}, Move:{最后移动的点}, PreMove:{上一个点的位置} }; this.DragSlider; this.DragTimer; //拖拽延迟定时器 this.DelayDragFrequency=150; this.AutoMargin={ Left:false, Right:false }; //左右2边间距是否跟K线一致 //事件回调 this.mapEvent=new Map(); //通知外部调用 key:JSCHART_EVENT_ID value:{Callback:回调,} this.UIElement=uielement; this.LastPoint=new Point(); //鼠标位置 //this.XStepPixel=10*GetDevicePixelRatio(); this.IsDestroy=false; //是否已经销毁了 this.HQChart=null; this.ChartDestory=function() //销毁 { this.IsDestroy=true; } this.GetHQChart=function() { return this.HQChart; } //设置事件回调 //{event:事件id, callback:回调函数} this.AddEventCallback=function(object) { if (!object || !object.event || !object.callback) return; var data={Callback:object.callback, Source:object}; this.mapEvent.set(object.event,data); } this.RemoveEventCallback=function(eventid) { if (!this.mapEvent.has(eventid)) return; this.mapEvent.delete(eventid); } this.GetEventCallback=function(id) //获取事件回调 { if (!this.mapEvent.has(id)) return null; var item=this.mapEvent.get(id); return item; } //创建 this.Create=function(option) { this.UIElement.JSChartContainer=this; //创建等待提示 this.ChartSplashPaint = new ChartSplashPaint(); this.ChartSplashPaint.Canvas = this.Canvas; this.ChartSplashPaint.SetTitle(this.LoadDataSplashTitle); this.ChartSplashPaint.IsEnableSplash=true; //创建框架 this.Frame=new JSScrollBarFrame(); this.Frame.ChartBorder=new ChartBorder(); this.Frame.ChartBorder.UIElement=this.UIElement; this.Frame.ChartBorder.Top=30; this.Frame.ChartBorder.Left=5; this.Frame.ChartBorder.Bottom=20; this.Frame.Canvas=this.Canvas; this.ChartSplashPaint.Frame = this.Frame; //背景 var chart=new ScrollBarBGChart(); chart.ChartFrame=this.Frame; chart.ChartBorder=this.Frame.ChartBorder; chart.Canvas=this.Canvas; chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.ChartPaint.push(chart); //创建滑块 var chart=new SliderChart(); chart.ChartFrame=this.Frame; chart.ChartBorder=this.Frame.ChartBorder; chart.Canvas=this.Canvas; chart.OffsetData=this.XOffsetData; chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); } this.SliderChart=chart; this.ChartPaint.push(chart); //this.UIElement.ondblclick=(e)=>{ this.UIOnDblClick(e); } this.UIElement.onmousedown=(e)=> { this.UIOnMouseDown(e); } this.UIElement.oncontextmenu=(e)=> { this.UIOnContextMenu(e); } this.UIElement.onmousemove=(e)=>{ this.UIOnMouseMove(e);} this.UIElement.onmouseout=(e)=>{ this.UIOnMounseOut(e); } this.UIElement.onmouseleave=(e)=>{ this.UIOnMouseleave(e); } //手机拖拽 //this.UIElement.ontouchstart=(e)=> { this.OnTouchStart(e); } //this.UIElement.ontouchmove=(e)=> {this.OnTouchMove(e); } //this.UIElement.ontouchend=(e)=> {this.OnTouchEnd(e); } } //创建一个图形 this.CreateChartPaint=function(name) { var chart=g_ChartPaintFactory.Create(name); if (!chart) return null; chart.ChartFrame=this.Frame; chart.ChartBorder=this.Frame.ChartBorder; chart.Canvas=this.Canvas; chart.Data=this.Frame.Data; chart.GetEventCallback=(id)=> { return this.GetEventCallback(id); } chart.GetHQChartCallback=()=>{ return this.GetHQChart(); } return chart; } this.GetChartPaintByClassName=function(name) { for(var i=0; irange.Min) min=range.Min; } if (IFrameSplitOperator.IsNumber(max) && IFrameSplitOperator.IsNumber(min)) { this.Frame.HorizontalMax=max; this.Frame.HorizontalMin=min; } } //未启动 this.UIOnDblClick=function(e) { } this.CancelDragTimer=function() { if (this.DragTimer) { clearTimeout(this.DragTimer); this.DragTimer=null; } } this.UIOnMouseDown=function(e) { this.CancelDragTimer(); this.DragSlider=null; this.DragMove={ Click:{ X:e.clientX, Y:e.clientY }, Move:{X:e.clientX, Y:e.clientY}, PreMove:{X:e.clientX, Y:e.clientY } }; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.SliderChart) { var clickData=this.SliderChart.PtInChart(x,y); if (!clickData) { if (!this.Frame.PtInClient(x,y)) return; //滚动块直接移动到鼠标点击的位置 var index=this.Frame.GetXData(x); index=Math.round(index); var pageRange=this.GetPageRange(); var showCount=pageRange.ShowCount; var start=index-parseInt(showCount/2); if (start<0) start=0; var end=start+showCount; if (end>=this.Frame.XPointCount) { end=this.Frame.XPointCount-1; start=end-showCount; } var drag={ UpdateData:{ StartIndex:start, EndIndex:end, Type:3 } }; this.DragUpdate(drag); return; } this.DragSlider={ Click:{ X:e.clientX, Y:e.clientY }, LastMove:{X:e.clientX, Y:e.clientY}, Data:clickData }; this.DragSlider.DrawCount=0; //重绘次数 } document.onmousemove=(e)=>{ this.DocOnMouseMove(e); } document.onmouseup=(e)=> { this.DocOnMouseUp(e); } } //去掉右键菜单 this.UIOnContextMenu=function(e) { e.preventDefault(); } this.UIOnMouseMove=function(e) { var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.DragSlider) return; var mouseStatus= mouseStatus={ Cursor:"default" };; //鼠标状态 var item=this.SliderChart.PtInChart(x,y); if (item) { switch(item.Data.Type) { case 0: mouseStatus={ Cursor:"grab", Name:"SliderChart"}; break; case 1: case 2: mouseStatus={ Cursor:"col-resize", Name:"SliderChart"}; break; } } if (mouseStatus) this.UIElement.style.cursor=mouseStatus.Cursor; } this.UIOnMounseOut=function(e) { } this.UIOnMouseleave=function(e) { } this.DocOnMouseMove=function(e) { this.DragMove.PreMove.X=this.DragMove.Move.X; this.DragMove.PreMove.Y=this.DragMove.Move.Y; this.DragMove.Move.X=e.clientX; this.DragMove.Move.Y=e.clientX; if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; var pixelTatio = GetDevicePixelRatio(); var x = (e.clientX-this.UIElement.getBoundingClientRect().left)*pixelTatio; var y = (e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; JSConsole.Chart.Log(`[JSScrollBarChartContainer::DocOnMouseMove] x=${x}, y=${y}`); if (this.DragSlider) { var drag=this.DragSlider; var moveSetp=(e.clientX-drag.LastMove.X)*pixelTatio; if (Math.abs(moveSetp)<1) return; var pageRange=this.GetPageRange(); var left=this.Frame.ChartBorder.GetLeft(); var right=this.Frame.ChartBorder.GetRight(); this.SliderChart.DragMode=true; var type=drag.Data.Data.Type; var xStart=this.SliderChart.XStart+moveSetp; var xEnd=this.SliderChart.XEnd+moveSetp; if (type==0) //整体移动 { if (xStart=right) { xStart=pageRange.Last.XStart; xEnd=pageRange.Last.XEnd; } this.SliderChart.XStart=xStart; this.SliderChart.XEnd=xEnd; } else if (type==1) //左移动 { if (xStart<=left) { xStart=pageRange.First.XStart; } else if (xStart>=right) { xStart=pageRange.Last.XEnd; } this.SliderChart.XStart=xStart; } else if (type==2) { if (xEnd>=right) { xEnd=pageRange.Last.XEnd; } else if (xEnd<=left) { xEnd=pageRange.First.XStart; } this.SliderChart.XEnd=xEnd; } drag.UpdateData={ XStart:xStart, XEnd:xEnd, Type:type }; drag.LastMove.X=e.clientX; drag.LastMove.Y=e.clientY; if (drag.DrawCount==0) { this.DragUpdate(drag); } else { this.DragTimer=setTimeout(()=> { this.DragUpdate(this.DragSlider); }, this.DelayDragFrequency); } } } this.DocOnMouseUp=function(e) { //清空事件 document.onmousemove=null; document.onmouseup=null; this.CancelDragTimer(); var dragSlider=this.DragSlider; this.DragMove=null; this.DragSlider=null; this.SliderChart.DragMode=false; this.DragUpdate(dragSlider); } this.DragUpdate=function(dragData) { if (!dragData || !dragData.UpdateData) return; this.UpdateXDataOffset(dragData.UpdateData); this.Draw(); ++dragData.DrawCount; } this.Reset=function(option) { this.SourceData=null; this.XOffsetData.Start=-1; this.XOffsetData.End=-1; this.XOffsetData.Count=0; this.Frame.Data=null; for(var i=0;ithis.XOffsetData.Start) { sendData.Start={ Index:this.XOffsetData.Start, Item:startItem}; sendData.End={ Index:this.XOffsetData.End, Item:endItem}; } else { sendData.Start={ Index:this.XOffsetData.End, Item:endItem }; sendData.End={ Index:this.XOffsetData.Start, Item:startItem }; } if (this.HQChart && this.HQChart.JSChartContainer) { var internalChart=this.HQChart.JSChartContainer; if (internalChart.ChartOperator) { var obj={ ID:JSCHART_OPERATOR_ID.OP_SCROOLBAR_SLIDER_CHANGED, Start:sendData.Start, End:sendData.End, Type:sendData.Type }; internalChart.ChartOperator(obj); } } var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SCROLLBAR_SLIDER_CHANGED); if (event) { event.Callback(event,sendData,this); } } this.ReloadResource=function(option) { this.Frame.ReloadResource(option); for(var i=0;i0) //上 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(right,top); } if ((this.BorderLine&2)>0) //下 { this.Canvas.moveTo(left,bottom); this.Canvas.lineTo(right,bottom); } if ((this.BorderLine&4)>0) //左 { this.Canvas.moveTo(left,top); this.Canvas.lineTo(left,bottom); } if ((this.BorderLine&8)>0) //右 { this.Canvas.moveTo(right,top); this.Canvas.lineTo(right,bottom); } this.Canvas.stroke(); } } this.GetXFromIndex=function(index) { var count=this.XPointCount; if (count==1) { if (index==0) return this.ChartBorder.GetLeft(); else return this.ChartBorder.GetRight(); } else if (count<=0) { return this.ChartBorder.GetLeft(); } else if (index>=count) { return this.ChartBorder.GetRight(); } else { var offset=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*index/count; return offset; } } this.GetYFromData=function(value) { if(value<=this.HorizontalMin) return this.ChartBorder.GetBottomEx(); if(value>=this.HorizontalMax) return this.ChartBorder.GetTopEx(); var height=this.ChartBorder.GetHeightEx()*(value-this.HorizontalMin)/(this.HorizontalMax-this.HorizontalMin); return this.ChartBorder.GetBottomEx()-height; } //X坐标转x轴数值 this.GetXData=function(x) { if (x<=this.ChartBorder.GetLeft()) return 0; if (x>=this.ChartBorder.GetRight()) return this.XPointCount; return (x-this.ChartBorder.GetLeft())*(this.XPointCount*1.0/this.ChartBorder.GetWidth()); } this.GetPreSetpWidth=function() { return this.XPointCount*1.0/this.ChartBorder.GetWidth(); } this.DrawVertical=function() { if (this.ChartBorder.Bottom<=5) return; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return var item=this.Data.Data[0]; var preYear=parseInt(item.Date/10000); var preDay=item.Date%10000; this.Canvas.font=this.XSplitTextFont; this.Canvas.fillStyle=this.XSplitTextColor; this.Canvas.textBaseline="top"; var yText=this.ChartBorder.GetBottom()+2; var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); var preXText=0; if (ChartData.IsMilliSecondPeriod(this.Data.Period)) { var preHour=null; for(var i=0;ipreXText) { this.Canvas.textAlign="center"; this.Canvas.fillText(text,x,yText); preXText=x+textWidth/2; } x=ToFixedPoint(x); this.Canvas.strokeStyle=this.XSplitLineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,top); this.Canvas.lineTo(x,bottom); this.Canvas.stroke(); preHour=hour; } } } else if (ChartData.IsMinutePeriod(this.Data.Period,true)) { for(var i=0;ipreXText) { this.Canvas.textAlign="center"; this.Canvas.fillText(text,x,yText); preXText=x+textWidth/2; } x=ToFixedPoint(x); this.Canvas.strokeStyle=this.XSplitLineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,top); this.Canvas.lineTo(x,bottom); this.Canvas.stroke(); preDay=day; } } } else { for(var i=0;ipreXText) { this.Canvas.textAlign="center"; this.Canvas.fillText(text,x,yText); preXText=x+textWidth/2; } x=ToFixedPoint(x); this.Canvas.strokeStyle=this.XSplitLineColor; this.Canvas.beginPath(); this.Canvas.moveTo(x,top); this.Canvas.lineTo(x,bottom); this.Canvas.stroke(); preYear=year; } } } } this.PtInClient=function(x,y) { var left=ToFixedPoint(this.ChartBorder.GetLeft()); var top=ToFixedPoint(this.ChartBorder.GetTop()); var right=ToFixedPoint(this.ChartBorder.GetRight()); var bottom=ToFixedPoint(this.ChartBorder.GetBottom()); if (x>=left && x<=right && y>=top && y<=bottom) return true; return false; } } ///////////////////////////////////////////////////////////////////////////////////////////////// // 滑块 // ///////////////////////////////////////////////////////////////////////////////////////////////// function SliderChart() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='SliderChart'; //类名 this.OffsetData; this.Color=g_JSChartResource.ScrollBar.Slider.BarAreaColor; this.BarColor=g_JSChartResource.ScrollBar.Slider.BarColor; this.BarWidth=g_JSChartResource.ScrollBar.Slider.BarWidth; this.BarPadding=g_JSChartResource.ScrollBar.Slider.BarPadding; //上下留白 this.MinCenterWidth=g_JSChartResource.ScrollBar.Slider.MinCenterWidth; this.DateFont=g_JSChartResource.ScrollBar.Slider.DateFont; this.DateColor=g_JSChartResource.ScrollBar.Slider.DateColor; this.AryRect=[]; //[{ Rect:{Left, Top, Right:, Bottom:, Width, Height:}, Type:0中间 1=左 2=右 }] this.XStart; this.XEnd; this.SizeChange=true; this.DragMode=false; this.ReloadResource=function(resource) { this.Color=g_JSChartResource.ScrollBar.Slider.BarAreaColor; this.BarColor=g_JSChartResource.ScrollBar.Slider.BarColor; this.DateFont=g_JSChartResource.ScrollBar.Slider.DateFont; this.DateColor=g_JSChartResource.ScrollBar.Slider.DateColor; } this.Draw=function() { this.AryRect=[]; if (!this.OffsetData || !IFrameSplitOperator.IsPlusNumber(this.OffsetData.Count)) return; if (!IFrameSplitOperator.IsNumber(this.OffsetData.Start) || !IFrameSplitOperator.IsNumber(this.OffsetData.End)) return; var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); var startData, endData; if (this.DragMode) { var xStart=this.XStart; var xEnd=this.XEnd; var startIndex=this.ChartFrame.GetXData(xStart); var endIndx=this.ChartFrame.GetXData(xEnd); startIndex=parseInt(startIndex); endIndx=parseInt(endIndx); startData={ Data:this.Data.Data[this.OffsetData.Start], X:xStart, Type:startIndexstartIndex?1:0 }; } else { var start=this.OffsetData.Start, end=this.OffsetData.End; var xStart=this.ChartFrame.GetXFromIndex(start); var xEnd=this.ChartFrame.GetXFromIndex(end); this.XStart=xStart; this.XEnd=xEnd; startData={ Data:this.Data.Data[this.OffsetData.Start], X:xStart, Type:xStartxStart?1:0 }; } this.Canvas.fillStyle=this.Color; var rtBar={ Left:Math.min(xStart,xEnd), Top:top, Width:Math.abs(xEnd-xStart), Height: bottom-top}; rtBar.Right=rtBar.Left+rtBar.Width; rtBar.Bottom=rtBar.Top+rtBar.Height; if (rtBar.Width=this.Data.Data.length) endData.Data=this.Data.Data[this.Data.Data.length-1]; } this.DrawDateTime(startData); this.DrawDateTime(endData); } this.DrawDateTime=function(data) { if (!data || !data.Data) return; var text=IFrameSplitOperator.FormatDateString(data.Data.Date); var top=this.ChartBorder.GetTop(); var bottom=this.ChartBorder.GetBottom(); var timeText=null; if (ChartData.IsMilliSecondPeriod(this.Data.Period)) { var time=parseInt(data.Data.Time/1000); text=IFrameSplitOperator.FormatTimeString(time,"HH:MM:SS"); } else if (ChartData.IsSecondPeriod(this.Data.Period)) { text=IFrameSplitOperator.FormatTimeString(time,"HH:MM:SS"); } else if (ChartData.IsMinutePeriod(this.Data.Period, true)) { timeText=IFrameSplitOperator.FormatTimeString(data.Data.Time,"HH:MM"); } if (data.Type==0) { this.Canvas.textAlign="right"; var x=data.X-this.BarWidth/2; } else if (data.Type==1) { this.Canvas.textAlign="left"; var x=data.X+this.BarWidth/2; } this.Canvas.font=this.DateFont; var fontHeight=this.Canvas.measureText("擎").width; this.Canvas.textBaseline="middle"; this.Canvas.fillStyle=this.DateColor; var yText=top+(bottom-top)/2; this.Canvas.fillText(text,x,yText); if (timeText) { yText+=fontHeight; this.Canvas.fillText(timeText,x,yText); } } this.PtInChart=function(x,y) { if (!IFrameSplitOperator.IsNonEmptyArray(this.AryRect)) return null; for(var i=this.AryRect.length-1; i>=0; --i) { var item=this.AryRect[i]; var rt=item.Rect; if (x>=rt.Left && x<=rt.Right && y>=rt.Top && y<=rt.Bottom) { return { Data:item }; } } return null; } } /////////////////////////////////////////////////////////////////////////////////////////////// // 滚动条K线背景色 // // ///////////////////////////////////////////////////////////////////////////////////////////////// function ScrollBarBGChart() { this.Canvas; //画布 this.ChartBorder; //边框信息 this.ChartFrame; //框架画法 this.Name; //名称 this.ClassName='ScrollBarBGChart'; //类名 this.SizeChange=true; this.Data; this.Color=g_JSChartResource.ScrollBar.BGChart.Color; //线段颜色 this.LineWidth=g_JSChartResource.ScrollBar.BGChart.LineWidth; //线段宽度 this.AreaColor=g_JSChartResource.ScrollBar.BGChart.AreaColor; //面积图颜色 this.ReloadResource=function(resource) { this.Color=g_JSChartResource.ScrollBar.BGChart.Color; //线段颜色 this.LineWidth=g_JSChartResource.ScrollBar.BGChart.LineWidth; //线段宽度 this.AreaColor=g_JSChartResource.ScrollBar.BGChart.AreaColor; //面积图颜色 } this.Draw=function() { if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; this.Canvas.save(); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); var bottom=this.ChartBorder.GetBottom(); this.Canvas.strokeStyle=this.Color; var bFirstPoint=true; var drawCount=0,x,y; var firstPoint={ }; for(var i=0;i0) { this.Canvas.stroke(); this.Canvas.lineTo(x,bottom); this.Canvas.lineTo(firstPoint.X,bottom); this.Canvas.closePath(); this.Canvas.fillStyle=this.AreaColor; this.Canvas.fill(); } this.Canvas.restore(); } this.GetMaxMin=function() { var range={ Max:null, Min:null }; if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return range; for(var i=0;ivalue) range.Min=value; } return range; } } /******************************************************************************** * 版本信息输出 * */ var HQCHART_VERSION="1.1.14083"; function PrintHQChartVersion() { var logo=` *************************************************************************************************************************************************************************** * * :%@@- * :@@@@- * =@@@@ :#@@@ .:+#@@@#=: :=*@@@@@@#+-. *@@@@. * :@@@@@ .@@@@@ .#@@@@@@@@@@@- +@@@@@@@@@@@@@+ @@@@@ -%@@* * +@@@@% #@@@@# *@@@@@@@@@@@@@@%. =@@@@@@@@@@@@@@@- @@@@@ -@@@@+ * %@@@@* @@@@@+ .%@@@@@@@@@@@@@@@@%: #@@@@@@@@@@@@@@@% @@@@# *@@@@= * @@@@@= @@@@@- .%@@@@@@@*++*%@@@@@@% .%@@@@@@@%*+==+**= -@@@@+ #@@@@- * @@@@@. @@@@@. #@@@@@%= =@@@@@@* %@@@@@@#: *@@@@- :::. .-+*###+: ::: .+##+: -%%@@@@@%%%% * .@@@@@ .@@@@@. +@@@@@% .@@@@@@ *@@@@@@: %@@@@: +@@@@@%. :%@@@@@@@@@@: *@@@ :@@@@@* @@@@@@@@@@@@ * :@@@@@ :@@@@@ @@@@@% :@@@@@+ @@@@@@: %@@@@-@@@@@@@@@. @@@@@@@@@@@@@. :@@@%-@@@@@@.:@@@@@@@@@@@# * -@@@@% -@@@@@ =@@@@@. %@@@@% %@@@@@- %@@@@@@@@@@@@@@* %@@@@@@@@@@@@+ -@@@@@@@@@@# -@@@@@@@@@@@. * +@@@@%=========#@@@@% @@@@@# :@@@@@ .@@@@@% @@@@@@@@%@@@@@@@ -%+:. .#@@@@* +@@@@@@@%%@. .::+@@@@#:: * #@@@@@@@@@@@@@@@@@@@# .@@@@@ .@@@@@ :@@@@@. @@@@@@#. #@@@@@. -@@@@* #@@@@@@: *@@@@+ * %@@@@@@@@@@@@@@@@@@@+ :@@@@@ .@@@@@ -@@@@@ @@@@@+ @@@@@. :@@@@* @@@@@% #@@@@- * @@@@@@@@@@@@@@@@@@@@: :@@@@% :@@@@@ +@@@@% -@@@@+ @@@@@ -@@@@+ @@@@@. @@@@@. * .@@@@@@@@@@@@@@@@@@@@ :@@@@% -@@@@% *@@@@% #@@@@. @@@@@ .=*#%%%@@@@@= :@@@@# @@@@@. * -@@@@@:::::::::=@@@@@ :@@@@@ @@@@@* +@@@@% @@@@@ @@@@% -#@@@@@@@@@@@@: -@@@@* @@@@@ * =@@@@% =@@@@% .@@@@@ :@@@@@. -@@@@% @@@@@ .@@@@* +@@@@@@@@@@@@@@. =@@@@+ .@@@@@ * +@@@@# +@@@@# @@@@@# %@@@@% :@@@@@ .@@@@% =@@@@= -@@@@@*-:..%@@@@ +@@@@= :@@@@# * *@@@@* *@@@@* +@@@@@: #@@@@@+ .@@@@@@ :@@@@% *@@@@- @@@@@. @@@@% #@@@@: =@@@@+ * %@@@@= %@@@@+ @@@@@@- .%@@@@@# #@@@@@# :@@@@% #@@@@: @@@@% @@@@* %@@@@. #@@@@- * @@@@@- @@@@@= =@@@@@@#=...-*@@@@@@@: @@@@@@%=. :+**. :@@@@* %@@@@. .@@@@* *@@@@= @@@@@ %@@@@+ * .@@@@@: .@@@@@: *@@@@@@@@@@@@@@@@@@@# =@@@@@@@@%%%@@@@@@ +@@@@- @@@@@ .@@@@@: :%@@@@@- .@@@@% %@@@@@*+- * :@@@@@ :@@@@@ +@@@@@@@@@@@@@@@@@@@# =@@@@@@@@@@@@@@@@% %@@@@ @@@@@ @@@@@@@@@@@@@@@: -@@@@* *@@@@@@@@- * =@@@@@ -@@@@@ :@@@@@@@@@@@@@@@@@@@# :@@@@@@@@@@@@@@@% @@@@@ %@@@% #@@@@@@@@@#@@@@. +@@@@- .@@@@@@@@# * *@@@@# =@@@@% :#@@@@@@@#: :@@@@@= =@@@@@@@@@@@+. @@@@@ :@@@+ *@@@@@@@- %@@@ *@@@= =@@@@@@@* * =++++- -++++= .:::. .=*+: :-=+++=:. ****= .=+. .-++=: :+++ -+=: .-=+=:. * * * HQChart * Ver: ${HQCHART_VERSION} * License: Apache License 2.0 * Source: https://github.com/jones2000/HQChart * ************************************************************************************************************************************************************************** `; console.log(logo); } PrintHQChartVersion(); /* 单独的网络接口 */ function JSNetwork() { } JSNetwork.HttpRequest=function(obj) //使用uniapp 网络接口接口 !!每家平台都喜欢自定义接口, 低层不都是一样的嘛 { let method=obj.type.toUpperCase(); uni.request({ url: obj.url, data: obj.data, method:method, success: (res)=> { obj.success(res.data); }, fail: obj.error, }); } //把给外界调用的方法暴露出来 export default { //类导出 JSChart:JSChart, //行情图形库 ChartData:ChartData, MARKET_SUFFIX_NAME:MARKET_SUFFIX_NAME, //判断股票属性 IFrameSplitOperator:IFrameSplitOperator, //格式化字符串方法 FrameSplitKLinePriceY:FrameSplitKLinePriceY, FrameSplitKLineX:FrameSplitKLineX, JSKLineInfoMap:JSKLineInfoMap, JSCHART_EVENT_ID:JSCHART_EVENT_ID, //可以订阅的事件类型 JSCHART_OPERATOR_ID:JSCHART_OPERATOR_ID, //图形控制类型 JSAlgorithm:JSAlgorithm, //算法类 JSComplier:JSComplier, //指标编译器 JSIndexScript:JSIndexScript, //系统指标库 GetDevicePixelRatio,GetDevicePixelRatio, ScriptIndexConsole:ScriptIndexConsole, //指标执行 无UI //style.js相关 STYLE_TYPE_ID:STYLE_TYPE_ID, HQChartStyle:HQChartStyle, //预定义全局的配色 黑 JSConsole:JSConsole, //日志输出 KLineTooltipPaint:KLineTooltipPaint, //K线tooltip MinuteTooltipPaint:MinuteTooltipPaint, //走势图tooltip CoordinateInfo:CoordinateInfo, //图形基类导出 IChartPainting:IChartPainting, //图形 IExtendChartPainting:IExtendChartPainting, //扩展图形 IChartTitlePainting:IChartTitlePainting, //标题类 IChartDrawPicture:IChartDrawPicture, //画图工具 DynamicTitleData:DynamicTitleData, //指标标题数据 //成交明细 JSDealChart:JSDealChart, DEAL_COLUMN_ID:DEAL_COLUMN_ID, //报价列表 JSReportChart:JSReportChart, REPORT_COLUMN_ID:REPORT_COLUMN_ID, //键盘精灵 JSKeyboardChart:JSKeyboardChart, KEYBOARD_COLUMN_ID:KEYBOARD_COLUMN_ID, //X轴滚动条 JSScrollBarChart:JSScrollBarChart, JSCHART_WORKER_MESSAGE_ID:JSCHART_WORKER_MESSAGE_ID, }