From 1022decde60ff8b1130b3d3ae9b301da597d5041 Mon Sep 17 00:00:00 2001 From: jones2000 Date: Tue, 27 Aug 2024 11:56:50 +0800 Subject: [PATCH] ver 13766 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 13762 小程序APIScriptIndex::FittingData()线段增属性IsShowTitle,BreakPoint,isDotLine,lineDash,isSingleLine 13761 APIScriptIndex::FittingData() 线段数据增加属性isDotLine,lineDash,isSingleLine --- umychart_indexapi/jscommon/umychart.node.js | 14698 +++++++++++----- umychart_indexapi/jsindexcontroller.js | 4 + umychart_uniapp_h5/umychart.uniapp.h5.js | 5 +- vuehqchart/src/jscommon/umychart.complier.js | 3 + vuehqchart/src/jscommon/umychart.version.js | 2 +- .../src/jscommon/umychart.vue/umychart.vue.js | 5 +- webhqchart.demo/jscommon/umychart.complier.js | 3 + webhqchart.demo/jscommon/umychart.version.js | 2 +- webhqchart/umychart.complier.js | 3 + webhqchart/umychart.version.js | 2 +- wechathqchart/umychart.index.wechat.js | 7 +- wechathqchart/umychart.version.wechat.js | 2 +- 12 files changed, 10641 insertions(+), 4095 deletions(-) diff --git a/umychart_indexapi/jscommon/umychart.node.js b/umychart_indexapi/jscommon/umychart.node.js index 590ab0faa..03a7abd69 100644 --- a/umychart_indexapi/jscommon/umychart.node.js +++ b/umychart_indexapi/jscommon/umychart.node.js @@ -25,7 +25,8 @@ StringFormat: 1=带单位万/亿 2=原始格式 Condition: 限制条件 { Symbol:'Index'/'Stock'(只支持指数/股票),Period:[](支持的周期), Include:[](指定支持的股票,代码全部大写包括后缀, Message:"提示信息")} OutName:动态输出变量名字 [{Name:原始变量名, DynamicName:动态名字格式}] 如 {Name:"MA1", DynamicName:"MA{M1}"}; - SplitType: Y轴分割类型 + SplitType: Y轴分割类型, + YAxis:{ FloatPrecision:小数位数, StringFormat:, EnableRemoveZero, ExcludeValue:不参数Y轴的计算 } //Y轴刻度输出格式 */ //周期条件枚举 @@ -78,7 +79,7 @@ function JSIndexScript() ['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],["VOL_OVERLAY", this.VOL_OVERLAY], ['RSI', this.RSI],['BRAR', this.BRAR], + ['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], @@ -112,6 +113,8 @@ function JSIndexScript() ["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], @@ -119,17 +122,15 @@ function JSIndexScript() ['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], - - ['Zealink-资金吸筹', this.Zealink_Index1], ['Zealink-牛熊区间', this.Zealink_Index2],['Zealink-持仓信号', this.Zealink_Index3], - ['Zealink-增减持',this.Zealink_Index4],['Zealink-大宗交易', this.Zealink_Index5], ['Zealink-信托持股', this.Zealink_Index6], - ['Zealink-官网新闻', this.Zealink_Index7], ['Zealink-高管要闻', this.Zealink_Index8],['Zealink-股权质押', this.Zealink_Index9], - ['Zealink-操盘BS点', this.Zealink_Index10],['Zealink-操盘BS点2', this.Zealink_Index11], - + //外包指标 ['放心股-操盘BS点',this.FXG_BSPoint], ['放心股-涨停多空线',this.FXG_INDEX], @@ -167,6 +168,33 @@ JSIndexScript.AddIndex=function(aryIndex) //添加自定义指标 } } +//修改指标属性 +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); @@ -617,6 +645,23 @@ 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= @@ -1581,7 +1626,7 @@ JSIndexScript.prototype.AMO = function () { let data = { - Name: 'AMO', Description: '成交金额', IsMainIndex: false, + 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\ @@ -3243,359 +3288,6 @@ EXITLONG: (CROSS(HSL,5) OR CROSS(K,80));' return data; } - -JSIndexScript.prototype.Zealink_Index1 = function () -{ - let data = - { - Name: '资金吸筹', Description: '资金吸筹', IsMainIndex: false, - Args: [], - Script: //脚本 -'VAR1:=REF((LOW+OPEN+CLOSE+HIGH)/4,1); \n\ -VAR2:= SMA(ABS(LOW - VAR1), 13, 1) / SMA(MAX(LOW - VAR1, 0), 10, 1);\n\ -VAR3:= EMA(VAR2, 10);\n\ -VAR4:= LLV(LOW, 33);\n\ -VAR5:= EMA(IF(LOW <= VAR4, VAR3, 0), 3) * 0.2;\n\ -主力进场: IF(VAR5 > REF(VAR5, 1), VAR5,0), COLORRED, NODRAW;\n\ -洗盘: IF(VAR5 < REF(VAR5, 1), VAR5,0), COLORYELLOW, NODRAW;\n\ -STICKLINE(VAR5> REF(VAR5, 1),0, VAR5, 20, 0), COLORRED;\n\ -STICKLINE(VAR5 < REF(VAR5, 1), 0, VAR5, 20, 0), COLORYELLOW;' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index2 = function () -{ - let data = - { - Name: '牛熊区间', Description: '牛熊区间', IsMainIndex: false,YSpecificMaxMin:{Max:100,Min:1,Count:4},YSplitScale:[1,50,100], - Args: [], - Script: //脚本 -'短高H:=(20*H+19*REF(H,1)+18*REF(H,2)+17*REF(H,3)+16*REF(H,4)+15*REF(H,5)+14*REF(H,6)\n\ -+ 13 * REF(H, 7) + 12 * REF(H, 8) + 11 * REF(H, 9) + 10 * REF(H, 10) + 9 * REF(H, 11) + 8 * REF(H, 12)\n\ -+ 7 * REF(H, 13) + 6 * REF(H, 14) + 5 * REF(H, 15) + 4 * REF(H, 16) + 3 * REF(H, 17) + 2 * REF(H, 18) +\n\ -REF(H, 20))/ 210, COLORBLUE, LINETHICK1;\n\ -短低L:= (20 * L + 19 * REF(L, 1) + 18 * REF(L, 2) + 17 * REF(L, 3) + 16 * REF(L, 4) + 15 * REF(L, 5) + 14 * REF(L, 6)\n\ -+ 13 * REF(L, 7) + 12 * REF(L, 8) + 11 * REF(L, 9) + 10 * REF(L, 10) + 9 * REF(L, 11) + 8 * REF(L, 12)\n\ -+ 7 * REF(L, 13) + 6 * REF(L, 14) + 5 * REF(L, 15) + 4 * REF(L, 16) + 3 * REF(L, 17) + 2 * REF(L, 18) +\n\ -REF(L, 20)) / 210, COLORBLUE, LINETHICK1;\n\ -D90H:= EMA(短高H, 90), COLORRED, LINETHICK1;\n\ -D90L:= EMA(短低L, 90), COLORRED, LINETHICK1;\n\ -D90差:= D90H - D90L;\n\ -D90顶:= D90H + D90差 * 2, COLORRED, LINETHICK1;\n\ -D90底:= D90L - D90差 * 2, COLORRED, LINETHICK1;\n\ -高0:= (EMA(EMA(H, 25), 25) - EMA(EMA(L, 25), 25)) * 1 + EMA(EMA(H, 25), 25), LINETHICK1, COLORWHITE;\n\ -低0:= EMA(EMA(L, 25), 25) - (EMA(EMA(H, 25), 25) - EMA(EMA(L, 25), 25)) * 1, LINETHICK1, COLORWHITE;\n\ -多头定位:= 低0 >= D90底 AND 高0 >= D90顶;\n\ -空头定位:= 高0 <= D90顶 AND 低0 <= D90底;\n\ -震荡定位:= 低0 >= D90底 AND 高0 <= D90顶;\n\ -牛市: IF(多头定位 == 1, 100, 1), COLORRED, NODRAW;\n\ -熊市: IF(空头定位 == 1, 100, 1), COLORGREEN, NODRAW;\n\ -震荡: IF(震荡定位 == 1, 100, 1), COLORGRAY, NODRAW;\n\ -STICKLINE(多头定位 == 1, 100, 1, 100, 0), COLORRED;\n\ -STICKLINE(空头定位 == 1, 100, 1, 100, 0), COLORGREEN;\n\ -STICKLINE(震荡定位 == 1, 100, 1, 100, 0), COLORGRAY;' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index3 = function () -{ - let data = - { - Name: '持仓信号', Description: '持仓信号', IsMainIndex: true, - Args: [], - Script: //脚本 -'买线:=EMA(C,2);\n\ -卖线:=EMA(SLOPE(C,30)*5+C,20); \n\ -BU:=CROSS(买线,卖线);\n\ -SEL:=CROSS(卖线,买线);\n\ -\n\ -STICKLINE(买线>=卖线 AND CLOSE>OPEN,LOW,HIGH,0,1),COLORRED;\n\ -STICKLINE(买线>=卖线 AND CLOSE=卖线 AND CLOSE>OPEN,CLOSE,OPEN,50,1),COLORRED;\n\ -STICKLINE(买线>=卖线 AND CLOSEOPEN,LOW,HIGH,0,1),COLORGREEN;\n\ -STICKLINE(买线<卖线 AND CLOSEOPEN,CLOSE,OPEN,50,1),COLORGREEN;\n\ -\n\ -HHJSJDA:=(3*CLOSE+OPEN+LOW+HIGH)/6;\n\ -HHJSJDB:(19*HHJSJDA+19*REF(HHJSJDA,1)+18*REF(HHJSJDA,2)+17*REF(HHJSJDA,3)+16*REF(HHJSJDA,4)+15*REF(HHJSJDA,5)+14*REF(HHJSJDA,6)\n\ -+13*REF(HHJSJDA,7)+12*REF(HHJSJDA,8)+11*REF(HHJSJDA,9)+10*REF(HHJSJDA,10)+9*REF(HHJSJDA,11)+8*REF(HHJSJDA,12)+7*REF(HHJSJDA,13)+6*REF(HHJSJDA,14)+5*REF(HHJSJDA,15)+4*REF(HHJSJDA,16)+3*REF(HHJSJDA,17)+2*REF\n\ -(HHJSJDA,20)+REF(HHJSJDA,19))/210,COLORYELLOW;\n\ -HHJSJDC:MA(HHJSJDB,5),COLORRED;\n\ -\n\ -SVAR11:=HHV(HIGH,34);\n\ -SVAR14:=CLOSE-REF(CLOSE,1);\n\ -SVAR15:=MAX(SVAR14,0);\n\ -SVAR16:=ABS(SVAR14);\n\ -SVAR17:=SMA(SVAR15,7,1)/SMA(SVAR16,7,1)*100;\n\ -SVAR18:=SMA(SVAR15,13,1)/SMA(SVAR16,13,1)*100;\n\ -SVAR19:=BARSCOUNT(CLOSE);\n\ -SVAR20:=SMA(MAX(SVAR14,0),6,1)/SMA(ABS(SVAR14),6,1)*100;\n\ -SVAR21:=(-200)*(HHV(HIGH,60)-CLOSE)/(HHV(HIGH,60)-LLV(LOW,60))+100;\n\ -SVAR1A:=(CLOSE-LLV(LOW,15))/(HHV(HIGH,15)-LLV(LOW,15))*100;\n\ -SVAR1B:=SMA((SMA(SVAR1A,4,1)-50)*2,3,1);\n\ -SVAR1C:=(INDEXC-LLV(INDEXL,14))/(HHV(INDEXH,14)-LLV(INDEXL,14))*100;\n\ -SVAR1D:=SMA(SVAR1C,4,1);\n\ -SVAR1E:=SMA(SVAR1D,3,1);\n\ -SVAR1F:=(HHV(HIGH,30)-CLOSE)/CLOSE*100;\n\ -SVAR22:=SVAR20<=25 AND SVAR21<-95 AND SVAR1F>20 AND SVAR1B<-30 AND SVAR1E<30 AND SVAR11-CLOSE>=-0.25 AND SVAR17<22 AND SVAR18<28 AND SVAR19>50;\n\ -BUY3:=CROSS(SVAR22,0.5) AND COUNT(SVAR22==1,10)==1;\n\ -\n\ -SVARF:=LOW*0.9;\n\ -SVAR10X:=100-3*SMA((OPEN-LLV(LOW,75))/(HHV(HIGH,75)-LLV(LOW,75))*100,20,1)+2*SMA(SMA((OPEN-LLV(LOW,75))/(HHV(HIGH,75)-LLV(LOW,75))*100,20,1),15,1);\n\ -SVAR11X:=SVARFREF(VOL,1) AND CLOSE>REF(CLOSE,1);\n\ -BUY2:=SVAR11X AND COUNT(SVAR11X,30)==1;\n\ -\n\ -VAR1:=(CLOSE+HIGH+LOW+OPEN)/4;\n\ -VAR2:=SUMBARS(VOL,CAPITAL);\n\ -VAR3:=HHV(VAR1,VAR2);\n\ -VAR4:=LLV(VAR1,VAR2);\n\ -VAR5:=(2*VAR1-VAR4-REF(VAR4,1))/(VAR3-VAR4);\n\ -VAR6:=(VAR1-VAR4)/(VAR3-VAR4);\n\ -VAR7:=IF(VAR1<=VAR4,VAR5*60,VAR6*60);\n\ -VAR8:=600*(EMA(CLOSE,3)-EMA(LOW,30))/EMA(LOW,30);\n\ -VAR9:=EMA(VAR8,7);\n\ -VARC:=HHV(HIGH,9)-LLV(LOW,9);\n\ -VARD:=HHV(HIGH,9)-CLOSE;\n\ -VARE:=CLOSE-LLV(LOW,9);\n\ -VARF:=VARD/VARC*100-70;\n\ -VAR10:=(CLOSE-LLV(LOW,60))/(HHV(HIGH,60)-LLV(LOW,60))*100;\n\ -VAR11:=(2*CLOSE+HIGH+LOW)/4;\n\ -VAR12:=SMA(VARE/VARC*100,3,1);\n\ -VAR13:=LLV(LOW,34);\n\ -VAR14:=SMA(VAR12,3,1)-SMA(VARF,9,1);\n\ -VAR15:=IF(VAR14>100,VAR14-100,0);\n\ -VAR16:=HHV(HIGH,34);\n\ -VAR17:=EMA((VAR11-VAR13)/(VAR16-VAR13)*100,8);\n\ -VAR18:=EMA(VAR17,5);\n\ -BUY:=STICKLINE(VAR17-VAR18>0,VAR17,VAR18,8,1),COLORRED;\n\ -SELL:=STICKLINE(VAR17-VAR18<0,VAR17,VAR18,8,1),COLORGREEN;\n\ -BUY1:=VAR17>VAR18 AND REF(VAR17,1)REF(VAR18,1);\n\ -\n\ -短高H:=(20*H+19*REF(H,1)+18*REF(H,2)+17*REF(H,3)+16*REF(H,4)+15*REF(H,5)+14*REF(H,6)\n\ -+13*REF(H,7)+12*REF(H,8)+11*REF(H,9)+10*REF(H,10)+9*REF(H,11)+8*REF(H,12)\n\ -+7*REF(H,13)+6*REF(H,14)+5*REF(H,15)+4*REF(H,16)+3*REF(H,17)+2*REF(H,18)+\n\ -REF(H,20))/210,COLORBLUE,LINETHICK1;\n\ -短低L:=(20*L+19*REF(L,1)+18*REF(L,2)+17*REF(L,3)+16*REF(L,4)+15*REF(L,5)+14*REF(L,6)\n\ -+13*REF(L,7)+12*REF(L,8)+11*REF(L,9)+10*REF(L,10)+9*REF(L,11)+8*REF(L,12)\n\ -+7*REF(L,13)+6*REF(L,14)+5*REF(L,15)+4*REF(L,16)+3*REF(L,17)+2*REF(L,18)+\n\ -REF(L,20))/210,COLORBLUE,LINETHICK1;\n\ -D90H:=EMA(短高H,90),COLORRED,LINETHICK1;\n\ -D90L:=EMA(短低L,90),COLORRED,LINETHICK1;\n\ -D90差:=D90H-D90L;\n\ -D90顶:=D90H+D90差*2,COLORRED,LINETHICK1;\n\ -D90底:=D90L-D90差*2,COLORRED,LINETHICK1;\n\ -高0:=(EMA(EMA(H,25),25)-EMA(EMA(L,25),25))*1+EMA(EMA(H,25),25),LINETHICK1,COLORWHITE;\n\ -低0:=EMA(EMA(L,25),25)-(EMA(EMA(H,25),25)-EMA(EMA(L,25),25))*1,LINETHICK1,COLORWHITE;\n\ -多头定位:=低0>=D90底 AND 高0>=D90顶;\n\ -空头定位:=高0<=D90顶 AND 低0<=D90底;\n\ -震荡定位:=低0>=D90底 AND 高0<=D90顶;\n\ -\n\ -牛市:=多头定位==1;\n\ -熊市:=空头定位==1;\n\ -震荡:=震荡定位==1;\n\ -\n\ -非牛市:=熊市 OR 震荡;\n\ -非熊市:=牛市 OR 震荡;\n\ -\n\ -BUY11:=BUY1 AND 非熊市;\n\ -SELL11:=SELL1 AND 震荡定位==0;\n\ -\n\ -BUY111:=BUY11 AND COUNT(BUY11,10)<2;\n\ -BUY0:=BUY111 AND COUNT(BUY111,21)==1;\n\ -SELL111:=SELL11 AND COUNT(SELL11,10)<2;\n\ -SELL0:=SELL111 AND COUNT(SELL111,10)==1;\n\ -\n\ -XK1:=EMA(100*(CLOSE-LLV(LOW,34))/(HHV(HIGH,34)-LLV(LOW,34)),3)/4;\n\ -上穿:=REF(XK1,1)<5 AND XK1>=5;\n\ -BUY4:=上穿 AND COUNT(XK1<2,12)<1;\n\ -\n\ -SELL2:=REF(XK1,1)<=22.5 AND XK1>22.5 AND COUNT(REF(XK1,1)>=22.5 AND XK1<22.5,5)>0;\n\ -SELL3:=REF(XK1,1)>=21.5 AND XK1<21.5 AND COUNT(REF(XK1,1)>=22.5 AND XK1<22.5,12)>1;\n\ -SELL4:=SELL2 OR SELL3 AND COUNT((SELL2 OR SELL3)==1,5)==1;\n\ -\n\ -SUPERDRAWTEXT(BUY0,L,"机会",2,10),COLORRED;\n\ -SUPERDRAWTEXT(SELL0,H,"风险",1,10),COLORGREEN;\n\ -SUPERDRAWTEXT(BUY2,L,"机会",2,10),COLORRED;\n\ -SUPERDRAWTEXT(BUY4,L,"机会",2,10),COLORRED;\n\ -SUPERDRAWTEXT(SELL4,H,"风险",1,10),COLORGREEN;' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index4 = function () -{ - let data = - { - Name: '股东实际增减持', Description: '股东实际增减持', IsMainIndex: false, FloatPrecision:0, - Args: [], - Script: //脚本 -'增持:NEWS(4),NODRAW,COLORRED;\n\ -减持:NEWS(5),NODRAW,COLORGREEN;\n\ -STICKLINE(增持>0,0,增持,1,0),COLORRED;\n\ -STICKLINE(减持<0,0,减持,1,0),COLORGREEN;' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index5 = function () -{ - let data = - { - Name: '大宗交易', Description: '大宗交易', IsMainIndex: false, FloatPrecision: 0, - Args: [], - Script: //脚本 - '交易次数:NEWS(7);' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index6 = function () -{ - let data = - { - Name: '信托持股', Description: '信托持股', IsMainIndex: false, FloatPrecision: 0, - Args: [], - Script: //脚本 - '家数:NEWS(6);' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index7 = function () -{ - let data = - { - Name: '官网新闻', Description: '官网新闻', IsMainIndex: false, FloatPrecision: 0, - Args: [], - Script: //脚本 - '个数:NEWS(8);' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index8 = function () -{ - let data = - { - Name: '高管要闻', Description: '高管要闻', IsMainIndex: false, FloatPrecision: 0, - Args: [], - Script: //脚本 - '个数:NEWS(9);' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index9 = function () -{ - let data = - { - Name: '股权质押', Description: '股权质押', IsMainIndex: false, FloatPrecision: 0, - Args: [], - Script: //脚本 - '次数:NEWS(10);' - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index10 = function () -{ - let data = - { - Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true, FloatPrecision: 0, - Args: [], - Script: //脚本 -"JJ:=(CLOSE+HIGH+LOW)/3; \n\ -A:=EMA(JJ,10); \n\ -B:=REF(A,1);\n\ -M1:=EMA(CLOSE,3);\n\ -M2:=EMA(CLOSE,8); \n\ -M3:=EMA(M2,13); \n\ -M4:=EMA(M2,55); \n\ -B1:=A>B AND REF(A,1)REF(B,1);\n\ -INDEXCLOSE:INDEXC,EXDATA;\n\ -INDEXOPEN:INDEXO,EXDATA;\n\ -DRAWICON(REF(B1,1),L*0.97,13);\n\ -DRAWICON(REF(S1,1),H*1.03,14);" - }; - - return data; -} - -JSIndexScript.prototype.Zealink_Index11 = function () -{ - let data = - { - Name: '操盘BS点', Description: '操盘BS点', IsMainIndex: true, FloatPrecision: 0, - Args: [], - Script: //脚本 -"JJ:=(CLOSE+HIGH+LOW)/3;\n\ -A:=EMA(JJ,10);\n\ -B:=REF(A,1);\n\ -M1:=EMA(CLOSE,3);\n\ -M2:=EMA(CLOSE,8); \n\ -M3:=EMA(M2,13);\n\ -M4:=EMA(M2,55);\n\ -持股区域:=STICKLINE(A>B,A,B,2,0),COLORYELLOW; \n\ -持币区域:=STICKLINE(A100,VR14-100,0);\n\ -VR16:=HHV(H,34);\n\ -VR17:=EMA((VR11-VR13)/(VR16-VR13)*100,8);\n\ -VR18:=EMA(VR17,5);\n\ -\n\ -B1:=A>B AND REF(A,1)REF(B,1);\n\ -\n\ -B9:=BARSLAST(REF(B1,1) AND (REF(VR17>VR18,1) OR MIN(VR17,VR18)>REF(MAX(VR17,VR18),1)));\n\ -S9:=BARSLAST(REF(S1,1) AND (REF(VR17VR18,1) OR MIN(VR17,VR18)>REF(MAX(VR17,VR18),1)) AND REF(B9,2)>=S9,L*0.97,13);\n\ -DRAWICON(REF(S1,1) AND (REF(VR17=B9,H*1.03,14);\n\ -\n\ -DRAWKLINE_IF(VR17>VR18,HIGH,CLOSE,LOW,OPEN),COLORRED;\n\ -DRAWKLINE_IF(VR17=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 (option.KLine.KLineDoubleClick==false) chart.MinuteDialog=this.MinuteDialog=null; - if (option.KLine.IsShowTooltip==false) chart.IsShowTooltip=false; + if (IFrameSplitOperator.IsBool(item.IsShowTooltip)) chart.IsShowTooltip=item.IsShowTooltip; + if (IFrameSplitOperator.IsBool(item.IsShowKLineDivTooltip)) chart.IsShowKLineDivTooltip=item.IsShowKLineDivTooltip; 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 }; + 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; @@ -4558,6 +4344,22 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) } } + if (chart.ClassName=="KLineChartContainer") + { + if (!option.DragSelectRect) + { + option.DragSelectRect={ Enable:true }; //默认开启区间选中画布 + } + + if (option.DragSelectRect) + { + var zindex=10; + var item=option.DragSelectRect; + if (IFrameSplitOperator.IsNumber(item.ZIndex)) zindex=item.ZIndex; + if (item.Enable) this.CreateExtraCanvasElement(JSChart.RectDragCanvasKey, { ZIndex:zindex }); //创建独立的区间选择画布 + } + } + //创建子窗口 chart.Create(option.Windows.length, option); @@ -4565,6 +4367,7 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) this.AdjustChartBorder(chart); + if (option.KLine) { if (option.KLine.PageSize > 0) //一屏显示的数据个数 @@ -4635,6 +4438,8 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitType=item.SplitType; chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultSplitType=item.SplitType; } + if (IFrameSplitOperator.IsNumber(item.FilterType)) subFrame.YSplitOperator.FilterType=item.FilterType; + if (!isNaN(item.Height)) chart.Frame.SubFrame[i].Height = item.Height; if (item.IsShowLeftText===false || item.IsShowLeftText===true) { @@ -4646,8 +4451,8 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) chart.Frame.SubFrame[i].Frame.IsShowYText[1]=item.IsShowRightText; chart.Frame.SubFrame[i].Frame.YSplitOperator.IsShowRightText=item.IsShowRightText; //显示右边刻度 } - if (item.TopSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.TopSpace=item.TopSpace; - if (item.BottomSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace=item.BottomSpace; + if (item.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 (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; @@ -4674,9 +4479,17 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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; + 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) @@ -4709,7 +4522,7 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) } //创建子窗口的指标 - let scriptData = new JSIndexScript(); + var scriptData = new JSIndexScript(); if (option.ColorIndex) //五彩K线 { @@ -4764,17 +4577,13 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) } else { + var scriptData = new JSIndexScript(); let indexInfo = scriptData.Get(item.Index); if (!indexInfo) continue; - - if (item.Lock) indexInfo.Lock=item.Lock; + JSIndexScript.ModifyAttribute(indexInfo, item); indexInfo.ID=item.Index; - var args=indexInfo.Args; - if (item.Args) args=item.Args; - if (item.IsShortTitle) indexInfo.IsShortTitle=item.IsShortTitle; - if (item.TitleFont) indexInfo.TitleFont=item.TitleFont; - if (IFrameSplitOperator.IsBool(item.IsSync)) indexInfo.IsSync=item.IsSync; - chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, args,indexInfo); //脚本执行 + + chart.WindowIndex[i] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args,indexInfo); //脚本执行 if (item.StringFormat>0) chart.WindowIndex[i].StringFormat=item.StringFormat; if (item.FloatPrecision>=0) chart.WindowIndex[i].FloatPrecision=item.FloatPrecision; } @@ -4794,11 +4603,13 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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)) chart.Frame.SubFrame[i].Frame.IsShowTitleArrow=item.IsShowTitleArrow; + 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) { @@ -4840,10 +4651,9 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) //创建改参数div chart.ModifyIndexDialog=this.ModifyIndexDialog; chart.ChangeIndexDialog=this.ChangeIndexDialog; - chart.MinuteDialog=this.MinuteDialog; //右键菜单 - if (option.IsShowRightMenu==true) chart.RightMenu=new KLineRightMenu(this.DivElement); + if (IFrameSplitOperator.IsBool(option.IsShowRightMenu)) chart.IsShowRightMenu=option.IsShowRightMenu; if (option.KLine) //k线图的属性设置 { @@ -4852,7 +4662,6 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) if (option.KLine.Period>=0) chart.Period=option.KLine.Period; if (option.KLine.MaxRequestDataCount>0) chart.MaxRequestDataCount=option.KLine.MaxRequestDataCount; if (option.KLine.Info && option.KLine.Info.length>0) chart.SetKLineInfo(option.KLine.Info,false); - if (option.KLine.KLineDoubleClick==false) chart.MinuteDialog=this.MinuteDialog=null; if (option.KLine.PageSize>0) chart.PageSize=option.KLine.PageSize; if (option.KLine.IsShowTooltip==false) chart.IsShowTooltip=false; } @@ -4946,6 +4755,8 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) chart.ModifyIndexDialog=this.ModifyIndexDialog; chart.ChangeIndexDialog=this.ChangeIndexDialog; + 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; @@ -4958,6 +4769,7 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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) { @@ -5031,6 +4843,22 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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); @@ -5061,7 +4889,7 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) if (option.MinuteInfo) chart.CreateMinuteInfo(option.MinuteInfo); - if (option.IsShowRightMenu==true) chart.RightMenu=new MinuteRightMenu(this.DivElement); + if (IFrameSplitOperator.IsBool(option.IsShowRightMenu)) chart.IsShowRightMenu=option.IsShowRightMenu; if (IFrameSplitOperator.IsNumber(option.DayCount)) chart.DayCount=option.DayCount; @@ -5091,6 +4919,8 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) chart.Frame.SubFrame[i].Frame.YSplitOperator.SplitType=item.SplitType; chart.Frame.SubFrame[i].Frame.YSplitOperator.DefaultSplitType=item.SplitType; } + if (IFrameSplitOperator.IsNumber(item.FilterType)) subFrame.YSplitOperator.FilterType=item.FilterType; + if (item.IsShowLeftText==false) { chart.Frame.SubFrame[i].Frame.IsShowYText[0]=item.IsShowLeftText; @@ -5113,13 +4943,14 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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; - if (item.BottomSpace>=0) chart.Frame.SubFrame[i].Frame.ChartBorder.BottomSpace=item.BottomSpace; + 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(); @@ -5181,7 +5012,8 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) if (item.TimeFormat) chart.TitlePaint[0].TimeFormat=item.TimeFormat; } - if (option.CorssCursorTouchEnd===true) chart.CorssCursorTouchEnd = option.CorssCursorTouchEnd; + 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个指标窗口设置 @@ -5235,13 +5067,16 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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)) chart.Frame.SubFrame[index].Frame.IsShowTitleArrow=item.IsShowTitleArrow; + 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; } } @@ -5422,6 +5257,8 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) } + /*废弃 + //统一全部使用 MinuteChartContainer //历史分钟走势图 this.CreateHistoryMinuteChartContainer=function(option) { @@ -5483,6 +5320,7 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) return chart; } + */ this.CreateKLineTrainChartContainer=function(option) { @@ -5610,7 +5448,7 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) if (IFrameSplitOperator.IsNonEmptyArray(option.Windows)) { //创建子窗口的指标 - let scriptData = new JSIndexScript(); + for(var i=0;i0) chart.AutoUpdateFrequency=option.AutoUpdateFrequency; + + //内置菜单 + if (option.EnablePopMenuV2===true) chart.InitalPopMenu(); + + //画图工具 + if (option.EnableDrawToolDialogV2===true) chart.InitalDrawToolDialog(); + if (option.EnableModifyDrawDialogV2===true) chart.InitalModifyDrawDialog(); + //注册事件 if (option.EventCallback) { @@ -5811,19 +5657,19 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) this.DivElement.JSChart=this; //div中保存一份 this.JSChartContainer.Draw(); } + } - if (IFrameSplitOperator.IsBool(option.CheckLatestVerion) && option.CheckLatestVerion==false) - { + this.CreateResizeListener=function() + { + this.ResizeListener = new ResizeObserver((entries)=>{ this.OnDivResize(entries); }); + this.ResizeListener.observe(this.DivElement); + } - } - else if (JSChart.LastVersion==null) - { - if (chart && typeof(chart.GetLatestVersion)=='function') - { - //由于域名都要备案,获取最新版本接口停止使用 - //chart.GetLatestVersion(); - } - } + this.OnDivResize=function(entries) + { + JSConsole.Chart.Log("[JSChart::OnDivResize] entries=", entries); + + this.OnSize( {Type:1} ); } //创建工具条 @@ -6000,12 +5846,6 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) } } - this.ChangMainDataControl=function(dataControl) - { - if (this.JSChartContainer && typeof(this.JSChartContainer.SetMainDataConotrl)=='function') - this.JSChartContainer.SetMainDataConotrl(dataControl); - } - this.AddOverlayIndex=function(obj) //{WindowIndex:窗口ID, IndexName:指标ID, Identify:叠加指标ID(可选), API} { if (this.JSChartContainer && typeof(this.JSChartContainer.AddOverlayIndex)=='function') @@ -6258,11 +6098,40 @@ function JSChart(divElement, bOffscreen, bCacheCanvas) 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) @@ -6463,6 +6332,12 @@ JSChart.ToFixedRect=function(value) return ToFixedRect(value); } +JSChart.GetScrollPosition=function() +{ + return GetScrollPosition(); +} + + var JSCHART_EVENT_ID= @@ -6623,6 +6498,35 @@ var JSCHART_EVENT_ID= 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_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, //自定义分时图背景颜色 } var JSCHART_OPERATOR_ID= @@ -6650,6 +6554,7 @@ var JSCHART_OPERATOR_ID= OP_SCROOLBAR_SLIDER_CHANGED:15, //滑块变动 OP_GOTO:16, //移动到某一个天或某一个分钟 + OP_GOTO_BY_DATAINDEX:17, //的移动到某一个数据起始位置 } var JSCHART_DRAG_ID= @@ -6735,6 +6640,67 @@ var JSCHART_WORKER_MESSAGE_ID= 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_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, //报价列表 筛选 +} + function PhoneDBClick() { @@ -6811,10 +6777,12 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) 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="数据加载中"; //下载数据提示信息 @@ -6886,19 +6854,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.Tooltip.id=Guid(); uielement.parentNode.appendChild(this.Tooltip); this.IsShowTooltip=true; //是否显示K线tooltip - - //区间选择 - this.SelectRect=document.createElement("div"); - this.SelectRect.className="jschart-selectrect"; - this.SelectRect.style.background=g_JSChartResource.SelectRectBGColor; - this.SelectRect.style["pointer-events"]="none"; - //this.SelectRect.style.opacity=g_JSChartResource.SelectRectAlpha; - this.SelectRect.id=Guid(); - this.SelectRect.oncontextmenu=function() { return false; }; //屏蔽选中区域系统右键菜单 - uielement.parentNode.appendChild(this.SelectRect); - - //区间选择右键菜单 - this.SelectRectRightMenu; + this.TooltipCache={ Type:null, IsShow:false, X:null, Y:null, Data:null, InnerHTML:null }; //缓存tooltip数据 //坐标轴风格方法 double-更加数值型分割 price-更加股票价格分割 this.FrameSplitData=new Map(); @@ -6914,6 +6870,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) 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: } @@ -6939,7 +6896,8 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) { IsValueFullRange:false , IsDisplayLatest:false, - SelectedBorder:{ Mode:0, SelFrame:0 } //边框选中模式 Mode:0=禁用 1=右侧标记选中 2=指标窗口标记选中 + SelectedBorder:{ Mode:0, SelFrame:0 }, //边框选中模式 Mode:0=禁用 1=右侧标记选中 2=指标窗口标记选中 + SelectedXBorder: { Mode:0, Date:null } //X边框选中模式 Mode:0=禁用 分时图图有效 //XDateFormat (多日分时图x轴底部日期格式) }; @@ -6958,12 +6916,91 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.StockCache={ Data:null }; //扩展数据缓存数据 + this.JSPopMenu; //内置菜单 + this.IsShowRightMenu=true; //显示右键菜单 + + this.DialogDrawTool; //画图工具 + this.DialogModifyDraw; //画图修改 + 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.InitalModifyDrawDialog=function() + { + if ( this.DialogModifyDraw) return; + + this.DialogModifyDraw=new JSDialogModifyDraw(); + this.DialogModifyDraw.Inital(this); + this.DialogModifyDraw.Create(); + } + + 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(); + } + //obj={ Element:, Canvas: } this.SetCorssCursorElement=function(obj) { @@ -7013,61 +7050,10 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) { this.IsDestroy=true; this.StopAutoUpdate(); - - if (this.GetLatestVersionTimer!=null) - { - clearTimeout(this.GetLatestVersionTimer); - this.GetLatestVersionTimer=null; - } } this.ChartDestory=this.ChartDestroy; //老版本写错了,需要兼容下 - - this.GetLatestVersionTimer=null; //获取最新版本 - this.GetLatestVersion=function() - { - if (this.GetLatestVersionTimer!=null) - { - clearTimeout(this.GetLatestVersionTimer); - this.GetLatestVersionTimer=null; - } - - var roundeTime=Math.floor(Math.random()*50); - var waittimer=1000*60*3+(roundeTime*1000); - var value="aHR0cHM6Ly9ocWNoYXJ0LnplYWxpbmsuY29tL2FwaS9HZXRWZXJzaW9u"; - JSConsole.Chart.Log("[JSChartContainer::GetLatestVersion] wait for get hqchart latest version. ",waittimer); - this.GetLatestVersionTimer = setTimeout(()=> - { - var width=0, height=0; - if (this.Frame && this.Frame.ChartBorder) - { - width=this.Frame.ChartBorder.GetChartWidth(); - height=this.Frame.ChartBorder.GetChartHeight(); - } - - var url=`${atob(value)}?width=${width}&height=${height}&type=h5`; - - if (JSChart.LastVersion!=null) return; //只请求一次 - - JSNetwork.HttpRequest({ - url: url, - type:"get", - dataType: "json", - async:true, - success:function(data) - { - JSConsole.Chart.Log("[JSChartContainer::GetLatestVersion] hqchart latest version. ",data); - JSChart.LastVersion=data; - }, - error:function(request, textStatus, errorThrown) - { - JSConsole.Chart.Log("[JSChartContainer::GetLatestVersion] Get HQChart latest version failed.", request); - } - }); - }, waittimer); - } - //设置焦点 this.SetFocus=function() { @@ -7183,6 +7169,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) 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; @@ -7377,6 +7364,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (this.TryClickButton(x,y,e)) { + this.IsOnTouch=false; return; } @@ -7392,13 +7380,30 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } } + 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; } @@ -7409,7 +7414,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } this.HideSelectRect(); - if (this.SelectRectRightMenu) this.SelectRectRightMenu.Hide(); + this.ClearDragSelectRect(); if (this.ChartPictureMenu) this.ChartPictureMenu.Hide(); var paint=this.GetRectSelectPaint(); @@ -7541,7 +7546,13 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) drawPictrueData.Y=(e.clientY-this.UIElement.getBoundingClientRect().top)*pixelTatio; if (this.GetChartDrawPictureByPoint(drawPictrueData)) { - if (drawPictrueData.ChartDrawPicture.EnableMove==true) + if (this.EnableEraseChartDrawPicture) //擦掉画线 + { + this.CurrentChartDrawPicture=null; + this.SelectChartDrawPicture=null; + this.ClearChartDrawPicture(drawPictrueData.ChartDrawPicture); + } + else { this.UpDownDrag=null; //画图优先 this.CurrentChartDrawPicture=drawPictrueData.ChartDrawPicture; @@ -7554,19 +7565,16 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (bDraw) this.Draw(); - drawPictrueData.ChartDrawPicture.Status=20; + 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}}; } - else - { - this.CurrentChartDrawPicture=null; - this.SelectChartDrawPicture=null; - } - + var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_DRAWPICTURE); //选中画图工具事件 if (event && event.Callback) { @@ -7661,6 +7669,10 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) else this.DrawDynamicInfo(); } + else if (bRedraw) + { + this.Draw(); + } else if (bDrawDynamicInfo) { this.DrawDynamicInfo(); @@ -7669,6 +7681,9 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } } + + if (!this.SelectChartDrawPicture) this.CloseModifyDrawDialog(); //当前没有选中画图 隐藏画图修改框 + document.onmousemove=(e)=>{ this.DocOnMouseMove(e); } document.onmouseup=(e)=> { this.DocOnMouseUp(e); } @@ -7748,7 +7763,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) var sendData={X:x, Y:y, e:e, ChartDrag:this.CustomChartDrag, Drag:drag }; this.TryDragMove_CustomChartDrag(sendData); } - else if (this.CurrentChartDrawPicture) + else if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) @@ -7800,13 +7815,11 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (moveSetp<5 && yMoveSetp<5) return; - //this.UIElement.style.cursor="default"; this.SetCursor({Cursor:"default"}); - var x=drag.Click.X-uielement.getBoundingClientRect().left; - var y=drag.Click.Y-uielement.getBoundingClientRect().top; - var x2=e.clientX-uielement.getBoundingClientRect().left; - var y2=e.clientY-uielement.getBoundingClientRect().top; - this.ShowSelectRect(x,y,x2,y2); + 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; @@ -8018,7 +8031,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) selectData.JSChartContainer=this; selectData.Stock={Symbol:this.Symbol, Name:this.Name}; - if (!this.BorderDrag && this.GetSelectRectData(selectData)) + if (this.ChartDragSelectRect.Enable && !this.BorderDrag && this.GetSelectRectData(selectData)) { var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_SELECT_RECT); var paint=this.GetRectSelectPaint(); @@ -8029,7 +8042,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) { X:drag.LastMove.X-uielement.getBoundingClientRect().left, Y:drag.LastMove.Y-uielement.getBoundingClientRect().top, - SelectData:selectData, //区间选择的数据 + SelectData:selectData, //区间选择的数据 RectSelectPaint:paint, //区间选择背景 IsShowMenu:true, e,e @@ -8045,17 +8058,19 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } else { - if (isShowMenu && this.SelectRectRightMenu) + if (isShowMenu) { - e.data= - { + var data= + { Chart:this, X:drag.LastMove.X-uielement.getBoundingClientRect().left, Y:drag.LastMove.Y-uielement.getBoundingClientRect().top, SelectData:selectData, //区间选择的数据 RectSelectPaint:paint //区间选择背景 }; - this.SelectRectRightMenu.DoModal(e); + + e.data=data; + this.PopupSelectRectMenuV2(data, e); } } } @@ -8078,6 +8093,13 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) 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; @@ -8290,6 +8312,12 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) return null; } + //扩展图形支持tooltip外部接口 + this.PtInExtendChartPaintTooltip=function(x,y,tooltip) + { + return null; + } + this.TryClickPaintEvent=function(eventID, ptClick, e) { var event=this.GetEventCallback(eventID); @@ -8393,6 +8421,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) { clearTimeout(this.DragTimer); this.DragTimer=null; + this.IsPress=false; } } @@ -8430,6 +8459,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; + this.IsPress=false; this.IsOnTouch=true; this.TouchDrawCount=0; this.PhonePinch=null; @@ -8508,6 +8538,8 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) 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; @@ -8521,7 +8553,11 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) { this.SetChartDrawPictureFirstPoint(drag.Click.X,drag.Click.Y,true); //只有1个点 直接完成 - if (this.FinishChartDrawPicturePoint()) this.DrawDynamicInfo({Corss:false, Tooltip:false}); + if (this.FinishChartDrawPicturePoint()) + { + if (drawPicture.IsDrawMain) this.Draw(); + else this.DrawDynamicInfo( {Corss:false, Tooltip:false} ); + } } if (e.cancelable) e.preventDefault(); @@ -8534,19 +8570,27 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) var pixelTatio = GetDevicePixelRatio(); //鼠标移动坐标是原始坐标 需要乘以放大倍速 if (this.GetChartDrawPictureByPoint(drawPictrueData)) { - drawPictrueData.ChartDrawPicture.Status=20; + 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); //选中画图工具事件 + + 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; } @@ -8558,6 +8602,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) 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; @@ -8603,6 +8648,14 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } 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)) { @@ -8658,7 +8711,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) //JSConsole.Chart.Log(`[JSChartContainer::OnTouchMove] moveAngle=${moveAngle} , moveUpDown=${moveUpDown}, moveSetp=${moveSetp}`); - if (this.CurrentChartDrawPicture) + if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) @@ -9073,6 +9126,15 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } } + //清空画布 + this.ClearCanvas=function(canvas) + { + if (!canvas) return; + if (!this.UIElement) return; + + canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height); + } + this.Draw=function() { if (this.ChartCorssCursor) this.ChartCorssCursor.Status=0; @@ -9196,6 +9258,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.DrawSelectedStatus(); this.DrawSelectedBorder(); + if (this.DrawSelectedXBorder) this.DrawSelectedXBorder(); var moveonPoint=null; if (this.LastMouseStatus && this.LastMouseStatus.MoveOnPoint) moveonPoint=this.LastMouseStatus.MoveOnPoint; @@ -9313,10 +9376,13 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) var item=this.ChartDrawPicture[i]; if (item.IsDrawFirst) continue; if (item.IsDrawMain && item.IsDrawMain()) continue; + if (this.SelectChartDrawPicture && this.SelectChartDrawPicture.Guid==item.Guid) continue; //当前选中在最后画 item.Draw(); } + if (this.SelectChartDrawPicture) this.SelectChartDrawPicture.Draw(); + if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10) { this.CurrentChartDrawPicture.Draw(); @@ -9333,6 +9399,12 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) //更新滚动条 if (typeof(this.UpdateScrollBar)=='function') this.UpdateScrollBar(); + + if (this.LastMouseStatus.MouseOnToolbar) //工具栏按钮提示信息 + { + var frame=this.LastMouseStatus.MouseOnToolbar.Frame; + if (frame && frame.DrawToolbarTooltip) frame.DrawToolbarTooltip(this.LastMouseStatus.MouseOnToolbar); + } //发送图形状态给外部 if (this.mapEvent.has(JSCHART_EVENT_ID.CHART_STATUS)) @@ -9400,7 +9472,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) var item=this.ExtendChartPaint[i]; if (item.IsCallbackDraw) { - if (["KLineYAxisBGPaint","DepthMapPaint","BackgroundPaint","MinuteBackgroundPaint"].includes(item.ClassName)) + if (["KLineYAxisBGPaint","DepthMapPaint","BackgroundPaint","MinuteBackgroundPaint", "SessionBreaksPaint"].includes(item.ClassName)) { if (item.FrameID==frame.Identify) item.Draw(); } @@ -9622,6 +9694,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.DrawSelectedStatus(); this.DrawSelectedBorder(); + if (this.DrawSelectedXBorder) this.DrawSelectedXBorder(); var moveonPoint=null; if (this.LastMouseStatus && this.LastMouseStatus.MoveOnPoint) moveonPoint=this.LastMouseStatus.MoveOnPoint; @@ -9712,14 +9785,11 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) } item.DrawStatus=drawStatus; - if (item.ClassName=="DynamicMinuteTitlePainting") - { - if (option && IFrameSplitOperator.IsNumber(option.ClientPos) && option.Point) - item.PointInfo={ ClientPos:option.ClientPos, Point:{ X:option.Point.X, Y:option.Point.Y }}; - else - item.PointInfo=null; - } - + var pointInfo=null; + if (option && IFrameSplitOperator.IsNumber(option.ClientPos) && option.Point) //当前鼠标所在位置的详细信息 包含盘前盘后 + pointInfo={ ClientPos:option.ClientPos, Point:{ X:option.Point.X, Y:option.Point.Y }}; + item.PointInfo=pointInfo; + item.Draw(moveonPoint, this.LastMouseStatus); } @@ -9738,7 +9808,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (option.Point) item.LatestPoint=option.Point; } - if (item.IsDynamic && item.DrawAfterTitle===true) item.Draw(); + if (item.IsDynamic && item.DrawAfterTitle===true) item.Draw(moveonPoint, this.LastMouseStatus); } if (this.EnableAnimation) @@ -9755,10 +9825,16 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) var item=this.ChartDrawPicture[i]; if (item.IsDrawFirst) continue; if (item.IsDrawMain && item.IsDrawMain()) continue; + if (this.SelectChartDrawPicture &&item.Guid==this.SelectChartDrawPicture.Guid) continue; //选中画图最后画 确保显示在最外面 item.Draw(moveonPoint, this.LastMouseStatus); } + if (this.SelectChartDrawPicture) + { + this.SelectChartDrawPicture.Draw(moveonPoint, this.LastMouseStatus); + } + if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10) { this.CurrentChartDrawPicture.Draw(); @@ -9874,6 +9950,9 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (this.PtInOverlayChartPaintTooltip(x,y,toolTip)) return toolTip; + + if (this.PtInExtendChartPaintTooltip(x,y,toolTip)) + return toolTip; return null; } @@ -10092,22 +10171,31 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) var drawPictrueData={}; drawPictrueData.X=x; drawPictrueData.Y=y; - if (this.GetChartDrawPictureByPoint(drawPictrueData) && - drawPictrueData.ChartDrawPicture && drawPictrueData.ChartDrawPicture.EnableMove==true) + if (this.GetChartDrawPictureByPoint(drawPictrueData) && drawPictrueData.ChartDrawPicture) { - - if (drawPictrueData.PointIndex===100) + if (this.EnableEraseChartDrawPicture) { - if (drawPictrueData.Cursor) this.SetCursor(drawPictrueData); //this.UIElement.style.cursor=drawPictrueData.Cursor; - else this.SetCursor({Cursor:"move"}); //this.UIElement.style.cursor="move"; + this.SetCursor({Cursor:"grabbing"}); } - else + else { - if (drawPictrueData.Cursor) this.SetCursor(drawPictrueData); //this.UIElement.style.cursor=drawPictrueData.Cursor - else this.SetCursor({Cursor:"pointer"}); //this.UIElement.style.cursor="pointer"; - } + 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; + bDrawPicture=true; + } + } + this.MoveOnChartDrawPicture=drawPictrueData.ChartDrawPicture; } else @@ -10302,6 +10390,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.SelectChartDrawPicture=null; if (this.ChartPictureMenu) this.ChartPictureMenu.Hide(); this.ClearChartDrawPicture(drawPicture); //删除选中的画图工具 + this.CloseModifyDrawDialog(); } else if (this.SelectedChart && this.SelectedChart.Selected.Identify) { @@ -10461,9 +10550,6 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) for(var i=0;iborderRight) x=borderRight; - if (x2>borderRight) x2=borderRight; - - if (xx2) left=x2; - if (y>y2) top=y2; + 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; + } + } - var width=Math.abs(x-x2); - var height=Math.abs(y-y2); + this.HideTooltip=function() + { + this.TooltipCache.IsShow=false; + this.TooltipCache.Type=null; + this.TooltipCache.InnerHTML=null; + this.TooltipCache.Data=null; - this.SelectRect.style.width = width+"px"; - this.SelectRect.style.height =height+"px"; - this.SelectRect.style.position = "absolute"; - this.SelectRect.style.left = left +"px"; - this.SelectRect.style.top = top +"px"; - this.SelectRect.style.display = "block"; + if (this.Tooltip.style.display!="none") this.Tooltip.style.display = "none"; } this.UpdateSelectRect=function(start,end) @@ -10888,7 +10992,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.HideSelectRect=function() { - this.SelectRect.style.display = "none"; + this.ClearDragSelectRect(); } this.ResetFrameXYSplit=function() @@ -10912,18 +11016,27 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (!subItem || !subItem.Frame) continue; var frame=subItem.Frame; + + //自定义刻度每次都调用 + frame.YCustomSplit=true; + var key=frame.Identify; var item= { ID:key, Frame:frame, ChartPaint:[] , Max:null, Min:null, OverlayFrame:[], //共享坐标 - SingleOverlay:[] //独立坐标 + SingleOverlay:[], //独立坐标 + MainOverlayFrame:[null, null], //叠加坐标在主坐标显示[0]=left [1]=right }; for(var j=0;j0) { - if (xPointcount+data.DataOffset>=data.Data.length+this.RightSpaceCount-1) return false; + if (xPointcount+data.DataOffset>=data.Data.length+this.RightSpaceCount) return false; data.DataOffset+=step; if (data.DataOffset+xPointcount>=data.Data.length+this.RightSpaceCount) @@ -11632,7 +11752,7 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (!IFrameSplitOperator.IsNumber(languageID)) { console.warn(`[JSChartContainer::SetLanguage] language=${language} error`); - return; + return; } if (this.LanguageID==languageID) return; @@ -11654,8 +11774,12 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) if (this.Frame && this.Frame.SetLanguage) this.Frame.SetLanguage(this.LanguageID); + //this.Frame.ClearYCoordinateMaxMin(); + this.ResetFrameXYSplit(); this.Frame.SetSizeChage(true); this.Draw(); + + if (this.PopMinuteChart) this.PopMinuteChart.SetLanguage(language); } this.ReloadTiltePaintResource=function(resource) //重新加载配置 @@ -11669,11 +11793,13 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) this.ReloadExtendChartPaintResource=function(resource) //扩展画法重新加载配置 { - for(var i in this.ExtendChartPaint) + for(var i=0;i=0) indexData.FloatPrecision=option.FloatPrecision; - if (option.StringFormat>0) indexData.StringFormat=option.StringFormat; - if (option.Args) indexData.Args=option.Args; - if (option.Lock) indexData.Lock=option.Lock; - } + JSIndexScript.ModifyAttribute(indexInfo, option); - this.WindowIndex[index] = new ScriptIndex(indexData.Name, indexData.Script, indexData.Args,indexData); //脚本执行 + this.WindowIndex[index] = new ScriptIndex(indexInfo.Name, indexInfo.Script, indexInfo.Args,indexInfo); //脚本执行 if (this.ClassName=="MinuteChartContainer" || this.ClassName=="MinuteChartHScreenContainer") var bindData=this.SourceData; else @@ -12340,14 +12511,19 @@ function JSChartContainer(uielement, OffscreenElement, cacheElement) //区间选择 this.GetRectSelectPaint=function() { - for(var i=0;i=this.Frame.SubFrame.length) return; + + var subFrame=this.Frame.SubFrame[windowIndex]; + if (!IFrameSplitOperator.IsNonEmptyArray(subFrame.OverlayIndex)) return; + + var aryIndexID=[]; + for(var i=0; i{ 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(); + } } function GetDevicePixelRatio() @@ -13005,11 +13791,12 @@ function GetScrollPosition() var scrollPos={}; var scrollTop=0; var scrollLeft=0; - if(document.documentElement && document.documentElement.scrollTop) + if (document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)) { scrollTop=document.documentElement.scrollTop; scrollLeft=document.documentElement.scrollLeft; - }else if(document.body) + } + else if(document.body) { scrollTop=document.body.scrollTop; scrollLeft=document.body.scrollLeft; @@ -13061,6 +13848,49 @@ 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() { @@ -13095,9 +13925,11 @@ function CoordinateInfo() this.LineDash=null; //当线段类型==2时 可以设置虚线样式 this.LineType=1; //线段类型 -1=不画线段 2=虚线, 8,9=集合竞价坐标 this.LineWidth; //线段宽度 + this.ExtendLine; //延长线长度[ ] { Width:长度 } [0]=左 [1]=右 实例: [null, { Width: 50}]; this.ExtendData; //扩展属性 //百分比 { PriceColor:, PercentageColor:, SplitColor:, Font: } //自定义刻度 { Custom:{ Position: 1=强制内部 }} + this.AreaData; //区域: { Start:, End:, BGColor:, Position:[0=左, 1=右] } } @@ -13152,6 +13984,8 @@ function ChartBorder() var item={ Left:this.Left+dayWidth*i, Right:this.Left+dayWidth*(i+1) }; item.LeftEx=item.Left+this.MultiDayMinute.Left; item.RightEx=item.Right-this.MultiDayMinute.Right; + if (i>0) item.Left+=1; //第2天的盘前 移到一个像素,跟上一天分开 + dayBorder.push(item); } @@ -13415,9 +14249,11 @@ function IChartFramePainting() 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; //客户区背景色 @@ -13434,7 +14270,8 @@ function IChartFramePainting() this.YSpecificMaxMin=null; //指定Y轴最大最小值 this.IsShowBorder = true; //是否显示边框 - this.IsShowTitleArrow=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 }; @@ -13495,6 +14332,7 @@ function IChartFramePainting() this.SizeChange=false; this.XYSplit=false; this.XSplit=false; + this.YCustomSplit=false; //自定义Y轴分割线 } this.DrawFrame=function() { } @@ -13820,6 +14658,26 @@ function IChartFramePainting() { } + + //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; + } } //空框架只画边框 @@ -13900,6 +14758,8 @@ function AverageWidthFrame() this.XTextExtend; //[0]=底部 { Align:0=默认(居中), 1=左对齐 } this.XLineExtend; //[0]=底部 { Mode:1, Color: } Mode=1 分割线 Mode=2短线 + this.FrameData={ SubFrameItem:null }; //窗口框架信息 + //画图工具刻度 this.DrawPicture={ @@ -14033,16 +14893,23 @@ function AverageWidthFrame() 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; - this.Canvas.font=this.ButtonTooltip.Font; - this.Canvas.textAlign="left"; - this.Canvas.textBaseline="middle"; + canvas.font=this.ButtonTooltip.Font; + canvas.textAlign="left"; + canvas.textBaseline="bottom"; - var textWidth=this.Canvas.measureText(text).width+8; + var mergin= this.ButtonTooltip.Mergin; + var textWidth=canvas.measureText(text).width+mergin.Left+mergin.Right; var textHeight=this.GetFontHeight(); - var bgHeight=textHeight+10; + var bgHeight=textHeight+mergin.Top+mergin.Bottom; if (mouseOnToolbar.ID=="TitleButton") { var x=mouseOnToolbar.Point.X; @@ -14068,14 +14935,33 @@ function AverageWidthFrame() if (y<0) y=border.TopEx+1; if (x+textWidth>border.ChartWidth) x=border.ChartWidth-textWidth-2; } - - - this.Canvas.fillStyle=this.ButtonTooltip.ColorBG; - this.Canvas.fillRect(x,y,textWidth,bgHeight); //画一个背景色, 不然是一个黑的背景 + 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(); - this.Canvas.fillStyle=this.ButtonTooltip.Color; - this.Canvas.fillText(text, x+4,y+bgHeight/2); + 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 是否限制在当前坐标下 @@ -14163,6 +15049,10 @@ function AverageWidthFrame() 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)= bottom - 2) { this.Canvas.textBaseline = 'bottom'; } - else if (y <= top + 2) + else if ((y-textHeight/2)<=top) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; @@ -14727,12 +15630,13 @@ function AverageWidthFrame() 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 <= top + 2) + else if (y-textHeight/2 <= top) { this.Canvas.textBaseline = 'top'; yText+=this.YTextTopOffset; @@ -14789,7 +15693,7 @@ function AverageWidthFrame() var right=border.RightEx; var pixelRatio = GetDevicePixelRatio(); //获取设备的分辨率 //JSConsole.Chart.Log('[AverageWidthFrame.DrawVertical] bottom',bottom); - if (this.ChartBorder.Bottom<=5*GetDevicePixelRatio()) return; //高度不够 不显示 + //if (this.ChartBorder.Bottom<=5*GetDevicePixelRatio()) return; //高度不够 不显示 var mapX=null; if (this.GetVerticalXCache) mapX=this.GetVerticalXCache(); @@ -14859,19 +15763,12 @@ function AverageWidthFrame() } } - if (item.BG && item.BG.Color) - { - var bgItem=item.BG; - this.Canvas.fillStyle=bgItem.Color; - var xStart=this.GetXFromIndex(bgItem.Index.Start); - var xEnd=this.GetXFromIndex(bgItem.Index.End); - var bgHeight=this.ChartBorder.Bottom; - if (IFrameSplitOperator.IsNumber(bgItem.Height)) bgHeight=bgItem.Height; - var rtBG={Left:xStart, Width:xEnd-xStart, Top:border.Bottom, Height: bgHeight }; - this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height); + if (item.BG && this.DrawDayVertical) + { + this.DrawDayVertical(item, x, border); } - if (this.VerticalInfo[i].Message[0]!=null) + if (this.VerticalInfo[i].Message[0]!=null && this.ChartBorder.Bottom>5*pixelRatio) { if (this.VerticalInfo[i].Font) this.Canvas.font=this.VerticalInfo[i].Font; @@ -15030,6 +15927,8 @@ function AverageWidthFrame() this.Canvas.font=this.DrawPicture.Font; var fontHeight=this.GetFontHeight(); + this.Canvas.textAlign="left"; + this.Canvas.textBaseline = "bottom"; if (range.X) { @@ -15055,6 +15954,7 @@ function AverageWidthFrame() { 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; @@ -15243,8 +16143,17 @@ function AverageWidthFrame() var pixelTatio = GetDevicePixelRatio(); var defaultTextHeight=18*pixelTatio; var textHeight=defaultTextHeight; - - var y = this.GetYFromData(item.Value); + var y; + + if (item.Value=="TopEx") y=border.TopEx; + else if (item.Value=="TopTitle") y=border.TopTitle; + else if (item.Value=="Top") y=border.Top; + else if (item.Value=="BottomEx") y=border.BottomEx; + else if (item.Value=="Bottom") y=border.Bottom; + else y = this.GetYFromData(item.Value); + + if (IFrameSplitOperator.IsNumber(item.YOffset)) y+=item.YOffset; + var position=0; var emptyBGColor; if (item.ExtendData && item.ExtendData.Custom) @@ -15509,7 +16418,7 @@ function AverageWidthFrame() else { var bgTop=yText-textHeight/2-1*pixelTatio; - if (i==0) + if (i==0 && textInfo.Text.length==0) { var textLeft=right; rtText.Left=textLeft; @@ -15524,6 +16433,16 @@ function AverageWidthFrame() var textLeft=right+textWidth-itemText.Width; } + if (item.ExtendLine && item.ExtendLine[1]) //右侧延长线 + { + var exLine=item.ExtendLine[1]; + if (IFrameSplitOperator.IsNumber(exLine.Width)) + { + if (i==0) this.DrawLine(right,textLeft+exLine.Width,y,item.LineColor,item.LineType,item); + textLeft+=exLine.Width; + } + } + if (emptyBGColor) { this.Canvas.fillStyle=emptyBGColor; @@ -15587,6 +16506,91 @@ function AverageWidthFrame() } } + this.DrawCustomAreaItem=function(item) //自定义Y轴区域 + { + if (!item.AreaData) return; + if (this.IsHScreen) return; //暂时不支持横屏 + + //item.AreaData; //区域: { Value[], BGColor:, Position:[0=左, 1=右] } + if (!IFrameSplitOperator.IsNonEmptyArray(item.AreaData.Value) || item.AreaData.Value.length!=2) return; + + var max=Math.max(item.AreaData.Value[0],item.AreaData.Value[1]); + var min=Math.min(item.AreaData.Value[0],item.AreaData.Value[1]); + if (min>=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; + 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; + } + + 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.Height1) + { + 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;imaxWidth) 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) return; + 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(); } @@ -16511,6 +17747,7 @@ function MinuteFrame() { case 0: case 1: + case 10://自定义的 this.DrawCustomItem(item); //自定义刻度 break; } @@ -17846,6 +19083,89 @@ function MinuteHScreenFrame() 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=0; --index) { if (yClose!=this.Data[index].Close) break; - result[index]=HistoryData.Copy(this.Data[index]); + var newItem=HistoryData.Copy(this.Data[index]); + newItem.RightSeed=seed; + result[index]=newItem; + yClose=this.Data[index].YClose; } @@ -23656,7 +25084,9 @@ function ChartData() if(yClose!=value && value!=0) seed *= yClose/value; - result[index]=HistoryData.CopyRight(this.Data[index],seed); + var newItem=HistoryData.CopyRight(this.Data[index],seed); + newItem.RightSeed=seed; + result[index]=newItem yClose=this.Data[index].YClose; } @@ -23667,11 +25097,14 @@ function ChartData() var seed=1; var close=this.Data[index].Close; result[index]=HistoryData.Copy(this.Data[index]); + result[index].RightSeed=seed; for(++index;index0) + this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); + } + + preKItemInfo=kItemInfo; } this.PtMax=ptMax; @@ -26927,6 +28404,7 @@ function ChartKLine() this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; + var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;i0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); + } + + preKItemInfo=kItemInfo; + } } this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点 @@ -27037,6 +28533,7 @@ function ChartKLine() this.ShowRange.ShowCount=xPointCount; this.DrawKRange.Start=this.Data.DataOffset; + var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;i0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); + } + + preKItemInfo=kItemInfo; + } } if (bFirstPoint==false) this.Canvas.stroke(); @@ -27103,6 +28618,7 @@ function ChartKLine() eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR); } + var preKItemInfo=null; for(var i=this.Data.DataOffset,j=0;i0) + this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value }); + } + + preKItemInfo=kItemInfo; } this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点 @@ -27472,6 +29001,11 @@ function ChartKLine() 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; @@ -27559,6 +29093,23 @@ function ChartKLine() } } + //是否是一字板 + 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) - { - if (isDrawBorder) - { - if ((dataWidth%2)!=0) dataWidth-=1; - } - - if (data.High>data.Close) //上影线 - { - if (colorData.Line) - { - this.Canvas.strokeStyle=colorData.Line.Color; - this.Canvas.beginPath(); - if (isHScreen) - { - this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x)); - this.Canvas.lineTo(ToFixedPoint(Math.max(yClose,yOpen)),ToFixedPoint(x)); - } - else - { - if (isDrawBorder) - { - 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(Math.min(yClose,yOpen))); - } - } - this.Canvas.stroke(); - } - - y=yClose; - } - else - { - y=yClose; - } - - if (isHScreen) - { - //实心 - if (!isEmptyBar && colorData.BarColor) - { - this.Canvas.fillStyle=colorData.BarColor; - if (Math.abs(yOpen-y)<1) - { - this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 - } - else - { - this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); - } - } - - if (colorData.Border) //空心 - { - if (Math.abs(yOpen-y)<1) - { - this.Canvas.fillStyle=colorData.Border.Color; - this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1 - } - else - { - this.Canvas.strokeStyle=colorData.Border.Color; - this.Canvas.beginPath(); - this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth)); - this.Canvas.stroke(); - } - } - } - else - { - - //实心 - if (!isEmptyBar && colorData.BarColor) - { - this.Canvas.fillStyle=colorData.BarColor; - if (Math.abs(yOpen-y)<1) - { - this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 - } - else - { - this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y))); - } - } - - if (colorData.Border) //空心 - { - if (Math.abs(yOpen-y)<1) - { - this.Canvas.fillStyle=colorData.Border.Color; - this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1 - } - else - { - this.Canvas.strokeStyle=colorData.Border.Color; - this.Canvas.beginPath(); - this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y)); - this.Canvas.stroke(); - } - } - } - - if (data.Open>data.Low) //下影线 - { - if (colorData.Line) - { - this.Canvas.strokeStyle=colorData.Line.Color; - this.Canvas.beginPath(); - if (isHScreen) - { - this.Canvas.moveTo(ToFixedPoint(Math.min(yClose,yOpen)),ToFixedPoint(x)); - this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x)); - } - else - { - if (isDrawBorder) - { - 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(Math.max(yClose,yOpen))); - this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow)); - } - } - this.Canvas.stroke(); - } - } - } - else - { - var lineColor; - if (isEmptyBar && colorData.Border) - { - lineColor=colorData.Border.Color; - } - else if (!isEmptyBar && colorData.BarColor) - { - lineColor=colorData.BarColor; - } - - if (lineColor) - { - this.Canvas.strokeStyle=lineColor; - 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.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); @@ -28450,6 +29808,198 @@ function ChartKLine() 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; @@ -28843,6 +30393,12 @@ function ChartKLine() 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(); @@ -28853,6 +30409,10 @@ function ChartKLine() 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=[]; @@ -28860,6 +30420,7 @@ function ChartKLine() 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线上 显示最大最小值坐标 @@ -28900,6 +30461,7 @@ function ChartKLine() { this.DrawCloseLine(); this.Canvas.restore(); + if (this.PriceGap.Enable) this.DrawPriceGap(); return; } else if (this.DrawType==2) @@ -28949,10 +30511,18 @@ function ChartKLine() { 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(); @@ -28960,13 +30530,47 @@ function ChartKLine() 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) @@ -28974,6 +30578,9 @@ function ChartKLine() 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; @@ -28981,26 +30588,32 @@ function ChartKLine() var defaultfloatPrecision=GetfloatPrecision(this.Symbol); this.Canvas.font=this.TextFont; - this.Canvas.fillStyle=this.TextColor; + 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); + //var text=ptTop.Value.toFixed(defaultfloatPrecision); if (ptTop.Align=='left') text=leftArrow+text; else text=text+rightArrow; if (ptTop.Y>(top-2)) @@ -29010,21 +30623,27 @@ function ChartKLine() } 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); + //var text=ptMin.Value.toFixed(defaultfloatPrecision); if (ptBottom.Align=='left') text=leftArrow+text; else text=text+rightArrow; if (ptBottom.Y<(bottom+1)) @@ -29038,13 +30657,15 @@ function ChartKLine() { 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 defaultfloatPrecision=GetfloatPrecision(this.Symbol); var xText=ptMax.Y; var yText=ptMax.X; if (IFrameSplitOperator.IsNumber(highYOffset)) xText+=highYOffset; @@ -29052,11 +30673,13 @@ function ChartKLine() this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); + var text=title.High; this.Canvas.font=this.TextFont; - this.Canvas.fillStyle=this.TextColor; + 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); + //var text=ptMax.Value.toFixed(defaultfloatPrecision); if (ptMax.Align=='left') text=leftArrow+text; else text=text+rightArrow; this.Canvas.fillText(text,0,0); @@ -29070,11 +30693,13 @@ function ChartKLine() this.Canvas.translate(xText, yText); this.Canvas.rotate(90 * Math.PI / 180); + var text=title.Low; this.Canvas.font=this.TextFont; - this.Canvas.fillStyle=this.TextColor; + 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); + //var text=ptMin.Value.toFixed(defaultfloatPrecision); if (ptMin.Align=='left') text=leftArrow+text; else text=text+rightArrow; this.Canvas.fillText(text,0,0); @@ -30621,6 +32246,181 @@ function ChartKLine() } } + //////////////////////////////////////////////////////////////////////////////// + //订单流样式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;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; + } + } + } } @@ -32566,6 +34578,7 @@ function ChartLine() this.LineWidth; //线段宽度 this.DrawType=0; //画图方式 0=无效数平滑 1=无效数不画断开 this.IsDotLine=false; //虚线 + this.LineDash=g_JSChartResource.DOTLINE.LineDash; this.BreakPoint; //断开的点索引 Set(); @@ -32611,7 +34624,7 @@ function ChartLine() this.Canvas.save(); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); - if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 + if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint=true; var drawCount=0; for(var i=this.Data.DataOffset,j=0;i0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; - if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 + if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint=true; var ptFirst=null;; //第1个点 @@ -32775,7 +34788,7 @@ function ChartLine() this.ClipClient(bHScreen); if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth * GetDevicePixelRatio(); this.Canvas.strokeStyle=this.Color; - if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线 + if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线 var bFirstPoint=true; var ptFirst=null;; //第1个点 @@ -33482,6 +35495,86 @@ function ChartOverlayLine() } } +//独立线段 +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() { @@ -34008,7 +36101,9 @@ function ChartPointDot() this.Draw=function() { - if (!this.IsShow || this.ChartFrame.IsMinSize) return; + if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; + if (this.IsShowIndexTitleOnly()) return; + if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { @@ -34026,6 +36121,7 @@ function ChartPointDot() 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; @@ -34215,10 +36311,11 @@ function ChartVolStick() this.DownColor=g_JSChartResource.DownBarColor; this.HistoryData; //历史数据 this.KLineDrawType=0; + this.ClassName='ChartVolStick'; - this.BarWidth; //固定宽度 目前只支持宽度为1 - + this.BarWidth; //固定宽度 目前只支持宽度为1 + this.BarType; //柱子状态 1=实心 0=空心 2=涨实跌空 如果设置了这个属性, 属性KLineDrawType无效 this.PtInChart=this.PtInBar; this.DrawSelectedStatus=this.DrawLinePoint; @@ -34248,6 +36345,8 @@ function ChartVolStick() var yBottom=this.ChartFrame.GetYFromData(0); + this.Canvas.save(); + if (dataWidth>=4 && !(this.BarWidth===1)) { yBottom=ToFixedRect(yBottom); @@ -34265,34 +36364,31 @@ function ChartVolStick() var y=this.ChartFrame.GetYFromData(value); var barColor=this.GetBarColor(kItem); var bUp=barColor.IsUp; - this.Canvas.fillStyle=barColor.Color; + var height=ToFixedRect(Math.abs(yBottom-y)>=1?yBottom-y:1);//高度调整为整数, 如果小于1, 统一使用1 y=yBottom-height; - if (this.KLineDrawType==6) //完全空心柱 + var bSolidBar=this.IsSolidBar(bUp); //实心柱子 + + if (bSolidBar) { - this.Canvas.strokeStyle=barColor.Color; - this.Canvas.beginPath(); - this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),height); - this.Canvas.stroke(); + this.Canvas.fillStyle=barColor.Color; + this.Canvas.fillRect(ToFixedRect(left),y,ToFixedRect(dataWidth),height); } - else if (bUp && (this.KLineDrawType==1 || this.KLineDrawType==2 || this.KLineDrawType==3)) //空心柱子 + else { - this.Canvas.strokeStyle=this.UpColor; + this.Canvas.strokeStyle=barColor.Color; this.Canvas.beginPath(); this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),height); this.Canvas.stroke(); } - else - { - this.Canvas.fillRect(ToFixedRect(left),y,ToFixedRect(dataWidth),height); - } } } else //太细了直接话线 { var preKItem=null; var barColor=null; + this.Canvas.linewidth=1*GetDevicePixelRatio(); for(var i=this.Data.DataOffset,j=0;idataWidth) 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() { @@ -37938,7 +40560,9 @@ function ChartBand() this.Draw=function() { - if (this.ChartFrame.IsMinSize) return; + if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return; + if (this.IsShowIndexTitleOnly()) return; + if (this.IsHideScriptIndex()) return; if (this.NotSupportMessage) { @@ -39487,7 +42111,9 @@ function ChartMultiBar() this.Draw=function() { - if (!this.IsShow || this.ChartFrame.IsMinSize) return; + 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); @@ -39664,6 +42290,8 @@ function ChartMultiLine() 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; @@ -40096,7 +42724,7 @@ function ChartMultiText() { if (IFrameSplitOperator.IsNumber(item.Time)) { - var key=`${kItem.Date}-${item.Time}`; + var key=`${item.Date}-${item.Time}`; } else { @@ -40150,17 +42778,23 @@ function ChartMultiText() { var border=this.ChartBorder.GetHScreenBorder(); var chartright=border.BottomEx; + var chartleft=border.TopEx; var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var left=this.ChartBorder.GetTop(); var right=this.ChartBorder.GetBottom(); + var top=border.RightEx; + var bottom=border.LeftEx; } else { var border=this.ChartBorder.GetBorder(); var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin; var chartright=border.RightEx; + var chartleft=border.LeftEx; var left=this.ChartBorder.GetLeft(); var right=this.ChartBorder.GetRight(); + var top=border.TopEx; + var bottom=border.BottomEx; } for(var i=this.Data.DataOffset,j=0;i=right) + if (x+textWidth/2>=chartright) { this.Canvas.textAlign='right'; - x=right; + x=chartright; } - else if (x-textWidth/2=start && item.Index=right) @@ -40496,6 +43142,316 @@ function ChartMultiSVGIcon() } } + +//图标集合(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() { @@ -42403,7 +45359,10 @@ function ExtendChartPaintFactory() [ ["FrameSplitPaint", { Create:function() { return new FrameSplitPaint(); } }], ["RectSelectPaint", { Create:function() { return new RectSelectPaint(); } }], - ["DragMovePaint", { Create:function() { return new DragMovePaint(); } }] + ["RectDragPaint", { Create:function() { return new RectDragPaint(); } }], + ["DragMovePaint", { Create:function() { return new DragMovePaint(); } }], + ["SessionBreaksPaint", { Create:function() { return new SessionBreaksPaint(); }}], + ["FrameButtomToolbarPaint", {Create:function() { return new FrameButtomToolbarPaint(); }}] ] ); @@ -42452,6 +45411,7 @@ function IExtendChartPainting() this.DrawAfterTitle=false; //是否在动态标题画完以后再画,防止动态标题覆盖 this.DrawAfterPicture=false; //是否在画图工具以后绘制 this.IsCallbackDraw=false; //在回调函数里绘制, 不在Draw()中绘制 + this.ID=Guid(); //上下左右间距 this.Left=5; @@ -43175,9 +46135,17 @@ function MinuteTooltipPaint() if (IFrameSplitOperator.IsNumber(close) && IFrameSplitOperator.IsNumber(this.YClose)) { title=g_JSChartLocalization.GetText('Tooltip-Increase',this.LanguageID); - var value=(close-this.YClose)/this.YClose*100; - color = this.TitlePaint.GetColor(value, 0); - text = value.toFixed(2)+'%'; + 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 }); } @@ -43599,7 +46567,7 @@ function MinuteLeftTooltipPaint() this.ForamtIncrease=function(price, TitleID) { if (!IFrameSplitOperator.IsNumber(price) || price==0) return null; - + var value=(price-this.YClose)/this.YClose*100; var titleItem= { @@ -43609,6 +46577,13 @@ function MinuteLeftTooltipPaint() TextColor:this.GetColor(value, 0) }; + if (this.YClose===0) + { + titleItem.Text="--.--"; + titleItem.TextColor=this.TitleColor + } + + return titleItem; } @@ -44446,235 +47421,6 @@ function StockChip() } } -//画图工具条 -function DrawToolsButton() -{ - this.newMethod=IExtendChartPainting; //派生 - this.newMethod(); - delete this.newMethod; - - this.ClassName='DrawToolsButton'; - this.HQChart; - this.ID=Guid(); - this.ToolsDiv; - // this.Color='rgb(105,105,105)'; //颜色 - this.Color = "#696969"; //input type="color"不支持rgb的颜色格式 - - //this.Left=5; - this.Top=5*GetDevicePixelRatio(); - this.Width=45*GetDevicePixelRatio(); //宽度 - - this.SetOption=function(option) - { - var pixelRatio=GetDevicePixelRatio(); - if (!option) return; - if (option.Width>10) this.Width=option.Width*pixelRatio; - } - - this.Clear=function() - { - if (this.ToolsDiv) this.ChartBorder.UIElement.parentNode.removeChild(this.ToolsDiv); - } - - this.Draw = function () { - if (this.SizeChange == false) return; - - //工具列表 - const TOOL_LIST = - [ - [ - { HTML: { Title: '线段', IClass: 'iconfont icon-draw_line', ID: 'icon-segment' }, Name: '线段' }, - { HTML: { Title: '尺子', IClass: 'iconfont icon-ruler', ID: 'icon_ruler' }, Name: '尺子' }, - { HTML: { Title: '射线', IClass: 'iconfont icon-draw_rays', ID: 'icon-beam' }, Name: '射线' }, - { HTML: { Title: '标价线', IClass: 'iconfont icon-price_line', ID: 'icon-price-line' }, Name: '标价线' }, - { HTML: { Title: '垂直线', IClass: 'iconfont icon-vertical_line', ID: 'icon-vertical-line' }, Name: '垂直线' }, - { HTML: { Title: '箭头', IClass: 'iconfont icon-draw_rays', ID: 'icon-beam2' }, Name: '箭头' }, - { HTML: { Title: '趋势线', IClass: 'iconfont icon-draw_trendline', ID: 'icon-trendline' }, Name: '趋势线' }, - { HTML: { Title: '水平线', IClass: 'iconfont icon-draw_hline', ID: 'icon-hline' }, Name: '水平线' }, - { HTML: { Title: '水平线段', IClass: 'iconfont icon-draw_hlinesegment', ID: 'icon-hlineseg' }, Name: '水平线段' }, - { HTML: { Title: '平行射线', IClass: 'iconfont icon-draw_p_rays_lines', ID: 'icon-rayslineseg' }, Name: '平行射线' }, - { HTML: { Title: '平行线', IClass: 'iconfont icon-draw_parallel_lines', ID: 'icon-parallellines' }, Name: '平行线' }, - { HTML: { Title: '平行通道', IClass: 'iconfont icon-draw_parallelchannel', ID: 'icon-parallelchannel' }, Name: '平行通道' }, - { HTML: { Title: '价格通道线', IClass: 'iconfont icon-draw_pricechannel', ID: 'icon-pricechannel' }, Name: '价格通道线' }, - { HTML: { Title: 'M头W底', IClass: 'iconfont icon-draw_wavemw', ID: 'icon-wavemw' }, Name: 'M头W底' }, - { HTML: { Title: '头肩型', IClass: 'iconfont icon-draw_head_shoulders_bt', ID: 'icon-Head-Shoulders' }, Name: '头肩型' }, - { HTML: { Title: '波浪尺', IClass: 'iconfont icon-waveruler', ID: 'icon-wave-ruler' }, Name: '波浪尺' }, - { HTML: { Title: 'AB波浪尺', IClass: 'iconfont icon-waveruler', ID: 'icon-wave-ruler2' }, Name: 'AB波浪尺' }, - { HTML: { Title: '箱型线', IClass: 'iconfont icon-draw_box', ID: 'icon-drawbox' }, Name: '箱型线' }, - { HTML: { Title: '涂鸦线段', IClass: 'iconfont icon-draw_line', ID: 'icon-segment2' }, Name: '涂鸦线段' }, - - ], - [ - { HTML: { Title: '圆弧', IClass: 'iconfont icon-draw_arc', ID: 'icon-arc' }, Name: '圆弧线' }, - { HTML: { Title: '矩形', IClass: 'iconfont icon-rectangle', ID: 'icon-rect' }, Name: '矩形' }, - { HTML: { Title: '平行四边形', IClass: 'iconfont icon-draw_quadrangle', ID: 'icon-quad' }, Name: '平行四边形' }, - { HTML: { Title: '三角形', IClass: 'iconfont icon-draw_triangle', ID: 'icon-triangle' }, Name: '三角形' }, - { HTML: { Title: '圆', IClass: 'iconfont icon-draw_circle', ID: 'icon-circle' }, Name: '圆' }, - { HTML: { Title: '对称角度', IClass: 'iconfont icon-draw_symangle', ID: 'icon-symangle' }, Name: '对称角度' }, - ], - [ - { HTML: { Title: '文本', IClass: 'iconfont icon-draw_text', ID: 'icon-text' }, Name: '文本' }, - { HTML: { Title: '向上箭头', IClass: 'iconfont icon-arrow_up', ID: 'icon-arrowup' }, Name: 'icon-arrow_up' }, - { HTML: { Title: '向下箭头', IClass: 'iconfont icon-arrow_down', ID: 'icon-arrowdown' }, Name: 'icon-arrow_down' }, - { HTML: { Title: '向左箭头', IClass: 'iconfont icon-arrow_left', ID: 'icon-arrowleft' }, Name: 'icon-arrow_left' }, - { HTML: { Title: '向右箭头', IClass: 'iconfont icon-arrow_right', ID: 'icon-arrowright' }, Name: 'icon-arrow_right' }, - ], - [ - { HTML: { Title: '江恩角度线', IClass: 'iconfont icon-draw_gannfan', ID: 'icon-gannfan' }, Name: '江恩角度线' }, - { HTML: { Title: '斐波那契周期线', IClass: 'iconfont icon-draw_fibonacci', ID: 'icon-fibonacci' }, Name: '斐波那契周期线' }, - { HTML: { Title: '阻速线', IClass: 'iconfont icon-draw_resline', ID: 'icon-resline' }, Name: '阻速线' }, - { HTML: { Title: '黄金分割', IClass: 'iconfont icon-draw_goldensection', ID: 'icon-goldensection' }, Name: '黄金分割' }, - { HTML: { Title: '百分比线', IClass: 'iconfont icon-draw_percentage', ID: 'icon-percentage' }, Name: '百分比线' }, - { HTML: { Title: '波段线', IClass: 'iconfont icon-draw_waveband', ID: 'icon-waveband' }, Name: '波段线' }, - { HTML: { Title: '线形回归线', IClass: 'iconfont icon-linear_3', ID: 'icon-waveband2' }, Name: '线形回归线' }, - { HTML: { Title: '线形回归带', IClass: 'iconfont icon-linear_1', ID: 'icon-waveband3' }, Name: '线形回归带' }, - { HTML: { Title: '延长线形回归带', IClass: 'iconfont icon-linear_2', ID: 'icon-waveband5' }, Name: '延长线形回归带' }, - ], - [{ HTML: { Title: '全部删除', IClass: 'iconfont icon-recycle_bin', ID: 'icon-delete' }, Name: '全部删除' }] - ]; - - var hqChart = this.HQChart; - - if (!this.ToolsDiv) { - var div = document.createElement("div"); - div.className = 'drawtools'; - div.id = this.ID; - - var spanList = ""; //一层菜单 - var menuTwoList = ""; //二层菜单 - var menuOne = new Array(); - TOOL_LIST.forEach(function(item,index){ - menuOne.push(item[0]); - }); - for (var i = 0; i < TOOL_LIST.length; i++) { - var itemOut = menuOne[i]; - var itemIn = TOOL_LIST[i]; - var menuTwoStr = ""; - var contentArrow = ""; - for (var j = 0; j < itemIn.length; j++) { - var currentItem = itemIn[j]; - var menuTwoName = currentItem.Name; - if(menuTwoName.indexOf('up') > -1){ - menuTwoName = "向上箭头"; - }else if(menuTwoName.indexOf('down') > -1){ - menuTwoName = "向下箭头"; - }else if(menuTwoName.indexOf('left') > -1){ - menuTwoName = "向左箭头"; - }else if(menuTwoName.indexOf('right') > -1){ - menuTwoName = "向右箭头"; - } - menuTwoStr += ''; - } - if (i !== TOOL_LIST.length - 1) { //不是“全部删除”项 - menuTwoList = ''; - contentArrow = ''; - } else { - menuTwoList = ""; - contentArrow = ""; - } - - var spanNode = '
' + menuTwoList + contentArrow +'
'; - spanList += spanNode; - } - this.ChartBorder.UIElement.parentNode.appendChild(div); - - div.innerHTML = spanList; - this.ToolsDiv = div; - - for (var i in TOOL_LIST) { - var item = TOOL_LIST[i][0]; - $('#' + this.ID + " .first-" + item.HTML.ID).hover(function(){ //箭头的旋转过渡 - $(".drawtools").find(".contentArrow").hide(); - $(this).find(".contentArrow").removeClass("trans").show(); - }); - $('#' + this.ID + " .first-" + item.HTML.ID+" .contentArrow").click(function(event){ //点击三角展示二级菜单 - event.stopPropagation(); - $(".drawtools").find(".menuTwo").hide(); - $(this).siblings('.menuTwo').show(); - }); - $('#' + this.ID + " .first-" + item.HTML.ID+" .trans").click(function(){ //点击三角隐藏二级菜单 - event.stopPropagation(); - $(this).siblings('.menuTwo').hide(); - }); - - - if (item.Name == '全部删除') { - $('#' + this.ID + " .first-icon-delete").click(function () { - $(".drawtools").find(".menuTwo").hide(); - $(this).siblings().removeClass('active'); - $(this).addClass('active'); - hqChart.ClearChartDrawPicture(); - $(".subTolls").css("display", "none"); - }); - } - else { - $('#' + this.ID + " .first-" + menuOne[i].HTML.ID).click( //一层菜单类名是:“first-”+item.HTML.ID - { - // DrawName: menuOne[i].Name, //把画法名字传进去 - CurrentIndex:i - }, - function (event) { - $(".drawtools").find(".menuTwo").hide(); - $(this).siblings().removeClass('active'); - $(this).addClass('active'); - hqChart.CreateChartDrawPicture(menuOne[event.data.CurrentIndex].Name); - } - ); - for (var j in TOOL_LIST[i]) { - var itemTwo = TOOL_LIST[i][j]; - let classname = itemTwo.HTML.IClass; //闭包问题 - $('#' + this.ID + ' .' + itemTwo.HTML.ID).hover(function(event){ - event.stopPropagation(); - $(this).closest('.icon-image').find(".contentArrow").addClass("trans"); - }); - $('#' + this.ID + ' .' + itemTwo.HTML.ID).click(//二层菜单 - { - DrawName: itemTwo.Name, //把画法名字传进去 - CurrentIndex:i, - CurrentData:itemTwo - }, - function (event) { - event.stopPropagation(); - $(this).closest('.icon-image').find(".contentArrow").hide(); - $(this).siblings().removeClass("current"); - $(this).addClass("current"); - $(this).closest('.icon-image').children('i').eq(0).removeClass().addClass(classname,"active").attr('title',event.data.CurrentData.HTML.Title); - menuOne.splice(event.data.CurrentIndex,1,event.data.CurrentData); - $(this).parent().hide(); - hqChart.CreateChartDrawPicture(event.data.DrawName); - } - ); - } - } - } - - } - var curID = this.ID; - $(document).click(function(event){ - if(!($("#"+curID).is(event.target)) && ($("#"+curID).has(event.target).length === 0)){ - $("#"+curID+" .menuTwo").hide(); - $("#"+curID+" .contentArrow").hide(); - } - }); - var scrollPos = GetScrollPosition(); - var pixelRatio=GetDevicePixelRatio(); - // var left=this.ChartBorder.GetChartWidth()-this.Right-this.ToolsWidth; - var left=ToFixedPoint(this.ChartBorder.GetRight()+this.Left); - // var top = this.Top+this.ChartBorder.UIElement.getBoundingClientRect().top+scrollPos.Top; - var top = this.ChartBorder.GetTop(); - this.ToolsDiv.style.left = left/pixelRatio + "px"; - this.ToolsDiv.style.top = top/pixelRatio + "px"; - this.ToolsDiv.style.width = (this.Width-5)/pixelRatio + "px"; - this.ToolsDiv.style.height = 'auto'; - this.ToolsDiv.style.position = "absolute"; - this.ToolsDiv.style.display = "block"; - // this.ToolsDiv.style.paddingLeft = "10px"; - - this.SizeChange == true; - } -} - - //窗口分割 function FrameSplitPaint() { @@ -45615,6 +48361,189 @@ function RectSelectPaint() } } } + +//鼠标拖动选中区域 +function RectDragPaint() +{ + this.newMethod=IExtendChartPainting; //派生 + this.newMethod(); + delete this.newMethod; + + this.ClassName='RectDragPaint'; + this.LineColor=g_JSChartResource.RectDrag.LineColor; //竖线 + this.LineWidth=g_JSChartResource.RectDrag.LineWidth; + this.BGColor=g_JSChartResource.RectDrag.BGColor; + this.ShowMode=0; //0=只画边框 1=遮挡未选中区域 2=整体全选 + this.Enable=false; + + this.FirstPoint; + this.SecondPoint; + + this.IsClearCanvas=true; //画布是否是清空状态 + + //设置参数接口 + this.SetOption=function(option) + { + if (option) + { + if (option.LineColor) this.LineColor=option.LineColor; + if (option.BGColor) this.BGColor=option.BGColor; + if (IFrameSplitOperator.IsNumber(option.ShowMode)) this.ShowMode=option.ShowMode; + } + } + + this.ReloadResource=function(resource) + { + this.LineColor=g_JSChartResource.RectDrag.LineColor; //竖线 + this.LineWidth=g_JSChartResource.RectDrag.LineWidth; + this.BGColor=g_JSChartResource.RectDrag.BGColor; //面积 + } + + this.ClearPoint=function() + { + this.FirstPoint=null; + this.SecondPoint=null; + + if (!this.IsClearCanvas) this.Draw(); + } + + this.SetFirstPoint=function(x, y) + { + this.FirstPoint={ X:x, Y:y }; + } + + this.SetSecondPoint=function(x, y) + { + this.SecondPoint={ X:x, Y:y }; + } + + this.DrawSelectedBorderMode=function(rtSelect) + { + this.Canvas.strokeStyle=this.LineColor; + this.Canvas.strokeRect(ToFixedPoint(rtSelect.Left),ToFixedPoint(rtSelect.Top),ToFixedRect(rtSelect.Width),ToFixedRect(rtSelect.Height)); + } + + this.DrawUnselectedMaskMode=function(rtSelect, rtClient) + { + if (this.BGColor) + { + this.Canvas.save(); + + var clipPath=new Path2D(); + clipPath.rect(rtClient.Left, rtClient.Top, rtClient.Width, rtSelect.Top-rtClient.Top); + + var leftPath=new Path2D(); + leftPath.rect(rtClient.Left,rtSelect.Top, rtSelect.Left-rtClient.Left, rtSelect.Height); + clipPath.addPath(leftPath); + + var rightPath=new Path2D(); + rightPath.rect(rtSelect.Right,rtSelect.Top, rtClient.Right-rtSelect.Right, rtSelect.Height); + clipPath.addPath(rightPath); + + var bottmPath=new Path2D(); + bottmPath.rect(rtClient.Left,rtSelect.Bottom, rtClient.Width, rtClient.Bottom-rtSelect.Bottom); + clipPath.addPath(bottmPath); + + this.Canvas.clip(clipPath); + + this.Canvas.fillStyle=this.BGColor; + this.Canvas.fillRect(rtClient.Left,rtClient.Top,rtClient.Width,rtClient.Height); + + this.Canvas.restore(); + } + + this.Canvas.strokeStyle=this.LineColor; + this.Canvas.strokeRect(ToFixedPoint(rtSelect.Left),ToFixedPoint(rtSelect.Top),ToFixedRect(rtSelect.Width),ToFixedRect(rtSelect.Height)); + } + + this.DrawFullselectedMode=function(rtSelect, rtClient) + { + if (this.BGColor) + { + this.Canvas.save(); + + var clipPath=new Path2D(); + clipPath.rect(rtClient.Left, rtClient.Top, rtSelect.Left-rtClient.Left, rtClient.Height); + + var rightPath=new Path2D(); + rightPath.rect(rtSelect.Right,rtClient.Top, rtClient.Right-rtSelect.Right, rtClient.Height); + clipPath.addPath(rightPath); + + this.Canvas.clip(clipPath); + + this.Canvas.fillStyle=this.BGColor; + this.Canvas.fillRect(rtClient.Left,rtClient.Top,rtClient.Width,rtClient.Height); + + this.Canvas.restore(); + } + + this.Canvas.strokeStyle=this.LineColor; + this.Canvas.strokeRect(ToFixedPoint(rtSelect.Left),ToFixedPoint(rtClient.Top),ToFixedRect(rtSelect.Width),ToFixedRect(rtClient.Height)); + } + + this.Draw=function() + { + if (!this.Enable) return; + if (!this.HQChart) return; + + var finder=this.HQChart.GetExtraCanvas(JSChart.RectDragCanvasKey); + if (!finder) return; + + this.Canvas=finder.Canvas; + this.HQChart.ClearCanvas(this.Canvas); + this.IsClearCanvas=true; + + if (!this.FirstPoint && !this.SecondPoint) return; + + var top=this.ChartBorder.GetTop(); + var bottom=this.ChartBorder.GetBottom(); + var left=this.ChartBorder.GetLeft(); + var right=this.ChartBorder.GetRight(); + + var rtClient={Left:left, Top:top, Right:right, Bottom:bottom }; + rtClient.Width=rtClient.Right-rtClient.Left; + rtClient.Height=rtClient.Bottom-rtClient.Top; + + var rtSelect= + { + Left:Math.min(this.FirstPoint.X,this.SecondPoint.X), + Right:Math.max(this.FirstPoint.X,this.SecondPoint.X), + Top:Math.min(this.FirstPoint.Y,this.SecondPoint.Y), + Bottom:Math.max(this.FirstPoint.Y,this.SecondPoint.Y) + } + + if (rtSelect.Topbottom) 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; + } +} + //深度图 支持横屏 /* 数据格式: @@ -46660,6 +49589,529 @@ function DragMovePaint() } +function SessionBreaksPaint() +{ + this.newMethod=IExtendChartPainting; //派生 + this.newMethod(); + delete this.newMethod; + + this.ClassName='SessionBreaksPaint'; + this.IsDynamic=false; + this.IsCallbackDraw=true; //在回调函数里绘制, 不在Draw()中绘制 + this.FrameID=0; + this.KDataFeature; //数据特征 { Symbol, Period, DataCount } + this.Data; + this.ChartFrame; + + this.BGColor=g_JSChartResource.SessionBreaksPaint.BGColor.slice(); + this.SplitLine= + { + Color:g_JSChartResource.SessionBreaksPaint.SplitLine.Color, + Width:g_JSChartResource.SessionBreaksPaint.SplitLine.Width, + Dash:g_JSChartResource.SessionBreaksPaint.SplitLine.Dash + }; + + this.MapPeriod=new Map( + [ + [0, { SplitType:1 }], //日 + [1, { SplitType:1 }], //周 + [2, { SplitType:2 }], //月 + [21, { SplitType:2 }], //双周 + + [4, { SplitType:3 }], //1分钟 + [5, { SplitType:3 }], //5分钟 + [6, { SplitType:3 }], //15分钟 + [7, { SplitType:3 }], + [8, { SplitType:3 }], + ]); //周期和分割对应关系 + + this.SetOption=function(option) //设置 + { + if (option.FrameID>0) 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 && y= aryInfo.length && i != aryInfo.length - 1) //最后一个数据放进去 + for (var i = 0; i < aryInfo.length; i += filter) { - data.push(aryInfo[aryInfo.length - 1]); + data.push(aryInfo[i]); } - else + } + else + { + for (var i = 0; i < aryInfo.length; i += filter) { - data.push(aryInfo[i]); + 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个和最后一个刻度 { @@ -47030,7 +50493,7 @@ function IFrameSplitOperator() return data; } - this.RemoveZero = function (aryInfo) //移除小数后面多余的0 + this.RemoveZero=function(aryInfo) //移除小数后面多余的0 { //所有的数字小数点后面都0,才会去掉 var isAllZero = [true, true, true, true]; @@ -47275,6 +50738,58 @@ function IFrameSplitOperator() return data; } + + this.Reset=function() //重置 + { + + } + + this.SetOption=function(option) { } + + //计算上下预留 + this.ReservedHeight=function(splitData) + { + if (!this.Frame) return; + if (this.Frame.IsHScreen) return; //横屏以后再搞 + + var yReserved=this.Frame.HorizontalReserved; + if (!yReserved) return; + + var reservedHeight=0; + if (IFrameSplitOperator.IsPlusNumber(yReserved.Top)) reservedHeight+=yReserved.Top; + if (IFrameSplitOperator.IsPlusNumber(yReserved.Bottom)) reservedHeight+=yReserved.Bottom; + if (reservedHeight<=0) return; + + var border=this.Frame.GetBorder(); + var top=border.TopEx; + var bottom=border.BottomEx; + var srcHeight=bottom-top; + if (srcHeight0) @@ -47922,6 +51458,8 @@ function FrameSplitKLinePriceY() } */ + this.ReservedHeight(splitData); //预留高度 + JSConsole.Chart.Log(`[FrameSplitKLinePriceY::Operator] fixed . Max=${splitData.Max} Min=${splitData.Min} Count=${splitData.Count}`); if (this.GetEventCallback) @@ -48225,7 +51763,7 @@ function FrameSplitKLinePriceY() this.Frame.HorizontalInfo[i]= new CoordinateInfo(); this.Frame.HorizontalInfo[i].Value=value; if (this.IsShowLeftText) this.Frame.HorizontalInfo[i].Message[0]=value.toFixed(floatPrecision); - if (this.IsShowRightText) this.Frame.HorizontalInfo[i].Message[1]=value.toFixed(floatPrecision); + if (this.IsShowRightText) this.Frame.HorizontalInfo[i].Message[1]=value.toFixed(floatPrecision); } } @@ -48471,7 +52009,7 @@ function FrameSplitKLinePriceY() this.CustomFixedCoordinate=function(option) //固定坐标刻度 { var defaultfloatPrecision=GetfloatPrecision(this.Symbol); - for(var i in option.Data) + for(var i=0; ithis.FLOATPRECISION_RANGE[0]) return floatPrecision; @@ -48713,20 +52269,25 @@ function FrameSplitY() this.FilterIgnoreYValue(); this.CustomCoordinate(); - if (this.SplitType!=1) this.Frame.HorizontalInfo = this.Filter(this.Frame.HorizontalInfo,(splitData.Max>0 && splitData.Min<0)); + if (this.SplitType!=1) + this.Frame.HorizontalInfo = this.Filter(this.Frame.HorizontalInfo,(splitData.Max>0 && 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); @@ -48739,7 +52300,6 @@ function FrameSplitY() } } - this.FormatValueString=function(value) { var text; @@ -48749,6 +52309,10 @@ function FrameSplitY() 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); @@ -48932,6 +52496,45 @@ function FrameSplitY() } } + this.MainOverlayFrameSplitY=function() + { + if (!this.Frame.GetMainOverlayFrame) return; + var aryOverlayFrame=this.Frame.GetMainOverlayFrame(); + if (!aryOverlayFrame ) return; + + if (aryOverlayFrame[1]) + { + var rightFrame=aryOverlayFrame[1]; + var ySplitOper=rightFrame.YSplitOperator; + if (ySplitOper) ySplitOper.Operator(); + + for(var i=0;i0) coordinate.TextColor=g_JSChartResource.UpTextColor; @@ -49777,7 +53384,7 @@ function FrameSplitMinutePriceY() var strPrice=price.toFixed(defaultfloatPrecision); //价格刻度字符串 if (this.IsShowLeftText) coordinate.Message[0]=strPrice - if (IFrameSplitOperator.IsNumber(this.YClose)) + if (IFrameSplitOperator.IsNumber(this.YClose) && this.YClose!=0) { var per=(price/this.YClose-1)*100; if (per>0) coordinate.TextColor=g_JSChartResource.UpTextColor; @@ -50341,6 +53948,9 @@ function ChartCorssCursor() 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=显示 @@ -50708,6 +54318,7 @@ function ChartCorssCursor() 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) { @@ -50737,37 +54348,40 @@ function ChartCorssCursor() this.Canvas.fillText(text,left+2,y,textWidth); } + var complexText= + { + ShowType:0, //0=单行(默认) 1=多行 + Font:this.Font, Color:this.TextColor, + Text:[ { Text:text, Margin:this.RightMargin } ], + }; + + var yTop=y-this.TextHeight/2; + if (this.StringFormatY.PercentageText) { if (this.TextFormat.Right==0) { text=this.StringFormatY.PercentageText+'%'; - textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 + complexText.Text[0].Text=text; } } if (this.StringFormatY.RText) { text=this.StringFormatY.RText; - var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素 + complexText.Text[0].Text=text; } - var complexText=null; if (this.StringFormatY.RComplexText && IFrameSplitOperator.IsNonEmptyArray(this.StringFormatY.RComplexText.Text)) { - var textWidth=0; complexText=this.StringFormatY.RComplexText; - for(var i=0; i0 && IFrameSplitOperator.IsNumber(complexText.Space)) - textWidth+=complexText.Space; - - textWidth+=itemWidth; - } + if (!complexText.Font) complexText.Font=this.Font; + if (!complexText.Color) complexText.Color=this.TextColor; } + + + + this.CalculateComplexTextSize(complexText, textSize); if (this.Frame.ChartBorder.Right>=30 && this.ShowTextMode.Right==1) { @@ -50777,66 +54391,53 @@ function ChartCorssCursor() { var frame=this.Frame.SubFrame[yValueExtend.FrameID]; isOverlayIndex=frame.OverlayIndex.length>0; - overlayIndexInterval=frame.Interval; + 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 && textWidth>overlayIndexInterval) //大于子坐标宽度 + //叠加坐标 + if (isOverlayIndex && textSize.Width>overlayIndexInterval && overlayIndexInterval>0) //大于子坐标宽度 { var drawRight=right+overlayIndexInterval; if (drawRight>chartRight) drawRight=chartRight; - var itemLeft=drawRight-2-textWidth; - this.DrawTextBGRect(itemLeft,y-this.TextHeight/2,textWidth,this.TextHeight); - if (complexText) - { - this.DrawComplexText(itemLeft,y,complexText); - } - else - { - this.Canvas.textAlign="right"; - this.Canvas.textBaseline="middle"; - this.Canvas.fillStyle=this.TextColor; - this.Canvas.fillText(text,drawRight-4,y,textWidth); - } + 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; @@ -50868,31 +54469,21 @@ function ChartCorssCursor() yOffset+=this.TextHeight; } } + */ } else if (this.ShowTextMode.Right==2) { this.Canvas.fillStyle=this.TextBGColor; - var showLeft=right-textWidth; - this.DrawTextBGRect(showLeft,y-this.TextHeight/2,textWidth,this.TextHeight); - - if (complexText) - { - this.DrawComplexText(showLeft,y,complexText); - } - else - { - this.Canvas.textAlign="left"; - this.Canvas.textBaseline="middle"; - this.Canvas.fillStyle=this.TextColor; - this.Canvas.fillText(text,showLeft+2,y,textWidth); - } + var showLeft=right-textSize.Width; + this.DrawTextBGRect(showLeft,yTop,textSize.Width,textSize.Height); + this.DrawComplexTextV2(showLeft,yTop,complexText,textSize); - if (this.RightButton.Enable) this.DrawRightButton(y-this.TextHeight/2, showLeft,this.TextHeight,this.TextHeight,buttonData); + if (this.RightButton.Enable) this.DrawRightButton(yTop, showLeft,this.TextHeight,this.TextHeight,buttonData); } } - //X轴 Bottom=10 使用第1个指标框位置 - if ((this.ShowTextMode.Bottom==1 || this.ShowTextMode.Bottom==2 || this.ShowTextMode.Bottom==10) && this.StringFormatX.Operator()) + //X轴 Bottom==8 自定义 + if ((this.ShowTextMode.Bottom==1 || this.ShowTextMode.Bottom==2 || this.ShowTextMode.Bottom==8) && this.StringFormatX.Operator()) { var text=this.StringFormatX.Text; this.Canvas.font=this.Font; @@ -50901,49 +54492,53 @@ function ChartCorssCursor() var yCenter=bottom+2+this.TextHeight/2; var yTop=bottom+2; + var bShowText=true; if (this.ShowTextMode.Bottom==2) { yCenter=bottom-this.TextHeight/2-2; yTop=bottom-this.TextHeight-2; } - else if (this.ShowTextMode.Bottom==10) + else if (this.ShowTextMode.Bottom==8) { - var frame=this.Frame.SubFrame[0].Frame; - if (frame.GetCorssCursorTop) + var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_CORSSCURSOR_POSITION); + if (event && event.Callback) { - var value=frame.GetCorssCursorTop(); - if (IFrameSplitOperator.IsNumber(value)) - { - yCenter=value+this.TextHeight/2; - yTop=value; - } + var sendData={ YCenter:yCenter, YTop:yTop, Height:this.TextHeight, IsShowText:bShowText }; + event.Callback(event, sendData, this); + + yCenter=sendData.YCenter; + yTop=sendData.YTop; + bShowText=sendData.IsShowText; } } //JSConsole.Chart.Log('[ChartCorssCursor::Draw] ',yCenter); - if (x-textWidth/2<3) //左边位置不够了, 顶着左边画 - { - this.DrawTextBGRect(x-1,yTop,textWidth,this.TextHeight); - this.Canvas.textAlign="left"; - this.Canvas.textBaseline="middle"; - this.Canvas.fillStyle=this.TextColor; - this.Canvas.fillText(text,x+1,yCenter,textWidth); - } - else if (x+textWidth/2>=right) + if (bShowText) { - 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); + if (x-textWidth/2<3) //左边位置不够了, 顶着左边画 + { + this.DrawTextBGRect(x-1,yTop,textWidth,this.TextHeight); + this.Canvas.textAlign="left"; + this.Canvas.textBaseline="middle"; + this.Canvas.fillStyle=this.TextColor; + this.Canvas.fillText(text,x+1,yCenter,textWidth); + } + else if (x+textWidth/2>=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); + } } } @@ -50987,38 +54582,151 @@ function ChartCorssCursor() this.Status=1; } - this.DrawComplexText=function(left, y, complexText) + this.DrawComplexTextV2=function(left, yTop, complexText, size) { this.Canvas.textAlign="left"; - this.Canvas.textBaseline="middle"; - var xText=left+2; - for(var i=0; i0 && IFrameSplitOperator.IsNumber(complexText.Space)) - xText+=complexText.Space; + textWidth+=itemWidth; + if (textHeight=bottom) - { - var yText=y; - this.Canvas.save(); - this.Canvas.translate(xText, yText); - this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 + 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.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.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.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.Canvas.restore(); + } } } @@ -51988,6 +55700,7 @@ function HQPriceStringFormat() { 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) @@ -51995,8 +55708,9 @@ function HQPriceStringFormat() var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_CORSSCURSOR_Y_TEXT); if (event) { - var data={ Value:this.Value, FrameID:this.FrameID }; + var data={ Value:this.Value, FrameID:this.FrameID, PreventDefault:false }; event.Callback(event,data,this); + if (data.PreventDefault==true) return false; } } @@ -52071,8 +55785,10 @@ function HQDateStringFormat() 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 }; + 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; } } @@ -52211,8 +55927,10 @@ function HQMinuteTimeStringFormat() var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_CORSSCURSOR_X_TEXT); if (event) { - var data={ Time:time, Index:showIndex }; + var data={ Time:time, Index:showIndex, PreventDefault:false }; event.Callback(event,data,this); + + if (data.PreventDefault==true) return false; } } @@ -54343,6 +58061,7 @@ function DynamicTitleData(data,name,color) this.FloatPrecision=2; //小数位数 this.IsShow=true; //是否显示 this.Callback; //绘制标题回调 + this.ExtendData; //扩展数据 } function DynamicChartTitlePainting() @@ -54360,9 +58079,11 @@ function DynamicChartTitlePainting() this.ColorIndex; //五彩K线名字 {Name:'名字'} this.IsShowColorIndexTitle=true; this.IsShowUpDownArrow=true; //指标数据是否显示 上涨下跌箭头 + this.TitleArrowType=0; //指标数据上涨下跌箭头类型 0=独立颜色 1=跟指标颜色一致 this.IsShowIndexName=true; //是否显示指标名字 this.IsShowIndexTitle=true; //是否显示指标标题信息 this.IsShowNameArrow=false; + this.NameArrowConfig=CloneData(g_JSChartResource.IndexTitle.NameArrow); this.TradeIndex; //专家系统名字{Name:'名字', Param:'参数'} this.IsShowTradeIndexTitle=true; @@ -54379,6 +58100,7 @@ function DynamicChartTitlePainting() this.BGBorderColor=g_JSChartResource.IndexTitleBorderColor; this.BGBorderMoveOnColor=g_JSChartResource.IndexTitleBorderMoveOnColor; this.BorderRoundRadius=2; //圆角矩形角度 + this.NameButtonStyle=g_JSChartResource.IndexTitleBorderStyle, this.OnDrawEvent; this.ParamSpace=2; //参数显示的间距 @@ -54387,6 +58109,7 @@ function DynamicChartTitlePainting() this.SelectedColor=g_JSChartResource.IndexTitleSelectedColor; this.IsKLineFrame=false; //是否是K线框架标题 + this.IsMinuteFrame=false; this.Identify; //指标ID this.SelectedChart; //选中的图形 this.ArgumentsText; //参数信息 @@ -54394,6 +58117,13 @@ function DynamicChartTitlePainting() this.MerginLeft=g_JSChartResource.IndexTitleMerginLeft; //标题输出左边间距 this.Buttons=[]; //按钮 + + this.UpDownArrowConfig= + { + UpColor:g_JSChartResource.IndexTitle.UpDownArrow.UpColor, + DownColor:g_JSChartResource.IndexTitle.UpDownArrow.DownColor, + UnchangeColor:g_JSChartResource.IndexTitle.UpDownArrow.UnchangeColor + }; //动态标题 @@ -54401,6 +58131,9 @@ function DynamicChartTitlePainting() this.DynamicTitle={ OutName:null, OutValue:null }; this.OverlayDynamicTitle=new Map(); //key , value={ OutName, OutValue } + this.IsShowMainIndexTitle=true; //是否显示主图指标标题 + this.MainTitlePaint=null; //主标题 + this.ReloadResource=function() { this.Font=g_JSChartResource.TitleFont; @@ -54814,10 +58547,12 @@ function DynamicChartTitlePainting() this.Buttons=[]; if (this.Frame.IsMinSize) return; - this.IsKLineFrame= this.Frame.ClassName=='KLineFrame' || this.Frame.ClassName=='KLineHScreenFrame'; + this.IsKLineFrame= this.Frame.IsKLineFrame(false); + this.IsMinuteFrame=this.Frame.IsMinuteFrame(false); this.IsDrawTitleBG=this.Frame.IsDrawTitleBG; this.IsShowNameArrow=this.Frame.IsShowNameArrow; this.IsShowUpDownArrow=this.Frame.IsShowTitleArrow; + this.TitleArrowType=this.Frame.TitleArrowType; this.IsShowIndexName=this.Frame.IsShowIndexName; this.IsShowOverlayIndexName=this.Frame.IsShowOverlayIndexName; this.OverlayIndexType.Position=this.Frame.OverlayIndexType.Position; @@ -54864,7 +58599,7 @@ function DynamicChartTitlePainting() this.Canvas.textBaseline="middle"; this.Canvas.font=this.Font; var pixelRatio=GetDevicePixelRatio(); - if (this.Title && this.IsShowIndexName) + if (this.Title && this.IsShowIndexName && this.IsShowMainIndexTitle) { if (this.IsDrawTitleBG) { @@ -54893,7 +58628,7 @@ function DynamicChartTitlePainting() } } - if (this.ArgumentsText && this.IsShowIndexName) + if (this.ArgumentsText && this.IsShowIndexName && this.IsShowMainIndexTitle) { var textWidth=this.Canvas.measureText(this.ArgumentsText).width+2; this.Canvas.fillStyle=this.TitleColor; @@ -54913,67 +58648,19 @@ function DynamicChartTitlePainting() if (isShowLastData) return; } - for(var i=0; i=200&& this.PointInfo.ClientPos<=299) || (this.PointInfo.ClientPos>=300&& this.PointInfo.ClientPos<=399) )) { - var item=this.Data[i]; - var outText=this.GetTitleItem(item, isShowLastData, i); - if (!outText) continue; - - var valueText=outText.Text; - var aryText=outText.ArrayText; - - if (aryText) //多变量输出 - { - var text; - for(var k=0;kright) break; - - if (titleItem.BG) //背景 - { - var textHeight=this.Canvas.measureText("擎").width+2; - var textWidth=this.Canvas.measureText(text).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,textWidth); - - left+=(textWidth+space); - } - else - { - 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; - if ((left+textWidth)>right) break; - - this.Canvas.fillText(text,left,bottom,textWidth); - left+=textWidth; - } + 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) //说明信息 { @@ -55012,7 +58699,9 @@ function DynamicChartTitlePainting() } else { - this.DrawOverlayIndex(left+10*GetDevicePixelRatio()); //间距多空点 和主指标区分开 + var xOffset=10*GetDevicePixelRatio(); //主指标区分开 间距多空点 + if (!this.IsShowMainIndexTitle) xOffset=0; + this.DrawOverlayIndex(left+xOffset); } } @@ -55132,8 +58821,12 @@ function DynamicChartTitlePainting() if (data.Out) return data.Out; } } + + if (item.DataType=="ChartBand") //默认不输出 + return null; + - var arrow=null; + var arrowSuper=null; //独立颜色 if (this.IsShowUpDownArrow) { @@ -55141,9 +58834,11 @@ function DynamicChartTitlePainting() if (dataIndex-1>=0) preValue=item.Data.Data[dataIndex-1]; if (IFrameSplitOperator.IsNumber(preValue)) { - if (preValue>value) arrow='↓'; - else if (preValuevalue) 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) { @@ -55202,6 +59090,7 @@ function DynamicChartTitlePainting() 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; @@ -55219,6 +59108,7 @@ function DynamicChartTitlePainting() 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; @@ -55358,9 +59248,10 @@ function DynamicChartTitlePainting() var spaceWidth=5*GetDevicePixelRatio(); var drawLeft=left; + var indexCount=0; for(item of this.OverlayIndex) { - left+=spaceWidth; + if (indexCount>0) left+=spaceWidth; var overlayItem=item[1]; var overlayID=item[0]; if (overlayItem.Title && this.IsShowOverlayIndexName) @@ -55426,6 +59317,8 @@ function DynamicChartTitlePainting() } if (left>right) break; + + ++indexCount; } } @@ -55453,10 +59346,16 @@ function DynamicChartTitlePainting() if (this.IsDrawTitleBG) { var title=this.Title; - if (this.IsShowNameArrow) 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+4*pixelRatio; + var bgWidth=textWidth+arrowWidth+4*pixelRatio; this.TitleRect= { @@ -55476,15 +59375,24 @@ function DynamicChartTitlePainting() 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,left+2*pixelRatio,bottom,textWidth); + 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,textWidth); + this.Canvas.fillText(this.Title,left,bottom); left+=textWidth; left+=this.TitleSpace; } @@ -55597,13 +59505,18 @@ function DynamicChartTitlePainting() { var pixelRatio=GetDevicePixelRatio(); var title=this.Title; - if (this.IsShowNameArrow) 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 roundRadius=this.BorderRoundRadius*pixelRatio; - var bgWidth=textWidth+4*pixelRatio+roundRadius*2; + var bgWidth=textWidth+arrowWidth+4*pixelRatio+roundRadius*2; - rtButton.Top=rtButton.YCenter-bgHeight/2-1, rtButton.Width=bgWidth; rtButton.Height=bgHeight; @@ -55621,21 +59534,43 @@ function DynamicChartTitlePainting() } } - this.Canvas.beginPath(); - this.Canvas.roundRect( ToFixedPoint(rtButton.Left), ToFixedPoint(rtButton.Top), ToFixedRect(rtButton.Width), ToFixedRect(rtButton.Height), [roundRadius]); - this.Canvas.closePath(); + 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(); + this.Canvas.fillStyle=this.BGColor; + this.Canvas.fill(); - if (borderColor) + if (borderColor) + { + this.Canvas.strokeStyle=borderColor; + this.Canvas.stroke(); + } + } + else { - this.Canvas.strokeStyle=borderColor; - this.Canvas.stroke(); + 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,rtButton.Left+roundRadius+2*pixelRatio,rtButton.YCenter,textWidth); + 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); + } } //绘制按钮 @@ -55695,7 +59630,7 @@ function DynamicChartTitlePainting() var rtButton={ Left:left, YCenter:yCenter }; this.DrawButton(item, rtButton, moveonPoint, mouseStatus); - this.Buttons.push({ ID:item.ID, Rect:rtButton, FrameID:this.Frame.Identify, Type:0 }); //Type 0=主图按钮 1=附图按钮 2=主图指标名字按钮 + this.Buttons.push({ ID:item.ID, Rect:rtButton, FrameID:this.Frame.Identify, Type:0, Data:item.Data }); //Type 0=主图按钮 1=附图按钮 2=主图指标名字按钮 left=rtButton.Right; @@ -55734,7 +59669,7 @@ function DynamicChartTitlePainting() var rtButton={ Left:left, YCenter:yCenter }; this.DrawButton(item, rtButton, moveonPoint, mouseStatus); - this.Buttons.push({ ID:item.ID, Rect:rtButton, FrameID:this.Frame.Identify, Type:1, OverlayID:toolbarInfo.ID, Title:overlayItem.Title }); + this.Buttons.push({ ID:item.ID, Rect:rtButton, FrameID:this.Frame.Identify, Type:1, OverlayID:toolbarInfo.ID, Title:overlayItem.Title, Data:item.Data }); left=rtButton.Right; @@ -55756,7 +59691,7 @@ function DynamicChartTitlePainting() var rect=item.Rect; if (x>rect.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.SelectPointColor=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; @@ -55986,7 +59922,7 @@ function IChartDrawPicture() var isHScreen=this.Frame.IsHScreen; if (isHScreen) { - for(var i in this.Point) + for(var i=0; i=data.Data.length) //超过当前数据,直接读固定时间 { @@ -56125,7 +60061,7 @@ function IChartDrawPicture() } data.FindDataIndexByDateTime(aryDateTime); - for(var i in aryDateTime) + for(var i=0; i=showCount) ++invaildX; @@ -56869,6 +60818,8 @@ function IChartDrawPicture() 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); @@ -57082,6 +61033,79 @@ function IChartDrawPicture() //复制 //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) @@ -57162,6 +61186,7 @@ IChartDrawPicture.ArrayDrawPricture= { 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(); }}, @@ -57172,7 +61197,9 @@ IChartDrawPicture.ArrayDrawPricture= { 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(); }}, @@ -57188,6 +61215,7 @@ IChartDrawPicture.ArrayDrawPricture= { 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(); } }, @@ -57203,10 +61231,12 @@ IChartDrawPicture.ArrayDrawPricture= { Name:"固定范围成交量分布图", ClassName:"ChartDrawVolProfile", Create:function() { return new ChartDrawVolProfile(); }}, { Name:"DisjointChannel", ClassName:"ChartDrawDisjontChannel", Create:function() { return new ChartDrawDisjontChannel();}}, - { Name:"FlatTop", ClassName:"ChartDrawDisjontChannel", Create:function() { return new ChartDrawFlatTop();}}, + { 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(); } }, @@ -57217,7 +61247,12 @@ IChartDrawPicture.ArrayDrawPricture= { 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:"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( @@ -57324,8 +61359,9 @@ function ChartDrawPictureLine() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; - var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); + var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:false} ); if (!drawPoint) return; if (drawPoint.length!=2) return; @@ -57361,6 +61397,7 @@ function ChartDrawPictureLine() 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; @@ -57380,6 +61417,103 @@ function ChartDrawPictureLine() } } +//趋势线角度 +function ChartTrendAngle() +{ + this.newMethod=ChartDrawPictureLine; //派生 + this.newMethod(); + delete this.newMethod; + + this.ClassName='ChartTrendAngle'; + this.AngleLineLength=100; + this.AngleLineDash=[3,3]; + this.Font=12*GetDevicePixelRatio() +"px 微软雅黑"; + this.Super_SetOption=this.SetOption; //父类函数 + + this.SetOption=function(option) + { + if (this.Super_SetOption) this.Super_SetOption(option); + if (option) + { + if (IFrameSplitOperator.IsNumber(option.AngleLineLength)) this.AngleLineLength=option.AngleLineLength; + if (option.Font) this.Font=option.Font; + if (option.AngleLineDash) this.AngleLineDash=option.AngleLineDash; + } + } + + 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(); + + this.DrawAngle(ptStart, ptEnd); + + var line={Start:ptStart, End:ptEnd}; + this.LinePoint.push(line); + + this.DrawPoint(drawPoint); //画点 + this.Canvas.restore(); + } + + this.DrawAngle=function(ptStart, ptEnd) + { + var pixelRatio=GetDevicePixelRatio(); + var angle=this.CalculateAngle(ptStart.X, ptStart.Y, ptEnd.X, ptEnd.Y); //角度 + var lineLength=this.AngleLineLength*pixelRatio; //角度线长度 + var ptRight={ X:ptStart.X+lineLength, Y:ptStart.Y }; + + if (this.AngleLineDash) this.Canvas.setLineDash(this.AngleLineDash); //画虚线 + + this.Canvas.lineWidth=1*GetDevicePixelRatio(); + this.Canvas.beginPath(); + this.Canvas.moveTo(ToFixedPoint(ptStart.X),ToFixedPoint(ptStart.Y)); + this.Canvas.lineTo(ToFixedPoint(ptRight.X),ToFixedPoint(ptRight.Y)); + this.Canvas.stroke(); + + this.Canvas.beginPath(); + if (angle<=180) + { + this.Canvas.arc(ptStart.X,ToFixedPoint(ptStart.Y),lineLength,0,(Math.PI / 180)*(360-angle), true); + var text=`${angle.toFixed(0)}°`; + } + else + { + this.Canvas.arc(ptStart.X,ToFixedPoint(ptStart.Y),lineLength,0,(Math.PI / 180)*(360-angle), false); + var text=`${(angle-360).toFixed(0)}°`; + } + + this.Canvas.stroke(); + + this.Canvas.textAlign="left"; + this.Canvas.textBaseline="middle"; + this.Canvas.font=this.Font; + this.Canvas.fillStyle=this.LineColor; + + if (this.AngleLineDash) this.Canvas.setLineDash([]); + + + this.Canvas.fillText(text,ptRight.X+5,ptRight.Y); + } +} + //画图工具-涂鸦线段 Y轴关联数值, X轴不关联 function ChartDrawGraffitiLine() { @@ -57523,6 +61657,7 @@ function ChartDrawGraffitiLine() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; @@ -57578,6 +61713,7 @@ function ChartDrawArrowLine() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; @@ -57641,6 +61777,118 @@ function ChartDrawArrowLine() } } +function ChartArrowMarker() +{ + this.newMethod=IChartDrawPicture; //派生 + this.newMethod(); + delete this.newMethod; + + this.ClassName='ChartArrowMarker'; + this.IsPointIn=this.IsPointIn_XYValue_Line; + + this.InsideLineConfig={ Angle:25, MaxWidth:70, WidthRate:0.3 }; + this.InsideWidth=70; + + this.OutLineConfig={ Angle:35, MaxWidth:100, WidthRate:0.4 }; + this.OutWidth=100; + + this.GetXYCoordinate=this.GetXYCoordinate_default; + this.OnlyMoveXIndex=true; + this.IsSupportMagnet=true; + + this.Super_SetOption=this.SetOption; //父类函数 + + this.SetOption=function(option) + { + this.Super_SetOption(option); + + if (option.AreaColor) this.AreaColor=option.AreaColor; + else this.AreaColor=IChartDrawPicture.ColorToRGBA(this.LineColor, 0.6); + } + + this.CalculatePoint=function(angle, ptStart, ptEnd, lineWidth) + { + var theta=angle; //三角斜边一直线夹角 + var headlen=lineWidth; //三角斜边长度 + + 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); + + return { Top:{X:topX+ptEnd.X, Y:topY+ptEnd.Y}, Bottom:{X:botX+ptEnd.X, Y:botY+ptEnd.Y} }; + } + + this.CalculateLineWidth=function(ptStart, ptEnd) + { + var a=ptStart.X-ptEnd.X; + var b=ptStart.Y-ptEnd.Y; + var c=Math.sqrt(a*a+b*b); + + this.InsideWidth=c*this.InsideLineConfig.WidthRate; + this.OutWidth=c*this.OutLineConfig.WidthRate; + + if (this.InsideWidth>this.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() { @@ -57696,6 +61944,7 @@ function ChartDrawPictureHaflLine() 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; @@ -57731,17 +61980,67 @@ function ChartDrawPictureHorizontalLine() 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.Label; //{Text:文本, Position: 0=左, 1=右 } + 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.Label) this.Label=option.Label; + 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; + } } } @@ -57751,17 +62050,13 @@ function ChartDrawPictureHorizontalLine() if (this.Super_ExportStorageData) { storageData=this.Super_ExportStorageData(); - if (this.Label) storageData.Label=this.Label; + if (this.LabelTitle) storageData.LabelTitle=this.LabelTitle; } return storageData; } - this.PointCount=1; - this.ClassName='ChartDrawPictureHorizontalLine'; - this.IsPointIn=this.IsPointIn_XYValue_Line; - this.Font=16*GetDevicePixelRatio() +"px 微软雅黑"; - + /* this.GetXYCoordinate=function() { if (this.IsFrameMinSize()) return null; @@ -57769,11 +62064,13 @@ function ChartDrawPictureHorizontalLine() 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; @@ -57801,8 +62098,9 @@ function ChartDrawPictureHorizontalLine() } else { - this.Canvas.moveTo(left,drawPoint[0].Y); - this.Canvas.lineTo(right,drawPoint[0].Y); + var yFixed=ToFixedPoint2(this.LineWidth,drawPoint[0].Y); + this.Canvas.moveTo(left,yFixed); + this.Canvas.lineTo(right,yFixed); } this.Canvas.stroke(); this.RestoreLineWidth(); @@ -57828,89 +62126,317 @@ function ChartDrawPictureHorizontalLine() this.DrawPoint(drawPoint); //显示价格 - this.LineText(drawPoint[0]) - /* - this.Canvas.fillStyle=this.LineColor; - this.Canvas.font=this.Font; - if (isHScreen) + 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="bottom"; - var xText=drawPoint[0].X; - var yText=left; - this.Canvas.translate(xText, yText); - this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 - var yValue=this.Frame.GetYData(drawPoint[0].X); - var text=yValue.toFixed(2); - if (this.Label) - { - if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); - else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; - } - this.Canvas.fillText(text,0,0); + 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); } - else + + 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="bottom"; - var yValue=this.Frame.GetYData(drawPoint[0].Y); - var text=yValue.toFixed(2); - if (this.Label) - { - if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); - else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; - } - this.Canvas.fillText(text,left,drawPoint[0].Y); + 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.Canvas.restore(); } - this.LineText=function(point) + this.DrawInsideLabel=function(point) { if (!point) return; var isHScreen=this.Frame.IsHScreen; - var left=this.Frame.ChartBorder.GetLeft(); + var config=this.InsideLabelConfig; + if (config.Position!=0 && config.Position!=1) return; + var margin=config.Margin; this.Canvas.fillStyle=this.LineColor; - this.Canvas.font=this.Font; + this.Canvas.font=config.Font; + var textHeight=this.Canvas.measureText("擎").width; + var border=this.Frame.GetBorder(); if (isHScreen) { - left=this.Frame.ChartBorder.GetTop(); - this.Canvas.textAlign="left"; - this.Canvas.textBaseline="bottom"; - var xText=point.X; - var yText=left; - this.Canvas.translate(xText, yText); - this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度 var yValue=this.Frame.GetYData(point.X); var text=yValue.toFixed(2); - if (this.Label) + 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) //右 { - if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); - else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; + 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; } - this.Canvas.fillText(text,2,0); + + 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 { - this.Canvas.textAlign="left"; - this.Canvas.textBaseline="bottom"; var yValue=this.Frame.GetYData(point.Y); var text=yValue.toFixed(2); - if (this.Label) + 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) { - if (this.Label.Position==0) text=this.Label.Text+yValue.toFixed(2); - else if (this.Label.Position==1) text=yValue.toFixed(2)+this.Label.Text; + 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.Canvas.fillText(text,left,point.Y); + } + } + + 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() { @@ -57934,24 +62460,45 @@ function ChartDrawHLine() this.TextFont=12*GetDevicePixelRatio() +"px 微软雅黑"; this.RightSpaceWidth=50; - this.ButtonPosition=0; //按钮位置, 0=价格后面, 1=价格上面 + 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 }, - SettingIcon: { Text:'\ue623',Color:'rgb(255,255,255)', Family:"iconfont", Size:16 } + 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) { @@ -57963,20 +62510,59 @@ function ChartDrawHLine() this.GetLabelCallback=option.GetLabelCallback; } - if (IFrameSplitOperator.IsNumber(option.Precision)) this.Precision=option.Precision; 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 (item.SettingIcon) this.Button.SettingIcon=CloneData(item.SettingIcon); + 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;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,drawLeft+1,yText+1); + this.Canvas.fillText(item.Name,xText,yText); } if (item.Text) { + this.Canvas.textAlign="right"; this.Canvas.fillStyle=item.TextColor; - this.Canvas.fillText(item.Text,drawLeft+labSize.NameWidth+1,yText+1); + this.Canvas.fillText(item.Text,yRightText,yText); } - yText+=labSize.LineHeight; + yText+=labelSize.LineHeight; } } - this.DrawRightLab=function(labInfo, rtLeftDraw) + this.DrawRightLabel=function(y) { - if (!labInfo) return; - if (!IFrameSplitOperator.IsNonEmptyArray(labInfo.AryText)) return; - if (labInfo.Position!=2) return; - var labSize=this.CalculateLabSize(labInfo); - - var drawLeft=rtLeftDraw.Right-labSize.Width; - var drawTop=rtLeftDraw.Bottom; - var lineSpace=0; - if (IFrameSplitOperator.IsNumber(labInfo.LineSpace)) lineSpace=labInfo.LineSpace; - - //背景色 - if (labInfo.BGColor) + 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) //超过窗口底部, 标签位置不动 { - this.Canvas.fillStyle=labInfo.BGColor; - var rtTop=drawTop; - this.Canvas.fillRect(ToFixedRect(drawLeft),ToFixedRect(rtTop),ToFixedRect(labSize.Width),ToFixedRect(labSize.Height)); + yBottom=border.Bottom; + yTop=yBottom-totalHeight; + option.Top=yTop; } - var yText=drawTop+1+lineSpace; + this.DrawValueText(y, rtDraw, option); - this.Canvas.textBaseline="top"; - for(var i=0;i1 实际数值就是长度 } + + if (item.Color) this.Canvas.strokeStyle=item.Color; + else this.Canvas.strokeStyle=this.LineColor; - if (item.Text) - { - this.Canvas.textAlign="right"; - this.Canvas.fillStyle=item.TextColor; - this.Canvas.fillText(item.Text,rtLeftDraw.Right-1,yText+1); - } + this.Canvas.beginPath(); + this.Canvas.moveTo(left,yFixed); + this.Canvas.lineTo(xRight,yFixed); + this.Canvas.stroke(); - yText+=labSize.LineHeight+lineSpace; + 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, labInfo) + 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([]); } - var yValue=this.Frame.GetYData(y); - var strValue=yValue.toFixed(this.Precision); - if (labInfo &&labInfo.PriceSuffixText) strValue+=labInfo.PriceSuffixText; - 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, Top:y- lineHeight/2, Width:textWidth+4, Height:lineHeight }; + 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="middle"; - this.Canvas.fillText(strValue,rtBG.Left+2,y); + this.Canvas.textBaseline="top"; + this.Canvas.fillText(strValue,xText,yText); rtDraw.Left=rtBG.Left; rtDraw.Top=rtBG.Top; @@ -58282,112 +63039,187 @@ function ChartDrawHLine() this.DrawButton(rtBG.Top, rtBG.Right, lineHeight, rtDraw); } - this.CalculateButtonSize=function() + //计算右侧价格标签大小 + this.CalculateValueText=function(y) { - var pixelRatio=GetDevicePixelRatio(); + 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); - if (this.Button.SettingIcon) + 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 icon=this.Button.SettingIcon; - var font=`${icon.Size*pixelRatio}px ${icon.Family}`; - this.Canvas.font=font; - var width=this.Canvas.measureText(icon.Text).width; - this.SettingButtonSize=width; + 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; } - if (this.Button.CloseIcon) + 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;i0) buttonWidth+=this.SettingButtonSize; - if (this.ColseButtonSize>0) - { - if (buttonWidth>0) buttonWidth+=this.ButtonSpace; - buttonWidth+=this.ColseButtonSize; - } + if (IFrameSplitOperator.IsNumber(margin.Top)) item.Height+=margin.Top; + if (IFrameSplitOperator.IsNumber(margin.Bottom)) item.Height+=margin.Bottom; + } - buttonWidth+=4; + if (this.VerticalButtonInfo.Width0) + yTop=rtButton.Bottom; + } + } + + this.DrawButton=function(drawTop, drawLeft, drawHeight, rtDraw) + { + if (!IFrameSplitOperator.IsNonEmptyArray(this.AryShowButton)) return; + if (this.ButtonPosition==3) return; //垂直按钮在DrawVerticalButton()调用 + + if (this.ButtonPosition==1) + { + drawTop-=drawHeight; + var chartWidth=this.Frame.ChartBorder.GetChartWidth(); + var chartLeft=this.Frame.ChartBorder.GetRight()+this.RightSpaceWidth; + if (drawLeft+this.ButtonBGWidth>chartWidth) //右边不够了 往左移动 { - var xLine=rtButton.Right+this.ButtonSpace/2; - xLine=ToFixedPoint(xLine); - this.Canvas.strokeStyle=this.ButtonSplitLineColor; - this.Canvas.beginPath(); - this.Canvas.moveTo(xLine,rtButton.Top); - this.Canvas.lineTo(xLine,rtButton.Bottom); - this.Canvas.stroke(); + drawLeft=chartWidth-this.ButtonBGWidth; } - */ - left=rtButton.Right+this.ButtonSpace; + if (rtDraw.Left>drawLeft) drawLeft=rtDraw.Left; + + } + else if (this.ButtonPosition==2) + { + drawTop-=drawHeight; + drawLeft=rtDraw.Left; } - if (this.Button.CloseIcon) + 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;iptEnd.Y) return 1; - else if (ptStart.XptEnd.Y) return 2; + 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; } @@ -59975,7 +64838,7 @@ function ChartDrawPictureGannFan() //isDotline 是否是虚线 this.DrawLine=function(ptStart,ptEnd,isDottedline) { - if (isDottedline) this.Canvas.setLineDash([5,10]); + if (isDottedline) this.Canvas.setLineDash(this.LineDash); this.Canvas.strokeStyle=this.LineColor; this.Canvas.beginPath(); @@ -60037,27 +64900,15 @@ function ChartDrawPictureGannFan() var lineHeight=Math.abs(ptStart.Y-ptEnd.Y); if (quadrant===1) { - /* - var line={Start:ptLineStart, End:new Point(), IsDottedLine:false}; - line.End.X=ptStart.X; - line.End.Y=top; - this.LinePoint.push(line); - - line={Start:ptLineStart, End:new Point(), IsDottedLine:false}; - line.End.X=right; - line.End.Y=ptStart.Y; - this.LinePoint.push(line); - */ - 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 in SPLIT_LINE_VALUE) + for(var i=0;i5) { - line={Start:ptLineStart, End:null, IsDottedLine:false,PtEnd:new Point(),Text:SPLIT_LINE_X_TITLE[i]}; + 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); @@ -60066,7 +64917,7 @@ function ChartDrawPictureGannFan() } if (lineHeight>5) { - line={Start:ptLineStart, End:null, IsDottedLine:false,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; + 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); @@ -60076,29 +64927,77 @@ function ChartDrawPictureGannFan() } } - else if (quadrant==4) + else if (quadrant==2) { - /* - var line={Start:ptLineStart, End:new Point(), IsDottedLine:false}; - line.End.X=ptStart.X; - line.End.Y=bottom; + var extendLine=this.CalculateExtendLinePoint(ptStart,ptEnd); + var line={Start:ptLineStart, End:extendLine.Start, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); - line={Start:ptLineStart, End:new Point(), IsDottedLine:false}; - line.End.X=right; - line.End.Y=ptStart.Y; + 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 in SPLIT_LINE_VALUE) + for(var i=0;i5) { - line={Start:ptLineStart, End:null, IsDottedLine:false,PtEnd:new Point(),Text:SPLIT_LINE_X_TITLE[i]}; + 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); @@ -60107,7 +65006,7 @@ function ChartDrawPictureGannFan() } if (lineHeight>5) { - line={Start:ptLineStart, End:null, IsDottedLine:false,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; + 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); @@ -60116,19 +65015,77 @@ function ChartDrawPictureGannFan() } } } - else return false; + 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'; //计算线段 @@ -60155,11 +65112,11 @@ function ChartDrawPictureResistanceLine() var line={Start:ptLineStart, End:extendLine.Start, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); - for(var i in SPLIT_LINE_VALUE) + for(var i=0;i5) { - line={Start:ptLineStart, End:null, IsDottedLine:false,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; + 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); @@ -60167,7 +65124,45 @@ function ChartDrawPictureResistanceLine() 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) { @@ -60175,11 +65170,11 @@ function ChartDrawPictureResistanceLine() var line={Start:ptLineStart, End:extendLine.End, IsDottedLine:false,PtEnd:ptLineEnd, Text:'1:1'}; this.LinePoint.push(line); - for(var i in SPLIT_LINE_VALUE) + for(var i=0;i5) { - line={Start:ptLineStart, End:null, IsDottedLine:false,PtEnd:new Point(), Text:SPLIT_LINE_Y_TITLE[i]}; + 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); @@ -60188,7 +65183,10 @@ function ChartDrawPictureResistanceLine() } } } - else return false; + else + { + return false; + } return true; } @@ -60215,6 +65213,23 @@ function ChartDrawPictureResistanceLine() } } +//阻速线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() { @@ -60236,6 +65251,7 @@ function ChartDrawPictureGoldenSection() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint) return; @@ -60413,6 +65429,7 @@ function ChartDrawPictureTriangle() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; @@ -60532,6 +65549,7 @@ function ChartDrawPictureSymmetryAngle() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; @@ -60626,6 +65644,7 @@ function ChartDrawPictureCircle() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint || drawPoint.length!=2) return; @@ -60689,6 +65708,7 @@ function ChartDrawPictureQuadrangle() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; @@ -60785,6 +65805,7 @@ function ChartDrawPictureFibonacci() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint) return; @@ -60987,6 +66008,7 @@ function ChartDrawLinearRegression(option) { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:true, IsCheckY:true} ); if (!drawPoint || drawPoint.length!=2) @@ -61381,6 +66403,7 @@ function ChartDrawPriceLine() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:true } ); if (!drawPoint) return; @@ -61449,7 +66472,7 @@ function ChartDrawPriceLine() } } -//画图工具-标价线2 支持横屏 +//画图工具-标价线2 支持横屏 支持价格文字在坐标内部显示 function ChartDrawPriceLineV2() { this.newMethod=IChartDrawPicture; //派生 @@ -61465,6 +66488,7 @@ function ChartDrawPriceLineV2() 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) @@ -61474,6 +66498,7 @@ function ChartDrawPriceLineV2() { if (option.TextColor) this.TextColor=option.TextColor; if (option.Title) this.Title=option.Title; + if (IFrameSplitOperator.IsNonEmptyArray(option.TextPosition)) this.TextPosition=option.TextPosition.slice(); } } @@ -61481,6 +66506,7 @@ function ChartDrawPriceLineV2() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( { IsCheckX:false, IsCheckY:true } ); if (!drawPoint) return; @@ -61542,16 +66568,23 @@ function ChartDrawPriceLineV2() var text=price.toFixed(2); var textWidth=this.Canvas.measureText(text).width+2*offset; + var centerPoint=null; if (this.IsHScreen) { - if (chartBorder.Bottom>10) + 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) { - var rtBG={ Left:(xText-textHeight/2), Top:yText , Width: textHeight, Height:textWidth }; + yText=yText-textWidth; + var rtBG={ Left:(xText-textHeight/2), Top:yText , Width:textHeight, Height: textWidth}; } else //框架内部显示 { - yText=yText-textWidth; - var rtBG={ Left:(xText-textHeight/2), Top:yText , Width:textHeight, Height: textWidth}; + var rtBG={ Left:(xText-textHeight/2), Top:yText , Width: textHeight, Height:textWidth }; } this.Canvas.fillStyle=this.LineColor; @@ -61567,13 +66600,13 @@ function ChartDrawPriceLineV2() if (this.Title) { var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio; - if (chartBorder.Bottom>10) + if (bDrawInside) { - var rtTitle={ Left:rtBG.Left, Top:bottom-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth }; + var rtTitle={Left:rtBG.Left, Top:rtBG.Top-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth}; } else { - var rtTitle={Left:rtBG.Left, Top:rtBG.Top-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth} + var rtTitle={ Left:rtBG.Left, Top:bottom-textWidth-1*pixelTatio, Width:textHeight, Height:textWidth }; } this.Canvas.fillStyle=this.LineColor; @@ -61586,17 +66619,25 @@ function ChartDrawPriceLineV2() this.Canvas.fillText(this.Title,0,0); this.Canvas.restore(); } + + centerPoint={ X:ptStart.X, Y:ptStart.Y+(ptEnd.Y-ptStart.Y)/2 }; //中心点 } else { - if (chartBorder.Right>10) + 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, 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; + var rtBG={ Left:xText-textWidth, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight}; } else //框架内部显示 { - var rtBG={ Left:xText-textWidth, Top:(yText-textHeight/2-1*pixelTatio) , Width:textWidth, Height: textHeight}; + 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; @@ -61608,14 +66649,14 @@ function ChartDrawPriceLineV2() if (this.Title) { var textWidth=this.Canvas.measureText(this.Title).width+2*pixelTatio; - if (chartBorder.Right>10) + if (bDrawInside) { - 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; + var rtTitle={Left:rtBG.Left-textWidth, Top:rtBG.Top, Width:textWidth, Height:textHeight} } else { - var rtTitle={Left:rtBG.Left-textWidth, Top:rtBG.Top, Width:textWidth, Height:textHeight} + 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; @@ -61624,9 +66665,11 @@ function ChartDrawPriceLineV2() 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() @@ -61646,11 +66689,13 @@ function 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; @@ -61705,6 +66750,298 @@ function ChartDrawVerticalLine() } } +//画图工具-十字线 支持横屏 +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() { @@ -61729,6 +67066,7 @@ function ChartDrawWaveRuler() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; @@ -61891,6 +67229,7 @@ function ChartDrawWaveRuler2Point() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; @@ -62023,6 +67362,7 @@ function ChartDrawBox() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; @@ -62253,6 +67593,7 @@ function ChartDrawTwoPointDemo() this.LinePoint=[]; this.PointInfo=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint) return; @@ -62490,6 +67831,7 @@ function ChartDrawHLineSegment() 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; @@ -63145,6 +68487,7 @@ function ChartDrawNote() this.TextRect=null; this.PtCenter=null; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint({IsCheckX:true, IsCheckY:true}); if (!drawPoint || drawPoint.length!=1) return; @@ -63528,6 +68871,7 @@ function ChartDrawAnchoredText() if (this.Status<2) return; if(this.Point.length!=1 || !this.Frame) return; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint(); if (!drawPoint || drawPoint.length!=1) return; @@ -63877,6 +69221,7 @@ function ChartDrawPriceLabel() { 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; @@ -64116,6 +69461,7 @@ function ChartDrawPriceNote() this.LinePoint=[]; this.TextRect=null; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; var drawPoint=this.CalculateDrawPoint( {IsCheckX:true, IsCheckY:true} ); if (!drawPoint) return; @@ -64460,6 +69806,7 @@ function ChartDrawFibWedge() 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; @@ -64843,6 +70190,8 @@ function ChartFibRetracement() { 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} ); @@ -65035,6 +70384,8 @@ function ChartFibSpeedResistanceFan() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; + var bCheckXY=false; var drawPoint=this.CalculateDrawPoint( {IsCheckX:bCheckXY, IsCheckY:bCheckXY} ); if (!drawPoint) return; @@ -65300,6 +70651,8 @@ function ChartPriceRange() { 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} ); @@ -65359,6 +70712,9 @@ function ChartPriceRange() 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); @@ -65374,6 +70730,23 @@ function ChartPriceRange() 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(); @@ -65417,6 +70790,8 @@ function ChartDateRange() { this.LinePoint=[]; if (this.IsFrameMinSize()) return; + if (!this.IsShow) return; + var bCheckXY=true; var drawPoint=this.CalculateDrawPoint( {IsCheckX:bCheckXY, IsCheckY:bCheckXY} ); if (!drawPoint) return; @@ -65478,8 +70853,13 @@ function ChartDateRange() //文字输出 + 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`; @@ -65487,8 +70867,28 @@ function ChartDateRange() 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(); @@ -65505,6 +70905,319 @@ function ChartDateRange() } } +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.YkagiItem.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; + } } ////////////////////////////////////////////////////////////////// @@ -68433,7 +74915,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.SourceDataLimit=new Map(); //每个周期缓存数据最大个数 key=周期 value=最大个数 this.CtrlMoveStep=5; //Ctrl+(Left/Right) 移动数据个数 - this.CustomShow=null; //首先显示的K线的起始日期 { Date:日期 PageSize:} + this.CustomShow=null; //首先显示的K线的起始日期 { Date:日期, Time:时间, PageSize:} this.ZoomType=0; //缩放模式 0=最右边固定缩放, 1=十字光标两边缩放 this.IsZoomLockRight=false; this.KLineSize=null; //{ DataWidth:, } @@ -68474,8 +74956,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.StockHistoryDayApiUrl= g_JSChartResource.Domain+'/API/StockHistoryDay'; //股票历史数据 this.TickApiUrl=g_JSChartResource.Domain+'/API/StockDetail'; //当天分笔数据 - this.MinuteDialog; //双击历史K线 弹出分钟走势图 - this.RightMenu; //右键菜单 + this.PopMinuteChart=null; //双击历史K线 弹出分钟走势图 this.BeforeBindMainData=null; //function(funcName) 在BindMainData() 调用前回调用 this.AfterBindMainData=null; //function(funcName) 在BindMainData() 调用前后调用 @@ -68483,8 +74964,9 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.KLineCalculate=null; //K线定制指标计算 this.KLineCalcOption=new Map(); //K线定制指标配置 - this.ScrollBar=null; //横向滚动条 - + this.ScrollBar=null; //横向滚动条 + this.IsAutoSyncDataOffset=true; //增量更新时,是否移动当前屏数据 + this.IsShowKLineDivTooltip=true; //是否显示K线tooltip this.GetKLineCalulate=function() { @@ -69019,47 +75501,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) var hisData=this.ChartOperator_Temp_GetHistroyData(); if (!hisData) return; //数据还没有到达 - var index=null; - if (ChartData.IsDayPeriod(this.Period,true)) - { - for(var i=0;i=obj.Date) - { - index=i; - break; - } - } - } - else if (ChartData.IsMinutePeriod(this.Period,true)) - { - let findTime=obj.Time; - if (IFrameSplitOperator.IsPlusNumber(findTime)) - { - for(var i=0;iobj.Date || (item.Date==obj.Date && item.Time>=findTime)) - { - index=i; - break; - } - } - } - else //只有日期 - { - for(var i=0;i=obj.Date) - { - index=i; - break; - } - } - } - } + var index=this.ChartOperator_GetIndex_ByDateTime(hisData, obj, this.Period, 0); if (index===null) { @@ -69087,6 +75529,29 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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; @@ -69179,6 +75644,63 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.UpdatePointByCursorIndex(); //更新十字光标位子 } + //定位K线的索引 + //searchType 0模糊匹配 1=精确匹配 + this.ChartOperator_GetIndex_ByDateTime=function(hisData, dateTime, period, searchType) + { + if (!hisData) return null; //数据还没有到达 + if (!IFrameSplitOperator.IsNonEmptyArray(hisData.Data)) return null; + if (!IFrameSplitOperator.IsPlusNumber(dateTime.Date) || dateTime.Date<19810101) return null; + + if (ChartData.IsDayPeriod(period, true)) + { + for(var i=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); @@ -69206,6 +75728,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) { 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; @@ -69228,6 +75751,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) { 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) @@ -69300,6 +75824,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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.ChartSplashPaint = new ChartSplashPaint(); @@ -69324,6 +75849,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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) @@ -69362,8 +75888,50 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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 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,y); } + this.OnCustomKeyDown=function(keyID, e) //自定义键盘事件 { if (keyID==37 && e.ctrlKey) //Ctrl+Left @@ -69478,6 +76046,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) var frame=g_ChartFrameFactory.Create("KLineFrame", { ID:i }); frame.Canvas=this.Canvas; + frame.GetExtraCanvas=(name)=>{ return this.GetExtraCanvas(name); }; frame.ChartBorder=border; frame.Identify=i; //窗口序号 frame.RightSpaceCount=this.RightSpaceCount; //右边 @@ -69536,6 +76105,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } var subFrame=new SubFrameItem(); + frame.FrameData.SubFrameItem=subFrame; subFrame.Frame=frame; if (i==0) subFrame.Height=20; @@ -69562,6 +76132,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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); }; @@ -69581,6 +76152,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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; @@ -69601,6 +76173,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } var subFrame=new SubFrameItem(); + frame.FrameData.SubFrameItem=subFrame; subFrame.Frame=frame; subFrame.Height=10; @@ -69638,8 +76211,10 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } //绑定主图K线数据 - this.BindMainData=function(hisData,showCount) + 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; @@ -69660,9 +76235,10 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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; - this.CursorIndex=showCount; - if (this.CursorIndex+dataOffset>=hisData.Data.length) this.CursorIndex=hisData.Data.length-1-dataOffset; - if (this.CursorIndex<0) this.CursorIndex=0; //不一定对啊 - if (this.CustomShow) //定制显示 1次有效 { this.SetCustomShow(this.CustomShow,hisData); @@ -69699,6 +76283,30 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } } + 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) //历史数据为空,当前收到数据大于一屏的数据,显示最新数据 + if (IFrameSplitOperator.IsNumber(lastDataCount)) { - newDataCount=hisData.Data.length-xPointCount; - JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] history data is empty. [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`); + if (lastDataCount>0 && hisData.Data.length>lastDataCount) + { + newDataCount=hisData.Data.length-lastDataCount; + JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`); + } + else if (lastDataCount==0 && hisData.Data.length>xPointCount) //历史数据为空,当前收到数据大于一屏的数据,显示最新数据 + { + newDataCount=hisData.Data.length-xPointCount; + JSConsole.Chart.Log(`[KLineChartContainer::UpdateMainData] history data is empty. [count=${lastDataCount}->${hisData.Data.length}], [newDataCount=${newDataCount}], [Pagesize=${xPointCount}]`); + } } this.ChartPaint[0].Data=hisData; @@ -69754,37 +76365,21 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.SetCustomShow=function(customShow,hisData) { - if (!customShow || !customShow.Date || customShow.Date<19910101) return; - - var firstDate=customShow.Date; - var index=null; - for(var i =0;i=firstDate) - { - index=i; - break; - } - } + var index=this.ChartOperator_GetIndex_ByDateTime(hisData,customShow, this.Period, 0); if (index===null) { - JSConsole.Chart.Log(`[KLineChartContainer::SetCustomShow] Can't find first date=${firstDate}`); + JSConsole.Chart.Log("[KLineChartContainer::SetCustomShow] Can't find index by customShow=",customShow); return; } - var count=hisData.Data.length-index; - if (customShow.PageSize>0) count=customShow.PageSize; - - var customShowCount=count; - var pageSize=this.GetMaxMinPageSize(); - if (count>pageSize.Max) customShowCount=pageSize.Max; - else if (count${this.SourceData.Data.length}]`); + 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; @@ -71139,7 +77746,8 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) //绑定数据 this.UpdateMainData(bindData,lastDataCount); - this.BindInstructionIndexData(bindData); //执行指示脚本 + this.UpdateOverlayMinuteRealtimeData(data); //更新叠加股票数据 + this.BindInstructionIndexData(bindData); //执行指示脚本 for(var i=0; i=0) indexData.FloatPrecision=option.FloatPrecision; - if (option.StringFormat>0) indexData.StringFormat=option.StringFormat; - if (option.Args) indexData.Args=option.Args; - if (option.TitleFont) indexData.TitleFont=option.TitleFont; - if (option.IsShortTitle) indexData.IsShortTitle=option.IsShortTitle; - if (option.Lock) indexData.Lock=option.Lock; - } - - return this.ChangeScriptIndex(windowIndex, indexData,option); + + JSIndexScript.ModifyAttribute(indexInfo, option); + return this.ChangeScriptIndex(windowIndex, indexInfo, option); } //主图指标 @@ -72125,7 +78778,8 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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.IsBool(obj.IsShowIndexTitle)) frame.IsShowIndexTitle=obj.IsShowIndexTitle; + 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(); @@ -72158,21 +78812,8 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } else if (indexInfo) { - var args=indexInfo.Args; - if (obj.Args) args=obj.Args; //外部可以设置参数 - let indexData = - { - Name:indexInfo.Name, Script:indexInfo.Script, Args: args, ID:indexName, - //扩展属性 可以是空 - KLineType:indexInfo.KLineType, YSpecificMaxMin:indexInfo.YSpecificMaxMin, YSplitScale:indexInfo.YSplitScale, - FloatPrecision:indexInfo.FloatPrecision, Condition:indexInfo.Condition, - OutName:indexInfo.OutName - }; - - if (IFrameSplitOperator.IsNumber(obj.FloatPrecision)) indexData.FloatPrecision=obj.FloatPrecision; - if (IFrameSplitOperator.IsNumber(obj.StringFormat)) indexData.StringFormat=obj.StringFormat; - if (IFrameSplitOperator.IsBool(obj.IsSync)) indexData.IsSync=obj.IsSync; - var scriptIndex=new OverlayScriptIndex(indexData.Name,indexData.Script,indexData.Args,indexData); //脚本执行 + 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; } @@ -72268,28 +78909,30 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) //{ Type: 0=普通坐标 1=百分比坐标 (右边坐标刻度) 2=对数对标 3=等比坐标, IsReverse:是否反转坐标 } this.ChangeCoordinateType=function(obj) { - if (!this.Frame && !this.Frame.SubFrame) return; - if (!this.Frame.SubFrame.length) return; + if (!this.Frame) return; + if (!IFrameSplitOperator.IsNonEmptyArray(this.Frame.SubFrame)) return; + if (!this.Frame.SubFrame[0]) return; + var frame=this.Frame.SubFrame[0].Frame; if (IFrameSplitOperator.IsNumber(obj)) //老版本 { var type=obj; if (type==2) //反转坐标 { - this.Frame.SubFrame[0].Frame.CoordinateType=1; + frame.CoordinateType=1; } else if(type==1) { - this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=type; + frame.YSplitOperator.CoordinateType=type; } else if (type==0) { - this.Frame.SubFrame[0].Frame.CoordinateType=0; - this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=0; + frame.CoordinateType=0; + frame.YSplitOperator.CoordinateType=0; } else if (type==3) //对数坐标 { - this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=2; + frame.Frame.YSplitOperator.CoordinateType=2; } else { @@ -72298,11 +78941,15 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } else { - if (obj.Type>=0 && obj.Type<=5) this.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType=obj.Type; - if (obj.IsReverse===true) this.Frame.SubFrame[0].Frame.CoordinateType=1; - else if (obj.IsReverse==false) this.Frame.SubFrame[0].Frame.CoordinateType=0; + if (obj.Type>=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(); @@ -72323,6 +78970,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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) { @@ -72333,6 +78981,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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=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; @@ -72577,17 +79240,25 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.BindIndexData(i,bindData); } + for(var i=0;i0) + if (IFrameSplitOperator.IsNonEmptyArray(option.Windows)) { var windows=option.Windows; - var systemScript = new JSIndexScript(); - for(var i in windows) + + for(var i=0; i=this.WindowIndex.length) break; //暂时不支持 动态增加/减少 var item=windows[i]; @@ -73054,17 +79690,25 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) else { var indexID=item.Index; + var systemScript = new JSIndexScript(); var indexInfo = systemScript.Get(indexID); if (indexInfo) { - var args=indexInfo.Args; - if (item.Args) indexInfo.Args=item.Args; + 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(); @@ -73862,32 +80506,346 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } } - //注册鼠标右键事件 this.OnRightMenu=function(x,y,e) { var pixelTatio = GetDevicePixelRatio(); //x,y 需要乘以放大倍速 - if (this.RightMenu) - { - var frameId=this.Frame.PtInFrame(x*pixelTatio,y*pixelTatio); - e.data={ Chart:this, FrameID:frameId }; - this.RightMenu.DoModal(e); - } - + 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 frameId=this.Frame.PtInFrame(x*pixelTatio,y*pixelTatio); 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 klineChart=this.ChartPaint[0]; + var klineType=klineChart.DrawType; + var bThinAKBar=klineChart.IsThinAKBar; + var priceGap=klineChart.PriceGap; //缺口配置信息 + var coordinateType=null, yCoordinateType=null; //坐标类型 + var mainFrame=null; + if (this.Frame.SubFrame[0] && this.Frame.SubFrame[0].Frame) mainFrame=this.Frame.SubFrame[0].Frame; + if (mainFrame) + { + coordinateType=mainFrame.CoordinateType; + if (mainFrame.YSplitOperator) yCoordinateType=mainFrame.YSplitOperator.CoordinateType; + } + + var aryKLineInfo=[]; //信息地雷 + 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=[]; - this.ChartDrawStorageCache; + 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} ); @@ -74321,16 +81279,13 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) } } } - - var event=null; - if (this.mapEvent.has(JSCHART_EVENT_ID.DBCLICK_KLINE)) event=this.mapEvent.get(JSCHART_EVENT_ID.DBCLICK_KLINE); - - if (!this.MinuteDialog && !event) return; var tooltip=new TooltipData(); if (!this.PtInChartPaintTooltip(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) //清空单击定时器 @@ -74339,15 +81294,15 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) this.ClickChartTimer=null; } - var data={ Tooltip:tooltip, Stock:{Symbol:this.Symbol, Name:this.Name }, X:e.clientX, Y:e.clientY }; + 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.MinuteDialog) - { - e.data={Chart:this,Tooltip:tooltip}; - this.MinuteDialog.DoModal(e); - } + //内置弹分时图 + if (!this.PopMinuteChart) return; + + this.ShowMinuteChartDialog({ Chart:this,Tooltip:tooltip, e:e }, x,y); } this.CancelAutoUpdate=function() //关闭停止更新 @@ -74394,7 +81349,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) self.RequestRealtimeData(); //更新最新行情 //self.ReqeustKLineInfoData(); } - else if (ChartData.IsMinutePeriod(self.Period,true) || ChartData.IsSecondPeriod(self.Period)) + else if (ChartData.IsMinutePeriod(self.Period,true) || ChartData.IsSecondPeriod(self.Period) || ChartData.IsMilliSecondPeriod(self.Period)) { self.RequestMinuteRealtimeData(); //请求分钟数据 } @@ -75266,7 +82221,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_TITLE_BUTTON); if (event && event.Callback) { - var data={ Info:button, PreventDefault:false }; //PreventDefault 是否阻止内置的点击处理 + var data={ Info:button, PreventDefault:false, e:e }; //PreventDefault 是否阻止内置的点击处理 event.Callback(event,data,this); if (data.PreventDefault) return; } @@ -75278,7 +82233,7 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CLICK_EXTENDCHART_BUTTON); if (event && event.Callback) { - var data={ Info:button, PreventDefault:false }; //PreventDefault 是否阻止内置的点击处理 + var data={ Info:button, PreventDefault:false, e:e }; //PreventDefault 是否阻止内置的点击处理 event.Callback(event,data,this); if (data.PreventDefault) return; } @@ -75367,6 +82322,18 @@ function KLineChartContainer(uielement,OffscreenElement, cacheElement) 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(); + } } //API 返回数据 转化为array[] @@ -75386,6 +82353,7 @@ KLineChartContainer.JsonDataToHistoryData=function(data) 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; @@ -75407,6 +82375,8 @@ KLineChartContainer.JsonDataToHistoryData=function(data) 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]; //后复权因子 @@ -75557,7 +82527,7 @@ KLineChartContainer.JsonDataToMinuteRealtimeDataV2=function(data,symbol) var date = 0, yclose = 1, open = 2, high = 3, low = 4, close = 5, vol = 6, amount = 7, time = 8, position=9; var orderFlow=JSCHART_DATA_FIELD_ID.KLINE_ORDERFLOW; var yClose=null; - + var aryMinuteData=[]; for (var i = 0; i < overlayData.data.length; ++i) { var item = new HistoryData(); @@ -75766,12 +82736,12 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.IsShowBeforeData=false; //是否显示盘前集合竞价数据 (当日) this.BeforeOpenData=null; //盘前集合竞价数据 - this.IsBeforeData=false; //是否支持显示盘前集合竞价数据 + this.IsBeforeData=false; //是否支持显示盘前集合竞价数据(当日) this.IsShowAfterData=false; //收盘集合竞价 this.AfterCloseData=null; //收盘集合竞价数据 - this.IsAfterData=false; //是否支持显示收盘集合竞价数据 - this.ShareAfterVol=0; //1=盘后数据成交量Y坐标和主图共享 2=盘后数据成交量Y坐标和盘前共享 + this.IsAfterData=false; //是否支持显示收盘集合竞价数据(当日) + this.ShareAfterVol=0; //1=盘后数据成交量Y坐标和主图共享 2=盘后数据成交量Y坐标和盘前共享 this.ExtendWidth={ Left: 120, Right:120 } ; //单日分时图 左右扩展图形宽度 this.IsShowLead=true; //指数是否显示领先指标 @@ -75781,7 +82751,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.IsShowMultiDayAfterData=false; //多日分时图 是否显示收盘集合竞价 this.MultiDayAfterCloseData=null; //多日分时图 收盘集合竞价数据 - this.MultiDayExtendWidth={ Left:20, Right:20 }; //多日分时图 左右扩展图形宽度 + this.MultiDayExtendWidth={ Left:40, Right:20 }; //多日分时图 左右扩展图形宽度 this.ChartDrawStorage=new ChartDrawStorage(); this.ChartDrawStorageCache=null; //首次需要创建的画图工具数据 @@ -75798,10 +82768,11 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.DayOffset={ Offset:0, ShowDayCount:-1, DataOffset:0, DayCount:1, }; //Offset 日期偏移 , DataOffset数据偏移 this.PageInfo={ Enable:false, Offset:-8888, ShowDayCount:4 }; //分页配置 - this.DataStatus={ MultiDay:false, LatestDay:false }; //MultiDay=多日 LatestDay:当天 + this.DataStatus={ MultiDay:false, LatestDay:false, LatestDate:null}; //MultiDay=多日 LatestDay:当天 LatestDate:最后的日期 this.ZoomStepPixel=50; - + this.BaselineType=0; //基准线类型 0=最新昨收盘 1=多日前昨收盘 + this.EnableNightDayBG=false; //是否启动夜盘背景色 //集合竞价设置 obj={ Left:true/false, Right:true/false, MultiDay:{Left:, Right:} } this.SetCallCationDataBorder=function(obj) @@ -75883,7 +82854,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) { this.ShowCallAuctionData({ Left:false, Right:false, MultiDay:{ Left:false, Right:false } }); } - if (button.ID==JSCHART_BUTTON_ID.CLOSE_OVERLAY_INDEX) + else if (button.ID==JSCHART_BUTTON_ID.CLOSE_OVERLAY_INDEX) { var id=button.IndexID; if (id) this.DeleteOverlayWindowsIndex(id); @@ -76148,11 +83119,10 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) //this.UIElement.style.cursor="default"; this.SetCursor({Cursor:"default"}); - var x=drag.Click.X-uielement.getBoundingClientRect().left; - var y=drag.Click.Y-uielement.getBoundingClientRect().top; - var x2=e.clientX-uielement.getBoundingClientRect().left; - var y2=e.clientY-uielement.getBoundingClientRect().top; - this.ShowSelectRect(x,y,x2,y2); + 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; @@ -76703,6 +83673,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) 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; @@ -76780,12 +83751,14 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) drawPictrueData.Y=(touches[0].clientY-uielement.getBoundingClientRect().top); if (this.GetChartDrawPictureByPoint(drawPictrueData)) { - drawPictrueData.ChartDrawPicture.Status=20; + 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) { @@ -76804,6 +83777,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) { this.DragTimer=setTimeout(function() { + self.IsPress=true; if (drag.Click.X==drag.LastMove.X && drag.Click.Y==drag.LastMove.Y) { var mouseDrag=self.MouseDrag; @@ -76820,6 +83794,8 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) if (this.EnableScrollUpDown==false) T_ShowCorssCursor(); //移动十字光标 + else if (this.IsClickShowCorssCursor) + T_ShowCorssCursor(); } if (this.EnableZoomIndexWindow) @@ -76870,7 +83846,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) var moveUpDown=Math.abs(drag.LastMove.Y-touches[0].clientY); moveSetp=parseInt(moveSetp); - if (this.CurrentChartDrawPicture) + if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.EnableMove===true) { var drawPicture=this.CurrentChartDrawPicture; if (drawPicture.Status==1 || drawPicture.Status==2) @@ -77229,22 +84205,158 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) //注册鼠标右键事件 this.OnRightMenu=function(x,y,e) { - if (this.RightMenu) - { - var frameId=this.Frame.PtInFrame(x,y); - e.data={ Chart:this, FrameID:frameId }; - this.RightMenu.DoModal(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 frameId=this.Frame.PtInFrame(x,y); 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 { return this.GetEventCallback(id); } //创建等待提示 @@ -77402,16 +84515,19 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) 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) + for(var i=0;i { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; + titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint.push(titlePaint); } @@ -77460,6 +84576,8 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) frame.GlobalOption=this.GlobalOption; if (i<2) frame.ChartBorder.TitleHeight=0; frame.XPointCount=243; + frame.HQChart=this; + frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (i>=2) { @@ -77510,6 +84628,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) } var subFrame=new SubFrameItem(); + frame.FrameData.SubFrameItem=subFrame; subFrame.Frame=frame; if (i==0) subFrame.Height=20; @@ -77548,6 +84667,8 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) frame.Identify=id; //窗口序号 frame.XPointCount=243; frame.GlobalOption=this.GlobalOption; + frame.HQChart=this; + frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } if (id>=2) @@ -77596,6 +84717,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) } var subFrame=new SubFrameItem(); + frame.FrameData.SubFrameItem=subFrame; subFrame.Frame=frame; subFrame.Height=10; @@ -77621,7 +84743,8 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) titlePaint.Frame=this.Frame.SubFrame[index].Frame; titlePaint.Canvas=this.Canvas; titlePaint.LanguageID=this.LanguageID; - titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } + titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); }; + titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint[index+1]=titlePaint; this.SetSubFrameOption(subFrame,option); @@ -77667,12 +84790,16 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) //删除某一个窗口的指标 this.DeleteIndexPaint=function(windowIndex,bCallDestroy) { - let paint=new Array(); //踢出当前窗口的指标画法 - for(let i in this.ChartPaint) + var subFrame=this.Frame.SubFrame[windowIndex].Frame; + if (!subFrame) return; + + var paint=[]; //踢出当前窗口的指标画法 + for(var i=0;i=this.Frame.SubFrame.length) windowIndex=2; - let indexData = - { - Name:indexInfo.Name, Script:indexInfo.Script, Args: indexInfo.Args, ID:indexName , - //扩展属性 可以是空 - KLineType:indexInfo.KLineType, YSpecificMaxMin:indexInfo.YSpecificMaxMin, YSplitScale:indexInfo.YSplitScale, - FloatPrecision:indexInfo.FloatPrecision, Condition:indexInfo.Condition,StringFormat:indexInfo.StringFormat, - OutName:indexInfo.OutName - }; + JSIndexScript.ModifyAttribute(indexInfo, option) - if (option) - { - if (option.FloatPrecision>=0) indexData.FloatPrecision=option.FloatPrecision; - if (option.StringFormat>0) indexData.StringFormat=option.StringFormat; - if (option.Args) indexData.Args=option.Args; - if (IFrameSplitOperator.IsNumber(option.YSplitType)) indexData.YSplitType=option.YSplitType; - if (option.Lock) indexData.Lock=option.Lock; - } - - return this.ChangeScriptIndex(windowIndex, indexData,option); + return this.ChangeScriptIndex(windowIndex, indexInfo, option); } //设置指标窗口个数 @@ -77841,6 +84953,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) 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(); @@ -77853,6 +84966,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.Frame.SubFrame.splice(count,currentLength-count); this.WindowIndex.splice(count,currentLength-count); + this.TitlePaint.splice(count+1,currentLength-count); } else { @@ -77868,6 +84982,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) titlePaint.LanguageID=this.LanguageID; titlePaint.GetEventCallback=(id)=> { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; + titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint[i+1]=titlePaint; } @@ -77909,9 +85024,10 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) var startWindowIndex=2; count+=startWindowIndex; - var dayCount=null; + var dayCount=null, symbol=null; if (IFrameSplitOperator.IsNumber(option.DayCount) && option.DayCount!=this.DayCount) dayCount= option.DayCount; //天数 - var bRefreshData= (dayCount!=null); + if (option.Symbol) symbol=option.Symbol; + var bRefreshData= (dayCount!=null || symbol!=null); //清空所有的指标图型 for(var i=startWindowIndex;i { return this.GetEventCallback(id); } titlePaint.SelectedChart=this.SelectedChart; + titlePaint.MainTitlePaint=this.TitlePaint[0]; this.TitlePaint[i+1]=titlePaint; } } - var systemScript = new JSIndexScript(); - 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;i1) - { - this.ChartDrawPicture=[]; - } - else - { - this.ReloadChartDrawPicture(); - } - + this.ReloadChartDrawPicture(); this.ResetDataStatus(); this.ClearIndexPaint(); //清空指标 this.Frame.ClearYCoordinateMaxMin(); @@ -78349,6 +85489,14 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.RequestData(); } + this.ChangeBaselineType=function(type) + { + if (this.BaselineType==type) return; + + this.BaselineType=type; + if (this.DayCount>1) this.RequestData(); + } + //[{ Symbol: , Color, Option: }] this.OverlaySymbols=function(aryData, option) { @@ -78589,7 +85737,11 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) } } - if (optionChanged) this.RequestData(); + if (optionChanged) + { + this.Frame.ClearYCoordinateMaxMin(); + this.RequestData(); + } } this.RequestData=function() @@ -78659,11 +85811,17 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) if (this.NetworkFilter) { + var callCation= + { + Before:this.IsShowMultiDayBeforeData , + After:this.IsShowMultiDayAfterData + } //集合竞价 + var obj= { Name:'MinuteChartContainer::RequestHistoryMinuteData', //类名::函数 Explain:'多日分时数据', - Request:{ Url:self.HistoryMinuteApiUrl, Data:{daycount:self.DayCount, symbol:self.Symbol}, Type:'POST' }, + Request:{ Url:self.HistoryMinuteApiUrl, Data:{daycount:self.DayCount, symbol:self.Symbol, callcation:callCation }, Type:'POST' }, Self:this, PreventDefault:false }; @@ -78826,10 +85984,13 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) var upperSymbol=this.Symbol.toUpperCase(); - - var yClose=this.DayData[0].YClose; var isFutures=MARKET_SUFFIX_NAME.IsFutures(upperSymbol); - if (IFrameSplitOperator.IsNumber(this.DayData[0].YClearing) && isFutures) yClose=this.DayData[0].YClearing; //期货使用前结算价 + var dayItem=this.DayData[0]; //最新 + if (this.BaselineType===1) dayItem=this.DayData[this.DayData.length-1]; //多日前 + + var yClose=dayItem.YClose; + if (IFrameSplitOperator.IsNumber(dayItem.YClearing) && isFutures) yClose=dayItem.YClearing; //期货使用前结算价 + this.BindMainData(sourceData,yClose); //外汇 均线暂时不用 @@ -78863,6 +86024,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.TitlePaint[0].IsShowDate=true; this.UpdateDataOffset(); this.UpdateFrameMaxMin(); //调整坐标最大 最小值 + this.CreateChartDrawPictureByStorage(); //创建画图工具 //执行脚本 if (this.Frame.SubFrame.length>2) @@ -79042,11 +86204,9 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) dateRange=this.SourceData.GetDateRange(); } - var callCation= - { - Before:(this.IsShowBeforeData && this.DayCount===1), - After:(this.IsShowAfterData && this.DayCount===1) - } //集合竞价 + var callCation={ Before:this.IsShowBeforeData, After:this.IsShowAfterData } //集合竞价 + if (this.DayCount>1) callCation={ Before:this.IsShowMultiDayBeforeData, After:this.IsShowMultiDayAfterData } //多日集合竞价 + var obj= { Name:'MinuteChartContainer::RequestMinuteData', //类名::函数名 @@ -79090,7 +86250,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) 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 }; + var data={ MinuteData:this.SourceData, Stock:{ Symbol:this.Symbol, Name:this.Name }, Option:option, DataStatus:this.DataStatus }; event.Callback(event,data,this); } @@ -79161,7 +86321,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.UpdateLatestMinuteDataV2(minuteData); this.UpdateHistoryMinuteUI(updateTime); this.RecvMinuteDataEvent({FunctionName:"RecvUpdateMinuteData"} ); - this.RequestOverlayMinuteData(); //请求叠加数据 (主数据下载完再下载) + this.RequestOverlayMinuteData(); //请求叠加数据 (主数据下载完再下载) this.BindAllOverlayIndexData(this.SourceData); this.AutoUpdateEvent(true, "MinuteChartContainer::RecvUpdateMinuteData"); this.AutoUpdate(); @@ -79288,6 +86448,9 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) if (this.IsBeforeData) this.BeforeOpenData=beforeOpenData; if (this.IsAfterData) this.AfterCloseData=afterCloseData; + var bFirstData=(this.DataStatus.LatestDay==false); //首条单日数据 + + this.DataStatus.LatestDate=data.stock[0].date; //保存下最后一天的日期 this.DataStatus.LatestDay=true; if (this.DayCount>1) //多日走势图 @@ -79304,6 +86467,15 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) return; } + if (this.IsOnTouch==true) //正在操作中不更新数据 + { + if (this.SourceData && IFrameSplitOperator.IsNonEmptyArray(this.SourceData.Data)) + { + this.AutoUpdate(); + return; + } + } + //原始数据 var sourceData=new ChartData(); sourceData.Data=aryMinuteData; @@ -79376,7 +86548,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) var chartInfo=this.GetChartMinuteInfo(); if (chartInfo) chartInfo.SourceData=this.SourceData; //数据绑定到信息地雷上 - this.RecvMinuteDataEvent( {FunctionName:"RecvMinuteData"} ); + this.RecvMinuteDataEvent( {FunctionName:"RecvMinuteData", Day:{ IsFirstData:bFirstData} } ); this.RequestMinuteInfoData(); this.RequestOverlayMinuteData();//请求叠加数据 (主数据下载完再下载) this.CreateChartDrawPictureByStorage(); //创建画图工具 @@ -80201,10 +87373,10 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) frame.MainFrame=subFrame.Frame; frame.ChartBorder=subFrame.Frame.ChartBorder; frame.GlobalOption=this.GlobalOption; - if (obj.ShowRightText===true) frame.IsShow=true; - else if (obj.ShowRightText===false) frame.IsShow=false; - if (obj.IsShareY===true) frame.IsShareY=true; + if (IFrameSplitOperator.IsBool(obj.ShowRightText)) frame.IsShow=obj.ShowRightText; + if (IFrameSplitOperator.IsBool(obj.IsShareY)) frame.IsShareY=obj.IsShareY; if (IFrameSplitOperator.IsBool(obj.IsCalculateYMaxMin)) frame.IsCalculateYMaxMin=obj.IsCalculateYMaxMin; //是否计算Y最大最小值 + if (IFrameSplitOperator.IsNumber(obj.IsShowMainFrame)) frame.IsShowMainFrame=obj.IsShowMainFrame; frame.YSplitOperator=new FrameSplitY(); frame.YSplitOperator.LanguageID=this.LanguageID; @@ -80232,10 +87404,8 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) } else if (indexInfo) { - let indexData = indexInfo; - if (obj.Args) indexData.Args=obj.Args; //外部可以设置参数 - - var scriptIndex=new OverlayScriptIndex(indexData.Name,indexData.Script,indexData.Args,indexData); //脚本执行 + 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; } @@ -80318,21 +87488,6 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.WindowIndex[windowIndex].Create(this,windowIndex); } - //获取当前的显示的指标 - this.GetIndexInfo=function() - { - var aryIndex=[]; - for(var i in this.WindowIndex) - { - var item=this.WindowIndex[i]; - var info={Name:item.Name}; - if (item.ID) info.ID=item.ID; - aryIndex.push(info); - } - - return aryIndex; - } - this.OnTouchFinished=function() { if (this.CorssCursorTouchEnd===true) //手势离开十字光标消失 @@ -80380,17 +87535,6 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) chart.SetOption(option); this.ExtendChartPaint.push(chart); return chart; - case '画图工具': - chart=new DrawToolsButton(); - 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 "MinuteBackgroundPaint": chart=new MinuteBackgroundPaint(); chart.Canvas=this.Canvas; @@ -80598,7 +87742,11 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) this.ReloadChartDrawPicture=function() { this.ChartDrawPicture=[]; - this.ChartDrawStorageCache; + 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 } ); @@ -80609,7 +87757,8 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) { if (!this.ChartDrawStorageCache || this.ChartDrawStorageCache.length<=0) return; - for(var i in this.ChartDrawStorageCache) + var self=this; + for(var i=0; i{ return this.GetActiveDrawPicture(); } if (drawPicture.ClassName==='ChartDrawPictureText') drawPicture.IsInitialized=true; @@ -80672,6 +87824,7 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) { var value=frame.GetXData(x); index=parseInt(value.toFixed(0)); + if (IFrameSplitOperator.IsNumber(data.DataOffset)) index+=data.DataOffset; //加上数据偏移 } else if (clientPos>=100 && clientPos<=199) { @@ -80795,6 +87948,134 @@ function MinuteChartContainer(uielement,offscreenElement,cacheElement) return false; } + + this.ClearSelectedXBorder=function() + { + if (!this.GlobalOption || !this.GlobalOption.SelectedXBorder) return; + var item=this.GlobalOption.SelectedXBorder; + item.Date=null; + } + + this.DrawSelectedXBorder=function() + { + if (this.DayCount<=1) return null; + if (this.Frame.IsHScreen===true) return null; + + if (!this.GlobalOption || !this.GlobalOption.SelectedXBorder) return; + var item=this.GlobalOption.SelectedXBorder; + if (!IFrameSplitOperator.IsPlusNumber(item.Mode)) return; + if (!IFrameSplitOperator.IsPlusNumber(item.Date)) return; + if (!IFrameSplitOperator.IsNonEmptyArray(this.DayData)) return; + + var rtSelected=null; + var dayIndex=item.DayIndex; + var border=this.Frame.ChartBorder.GetBorder(); + var rtClient={ Left:border.Left, Top:border.Top, Right:border.Right, Bottom: border.Bottom }; + rtClient.Width=rtClient.Right-rtClient.Left; + var mainFrame=this.Frame.SubFrame[0].Frame; //主图框架 + var xPointCount=mainFrame.XPointCount; + var minuteCount=mainFrame.MinuteCount; + var lDayCount=xPointCount/minuteCount; + var dayWidth=rtClient.Width/lDayCount; + + if (border.DayBorder) + { + var dayIndex=-1; + 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; + } } //盘前数据 @@ -80804,7 +88085,7 @@ MinuteChartContainer.JsonDataToBeforeOpenData=function(data) var upperSymbol=symbol.toUpperCase(); var isSHSZ=MARKET_SUFFIX_NAME.IsSHSZ(upperSymbol); - var yClose=data.stock[0].yclos; + var yClose=data.stock[0].yclose; var preClose=data.stock[0].yclose; //前一个数据价格 var stockData=data.stock[0]; var date=stockData.date; //日期 @@ -81431,6 +88712,7 @@ MinuteChartContainer.JosnDataToAfterCloseDataArray=function(data) /* 历史分钟走势图 */ +/* 废弃 统一使用 MinuteChartContainer function HistoryMinuteChartContainer(uielement) { this.newMethod=MinuteChartContainer; //派生 @@ -81475,17 +88757,6 @@ function HistoryMinuteChartContainer(uielement) this.TitlePaint[0].Frame=this.Frame.SubFrame[0].Frame; this.TitlePaint[0].Canvas=this.Canvas; this.TitlePaint[0].IsShowDate=true; - - /* - //主图叠加画法 - var paint=new ChartOverlayKLine(); - paint.Canvas=this.Canvas; - paint.ChartBorder=this.Frame.SubFrame[0].Frame.ChartBorder; - paint.ChartFrame=this.Frame.SubFrame[0].Frame; - paint.Name="Overlay-KLine"; - this.OverlayChartPaint[0]=paint; - */ - } //设置交易日期 @@ -81631,6 +88902,7 @@ HistoryMinuteChartContainer.JsonDataToMinuteData=function(data) return aryMinuteData; } +*/ ///////////////////////////////////////////////////////////////////////////// // 自定义指数 @@ -82458,6 +89730,7 @@ function KLineChartHScreenContainer(uielement) { if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash == true) return; + this.IsPress=false; this.PhonePinch=null; this.IsOnTouch=true; this.TouchDrawCount=0; @@ -82577,6 +89850,7 @@ function KLineChartHScreenContainer(uielement) var self=this; this.DragTimer=setTimeout(function() { + self.IsPress=false; if (drag.Click.X==drag.LastMove.X && drag.Click.Y==drag.LastMove.Y) //手指没有移动,出现十字光标 { var mouseDrag=self.MouseDrag; @@ -82825,6 +90099,7 @@ function KLineChartHScreenContainer(uielement) 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(); @@ -82870,6 +90145,7 @@ function KLineChartHScreenContainer(uielement) var frame=g_ChartFrameFactory.Create("KLineHScreenFrame", { ID:i }); frame.Canvas=this.Canvas; + frame.GetExtraCanvas=(name)=>{ return this.GetExtraCanvas(name); }; frame.ChartBorder=border; frame.Identify=i; //窗口序号 frame.RightSpaceCount=this.RightSpaceCount; //右边 @@ -82919,6 +90195,7 @@ function KLineChartHScreenContainer(uielement) } var subFrame=new SubFrameItem(); + frame.FrameData.SubFrameItem=subFrame; subFrame.Frame=frame; if (i==0) subFrame.Height=20; @@ -82968,6 +90245,7 @@ function MinuteChartHScreenContainer(uielement) 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(); @@ -83021,6 +90299,8 @@ function MinuteChartHScreenContainer(uielement) frame.Identify=i; if (i<2) frame.ChartBorder.TitleHeight=0; frame.XPointCount=243; + frame.HQChart=this; + frame.GetEventCallback=(id)=> { return this.GetEventCallback(id); } var DEFAULT_HORIZONTAL=[9,8,7,6,5,4,3,2,1]; frame.HorizontalMax=DEFAULT_HORIZONTAL[0]; @@ -83063,6 +90343,7 @@ function MinuteChartHScreenContainer(uielement) } var subFrame=new SubFrameItem(); + frame.FrameData.SubFrameItem=subFrame; subFrame.Frame=frame; if (i==0) subFrame.Height=20; @@ -86203,142 +93484,6 @@ function KLineInfoTooltip(divElement) } } -//历史K线上双击 弹出分钟走势图框 -function MinuteDialog(divElement) -{ - this.newMethod=IDivDialog; //派生 - this.newMethod(divElement); - delete this.newMethod; - - - this.JSChart=null; - this.Height=500; - this.Width=600; - this.Symbol; - this.TradeDate; - this.HistoryData; - - //显示窗口 - this.Show=function(left,top,width,height) - { - var div=document.getElementById(this.ID); - if (!div) return false; - - var findDiv=div.getElementsByClassName("minute-hqchart"); - if (!findDiv || findDiv.length!=1) return false; - var klineDiv=findDiv[0]; - - if (IFrameSplitOperator.IsNumber(width)) div.style.width=width+"px"; - if (IFrameSplitOperator.IsNumber(height)) div.style.height=height+"px"; - if (IFrameSplitOperator.IsNumber(left)) div.style.left=left+"px"; - if (IFrameSplitOperator.IsNumber(top)) div.style.top=top+"px"; - - div.style.display='block'; - - var klineWdith=klineDiv.offsetWidth; - var klineTop=klineDiv.offsetTop; - klineDiv.style.width=klineWdith+"px"; - klineDiv.style.height=(height-klineTop-5)+"px"; - } - - this.Create=function() - { - this.ID=Guid(); - var div=document.createElement('div'); - div.className='jchart-kline-minute-box'; - div.id=this.ID; - var hqchartID=Guid(); - div.innerHTML=`
`; - div.style.width=this.Height+'px'; - div.style.height=this.Width+'px'; - - this.DivElement.appendChild(div); - this.JSChart=JSChart.Init(document.getElementById(hqchartID)); - - var option= - { - Type:'历史分钟走势图', - Symbol:this.Symbol, //股票代码 - IsAutoUpdate:false, //是自动更新数据 - - IsShowRightMenu:false, //右键菜单 - HistoryMinute: { TradeDate:this.TradeDate, IsShowName:false, IsShowDate:false } //显示的交易日期 - }; - - this.JSChart.SetOption(option); - } - - this.BindClose=function(chart) - { - //关闭按钮 - $("#"+this.ID+" .close-munite").click( - { - Chart:chart - }, - function(event) - { - var chart=event.data.Chart; - chart.MinuteDialog.Hide(); - } - ); - } - - this.DoModal=function(event) - { - this.UpColor=g_JSChartResource.UpTextColor; - this.DownColor=g_JSChartResource.DownTextColor; - this.UnchagneColor=g_JSChartResource.UnchagneTextColor; - - var chart=event.data.Chart; - var tooltip=event.data.Tooltip; - var dialog=chart.MinuteDialog; - - dialog.Symbol=chart.Symbol; - dialog.TradeDate=tooltip.Data.Date; - - if(!dialog) return; - if (dialog.ID==null) - { - dialog.Create(); //第1次 需要创建div - } - else - { - dialog.JSChart.JSChartContainer.TradeDate=dialog.TradeDate; - dialog.JSChart.ChangeSymbol(this.Symbol); - } - - var left=event.clientX; - var top=event.clientY+10; - - var pixelTatio=GetDevicePixelRatio(); - dialog.Show(500/pixelTatio,100/pixelTatio,600,500); - dialog.JSChart.OnSize(); - - this.BindClose(chart); - - this.GetColor=function(price,yclse) - { - if(price>yclse) return this.UpColor; - else if (price"+""+strNewDate+" "+ - "开:"+strData.Open.toFixed(2)+""+ - "高:"+strData.High.toFixed(2)+""+ - "低:"+strData.Low.toFixed(2)+""+ - "收:"+strData.Close.toFixed(2)+""+ - "量:"+IFrameSplitOperator.FormatValueString(strData.Vol,2)+""+ - "额:"+IFrameSplitOperator.FormatValueString(strData.Amount,2)+""; - $(".minute-dialog-title span").html(str); - } -} - function MinuteSelectRectDialog(divElement) { this.newMethod=IDivDialog; //派生 @@ -86845,1610 +93990,218 @@ function KLineMatchDialog(divElement) var pageCount = 0; var paginationHtml = ''; - $('#'+this.ID+' .dataCount').html('个数:'+count); - - for(let i = 0; i < count ; i++){ - var dataObj = {}; - if(i == 0){ - dataObj = { - Symbol:this.Sample.Stock.Symbol, - Name:this.Sample.Stock.Name, - Rate:'形态源', - Color:'red', - Date:`${this.Sample.Date.Start}-${this.Sample.Date.End}` - }; - }else{ - let dataItem = this.MatchData[i - 1]; - dataObj = { - Symbol:dataItem.Symbol, - Name:dataItem.Name, - Rate:Number(dataItem.Similar * 100).toFixed(2), - Color:'', - Date:`${dataItem.Start}-${dataItem.End}` - }; - } - pageData.MetaData.push(dataObj); - } - - if(pageData.Count % 10 == 0){ - pageCount = pageData.Count / 10; - }else{ - pageCount = Math.floor(pageData.Count / 10) + 1; - } - pageData.PageCount = pageCount; - - this.PaginationMetaData(pageData); - this.PageData = pageData; - JSConsole.Chart.Log('[KLineMatchDialog::DoModal pageData]',pageData); - - this.RenderDom(1); - - this.PaginationInit('#'+this.ID,pageData.PageCount,this.paginationCallback); - // $('#' + this.ID + ' .pagination').html(paginationHtml); - - - } - this.RenderDom = function(page){ - let currentPageData = this.PageData.NewData[page]; - JSConsole.Chart.Log('[KLineMatchDialog::RenderDom currentPageData]',currentPageData); - let bodyHtml = ''; - for(let i = 0; i < currentPageData.length; i++){ - bodyHtml += ` - ${currentPageData[i].Name} - ${currentPageData[i].Rate} - ${currentPageData[i].Date} - `.trim(); - } - - $('#'+this.ID + ' .matchTable tbody').html(bodyHtml) - } - var _this = this; - this.paginationCallback = function(page) { - _this.RenderDom(page); - _this.PaginationInit('#'+_this.ID,_this.PageData.PageCount,_this.paginationCallback); //更新UI - } - this.PaginationInit = function(id, maxPageNum, callback) { //初始化分页 - var spanStr = ""; - var currentPageNum = $(id + " .pagination").data("current"); - var lastPageNum = 0; - var showCountPage = 5; //只显示5个数字项 - - if (currentPageNum < showCountPage) { //当前页小于预显示页数 - if (maxPageNum >= showCountPage) { - for (var j = 0; j < showCountPage; j++) { //上 1 2 3 4 5 下 - spanStr += (j + 1) != currentPageNum ? "" + (j + 1) + "" : "" + (j + 1) + ""; - } - } else { - for (var j = 0; j < maxPageNum; j++) { //上 1 2 3 4 5 下 - spanStr += (j + 1) != currentPageNum ? "" + (j + 1) + "" : "" + (j + 1) + ""; - } - } - } else { //大于5时,最终页数是当前页数加1 - lastPageNum = (currentPageNum + 1) > maxPageNum ? currentPageNum : (currentPageNum + 1); - - for (var i = currentPageNum - 3; i <= lastPageNum; i++) { //含最终项之前的五项 - spanStr += i != currentPageNum ? "" + i + "" : "" + i + ""; - } - } - - spanStr = "上一页" + spanStr + "下一页"; - $(id + " .pagination").html(spanStr); - $(id + " .pagination span").bind('click', { "maxpage": maxPageNum, "Callback": callback }, this.PaginationCurrentIndex); - // return spanStr; - } - - this.PaginationCurrentIndex = function(event) { //分页切换 - var text = $(this).text(); - JSConsole.Chart.Log('[::PaginationCurrentIndex text]',text); - var currentPageNum = Number($(this).parent().data("current")); - var maxPageNum = event.data.maxpage; - var callback = event.data.Callback; - var flag = 1; - if (text === "上一页") { - flag = currentPageNum === 1 ? currentPageNum : currentPageNum - 1; - } else if (text === "下一页") { - flag = currentPageNum === maxPageNum ? currentPageNum : currentPageNum + 1; - } else { - flag = Number(text); - } - $(this).parent().data("current", flag); //将当前页存到dom上 - callback(flag); - } - - this.PaginationMetaData = function(data){ //假分页数据,每页10条数据 - // data = {NewData:{},MetaData:[],PageCount:0,Callback:null}; - var newData = {}; - var metaData = data.MetaData; - var pageCount = data.PageCount; - - for(let i = 0; i < pageCount; i++){ - var itemArr = []; - for(let j = 0; j < 10; j++){ - var itemIndex = 10*i + j; - if(itemIndex <= metaData.length - 1){ - var item = metaData[itemIndex]; - itemArr.push(item); - }else { - break; - } - } - newData[i+1] = itemArr; - } - data.NewData = newData; - } - - //显示 - this.DoModal=function(event) - { - var chart=event.data.Chart; - if (this.ID==null) this.Create(); //第1次 需要创建div - this.MatchData=event.data.MatchData; - this.Sample=event.data.Sample; - this.HQChart=chart; - - this.BindData(); - - - //居中显示 - var border=chart.Frame.ChartBorder; - var scrollPos=GetScrollPosition(); - var left=border.GetWidth()/2; - var top=border.GetHeight()/2; - - this.Show(left,top,200,200); //显示 - } -} - -//等待动画窗口 -function WaitDialog(divElement) -{ - this.newMethod=IDivDialog; //派生 - this.newMethod(divElement); - delete this.newMethod; - - this.Title='加载中......'; - this.Dialog; - - //隐藏窗口 - this.Close=function() - { - if (this.Dialog) - { - this.DivElement.removeChild(this.Dialog); - this.Dialog=null; - } - } - - this.SetTitle=function(title) - { - this.Title=title; - if (!this.Dialog) return; - //TODO: 更新标题数据 - } - - this.Create=function() - { - this.ID=Guid(); - var div=document.createElement('div'); - div.className='jchart-wait-box'; - div.id=this.ID; - div.innerHTML= - `
-
- ${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); //显示 - } -} - -//K线右键菜单类 -//id:"kline" -function KLineRightMenu(divElement) -{ - this.newMethod=IDivDialog; //派生 - this.newMethod(divElement); - delete this.newMethod; - - this.option={}; - - this.Create = function () { - var _self = this; - - this.ID=Guid(); - - _self.BindData(); - _self.BindEvent(); - } - this.BindData=function(){ - var _self = this; - - var id=this.DivElement.id; - var $body = $("#" + id); - - $body.find("div[id^='topMenu_']").remove(); - $body.find("div[id^='childMenu_']").remove(); - - var $topMenu = $("
"); - $topMenu.attr("id", "topMenu_"+_self.ID).addClass("context-menu-wrapper topmenu").hide(); - $body.append($topMenu); - - var $topTable = $(""); - $topTable.attr({ id: "topTable_" + _self.ID, cellspacing: "0", cellpadding: "0" }).addClass("context-menu"); - $topMenu.append($topTable); - - $topTable.append(_self.childrenList(_self.option.data)); - - for (var i = 0; i < _self.option.data.length; i++) { - var isHasChildren = typeof _self.option.data[i].children != "undefined"; - - if (isHasChildren) { - - var $childMenu = $("
"); - $childMenu.attr({ id: "childMenu_"+_self.ID + i, "data-index": i }).addClass("context-menu-wrapper").hide(); - $body.append($childMenu); - - var $childTable = $("
"); - $childTable.attr({ id: "childTable_" + _self.ID + i, cellspacing: "0", cellpadding: "0" }).addClass("context-menu"); - $childMenu.append($childTable); - - $childTable.append(_self.childrenList(_self.option.data[i].children)); - } - } - } - - this.Update=function() - { - var _self = this; - //var id=this.DivElement.id; - //var $body=$("#"+id); - // - //var $topTable = $("#topTable_" + _self.ID); - //$topTable.empty(); - //$topTable.append(_self.childrenList(_self.option.data)); - // - //for (var i = 0; i < _self.option.data.length; i++) { - // var isHasChildren = typeof _self.option.data[i].children != "undefined"; - // - // if (isHasChildren) { - // var $childTable = $("#childTable_" + _self.ID + i); - // $childTable.empty(); - // $childTable.append(_self.childrenList(_self.option.data[i].children)); - // } - //} - - _self.BindData(); - _self.BindEvent(); - } - - this.childrenList = function(list) { - var result = []; - - for (var i = 0; i < list.length; i++) { - var isBorder = typeof list[i].isBorder != "undefined" && list[i].isBorder; - - var $tr = $(""); - $tr.addClass("font_Arial context-menu"); - if (isBorder) - $tr.addClass("border"); - - var $td1 = $(" + + + + `.trim(); } - - return data; + + $('#'+this.ID + ' .matchTable tbody').html(bodyHtml) } -} - -//K线区间选择右键菜单 -function KLineSelectRightMenu(divElement) -{ - this.newMethod=KLineRightMenu; //派生 - this.newMethod(divElement); - delete this.newMethod; - - this.DoModal=function(event) - { - var chart=event.data.Chart; - var rightMenu=this; - var x = event.data.X; - var y = event.data.Y; - - var dataList= - [ - { - text: "区间统计", - click: function () - { - JSConsole.Chart.Log('[KLineSelectRightMenu::click] 区间统计'); - rightMenu.Hide(); - var dialog=new KLineSelectRectDialog(divElement); - dialog.DoModal(event); + var _this = this; + this.paginationCallback = function(page) { + _this.RenderDom(page); + _this.PaginationInit('#'+_this.ID,_this.PageData.PageCount,_this.paginationCallback); //更新UI + } + this.PaginationInit = function(id, maxPageNum, callback) { //初始化分页 + var spanStr = ""; + var currentPageNum = $(id + " .pagination").data("current"); + var lastPageNum = 0; + var showCountPage = 5; //只显示5个数字项 + + if (currentPageNum < showCountPage) { //当前页小于预显示页数 + if (maxPageNum >= showCountPage) { + for (var j = 0; j < showCountPage; j++) { //上 1 2 3 4 5 下 + spanStr += (j + 1) != currentPageNum ? "" + (j + 1) + "" : "" + (j + 1) + ""; } - }, - { - text:'区间放大', - click:function() - { - JSConsole.Chart.Log('[KLineSelectRightMenu::click] 区间放大'); - var chart=event.data.Chart; - chart.ShowSelectData(event.data.SelectData); + } else { + for (var j = 0; j < maxPageNum; j++) { //上 1 2 3 4 5 下 + spanStr += (j + 1) != currentPageNum ? "" + (j + 1) + "" : "" + (j + 1) + ""; } } - ]; + } else { //大于5时,最终页数是当前页数加1 + lastPageNum = (currentPageNum + 1) > maxPageNum ? currentPageNum : (currentPageNum + 1); - rightMenu.Show({ - x:x, - y:y, - position:chart.Frame.Position, - data:dataList - }); + for (var i = currentPageNum - 3; i <= lastPageNum; i++) { //含最终项之前的五项 + spanStr += i != currentPageNum ? "" + i + "" : "" + i + ""; + } + } + + spanStr = "上一页" + spanStr + "下一页"; + $(id + " .pagination").html(spanStr); + $(id + " .pagination span").bind('click', { "maxpage": maxPageNum, "Callback": callback }, this.PaginationCurrentIndex); + // return spanStr; + } + + this.PaginationCurrentIndex = function(event) { //分页切换 + var text = $(this).text(); + JSConsole.Chart.Log('[::PaginationCurrentIndex text]',text); + var currentPageNum = Number($(this).parent().data("current")); + var maxPageNum = event.data.maxpage; + var callback = event.data.Callback; + var flag = 1; + if (text === "上一页") { + flag = currentPageNum === 1 ? currentPageNum : currentPageNum - 1; + } else if (text === "下一页") { + flag = currentPageNum === maxPageNum ? currentPageNum : currentPageNum + 1; + } else { + flag = Number(text); + } + $(this).parent().data("current", flag); //将当前页存到dom上 + callback(flag); + } + + this.PaginationMetaData = function(data){ //假分页数据,每页10条数据 + // data = {NewData:{},MetaData:[],PageCount:0,Callback:null}; + var newData = {}; + var metaData = data.MetaData; + var pageCount = data.PageCount; + + for(let i = 0; i < pageCount; i++){ + var itemArr = []; + for(let j = 0; j < 10; j++){ + var itemIndex = 10*i + j; + if(itemIndex <= metaData.length - 1){ + var item = metaData[itemIndex]; + itemArr.push(item); + }else { + break; + } + } + newData[i+1] = itemArr; + } + data.NewData = newData; } - this.Show=function (obj) + //显示 + this.DoModal=function(event) { - var _self = this; - $.extend(_self.option, obj); - - //判断是否重复创建 - if (!_self.ID) _self.Create(); - //判断下如果DOM没了需要重新创建 - var divIdName='topMenu_'+_self.ID; - var divDom=document.getElementById(divIdName); - if (!divDom) _self.Create(); - - var $topMenu = $("#topMenu_"+_self.ID), - topWidth = $topMenu.outerWidth(), - topHeight = $topMenu.outerHeight(); - - $topMenu.contextmenu(function() - { - return false; //屏蔽系统右键菜单 - }); - - var x = _self.option.x, - y = _self.option.y; - - if (topWidth > _self.option.position.X + _self.option.position.W- x) //超过了右边距 - x = x - topWidth; - - if (topHeight > _self.option.position.Y +_self.option.position.H - y)//超过了下边距 - y = y - topHeight; + var chart=event.data.Chart; + if (this.ID==null) this.Create(); //第1次 需要创建div + this.MatchData=event.data.MatchData; + this.Sample=event.data.Sample; + this.HQChart=chart; - $topMenu.hide(); - $topMenu.css({ position:"absolute",left: x + "px", top: y + "px" }).show(); + this.BindData(); + - $("#topMenu_" + _self.ID).find("tr").show(); //把菜单列表显示 + //居中显示 + var border=chart.Frame.ChartBorder; + var scrollPos=GetScrollPosition(); + var left=border.GetWidth()/2; + var top=border.GetHeight()/2; - this.isInit = true; + this.Show(left,top,200,200); //显示 } } -//分钟数据右键菜单 -function MinuteRightMenu(divElement) +//等待动画窗口 +function WaitDialog(divElement) { - this.newMethod=KLineRightMenu; //派生 + this.newMethod=IDivDialog; //派生 this.newMethod(divElement); delete this.newMethod; - this.DoModal=function(event) - { - var chart=event.data.Chart; - var rightMenu=chart.RightMenu; - var x = event.offsetX; - var y = event.offsetY; - - var dataList= - [ - { - text: "叠加品种", - children: this.GetOverlay(chart) - }, - { - text: "多日分时图", - children: this.GetDayCount(chart) - }, - { - text:'指标窗口个数', - children: this.GetIndexWindowCount(chart) - }, - { - text: "副图指标切换", - children: this.GetIndex(chart) - }, - { - text:"区间选择", - children:this.GetSelectRect(chart) - }, - - ]; - - var symbol=chart.Symbol; - if (MARKET_SUFFIX_NAME.IsSHSZStockA(symbol)) - { - dataList.push({text:'集合竞价',children: this.GetShowBeforeData(chart)}); - } - - dataList.push({text:"工具", children:this.GetTools(chart)}); - - var identify=event.data.FrameID; - var overlayIndex=this.GetOverlayIndex(chart,identify); - if (overlayIndex && overlayIndex.length>0) - { - var delOverlayIndexMenu={ text:'删除叠加指标', children:this.GetDeleteOverlayIndex(chart,overlayIndex) } - dataList.splice(3,0,delOverlayIndexMenu); - } - - var identify=event.data.FrameID; - JSConsole.Chart.Log('[MinuteRightMenu::DoModal]',identify); - rightMenu.Show({ - windowIndex :identify, - x:x+chart.UIElement.offsetLeft, - y:y+chart.UIElement.offsetTop, - position:chart.Frame.Position, - data:dataList - }) - - $(document).click(function () { - rightMenu.Hide(); - }); - } - - this.GetDayCount=function(chart) - { - var data= - [ - { - text: "当日分时图", - click: function () { chart.ChangeDayCount(1); }, - isBorder:true - }, - { - text: "最近2日", - click: function () { chart.ChangeDayCount(2); } - }, - { - text: "最近3日", - click: function () { chart.ChangeDayCount(3); } - }, - { - text: "最近4日", - click: function () { chart.ChangeDayCount(4); } - }, - { - text: "最近5日", - click: function () { chart.ChangeDayCount(5); } - }, - { - text: "最近6日", - click: function () { chart.ChangeDayCount(6); } - } - ]; - - if ((chart.DayCount-1)>=0 && (chart.DayCount-1)=0 && (count-1) +
+ ${this.Title} +
+ `.trim(); - return data; + this.DivElement.appendChild(div); + this.Dialog=div; } - //工具 - this.GetTools=function(chart) + //显示 + this.DoModal=function(event) { - var data=[]; - var drawTools=chart.GetExtendChartByClassName('DrawToolsButton'); - if (drawTools) - { - data.push( - { - text: "关闭画图工具", - click: function () - { - var toolsWidth=drawTools.Chart.Width; - var toolsIndex=parseInt(drawTools.Index); - chart.DeleteExtendChart(drawTools); - chart.Frame.ChartBorder.Right-=toolsWidth; - chart.SetSizeChange(true); - chart.Draw(); - } - } - ); - } - else - { - data.push( - { - text: "画图工具", - click: function () { - var option={Name:'画图工具', Top:chart.Frame.ChartBorder.Top }; - var extendChart=chart.CreateExtendChart(option.Name, option); //创建扩展图形 - chart.SetSizeChange(true); - chart.Draw(); - } - } - ); - } + 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; - return data; + this.Show(left,top,200,40); //显示 } } @@ -88912,6 +94665,7 @@ var MARKET_SUFFIX_NAME= SHFE: '.SHF', //上期所 (Shanghai Futures Exchange) | 上期所-能源 SHFE2:'.SHFE', //上期所 (Shanghai Futures Exchange) | 上期所-能源 CFFEX: '.CFE', //中期所 (China Financial Futures Exchange) + CFFEX2:'.CFFEX', //中期所 (China Financial Futures Exchange) DCE: '.DCE', //大连商品交易所(Dalian Commodity Exchange) CZCE: '.CZC', //郑州期货交易所 GZFE:".GZFE", //广州期货交易所 @@ -89123,6 +94877,7 @@ var MARKET_SUFFIX_NAME= { if (!upperSymbol) return false; if (upperSymbol.indexOf(this.CFFEX) > 0) return true; + if (upperSymbol.indexOf(this.CFFEX2) > 0) return true; return false; }, @@ -89408,6 +95163,16 @@ var MARKET_SUFFIX_NAME= return 2; }, + GetSHDecimal:function(symbol) + { + return 2; + }, + + GetSZDecimal:function(symbol) + { + return 2; + }, + GetFHKDecimal:function(symbol) //港股指数期货 小数位数 { return 0; @@ -89674,7 +95439,8 @@ function MinuteTimeStringData() return this.Futures.get(splitData.Name); } - this.GetUSA=function() + // type=时间类型 + this.GetUSA=function(upperSymbol) { if (!this.USA) this.USA=this.CreateUSAData(0); return this.USA; @@ -89895,7 +95661,7 @@ function MinuteTimeStringData() 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(true); + 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); @@ -90628,8 +96394,8 @@ function FuturesTimeData() [ { Value: 900, Text: '9:00' }, { Value: 1000, Text: '10:00' }, - { Value: 1330, Text: '13:30' }, - { Value: 1430, Text: '14:30' }, + { Value: 1100, Text: '11:00' }, + { Value: 1400, Text: '14:00' }, { Value: 1500, Text: '15:00' }, ], Min: //最小模式 @@ -91225,6 +96991,7 @@ function FuturesTimeData() [MARKET_SUFFIX_NAME.SHFE + '-SC', {Time:5,Decimal:1,Name:'原油'}], [MARKET_SUFFIX_NAME.SHFE + '-LU', {Time:6,Decimal:0,Name:'低硫燃油'}], [MARKET_SUFFIX_NAME.SHFE + '-BC', {Time:4,Decimal:0,Name:'国际铜'}], + [MARKET_SUFFIX_NAME.SHFE + '-EC', {Time:0,Decimal:0,Name:'集运指数'}], //郑州期货交易所 [MARKET_SUFFIX_NAME.CZCE + '-CF', {Time:6,Decimal:0,Name:"棉花"}], @@ -91267,6 +97034,9 @@ function FuturesTimeData() [MARKET_SUFFIX_NAME.CFFEX + '-IC', {Time:2,Decimal:1,Name:'中证股指期货'}], [MARKET_SUFFIX_NAME.CFFEX + '-IF', {Time:2,Decimal:1,Name:'沪深股指期货'}], [MARKET_SUFFIX_NAME.CFFEX + '-IM', {Time:2,Decimal:1,Name:'中证1000股指期货'}], + [MARKET_SUFFIX_NAME.CFFEX + '-IO', {Time:2,Decimal:1,Name:'沪深300股指期权'}], + [MARKET_SUFFIX_NAME.CFFEX + '-MO', {Time:2,Decimal:1,Name:'中证1000股指期权'}], + [MARKET_SUFFIX_NAME.CFFEX + '-HO', {Time:2,Decimal:1,Name:'上证50股指期权'}], //广州期货交易所 [MARKET_SUFFIX_NAME.GZFE+'-SI', {Time:0,Decimal:2,Name:"工业硅"}], @@ -92753,6 +98523,10 @@ function GetfloatPrecision(symbol) //获取小数位数 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; @@ -92947,6 +98721,38 @@ var g_JSComplierResource= 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; @@ -92999,6 +98805,12 @@ var g_JSComplierResource= { 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; } } @@ -93905,7 +99717,15 @@ function Node(ErrorHandler) "CAPITAL","TOTALCAPITAL","EXCHANGE", "HYBLOCK","DYBLOCK","GNBLOCK","FGBLOCK","ZSBLOCK","ZHBLOCK","ZDBLOCK","HYZSCODE", "GNBLOCKNUM","FGBLOCKNUM","ZSBLOCKNUM","ZHBLOCKNUM","ZDBLOCKNUM", - "HYSYL","HYSJL","FROMOPEN" + "HYSYL","HYSJL","FROMOPEN", + //资金流向 + "LARGEINTRDVOL","LARGEOUTTRDVOL", + "TRADENUM","TRADEINNUM","TRADEOUTNUM", + "LARGETRDINNUM","LARGETRDOUTNUM", + "CUR_BUYORDER","CUR_SELLORDER", + "ACTINVOL","ACTOUTVOL", + "BIDORDERVOL","BIDCANCELVOL","AVGBIDPX", + "OFFERORDERVOL","OFFERCANCELVOL","AVGOFFERPX", ]); if (setVariantName.has(varName)) @@ -93998,6 +99818,15 @@ function Node(ErrorHandler) 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 }; @@ -94108,6 +99937,15 @@ function Node(ErrorHandler) return; } + //"MA.MA1"(10,5,5)" + if (callee.Type==Syntax.Literal) + { + var item={ ID:JS_EXECUTE_JOB_ID.JOB_EXECUTE_INDEX, Args:args, FunctionName:callee.Value, DynamicName:callee.Value }; + if (token) item.Token={ Index:token.Start, Line:token.LineNumber }; + this.ExecuteIndex.push(item); + return; + } + if (callee.Name=='COVER_C' || callee.Name=='COVER_O' || callee.Name=='COVER_H' || callee.Name=='COVER_L' || callee.Name=='COVER_A' || callee.Name=='COVER_V') //跨周期函数 { var periodName=args[0].Value; @@ -94372,11 +100210,11 @@ function JSParser(code) return this.LookAhead.Type==7 /*Punctuator*/ && this.LookAhead.Value==value; } - this.Expect=function(value) + this.Expect=function(value, message) { let token=this.NextToken(); if (token.Type!=7 /*Punctuator*/ || token.Value!=value) - this.ThrowUnexpectedToken(token); + this.ThrowUnexpectedToken(token, message); } //是否是赋值操作符 @@ -94801,7 +100639,7 @@ function JSParser(code) // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). this.ExpectCommaSeparator=function() { - this.Expect(','); + this.Expect(',',"函数参数格式错误"); } // https://tc39.github.io/ecma262/#sec-primary-expression @@ -95994,6 +101832,7 @@ function JSAlgorithm(errorHandler,symbolData) if (!Array.isArray(dayCount)) { + dayCount=parseInt(dayCount); //转整形 if (dayCount<=0) dayCount=1; if (!data || !data.length) return result; @@ -96101,6 +101940,7 @@ function JSAlgorithm(errorHandler,symbolData) } else { + dayCount=parseInt(dayCount); //转整形 if (dayCount<=0) return result; var offset=0; @@ -96206,7 +102046,7 @@ function JSAlgorithm(errorHandler,symbolData) } else { - var i=0; + var i=n; var lastData=null; for(;idata.length) n=data.length; @@ -96729,6 +102570,7 @@ function JSAlgorithm(errorHandler,symbolData) else { if (!IFrameSplitOperator.IsNonEmptyArray(data)) return result; + n=parseInt(n); if (n<=0) n=data.length; else if (n>data.length) n=data.length; @@ -97665,6 +103507,35 @@ function JSAlgorithm(errorHandler,symbolData) return result; } + //反向过滤连续出现的信号. + //用法:FILTERX(X,N):X满足条件后,将其前N周期内的数据置为0,N为常量. + //例如:FILTERX(CLOSE>OPEN,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=[]; @@ -97684,6 +103555,52 @@ function JSAlgorithm(errorHandler,symbolData) 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周期内第一个条件成立到当前的周期数. 用法: @@ -101705,10 +107622,15 @@ function JSAlgorithm(errorHandler,symbolData) return this.FILTER(args[0],args[1]); case 'TFILTER': return this.TFILTER(args[0],args[1],args[2]); + case "FILTERX": + return this.FILTERX(args[0],args[1],node); case 'SLOPE': return this.SLOPE(args[0],args[1]); case 'BARSLAST': return this.BARSLAST(args[0]); + case "BARSLASTS": + //this.ThrowUnexpectedNode(node,`函数'BARSLASTS'还在开发中`, name); + return this.BARSLASTS(args[0],args[1],node); case 'BARSCOUNT': return this.BARSCOUNT(args[0]); case 'BARSSINCEN': @@ -103194,6 +109116,11 @@ function JSDraw(errorHandler,symbolData) return color; } + this.STICKTYPE=function(value) + { + return value; + } + //数据左右偏移 this.XMOVE=function(offset) { @@ -103206,6 +109133,17 @@ function JSDraw(errorHandler,symbolData) return offset; } + this.LINEDASH=function(aryData) + { + if (IFrameSplitOperator.IsNonEmptyArray(aryData)) return aryData.slice(); + return []; + } + + this.KLINETYPE=function(type) + { + return type; + } + this.FIRSTDRAW=function(value) { return value; @@ -103804,7 +109742,7 @@ function JSDraw(errorHandler,symbolData) { for(var i in condition) { - drawData[i]=null; + drawData.Data[i]=null; if (!condition[i]) continue; if (isNumber) @@ -103829,7 +109767,7 @@ function JSDraw(errorHandler,symbolData) var count=this.SymbolData.Data.Data.length; for(var i=0; i { + 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)) { @@ -108226,6 +114314,42 @@ function JSSymbolData(ast,option,jsExecute) } } + 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; 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) { @@ -110398,6 +116651,15 @@ function JSExecute(ast,option) 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表达式. @@ -110435,6 +116697,15 @@ function JSExecute(ast,option) 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': //行情最新数据 @@ -110514,6 +116785,9 @@ function JSExecute(ast,option) 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=[]; @@ -110551,12 +116825,18 @@ function JSExecute(ast,option) 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; @@ -110692,7 +116972,8 @@ function JSExecute(ast,option) return this.SymbolData.GetSymbolPeriodCacheData(JSComplierHelper.GetConvertValueName(funcName),args[0]); case "SYSPARAM": - return this.SymbolData.SysParam(args[0], this); + node.Out=this.SymbolData.SysParam(args[0], this); + break; case "TESTSKIP": var bExit=this.Algorithm.TESTSKIP(args[0],node); @@ -110942,6 +117223,7 @@ function JSExplainer(ast,option) this.JobList=[]; //执行的任务队列 this.VarTable=new Map(); //变量表 this.OutVarTable=[]; //输出变量 + this.MaxValueLength=150; //最长的字符 //脚本自动变量表, 只读 this.ConstVarTable=new Map( @@ -110952,7 +117234,7 @@ function JSExplainer(ast,option) ['VOLR',"量比"], ['VOLINSTK',"持仓量"], ["OPI","持仓量"], ["ZSTJJ","均价"], ["QHJSJ","结算价"], ["SETTLE", "结算价"], //日期类 - ['DATE',"日期"],['YEAR',"年份"],['MONTH',"月份"],['PERIOD', "周期"],['WEEK',"星期"],["TIME","时间"], + ['DATE',"日期"],['YEAR',"年份"],['MONTH',"月份"],["DAY","日"],['PERIOD', "周期"],['WEEK',"星期"],["TIME","时间"], //大盘数据 ['INDEXA',"大盘成交额"],['INDEXC',"大盘收盘价"],['INDEXH',"大盘最高价"],['INDEXL',"大盘最低价"],['INDEXO',"大盘开盘价"],['INDEXV',"大盘成交量"], @@ -110996,6 +117278,24 @@ function JSExplainer(ast,option) ['DRAWNULL',"无效数据"], ["TR", "求真实波幅"], + ["LARGEINTRDVOL","逐笔买入大单成交量"], + ["LARGEOUTTRDVOL","逐笔卖出大单成交量"], + ["TRADENUM", "逐笔成交总单数"], + ["TRADEINNUM", "逐笔买入成交单数"], + ["TRADEOUTNUM", "逐笔卖出成交单数"], + ["LARGETRDINNUM", "逐笔买入大单成交单数"], + ["LARGETRDOUTNUM", "逐笔卖出大单成交单数"], + ["CUR_BUYORDER", "总委买量"], + ["CUR_SELLORDER", "总委卖量"], + ["ACTINVOL", "主动买成交量"], + ["ACTOUTVOL", "主动卖成交量"], + ["BIDORDERVOL", "累计总有效委买量"], + ["BIDCANCELVOL", "累计总有效撤买量"], + ["AVGBIDPX", "最新委买均价"], + ["OFFERORDERVOL", "累计总有效委卖量"], + ["OFFERCANCELVOL", "累计总有效撤卖量"], + ["AVGOFFERPX", "最新委卖均价"], + ]); if (option) @@ -111042,9 +117342,10 @@ function JSExplainer(ast,option) if (!this.AST) this.ThrowError(); if (!this.AST.Body) this.ThrowError(); - for(let i in this.AST.Body) + for(var i=0; i=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; @@ -112440,6 +118774,16 @@ function ScriptIndex(name,script,args,option) 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) //赋值到新实例出来 @@ -112701,6 +119045,11 @@ function ScriptIndex(name,script,args,option) if (this.ID) chart.IndexID=this.ID; + if (this.YAxis) + { + if (IFrameSplitOperator.IsBool(this.YAxis.ExcludeValue)) chart.IsExcludeYValue=this.YAxis.ExcludeValue; + } + chart.Script=this; //指标内容绑定上去 } @@ -112747,7 +119096,15 @@ function ScriptIndex(name,script,args,option) if (!isNaN(width) && width>0) line.LineWidth=width; } - if (varItem.IsDotLine) line.IsDotLine=true; //虚线 + 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; @@ -112862,6 +119219,54 @@ function ScriptIndex(name,script,args,option) 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) { @@ -112929,7 +119334,7 @@ function ScriptIndex(name,script,args,option) 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); } @@ -113030,6 +119435,7 @@ function ScriptIndex(name,script,args,option) let titleIndex=windowIndex+1; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); + this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } @@ -113091,6 +119497,7 @@ function ScriptIndex(name,script,args,option) 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); } @@ -113185,6 +119592,7 @@ function ScriptIndex(name,script,args,option) if (varItem.UpColor) chart.UpColor=varItem.UpColor; if (varItem.DownColor) chart.DownColor=varItem.DownColor; + if (IFrameSplitOperator.IsNumber(varItem.StickType)) chart.BarType=varItem.StickType; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); @@ -113217,6 +119625,13 @@ function ScriptIndex(name,script,args,option) 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); } @@ -113283,10 +119698,12 @@ function ScriptIndex(name,script,args,option) 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); } @@ -113592,6 +120009,7 @@ function ScriptIndex(name,script,args,option) //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); + this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } @@ -113615,6 +120033,7 @@ function ScriptIndex(name,script,args,option) 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); } @@ -113668,6 +120087,7 @@ function ScriptIndex(name,script,args,option) //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); + this.SetChartIndexName(chartText); hqChart.ChartPaint.push(chartText); } @@ -113806,13 +120226,21 @@ function ScriptIndex(name,script,args,option) this.ReloadChartResource(hqChart, windowIndex, chart); + this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); var titleIndex=windowIndex+1; - var titleData=new DynamicTitleData(chart.Data,chart.Name, null); - titleData.DataType="ChartMultiLine"; - titleData.Lines=chart.Lines; - hqChart.TitlePaint[titleIndex].Data[i]=titleData; + 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) @@ -113826,6 +120254,7 @@ function ScriptIndex(name,script,args,option) 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; @@ -113852,6 +120281,7 @@ function ScriptIndex(name,script,args,option) titleData.DataType="MULTI_BAR"; hqChart.TitlePaint[titleIndex].Data[id]=titleData; + this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } @@ -113865,12 +120295,13 @@ function ScriptIndex(name,script,args,option) 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 ChartMultiSVGIcon(); + let chart=new ChartMultiSVGIconV2(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=hqChart.Frame.SubFrame[windowIndex].Frame.ChartBorder; @@ -113878,7 +120309,9 @@ function ScriptIndex(name,script,args,option) chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Family=varItem.Draw.DrawData.Family; - chart.Icon= varItem.Draw.DrawData.Icon; + chart.AryIcon= varItem.Draw.DrawData.Icon; + chart.BuildCacheData(); + this.SetChartIndexName(chart); hqChart.ChartPaint.push(chart); } @@ -113983,6 +120416,33 @@ function ScriptIndex(name,script,args,option) 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(); @@ -114117,7 +120577,15 @@ function ScriptIndex(name,script,args,option) if (windowIndex>=1 && hqChart.Frame) { - hqChart.Frame.SubFrame[windowIndex].Frame.YSplitOperator.FloatPrecision=this.FloatPrecision; + //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; //固定刻度 } @@ -114134,7 +120602,7 @@ function ScriptIndex(name,script,args,option) } */ - for(let i in this.OutVar) + for(let i=0; i0) hqChart.TitlePaint[titleIndex].ArgumentsText=`(${indexParam})`; + if (indexParam.length>0) titlePaint.ArgumentsText=`(${indexParam})`; } - if (this.TitleFont) hqChart.TitlePaint[titleIndex].Font=this.TitleFont; + if (this.TitleFont) titlePaint.Font=this.TitleFont; return true; } @@ -114489,10 +120963,17 @@ function OverlayScriptIndex(name,script,args,option) if (!IFrameSplitOperator.IsNonEmptyArray(this.OutVar)) return; //修改Y轴分割方式 - if (IFrameSplitOperator.IsNumber(this.YSplitType)) this.OverlayIndex.Frame.Frame.YSplitOperator.SplitType=this.YSplitType; + 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 }; + var titleInfo={ Data:[], Title:this.Name, Frame:this.OverlayIndex.Frame.Frame, Script:this, IsShowIndexTitle:this.IsShowIndexTitle }; let indexParam=''; for(var i in this.Arguments) { @@ -114928,6 +121409,7 @@ function OverlayScriptIndex(name,script,args,option) titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=new DynamicTitleData(chart.Data,varItem.Name,clrTitle); + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -114963,6 +121445,7 @@ function OverlayScriptIndex(name,script,args,option) 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); } @@ -115065,6 +121548,7 @@ function OverlayScriptIndex(name,script,args,option) if (varItem.UpColor) chart.UpColor=varItem.UpColor; if (varItem.DownColor) chart.DownColor=varItem.DownColor; + if (IFrameSplitOperator.IsNumber(varItem.StickType)) chart.BarType=varItem.StickType; if (varItem.LineWidth) { let width=parseInt(varItem.LineWidth.replace("LINETHICK","")); @@ -115103,6 +121587,7 @@ function OverlayScriptIndex(name,script,args,option) if (IFrameSplitOperator.IsBool(varItem.IsFirstDraw)) chart.IsDrawFirst=varItem.IsFirstDraw; + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -115181,7 +121666,7 @@ function OverlayScriptIndex(name,script,args,option) 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); } @@ -115281,6 +121766,7 @@ function OverlayScriptIndex(name,script,args,option) //var titleIndex=windowIndex+1; //hqChart.TitlePaint[titleIndex].Data[id]=new DynamicTitleData(bar.Data,varItem.Name,bar.Color); + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -115431,6 +121917,7 @@ function OverlayScriptIndex(name,script,args,option) this.ReloadChartResource(hqChart, windowIndex, chart); + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -115494,6 +121981,7 @@ function OverlayScriptIndex(name,script,args,option) titleData.DataType="MULTI_BAR"; titlePaint.OverlayIndex.get(overlayIndex.Identify).Data[id]=titleData; + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -115510,6 +121998,7 @@ function OverlayScriptIndex(name,script,args,option) chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Texts=varItem.Draw.DrawData; + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -115517,7 +122006,7 @@ function OverlayScriptIndex(name,script,args,option) { var overlayIndex=this.OverlayIndex; var frame=overlayIndex.Frame; - let chart=new ChartMultiSVGIcon(); + let chart=new ChartMultiSVGIconV2(); chart.Canvas=hqChart.Canvas; chart.Name=varItem.Name; chart.ChartBorder=frame.Frame.ChartBorder; @@ -115526,7 +122015,9 @@ function OverlayScriptIndex(name,script,args,option) chart.Data=hqChart.ChartPaint[0].Data;//绑定K线 chart.Family=varItem.Draw.DrawData.Family; - chart.Icon= varItem.Draw.DrawData.Icon; + chart.AryIcon= varItem.Draw.DrawData.Icon; + chart.BuildCacheData(); + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -115555,6 +122046,7 @@ function OverlayScriptIndex(name,script,args,option) this.ReloadChartResource(hqChart, windowIndex, chart); + this.SetChartIndexName(chart); frame.ChartPaint.push(chart); } @@ -116462,6 +122954,9 @@ function APIScriptIndex(name,script,args,option, isOverlay) if (IFrameSplitOperator.IsBool(item.isshow)) outVarItem.IsShow = item.isshow; //是否绘制线段 if (item.isexdata==true) outVarItem.IsExData = true; if (item.BreakPoint) outVarItem.BreakPoint=item.BreakPoint; + 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); } @@ -116530,6 +123025,7 @@ function APIScriptIndex(name,script,args,option, isOverlay) if (IFrameSplitOperator.IsBool(draw.IsFullRangeMaxMin)) drawItem.IsFullRangeMaxMin=draw.IsFullRangeMaxMin; if (draw.Arrow) drawItem.Arrow=draw.Arrow; if (IFrameSplitOperator.IsNumber(draw.LineWidth)) drawItem.LineWidth=draw.LineWidth; + result.push(outVarItem); } @@ -116616,8 +123112,7 @@ function APIScriptIndex(name,script,args,option, isOverlay) drawItem.Text=draw.Text; drawItem.Name=draw.Name; drawItem.DrawType=draw.DrawType; - drawItem.DrawData={ Icon:this.FittingMultiText(draw.DrawData.Icon,date,time,hqChart), Family:draw.DrawData.Family }; - this.GetKLineData(drawItem.DrawData.Icon, hqChart); + drawItem.DrawData={ Icon:draw.DrawData.Icon, Family:draw.DrawData.Family }; outVarItem.Draw=drawItem; result.push(outVarItem); @@ -116706,6 +123201,20 @@ function APIScriptIndex(name,script,args,option, isOverlay) 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.FittingArray(draw.Data,date,time,hqChart); + + outVarItem.Draw=drawItem; + if (draw.LineWidth) outVarItem.LineWidth=draw.LineWidth; + if (draw.UpColor) outVarItem.UpColor=draw.UpColor; + if (draw.DownColor) outVarItem.DownColor=draw.DownColor; + + result.push(outVarItem); + } else { var find=g_ScriptIndexChartFactory.Get(draw.DrawType); //外部挂接 @@ -116908,7 +123417,8 @@ function APIScriptIndex(name,script,args,option, isOverlay) for(var i=0;i= 1) outVarItem.LineWidth = item.linewidth; - if (IFrameSplitOperator.IsBool(item.isshow)) outVarItem.IsShow = false; + if (IFrameSplitOperator.IsBool(item.isshow)) outVarItem.IsShow = item.isshow; if (item.isexdata == true) outVarItem.IsExData = true; + if (item.BreakPoint) outVarItem.BreakPoint=item.BreakPoint; + 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); } diff --git a/wechathqchart/umychart.version.wechat.js b/wechathqchart/umychart.version.wechat.js index dd5902275..45ec62bbf 100644 --- a/wechathqchart/umychart.version.wechat.js +++ b/wechathqchart/umychart.version.wechat.js @@ -5,7 +5,7 @@ -var HQCHART_VERSION="1.1.13752"; +var HQCHART_VERSION="1.1.13762"; function PrintHQChartVersion() {
"); - if(list[i].selected){ - $td1.addClass("spacer context-menu").html("√"); - }else{ - $td1.addClass("spacer context-menu"); - } - - var $td2 = $(""); - $td2.addClass("text").html(list[i].text); - - var $td3 = $(""); - $td3.addClass("right shortcut"); - - var $td4 = $(""); - $td4.addClass(typeof list[i].children != "undefined" ? "submenu-arrow" : "context-menu spacer"); - - $tr.append($td1).append($td2).append($td3).append($td4); - - result.push($tr); - } - return result; - } - - this.Show=function (obj) { - var _self = this; - $.extend(_self.option, obj); - - if (!_self.ID) _self.Create(); //判断是否重复创建 - else _self.Update(); //更新菜单状态 - - var $topMenu = $("#topMenu_"+_self.ID), - topWidth = $topMenu.outerWidth(), - topHeight = $topMenu.outerHeight(); - - var x = _self.option.x, - y = _self.option.y; - - if (topWidth > _self.option.position.X + _self.option.position.W- x) //超过了右边距 - x = x - topWidth; - - if (topHeight > _self.option.position.Y +_self.option.position.H - y)//超过了下边距 - y = y - topHeight; - - $topMenu.hide(); - $topMenu.css({ position:"absolute",left: x + "px", top: y + "px" }).show(); - - this.isInit = true; - } - - this.Hide=function () { - var _self = this; - if (typeof($)=="undefined") return; - $("#topMenu_" + _self.ID).hide(); - $("[id^='childMenu_" + _self.ID + "']").hide(); - } - - this.BindEvent=function () { - var _self = this; - var $childMenu = $("[id^='childMenu_" + _self.ID + "']"); - - $("#topTable_" + _self.ID).find("tr").mouseenter(function () { - var $this = $(this), - index = $this.index(), - $topMenu = $("#topMenu_" + _self.ID), - $child = $("#childMenu_" + _self.ID + index), - trWidth = $this.outerWidth(), - trHeight = $this.outerHeight(); - - var left = $topMenu.position().left + trWidth + 1; - var top = $topMenu.position().top + (trHeight * index); - - if (trWidth > _self.option.position.X + _self.option.position.W - left) //超过了右边距 - left = left - trWidth - $topMenu.outerWidth() - 2; - - if ($child.outerHeight() > _self.option.position.Y +_self.option.position.H - top)//超过了下边距 - top = $topMenu.position().top + $topMenu.outerHeight() - $child.outerHeight(); - - $childMenu.hide(); - $child.css({ left: left + "px", top: top + "px" }).show(); - }).mouseleave(function () { - var index = $(this).index(); - setTimeout(function () { - if ($("#childMenu_" + _self.ID + index).attr("data-isShow") != 1) { - $("#childMenu_" + _self.ID + index).hide(); - } - }, 10) - - }).click(function () { - var $this = $(this); - var index = $this.index(); - - if ($.type(_self.option.data[index].click) == "function") { - _self.option.data[index].click(_self.option.returnData); - $this.hide(); - } - }).contextmenu(function() - { - return false; //屏蔽系统右键菜单 - }); - - - $childMenu.mouseenter(function () { - $(this).attr("data-isShow", "1"); - }).mouseleave(function () { - $(this).attr("data-isShow", "0"); - }).contextmenu(function() - { - return false; //屏蔽系统右键菜单 - }); - - $childMenu.find("tr").click(function () { - var $this = $(this); - var divIndex = parseInt($this.closest("div").attr("data-index")); - var trIndex = $this.index(); - - if ($.type(_self.option.data[divIndex].children[trIndex].click) == "function") { - _self.option.data[divIndex].children[trIndex].click(_self.option.windowIndex || 1); - $childMenu.hide(); - } - }); - } - - this.GetPeriod=function (chart) - { - var data= - [ - { - text: "日线", Value:0, - click: function () { chart.ChangePeriod(0); } - }, - { - text: "周线",Value:1, - click: function () { chart.ChangePeriod(1); } - }, - { - text: "双周线",Value:21, - click: function () { chart.ChangePeriod(21); } - }, - { - text: "月线",Value:2, - click: function () { chart.ChangePeriod(2); } - }, - { - text: "季线",Value:9, - click: function () { chart.ChangePeriod(9); } - }, - { - text: "半年",Value:22, - click: function () { chart.ChangePeriod(22); } - }, - { - text: "年线",Value:3, - click: function () { chart.ChangePeriod(3); } - }, - { - text: "1分",Value:4, - click: function () { chart.ChangePeriod(4); } - }, - { - text: "5分",Value:5, - click: function () { chart.ChangePeriod(5); } - }, - { - text: "15分",Value:6, - click: function () { chart.ChangePeriod(6); } - }, - { - text: "30分",Value:7, - click: function () { chart.ChangePeriod(7); } - }, - { - text: "60分",Value:8, - click: function () { chart.ChangePeriod(8); } - }, - { - text: "2小时",Value:11, - click: function () { chart.ChangePeriod(11); } - }, - { - text: "4小时",Value:12, - click: function () { chart.ChangePeriod(12); } - }, - { - text: "分笔",Value:10, - click: function () { chart.ChangePeriod(10); } - }, - { - text: "自定义周期:3分钟",Value:20003, - click: function () { chart.ChangePeriod(20003); } - }, - { - text: "自定义周期:35分钟",Value:20035, - click: function () { chart.ChangePeriod(20035); } - }, - { - text: "自定义周期:8日",Value:40008, - click: function () { chart.ChangePeriod(40008); } - } - ]; - - for(var i in data) - { - var item=data[i]; - if (item.Value==chart.Period) - { - item.selected=true; - break; - } - } - - return data; - } - - this.GetRight=function(chart) - { - var data= - [ - { - text: "不复权", - click: function () { chart.ChangeRight(0); } - }, - { - text: "前复权", - click: function () { chart.ChangeRight(1); } - }, - { - text: "后复权", - click: function () { chart.ChangeRight(2); } - } - ]; - - if (chart.Right>=0 && chart.Right0) - { - data[data.length-1].isBorder=true; - data.push( - { - text: "取消叠加", - click: function () { chart.ClearOverlaySymbol();} - } - ); - } - - return data; - } - - //K线类型设置 - this.GetKLineType=function(chart) - { - var data= - [ - { - text: "K线(空心阳线)", - click: function () { chart.ChangeKLineDrawType(3);} - }, - { - text: "K线(实心阳线)", - click: function () { chart.ChangeKLineDrawType(0); } - }, - { - text: "美国线", - click: function () { chart.ChangeKLineDrawType(2, true ,{ IsThinAKBar:false }); } - }, - { - text: "收盘线", - click: function () { chart.ChangeKLineDrawType(1); } - }, - { - text: "收盘面积", - click: function () { chart.ChangeKLineDrawType(4); } - }, - { - text: "K线(空心阳线阴线)", - click: function () { chart.ChangeKLineDrawType(6);} - }, - { - text: "Heikin Ashi", - click: function () { chart.ChangeKLineDrawType(11);} - }, - { - text: "Line Break", - click: function () { chart.ChangeKLineDrawType(12);} - }, - { - text: "High-low", - click: function () { chart.ChangeKLineDrawType(13);} - }, - { - text: "HLC Area", - click: function () { chart.ChangeKLineDrawType(15);} - } - ]; - - switch(chart.KLineDrawType) - { - case 0: - data[1].selected=true; - break; - case 1: - data[3].selected=true; - break; - case 2: - data[2].selected=true; - break; - case 3: - data[0].selected=true; - break; - case 4: - data[4].selected=true; - break; - case 6: - data[5].selected=true; - break; - case 11: - data[6].selected=true; - break; - case 12: - data[7].selected=true; - break; - case 13: - data[8].selected=true; - break; - case 15: - data[9].selected=true; - break; - } - return data; - } - - //指标窗口个数 - this.GetIndexWindowCount=function(chart) - { - var data= - [ - { - text: "1个窗口", - click: function () { chart.ChangeIndexWindowCount(1); } - }, - { - text: "2个窗口", - click: function () { chart.ChangeIndexWindowCount(2); } - }, - { - text: "3个窗口", - click: function () { chart.ChangeIndexWindowCount(3); } - }, - { - text: "4个窗口", - click: function () { chart.ChangeIndexWindowCount(4); } - }, - { - text: "5个窗口", - click: function () { chart.ChangeIndexWindowCount(5); } - } - ]; - - var count=chart.Frame.SubFrame.length; - if ((count-1)>=0 && (count-1)0) - { - if (chart.Frame.SubFrame[0].Frame.CoordinateType==1) - { - data[2].selected=true; - data[2].click=function() { chart.ChangeCoordinateType( { IsReverse:false } ); } //取消反转 - } - - if (chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType==1) data[1].selected=true; //百分比 - else if (chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType==0) data[0].selected=true; //普通坐标 - else if (chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType==2) data[3].selected=true; //对数 - else if (chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType==3) data[4].selected=true; //等比坐标 - else if (chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType==4) data[5].selected=true; //等分坐标 - else if (chart.Frame.SubFrame[0].Frame.YSplitOperator.CoordinateType==5) data[6].selected=true; //黄金分割 - } - - return data; - } - - //拖拽模式 - this.GetDragModeType=function(chart) - { - var data= - [ - { - text: "禁止拖拽", - click: function () { chart.DragMode=0; } - }, - { - text: "启动拖拽", - click: function () { chart.DragMode=1; } - }, - { - text: "区间选择", - click: function () { chart.DragMode=2; } - } - ]; - - if (chart.DragMode>=0 && chart.DragMode0) - { - data[data.length-1].isBorder=true; - var item={ text:'删除所有', click:function() { chart.ClearKLineInfo()} }; - data.push(item); - - } - - return data; - } - - this.CreateKlineInfoItem=function(infoName,bExist,chart) - { - var item= - { - text:infoName, - selected:bExist - } - - if (bExist) item.click=function() { chart.DeleteKLineInfo(infoName) }; - else item.click=function() { chart.AddKLineInfo(infoName,true) } - - return item; - } - - this.DoModal=function(event) - { - var chart=event.data.Chart; - var rightMenu=chart.RightMenu; - var x = event.offsetX; - var y = event.offsetY; - - var dataList=[{ - text: "分析周期", - children: this.GetPeriod(chart) - }, - { - text: "复权处理", - children: this.GetRight(chart) - }, - { - text: "指标切换", - children: this.GetIndex(chart) - }, - { - text:"五彩K线", - children: this.GetColorIndex(chart) - }, - { - text:'专家系统', - children: this.GetTradeIndex(chart) - }, - { - text:'信息地雷', - children: this.GetKLineInfo(chart) - }, - { - text: "叠加品种", - children: this.GetOverlay(chart) - }, - { - text:'主图线型', - children: this.GetKLineType(chart) - }, - { - text:"坐标类型", - children:this.GetCoordinateType(chart) - }, - { - text:'指标窗口个数', - children: this.GetIndexWindowCount(chart) - }, - { - text:'鼠标拖拽', - children: this.GetDragModeType(chart) - }, - { - text:"工具", - children:this.GetTools(chart) - } - ]; - - var upperSymbol=chart.Symbol.toUpperCase(); - if(MARKET_SUFFIX_NAME.IsSHSZIndex(chart.Symbol) || MARKET_SUFFIX_NAME.IsBIT(upperSymbol)) - { - dataList.splice(1,1); + $('#'+this.ID+' .dataCount').html('个数:'+count); + + for(let i = 0; i < count ; i++){ + var dataObj = {}; + if(i == 0){ + dataObj = { + Symbol:this.Sample.Stock.Symbol, + Name:this.Sample.Stock.Name, + Rate:'形态源', + Color:'red', + Date:`${this.Sample.Date.Start}-${this.Sample.Date.End}` + }; + }else{ + let dataItem = this.MatchData[i - 1]; + dataObj = { + Symbol:dataItem.Symbol, + Name:dataItem.Name, + Rate:Number(dataItem.Similar * 100).toFixed(2), + Color:'', + Date:`${dataItem.Start}-${dataItem.End}` + }; + } + pageData.MetaData.push(dataObj); } - var identify=event.data.FrameID; - var overlayIndex=this.GetOverlayIndex(chart,identify); - if (overlayIndex && overlayIndex.length>0) - { - var delOverlayIndexMenu={ text:'删除叠加指标', children:this.GetDeleteOverlayIndex(chart,overlayIndex) } - dataList.splice(3,0,delOverlayIndexMenu); + if(pageData.Count % 10 == 0){ + pageCount = pageData.Count / 10; + }else{ + pageCount = Math.floor(pageData.Count / 10) + 1; } + pageData.PageCount = pageCount; - JSConsole.Chart.Log('[KLineRightMenu::DoModal]',identify); - rightMenu.Show({ - windowIndex :identify, - x:x+chart.UIElement.offsetLeft, - y:y+chart.UIElement.offsetTop, - position:chart.Frame.Position, - data:dataList - }) + this.PaginationMetaData(pageData); + this.PageData = pageData; + JSConsole.Chart.Log('[KLineMatchDialog::DoModal pageData]',pageData); - $(document).click(function () { - rightMenu.Hide(); - }); - } + this.RenderDom(1); - this.GetOverlayIndex=function(chart, windowsIndex) - { - if (windowsIndex>=chart.Frame.SubFrame.length || windowsIndex<0) return []; + this.PaginationInit('#'+this.ID,pageData.PageCount,this.paginationCallback); + // $('#' + this.ID + ' .pagination').html(paginationHtml); - var result=[]; - var item=chart.Frame.SubFrame[windowsIndex]; - for(var i in item.OverlayIndex) - { - var overlayItem=item.OverlayIndex[i]; - result.push({Name:overlayItem.Script.Name, Identify:overlayItem.Identify}); - } - return result; } - - this.GetDeleteOverlayIndex=function(chart,overlayIndex) - { - var data=[]; - for(var i in overlayIndex) - { - let identify=overlayIndex[i].Identify; - data.push({text:overlayIndex[i].Name, click:function() - { - chart.DeleteOverlayWindowsIndex(identify) - }}); + this.RenderDom = function(page){ + let currentPageData = this.PageData.NewData[page]; + JSConsole.Chart.Log('[KLineMatchDialog::RenderDom currentPageData]',currentPageData); + let bodyHtml = ''; + for(let i = 0; i < currentPageData.length; i++){ + bodyHtml += `
${currentPageData[i].Name}${currentPageData[i].Rate}${currentPageData[i].Date}