umychart.chartpaint.wechat.js 386 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210
  1. /*
  2. copyright (c) 2018 jones
  3. http://www.apache.org/licenses/LICENSE-2.0
  4. 开源项目 https://github.com/jones2000/HQChart
  5. jones_2000@163.com
  6. 小程序图形库
  7. */
  8. //行情数据结构体 及涉及到的行情算法(复权,周期等)
  9. import
  10. {
  11. ChartData, HistoryData,
  12. SingleData, MinuteData,
  13. Rect,RectV2,
  14. JSCHART_EVENT_ID,
  15. OVERLAY_STATUS_ID,
  16. JSCHART_CORSSCURSOR_STATUS_ID,
  17. CloneData
  18. } from "./umychart.data.wechat.js";
  19. import
  20. {
  21. g_JSChartResource,
  22. g_JSChartLocalization,
  23. JSChartResource,
  24. } from './umychart.resource.wechat.js'
  25. import
  26. {
  27. IFrameSplitOperator,
  28. } from './umychart.framesplit.wechat.js'
  29. import
  30. {
  31. JSCommonCoordinateData,
  32. MARKET_SUFFIX_NAME
  33. } from "./umychart.coordinatedata.wechat.js";
  34. import { JSConsole } from "./umychart.console.wechat.js";
  35. import { Path2DHelper } from "./umychart.data.wechat.js"
  36. //配色
  37. function JSChartPaintResource()
  38. {
  39. //指标不支持信息
  40. this.Index=
  41. {
  42. NotSupport : { Font: "14px 微软雅黑", TextColor: "rgb(52,52,52)" }
  43. }
  44. }
  45. var g_JSChartPaintResource = new JSChartPaintResource();
  46. function GetFontHeight(context, font, word)
  47. {
  48. if (!context) return null;
  49. if (font) context.font=font;
  50. var text='擎';
  51. if (IFrameSplitOperator.IsString(word)) text=word;
  52. var fontInfo=context.measureText(text);
  53. //var textHeight=fontInfo.fontBoundingBoxAscent + fontInfo.fontBoundingBoxDescent;
  54. var textHeight=fontInfo.width+2;
  55. return textHeight;
  56. }
  57. function ColorToRGBA(color,opacity)
  58. {
  59. var reg = /^(rgb|RGB)/;
  60. if (reg.test(color))
  61. {
  62. var strHex = "#";
  63. var colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); // 把RGB的3个数值变成数组
  64. // 转成16进制
  65. for (var i = 0; i < colorArr.length; i++)
  66. {
  67. var hex = Number(colorArr[i]).toString(16);
  68. if (hex === "0") hex += hex;
  69. strHex += hex;
  70. }
  71. color=strHex;
  72. }
  73. return "rgba(" + parseInt("0x" + color.slice(1, 3)) + "," + parseInt("0x" + color.slice(3, 5)) + "," + parseInt("0x" + color.slice(5, 7)) + "," + opacity + ")";
  74. }
  75. //图新画法接口类
  76. function IChartPainting()
  77. {
  78. this.Canvas; //画布
  79. this.ChartBorder; //边框信息
  80. this.ChartFrame; //框架画法
  81. this.Name; //名称
  82. this.ClassName = 'IChartPainting'; //类名
  83. this.Data = new ChartData(); //数据区
  84. this.Script; //图形对应的指标脚本 (只有指标图形才有)
  85. this.NotSupportMessage = null;
  86. this.MessageFont = g_JSChartPaintResource.Index.NotSupport.Font;
  87. this.MessageColor = g_JSChartPaintResource.Index.NotSupport.TextColor;
  88. this.IsDrawFirst = false; //是否比K线先画
  89. this.IsShow = true; //是否显示
  90. this.IsVisible=true; //是否显示 (预留给外部单独设置线段显隐)
  91. this.GetEventCallback;
  92. this.Draw = function () { }
  93. this.BuildKey=function(item)
  94. {
  95. if (IFrameSplitOperator.IsNumber(item.Time)) return `${item.Date}-${item.Time}`;
  96. else return item.Date;
  97. }
  98. this.GetYFromData=function(value,isLimit)
  99. {
  100. return this.ChartFrame.GetYFromData(value,isLimit);
  101. }
  102. this.GetBorder=function()
  103. {
  104. if (this.ChartFrame.IsHScreen) return this.ChartBorder.GetHScreenBorder();
  105. return this.ChartBorder.GetBorder();
  106. }
  107. this.IsMinuteFrame=function()
  108. {
  109. var isMinute=(this.ChartFrame.ClassName=="MinuteFrame" || this.ChartFrame.ClassName=="MinuteHScreenFrame" ||
  110. this.ChartFrame.ClassName=="OverlayMinuteFrame" || this.ChartFrame.ClassName=="OverlayMinuteHScreenFrame");
  111. return isMinute
  112. }
  113. //是否隐藏指标
  114. this.IsHideScriptIndex=function()
  115. {
  116. if (this.Script && this.Script.IsShow==false) return true;
  117. return false;
  118. }
  119. this.DrawNotSupportmessage=function()
  120. {
  121. this.Canvas.font = this.MessageFont;
  122. this.Canvas.fillStyle = this.MessageColor;
  123. var left = this.ChartBorder.GetLeft();
  124. var width = this.ChartBorder.GetWidth();
  125. var top = this.ChartBorder.GetTopEx();
  126. var height = this.ChartBorder.GetHeightEx();
  127. var x = left + width / 2;
  128. var y = top + height / 2;
  129. var bHScreen=this.ChartFrame.IsHScreen;
  130. if (bHScreen)
  131. {
  132. this.Canvas.save();
  133. this.Canvas.translate(x, y);
  134. this.Canvas.rotate(90 * Math.PI / 180);
  135. x=0,y=0;
  136. }
  137. this.Canvas.textAlign = "center";
  138. this.Canvas.textBaseline = "middle";
  139. this.Canvas.fillText(this.NotSupportMessage, x, y);
  140. if (bHScreen) this.Canvas.restore();
  141. }
  142. this.GetTooltipData = function (x, y, tooltip)
  143. {
  144. return false;
  145. }
  146. this.GetMaxMin = function ()
  147. {
  148. var xPointCount = this.ChartFrame.XPointCount;
  149. var range = {};
  150. range.Min = null;
  151. range.Max = null;
  152. if (!this.Data || !this.Data.Data) return range;
  153. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  154. {
  155. var value = this.Data.Data[i];
  156. if (value == null || isNaN(value)) continue;
  157. if (range.Max == null) range.Max = value;
  158. if (range.Min == null) range.Min = value;
  159. if (range.Max < value) range.Max = value;
  160. if (range.Min > value) range.Min = value;
  161. }
  162. return range;
  163. }
  164. this.GetDynamicFont = function (dataWidth) //根据宽度自动获取对应字体
  165. {
  166. var font;
  167. if (dataWidth < 5) font = '4px Arial'; //字体根据数据宽度动态调整
  168. else if (dataWidth < 7) font = '6px Arial';
  169. else if (dataWidth < 9) font = '8px Arial';
  170. else if (dataWidth < 11) font = '10px Arial';
  171. else if (dataWidth < 13) font = '12px Arial';
  172. else if (dataWidth < 15) font = '14px Arial';
  173. else font = '16px Arial';
  174. return font;
  175. }
  176. this.GetDynamicFontEx=function(dataWidth, distanceWidth, maxSize, minSize, zoom, fontname) //根据宽度自动获取对应字体
  177. {
  178. if (maxSize==minSize)
  179. {
  180. var font=`${maxSize.toFixed(0)}px ${fontname}` ;
  181. return font;
  182. }
  183. var fontSize=(dataWidth+distanceWidth);
  184. if (zoom)
  185. {
  186. if (zoom.Type==0)
  187. {
  188. if (zoom.Value>0) fontSize=(dataWidth*zoom.Value);
  189. }
  190. else if (zoom.Type==1)
  191. {
  192. if (zoom.Value>0) fontSize=(dataWidth+distanceWidth)*zoom.Value;
  193. }
  194. else if (zoom.Type==2)
  195. {
  196. if (IFrameSplitOperator.IsNumber(zoom.Value))
  197. fontSize=(dataWidth+distanceWidth) + (2*zoom.Value);
  198. }
  199. }
  200. if (fontSize<minSize) fontSize=minSize;
  201. else if (fontSize>maxSize) fontSize=maxSize;
  202. var font=`${fontSize.toFixed(0)}px ${fontname}` ;
  203. return font;
  204. }
  205. this.SetFillStyle = function (color, x0, y0, x1, y1)
  206. {
  207. if (Array.isArray(color))
  208. {
  209. let gradient = this.Canvas.createLinearGradient(x0, y0, x1, y1);
  210. var offset = 1 / (color.length-1);
  211. for (var i=0;i<color.length;++i)
  212. {
  213. gradient.addColorStop(i * offset, color[i]);
  214. }
  215. this.Canvas.fillStyle = gradient;
  216. }
  217. else
  218. {
  219. this.Canvas.fillStyle = color;
  220. }
  221. }
  222. this.GetFontHeight=function(font)
  223. {
  224. return GetFontHeight(this.Canvas, font, "擎");
  225. }
  226. this.GetLockRect=function()
  227. {
  228. return this.ChartFrame.GetLockRect();
  229. }
  230. this.ClipClient=function(isHScreen) //裁剪客户端
  231. {
  232. if (isHScreen==true)
  233. {
  234. var left=this.ChartBorder.GetLeftEx();
  235. var right=this.ChartBorder.GetRightEx();
  236. var top=this.ChartBorder.GetTop();
  237. var bottom=this.ChartBorder.GetBottom();
  238. }
  239. else
  240. {
  241. var left=this.ChartBorder.GetLeft();
  242. var right=this.ChartBorder.GetRight();
  243. var top=this.ChartBorder.GetTopEx();
  244. var bottom=this.ChartBorder.GetBottomEx();
  245. }
  246. this.Canvas.beginPath();
  247. this.Canvas.rect(left,top,(right-left),(bottom-top));
  248. //this.Canvas.stroke(); //调试用
  249. this.Canvas.clip();
  250. }
  251. }
  252. //K线画法
  253. function ChartKLine()
  254. {
  255. this.newMethod = IChartPainting; //派生
  256. this.newMethod();
  257. delete this.newMethod;
  258. this.ClassName = 'ChartKLine';
  259. this.Symbol; //股票代码
  260. this.DrawType = 0; // 0=K线 1=收盘价线 2=美国线 3=空心K线柱子 4=收盘价面积 6=空心阴线阳线柱 9=自定义颜色K线
  261. this.CloseLineColor = g_JSChartResource.CloseLineColor;
  262. this.CloseLineAreaColor = g_JSChartResource.CloseLineAreaColor;
  263. this.UpColor = g_JSChartResource.UpBarColor;
  264. this.DownColor = g_JSChartResource.DownBarColor;
  265. this.UnchagneColor = g_JSChartResource.UnchagneBarColor; //平盘
  266. this.ColorData; //五彩K线颜色 >0 UpColor 其他 DownColor
  267. this.TradeData; //交易系统 包含买卖数据{Buy:, Sell:}
  268. this.IsShowMaxMinPrice = true; //是否显示最大最小值
  269. this.TextFont = g_JSChartResource.KLine.MaxMin.Font;
  270. this.TextColor = g_JSChartResource.KLine.MaxMin.Color;
  271. this.InfoPointColor = g_JSChartResource.KLine.Info.Color;
  272. this.InfoPointColor2 = g_JSChartResource.KLine.Info.Color2;
  273. this.InfoDrawType = 0; //0=在底部画远点 1=在最低价画三角
  274. this.PtMax; //最大值的位置
  275. this.PtMin; //最小值的位置
  276. this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度
  277. this.MinColorBarWidth=g_JSChartResource.MinColorKBarWidth;
  278. this.CustomKLine; //自定义K线, key=date*1000000+time, key={ Color:, DrawType: }
  279. //当前屏显示K线信息
  280. this.ShowRange={ }; //K线显示范围 { Start:, End:, DataCount:, ShowCount: }
  281. this.DrawKRange={ Start:null, End:null }; //当前屏K线的索引{ Start: , End:}
  282. //未回补的价格缺口
  283. this.PriceGap={ Enable:false, Count:1 };
  284. this.PriceGapStyple=
  285. {
  286. Line:{ Color:g_JSChartResource.PriceGapStyple.Line.Color },
  287. Text:{ Color:g_JSChartResource.PriceGapStyple.Text.Color, Font: g_JSChartResource.PriceGapStyple.Text.Font }
  288. };
  289. this.AryPriceGapCache=[]; //缺口数据 { }
  290. this.OneLimitBarType=0; //一字板颜色类型 4个价格全部都在同一个价位上 0=使用平盘颜色 1=跟昨收比较
  291. this.EnableColorBar=false; //K线柱子是否支持自定义颜色
  292. this.DrawAKLine = function () //美国线
  293. {
  294. var isHScreen = (this.ChartFrame.IsHScreen === true);
  295. var dataWidth = this.ChartFrame.DataWidth;
  296. var distanceWidth = this.ChartFrame.DistanceWidth;
  297. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
  298. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
  299. var chartright = this.ChartBorder.GetRight();
  300. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  301. var xPointCount = this.ChartFrame.XPointCount;
  302. this.ShowRange.Start=this.Data.DataOffset;
  303. this.ShowRange.End=this.ShowRange.Start;
  304. this.ShowRange.DataCount=0;
  305. this.ShowRange.ShowCount=xPointCount;
  306. this.DrawKRange.Start=this.Data.DataOffset;
  307. var eventUnchangeKLine=null; //定制平盘K线颜色事件
  308. if (this.GetEventCallback)
  309. {
  310. eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR);
  311. }
  312. var upColor=this.UpColor;
  313. var downColor=this.DownColor;
  314. var unchagneColor=this.UnchagneColor;
  315. var ptMax = { X: null, Y: null, Value: null, Align: 'left' };
  316. var ptMin = { X: null, Y: null, Value: null, Align: 'left' };
  317. var preKItemInfo=null;
  318. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount)
  319. {
  320. var data = this.Data.Data[i];
  321. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  322. var left = xOffset;
  323. var right = xOffset + dataWidth;
  324. if (right > chartright) break;
  325. var x = left + (right - left) / 2;
  326. var yLow = this.ChartFrame.GetYFromData(data.Low);
  327. var yHigh = this.ChartFrame.GetYFromData(data.High);
  328. var yOpen = this.ChartFrame.GetYFromData(data.Open);
  329. var yClose = this.ChartFrame.GetYFromData(data.Close);
  330. this.DrawKRange.End=i;
  331. var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right } };
  332. if (ptMax.Value == null || ptMax.Value < data.High) //求最大值
  333. {
  334. ptMax.X = x;
  335. ptMax.Y = yHigh;
  336. ptMax.Value = data.High;
  337. ptMax.Align = j < xPointCount / 2 ? 'left' : 'right';
  338. }
  339. if (ptMin.Value == null || ptMin.Value > data.Low) //求最小值
  340. {
  341. ptMin.X = x;
  342. ptMin.Y = yLow;
  343. ptMin.Value = data.Low;
  344. ptMin.Align = j < xPointCount / 2 ? 'left' : 'right';
  345. }
  346. if (data.Open < data.Close)
  347. {
  348. this.Canvas.strokeStyle =upColor; //阳线
  349. }
  350. else if (data.Open > data.Close)
  351. {
  352. this.Canvas.strokeStyle = downColor; //阴线
  353. }
  354. else
  355. {
  356. if (eventUnchangeKLine && eventUnchangeKLine.Callback)
  357. {
  358. var sendData={ KItem:data, DataIndex:i, DefaultColor:unchagneColor, BarColor:null };
  359. eventUnchangeKLine.Callback(eventUnchangeKLine, sendData, this);
  360. if (sendData.BarColor) unchagneColor=sendData.BarColor;
  361. }
  362. this.Canvas.strokeStyle =unchagneColor; //平线
  363. }
  364. this.Canvas.beginPath(); //最高-最低
  365. if (isHScreen)
  366. {
  367. if (data.High==data.Low && dataWidth < this.MinBarWidth)
  368. {
  369. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  370. this.Canvas.lineTo(yLow-1, ToFixedPoint(x));
  371. }
  372. else
  373. {
  374. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  375. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  376. }
  377. }
  378. else
  379. {
  380. if (data.High==data.Low && dataWidth < this.MinBarWidth)
  381. {
  382. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  383. this.Canvas.lineTo(ToFixedPoint(x), yLow+1);
  384. }
  385. else
  386. {
  387. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  388. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  389. }
  390. }
  391. this.Canvas.stroke();
  392. if (dataWidth >= this.MinBarWidth)
  393. {
  394. this.Canvas.beginPath(); //开盘
  395. if (isHScreen)
  396. {
  397. this.Canvas.moveTo(ToFixedPoint(yOpen), left);
  398. this.Canvas.lineTo(ToFixedPoint(yOpen), x);
  399. }
  400. else
  401. {
  402. this.Canvas.moveTo(left, ToFixedPoint(yOpen));
  403. this.Canvas.lineTo(x, ToFixedPoint(yOpen));
  404. }
  405. this.Canvas.stroke();
  406. this.Canvas.beginPath(); //收盘
  407. if (isHScreen)
  408. {
  409. this.Canvas.moveTo(ToFixedPoint(yClose), right);
  410. this.Canvas.lineTo(ToFixedPoint(yClose), x);
  411. }
  412. else
  413. {
  414. this.Canvas.moveTo(right, ToFixedPoint(yClose));
  415. this.Canvas.lineTo(x, ToFixedPoint(yClose));
  416. }
  417. this.Canvas.stroke();
  418. }
  419. if (this.Data.DataType == 0 && ChartData.IsDayPeriod(this.Data.Period,true)) //信息地雷
  420. {
  421. var infoItem = { X: x, Xleft: left, XRight: right, YMax: yHigh, YMin: yLow, DayData: data, Index: j };
  422. this.DrawInfoDiv(infoItem);
  423. }
  424. if (this.PriceGap.Enable && preKItemInfo)
  425. {
  426. this.CheckPriceGap(kItemInfo);
  427. var value=this.IsPriceGap(kItemInfo,preKItemInfo);
  428. if (value>0)
  429. this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value });
  430. }
  431. preKItemInfo=kItemInfo;
  432. }
  433. this.PtMax = ptMax;
  434. this.PtMin = ptMin;
  435. }
  436. this.DrawCloseLine = function () //收盘价线
  437. {
  438. var isHScreen = (this.ChartFrame.IsHScreen === true);
  439. var dataWidth = this.ChartFrame.DataWidth;
  440. var distanceWidth = this.ChartFrame.DistanceWidth;
  441. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  442. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  443. var chartright = this.ChartBorder.GetRight();
  444. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  445. var xPointCount = this.ChartFrame.XPointCount;
  446. this.ShowRange.Start=this.Data.DataOffset;
  447. this.ShowRange.End=this.ShowRange.Start;
  448. this.ShowRange.DataCount=0;
  449. this.ShowRange.ShowCount=xPointCount;
  450. this.DrawKRange.Start=this.Data.DataOffset;
  451. var bFirstPoint = true;
  452. this.Canvas.beginPath();
  453. this.Canvas.strokeStyle = this.CloseLineColor;
  454. var preKItemInfo=null;
  455. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount)
  456. {
  457. var data = this.Data.Data[i];
  458. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  459. var left = xOffset;
  460. var right = xOffset + dataWidth;
  461. if (right > chartright) break;
  462. var x = left + (right - left) / 2;
  463. var yClose = this.ChartFrame.GetYFromData(data.Close);
  464. this.DrawKRange.End=i;
  465. if (bFirstPoint) {
  466. if (isHScreen) this.Canvas.moveTo(yClose, x);
  467. else this.Canvas.moveTo(x, yClose);
  468. bFirstPoint = false;
  469. }
  470. else {
  471. if (isHScreen) this.Canvas.lineTo(yClose, x);
  472. else this.Canvas.lineTo(x, yClose);
  473. }
  474. if (this.PriceGap.Enable )
  475. {
  476. var yLow=this.GetYFromData(data.Low, false);
  477. var yHigh=this.GetYFromData(data.High, false);
  478. var yOpen=this.GetYFromData(data.Open, false);
  479. var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }};
  480. if (preKItemInfo)
  481. {
  482. this.CheckPriceGap(kItemInfo);
  483. var value=this.IsPriceGap(kItemInfo,preKItemInfo);
  484. if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value });
  485. }
  486. preKItemInfo=kItemInfo;
  487. }
  488. }
  489. if (bFirstPoint == false) this.Canvas.stroke();
  490. }
  491. this.DrawCloseArea = function () //收盘价面积
  492. {
  493. var isHScreen = (this.ChartFrame.IsHScreen === true);
  494. var dataWidth = this.ChartFrame.DataWidth;
  495. var distanceWidth = this.ChartFrame.DistanceWidth;
  496. var xPointCount = this.ChartFrame.XPointCount;
  497. if (isHScreen)
  498. {
  499. var border=this.ChartBorder.GetHScreenBorder();
  500. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  501. var chartright=border.BottomEx;
  502. var borderLeft=border.TopEx;
  503. }
  504. else
  505. {
  506. var border=this.ChartBorder.GetBorder();
  507. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  508. var chartright=border.RightEx;
  509. var borderLeft=border.LeftEx;
  510. }
  511. var bFirstPoint = true;
  512. var firstPoint = null;
  513. this.Canvas.beginPath();
  514. this.Canvas.strokeStyle = this.CloseLineColor;
  515. var ptLast=null;
  516. this.ShowRange.Start=this.Data.DataOffset;
  517. this.ShowRange.End=this.ShowRange.Start;
  518. this.ShowRange.DataCount=0;
  519. this.ShowRange.ShowCount=xPointCount;
  520. this.DrawKRange.Start=this.Data.DataOffset;
  521. if (this.Data.DataOffset>0) //把最左边的一个点连上
  522. {
  523. var data=this.Data.Data[this.Data.DataOffset-1];
  524. if (data && IFrameSplitOperator.IsNumber(data.Close))
  525. {
  526. var x=borderLeft;
  527. var yClose=this.GetYFromData(data.Close,false);
  528. if (isHScreen)
  529. {
  530. this.Canvas.moveTo(yClose,x);
  531. firstPoint={ X:yClose, Y:x };
  532. }
  533. else
  534. {
  535. this.Canvas.moveTo(x,yClose);
  536. firstPoint={ X:x, Y:yClose };
  537. }
  538. bFirstPoint=false;
  539. }
  540. }
  541. var preKItemInfo=null;
  542. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount)
  543. {
  544. var data = this.Data.Data[i];
  545. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  546. var left = xOffset;
  547. var right = xOffset + dataWidth;
  548. if (right > chartright) break;
  549. var x = left + (right - left) / 2;
  550. var yClose = this.ChartFrame.GetYFromData(data.Close);
  551. this.DrawKRange.End=i;
  552. if (bFirstPoint)
  553. {
  554. if (isHScreen)
  555. {
  556. this.Canvas.moveTo(yClose, x);
  557. firstPoint = { X: yClose, Y: x };
  558. }
  559. else
  560. {
  561. this.Canvas.moveTo(x, yClose);
  562. firstPoint = { X: x, Y: yClose };
  563. }
  564. bFirstPoint = false;
  565. }
  566. else
  567. {
  568. if (isHScreen) this.Canvas.lineTo(yClose, x);
  569. else this.Canvas.lineTo(x, yClose);
  570. }
  571. if (i==this.Data.Data.length-1)
  572. {
  573. ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright };
  574. }
  575. if (this.PriceGap.Enable )
  576. {
  577. var yLow=this.GetYFromData(data.Low, false);
  578. var yHigh=this.GetYFromData(data.High, false);
  579. var yOpen=this.GetYFromData(data.Open, false);
  580. var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }};
  581. if (preKItemInfo)
  582. {
  583. this.CheckPriceGap(kItemInfo);
  584. var value=this.IsPriceGap(kItemInfo,preKItemInfo);
  585. if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value });
  586. }
  587. preKItemInfo=kItemInfo;
  588. }
  589. }
  590. this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点
  591. if (bFirstPoint) return;
  592. this.Canvas.stroke();
  593. //画面积
  594. if (isHScreen)
  595. {
  596. this.Canvas.lineTo(this.ChartBorder.GetLeft(), x);
  597. this.Canvas.lineTo(this.ChartBorder.GetLeft(), firstPoint.Y);
  598. }
  599. else
  600. {
  601. this.Canvas.lineTo(x, this.ChartBorder.GetBottom());
  602. this.Canvas.lineTo(firstPoint.X, this.ChartBorder.GetBottom());
  603. }
  604. this.Canvas.closePath();
  605. if (Array.isArray(this.CloseLineAreaColor))
  606. {
  607. if (isHScreen)
  608. {
  609. let gradient = this.Canvas.createLinearGradient(this.ChartBorder.GetRightEx(), this.ChartBorder.GetTop(), this.ChartBorder.GetLeft(), this.ChartBorder.GetTop());
  610. gradient.addColorStop(0, this.CloseLineAreaColor[0]);
  611. gradient.addColorStop(1, this.CloseLineAreaColor[1]);
  612. this.Canvas.fillStyle = gradient;
  613. }
  614. else
  615. {
  616. let gradient = this.Canvas.createLinearGradient(firstPoint.X, this.ChartBorder.GetTopEx(), firstPoint.X, this.ChartBorder.GetBottom());
  617. gradient.addColorStop(0, this.CloseLineAreaColor[0]);
  618. gradient.addColorStop(1, this.CloseLineAreaColor[1]);
  619. this.Canvas.fillStyle = gradient;
  620. }
  621. }
  622. else
  623. {
  624. this.Canvas.fillStyle = this.CloseLineAreaColor;
  625. }
  626. this.Canvas.fill();
  627. }
  628. this.DrawKBar = function ()
  629. {
  630. var isHScreen = (this.ChartFrame.IsHScreen === true);
  631. var dataWidth = this.ChartFrame.DataWidth;
  632. var distanceWidth = this.ChartFrame.DistanceWidth;
  633. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  634. var chartright = this.ChartBorder.GetRight();
  635. var xPointCount = this.ChartFrame.XPointCount;
  636. var border=this.ChartBorder.GetBorder();
  637. if (isHScreen)
  638. {
  639. xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  640. chartright = this.ChartBorder.GetBottom();
  641. }
  642. var ptMax = { X: null, Y: null, Value: null, Align: 'left' };
  643. var ptMin = { X: null, Y: null, Value: null, Align: 'left' };
  644. var upColor = this.UpColor;
  645. var downColor = this.DownColor;
  646. var unchagneColor = this.UnchagneColor;
  647. var ptLast=null;
  648. this.ShowRange.Start=this.Data.DataOffset;
  649. this.ShowRange.End=this.ShowRange.Start;
  650. this.ShowRange.DataCount=0;
  651. this.ShowRange.ShowCount=xPointCount;
  652. this.DrawKRange.Start=this.Data.DataOffset;
  653. var eventUnchangeKLine=null; //定制平盘K线颜色事件
  654. if (this.GetEventCallback)
  655. {
  656. eventUnchangeKLine=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_UNCHANGE_KLINE_COLOR);
  657. }
  658. var preKItemInfo=null;
  659. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth), ++this.ShowRange.DataCount)
  660. {
  661. var data = this.Data.Data[i];
  662. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  663. var left = xOffset;
  664. var right = xOffset + dataWidth;
  665. if (right > chartright) break;
  666. this.DrawKRange.End=i;
  667. var x = left + (right - left) / 2;
  668. var yLow = this.ChartFrame.GetYFromData(data.Low);
  669. var yHigh = this.ChartFrame.GetYFromData(data.High);
  670. var yOpen = this.ChartFrame.GetYFromData(data.Open);
  671. var yClose = this.ChartFrame.GetYFromData(data.Close);
  672. var y = yHigh;
  673. var kItemInfo={ Data:data, Coordinate:{ X:x, Low:yLow, High:yHigh, Close:yClose, Open:yOpen, Left:left, Right:right }};
  674. if (ptMax.Value == null || ptMax.Value < data.High) //求最大值
  675. {
  676. ptMax.X = x;
  677. ptMax.Y = yHigh;
  678. ptMax.Value = data.High;
  679. ptMax.Align = j < xPointCount / 2 ? 'left' : 'right';
  680. }
  681. if (ptMin.Value == null || ptMin.Value > data.Low) //求最小值
  682. {
  683. ptMin.X = x;
  684. ptMin.Y = yLow;
  685. ptMin.Value = data.Low;
  686. ptMin.Align = j < xPointCount / 2 ? 'left' : 'right';
  687. }
  688. if (this.ColorData) ///五彩K线颜色设置
  689. {
  690. if (i < this.ColorData.length)
  691. upColor = downColor = unchagneColor = (this.ColorData[i] > 0 ? this.UpColor : this.DownColor);
  692. else
  693. upColor = downColor = unchagneColor = this.DownColor;
  694. }
  695. var kLineOption=this.GetCustomKLine(data);
  696. if (kLineOption)
  697. {
  698. var barColor=kLineOption.Color;
  699. if (!barColor)
  700. {
  701. if (data.Open<data.Close) barColor=upColor;
  702. else if (data.Open>data.Close) barColor=downColor;
  703. else barColor=unchagneColor;
  704. }
  705. var drawType=this.DrawType;
  706. if (IFrameSplitOperator.IsNumber(kLineOption.DrawType)) drawType=kLineOption.DrawType;
  707. this.DrawKBar_Custom(data, dataWidth, barColor, drawType, kLineOption, x, y, left, right, yLow, yHigh, yOpen, yClose, border, isHScreen);
  708. }
  709. else if ((this.DrawType==9 || this.EnableColorBar) && data.ColorData)
  710. {
  711. this.DrawColorKBar(data, data.ColorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  712. }
  713. else if (data.Open < data.Close) //阳线
  714. {
  715. this.DrawKBar_Up(data, dataWidth, upColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  716. }
  717. else if (data.Open > data.Close) //阴线
  718. {
  719. this.DrawKBar_Down(data, dataWidth, downColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  720. }
  721. else // 平线
  722. {
  723. var barColor=unchagneColor;
  724. if (eventUnchangeKLine && eventUnchangeKLine.Callback)
  725. {
  726. var sendData={ KItem:data, DataIndex:i, DefaultColor:barColor, BarColor:null };
  727. eventUnchangeKLine.Callback(eventUnchangeKLine, sendData, this);
  728. if (sendData.BarColor) barColor=sendData.BarColor;
  729. }
  730. this.DrawKBar_Unchagne(data, dataWidth, barColor, this.DrawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  731. }
  732. if (this.Data.DataType == 0 && ChartData.IsDayPeriod(this.Data.Period,true)) //信息地雷
  733. {
  734. var infoItem = { X: x, Xleft: left, XRight: right, YMax: yHigh, YMin: yLow, DayData: data, Index: j };
  735. this.DrawInfoDiv(infoItem);
  736. }
  737. if (i==this.Data.Data.length-1)
  738. {
  739. ptLast={ X:x, Y:yClose, XLeft:left, XRight:right, KItem:data, ChartRight:chartright };
  740. }
  741. if (this.PriceGap.Enable && preKItemInfo)
  742. {
  743. this.CheckPriceGap(kItemInfo);
  744. var value=this.IsPriceGap(kItemInfo,preKItemInfo);
  745. if (value>0) this.AryPriceGapCache.push({ Data:[preKItemInfo, kItemInfo], Type:value });
  746. }
  747. preKItemInfo=kItemInfo;
  748. }
  749. this.DrawLastPointEvent(ptLast); //通知外部绘制最后一个点
  750. this.PtMax = ptMax;
  751. this.PtMin = ptMin;
  752. }
  753. this.DrawKBar_Up = function(data, dataWidth, upColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //阳线
  754. {
  755. var isEmptyBar=(drawType==3 || drawType==6);
  756. if (dataWidth >= this.MinBarWidth)
  757. {
  758. if (isEmptyBar)
  759. {
  760. if ((dataWidth%2)!=0) dataWidth-=1;
  761. }
  762. this.Canvas.strokeStyle = upColor;
  763. if (data.High > data.Close) //上影线
  764. {
  765. this.Canvas.beginPath();
  766. if (isHScreen)
  767. {
  768. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  769. this.Canvas.lineTo(ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : yClose), ToFixedPoint(x));
  770. }
  771. else
  772. {
  773. if (isEmptyBar)
  774. {
  775. var xFixed=left+dataWidth/2;
  776. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y));
  777. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen)));
  778. }
  779. else
  780. {
  781. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  782. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yClose));
  783. }
  784. }
  785. this.Canvas.stroke();
  786. y = yClose;
  787. }
  788. else
  789. {
  790. y = yClose;
  791. }
  792. this.Canvas.fillStyle = upColor;
  793. if (isHScreen)
  794. {
  795. if (Math.abs(yOpen - y) < 1)
  796. {
  797. this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  798. }
  799. else
  800. {
  801. if (isEmptyBar) //空心柱
  802. {
  803. this.Canvas.beginPath();
  804. this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth));
  805. this.Canvas.stroke();
  806. }
  807. else
  808. {
  809. //宽度是负数竟然不会画, h5就可以
  810. //this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth));
  811. this.Canvas.fillRect(ToFixedRect(Math.min(yOpen, y)), ToFixedRect(left), ToFixedRect(Math.abs(yOpen - y)), ToFixedRect(dataWidth));
  812. }
  813. }
  814. }
  815. else
  816. {
  817. if (Math.abs(yOpen - y) < 1)
  818. {
  819. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
  820. }
  821. else
  822. {
  823. if (isEmptyBar) //空心柱
  824. {
  825. this.Canvas.beginPath();
  826. this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y));
  827. this.Canvas.stroke();
  828. }
  829. else
  830. {
  831. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y));
  832. }
  833. }
  834. }
  835. if (data.Open > data.Low) //下影线
  836. {
  837. this.Canvas.beginPath();
  838. if (isHScreen)
  839. {
  840. this.Canvas.moveTo(ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : y), ToFixedPoint(x));
  841. this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
  842. }
  843. else
  844. {
  845. if (isEmptyBar)
  846. {
  847. var xFixed=left+dataWidth/2;
  848. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen)));
  849. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow));
  850. }
  851. else
  852. {
  853. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  854. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
  855. }
  856. }
  857. this.Canvas.stroke();
  858. }
  859. }
  860. else
  861. {
  862. this.Canvas.beginPath();
  863. if (isHScreen)
  864. {
  865. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  866. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  867. }
  868. else
  869. {
  870. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  871. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  872. }
  873. this.Canvas.strokeStyle = upColor;
  874. this.Canvas.stroke();
  875. }
  876. }
  877. this.DrawKBar_Down=function(data, dataWidth, downColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //阴线
  878. {
  879. var isEmptyBar=(drawType==6);
  880. if (dataWidth >= this.MinBarWidth)
  881. {
  882. if (isEmptyBar)
  883. {
  884. if ((dataWidth%2)!=0) dataWidth-=1;
  885. }
  886. this.Canvas.strokeStyle = downColor;
  887. if (data.High > data.Close) //上影线
  888. {
  889. this.Canvas.beginPath();
  890. if (isHScreen)
  891. {
  892. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  893. this.Canvas.lineTo(ToFixedPoint(yOpen), ToFixedPoint(x));
  894. }
  895. else
  896. {
  897. if (isEmptyBar)
  898. {
  899. var xFixed=left+dataWidth/2;
  900. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y));
  901. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen)));
  902. }
  903. else
  904. {
  905. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  906. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yOpen));
  907. }
  908. }
  909. this.Canvas.stroke();
  910. y = yOpen;
  911. }
  912. else
  913. {
  914. y = yOpen
  915. }
  916. this.Canvas.fillStyle = downColor;
  917. if (isHScreen)
  918. {
  919. if (Math.abs(yClose - y) < 1)
  920. {
  921. this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  922. }
  923. else
  924. {
  925. //宽度是负数竟然不会画, h5就可以
  926. this.Canvas.fillRect(ToFixedRect(Math.min(yClose, y)), ToFixedRect(left), ToFixedRect(Math.abs(yClose - y)), ToFixedRect(dataWidth));
  927. }
  928. }
  929. else
  930. {
  931. if (Math.abs(yClose - y) < 1)
  932. {
  933. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
  934. }
  935. else
  936. {
  937. if (isEmptyBar) //空心柱
  938. {
  939. this.Canvas.beginPath();
  940. this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y));
  941. this.Canvas.stroke();
  942. }
  943. else
  944. {
  945. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y));
  946. }
  947. }
  948. }
  949. if (data.Open > data.Low) //下影线
  950. {
  951. this.Canvas.beginPath();
  952. if (isHScreen)
  953. {
  954. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  955. this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
  956. }
  957. else
  958. {
  959. if (isEmptyBar)
  960. {
  961. var xFixed=left+dataWidth/2;
  962. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen)));
  963. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow));
  964. }
  965. else
  966. {
  967. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  968. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
  969. }
  970. }
  971. this.Canvas.stroke();
  972. }
  973. }
  974. else
  975. {
  976. this.Canvas.beginPath();
  977. if (isHScreen)
  978. {
  979. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  980. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  981. }
  982. else
  983. {
  984. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  985. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  986. }
  987. this.Canvas.strokeStyle = downColor;
  988. this.Canvas.stroke();
  989. }
  990. }
  991. this.DrawKBar_Unchagne=function(data, dataWidth, unchagneColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen) //平线
  992. {
  993. if (this.OneLimitBarType===1 && this.IsOneLimitBar(data)) //一字板
  994. {
  995. unchagneColor=this.GetOneLimitBarColor(data);
  996. }
  997. if (dataWidth >= this.MinBarWidth)
  998. {
  999. if ((dataWidth%2)!=0) dataWidth-=1;
  1000. this.Canvas.strokeStyle = unchagneColor;
  1001. this.Canvas.beginPath();
  1002. if (data.High > data.Close) //上影线
  1003. {
  1004. if (isHScreen)
  1005. {
  1006. this.Canvas.moveTo(y, ToFixedPoint(x));
  1007. this.Canvas.lineTo(yOpen, ToFixedPoint(x));
  1008. }
  1009. else
  1010. {
  1011. var xFixed=left+dataWidth/2;
  1012. this.Canvas.moveTo(ToFixedPoint(xFixed), y);
  1013. this.Canvas.lineTo(ToFixedPoint(xFixed), yOpen);
  1014. }
  1015. y = yOpen;
  1016. }
  1017. else
  1018. {
  1019. y = yOpen;
  1020. }
  1021. if (isHScreen)
  1022. {
  1023. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(left));
  1024. this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(right));
  1025. }
  1026. else
  1027. {
  1028. this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(y));
  1029. this.Canvas.lineTo(ToFixedPoint(left+dataWidth), ToFixedPoint(y));
  1030. }
  1031. if (data.Open > data.Low) //下影线
  1032. {
  1033. if (isHScreen)
  1034. {
  1035. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  1036. this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
  1037. }
  1038. else
  1039. {
  1040. var xFixed=left+dataWidth/2;
  1041. this.Canvas.moveTo(ToFixedPoint(xFixed), ToFixedPoint(y));
  1042. this.Canvas.lineTo(ToFixedPoint(xFixed), ToFixedPoint(yLow));
  1043. }
  1044. }
  1045. this.Canvas.stroke();
  1046. }
  1047. else
  1048. {
  1049. this.Canvas.beginPath();
  1050. if (isHScreen)
  1051. {
  1052. if (data.High==data.Low)
  1053. {
  1054. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  1055. this.Canvas.lineTo(yLow-1,ToFixedPoint(x));
  1056. }
  1057. else
  1058. {
  1059. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  1060. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  1061. }
  1062. }
  1063. else
  1064. {
  1065. if (data.High==data.Low)
  1066. {
  1067. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  1068. this.Canvas.lineTo(ToFixedPoint(x),yLow+1);
  1069. }
  1070. else
  1071. {
  1072. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  1073. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  1074. }
  1075. }
  1076. this.Canvas.strokeStyle = unchagneColor;
  1077. this.Canvas.stroke();
  1078. }
  1079. }
  1080. //是否是一字板
  1081. this.IsOneLimitBar=function(kItem)
  1082. {
  1083. if (kItem.Open==kItem.Close && kItem.High==kItem.Low && kItem.Open==kItem.High) return true;
  1084. return false;
  1085. }
  1086. //一字板颜色 和昨收比较
  1087. this.GetOneLimitBarColor=function(kItem)
  1088. {
  1089. if (!kItem || !IFrameSplitOperator.IsNumber(kItem.YClose)) return this.UnchagneColor;
  1090. if (kItem.Close>kItem.YClose) return this.UpColor;
  1091. else if (kItem.Close<kItem.YClose) return this.DownColor;
  1092. else return this.UnchagneColor;
  1093. }
  1094. this.DrawKBar_Custom=function(data, dataWidth, barColor, drawType, option, x, y, left, right, yLow, yHigh, yOpen, yClose, border, isHScreen)
  1095. {
  1096. if (option.BGColor) //画背景色
  1097. {
  1098. this.Canvas.fillStyle=option.BGColor;
  1099. var distanceWidth=this.ChartFrame.DistanceWidth;
  1100. if (isHScreen)
  1101. {
  1102. var yLeft=left-(distanceWidth/2);
  1103. var yRight=right+(distanceWidth/2);
  1104. var xTop=border.RightEx;
  1105. var xBottom=border.LeftEx;
  1106. this.Canvas.fillRect(ToFixedRect(xBottom),ToFixedRect(yLeft),ToFixedRect(xTop-xBottom),ToFixedRect(yRight-yLeft));
  1107. }
  1108. else
  1109. {
  1110. var xLeft=left-(distanceWidth/2);
  1111. var xRight=right+(distanceWidth/2);
  1112. var yTop=border.TopEx;
  1113. var yBottom=border.BottomEx;
  1114. this.Canvas.fillRect(ToFixedRect(xLeft),ToFixedRect(yTop),ToFixedRect(xRight-xLeft),ToFixedRect(yBottom-yTop));
  1115. }
  1116. }
  1117. if (dataWidth>=4)
  1118. {
  1119. this.Canvas.strokeStyle=barColor;
  1120. if (data.High>data.Close) //上影线
  1121. {
  1122. this.Canvas.beginPath();
  1123. if (isHScreen)
  1124. {
  1125. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  1126. this.Canvas.lineTo(ToFixedPoint(drawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x));
  1127. }
  1128. else
  1129. {
  1130. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  1131. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(drawType==3?Math.min(yClose,yOpen):yClose));
  1132. }
  1133. this.Canvas.stroke();
  1134. y=yClose;
  1135. }
  1136. else
  1137. {
  1138. y=yClose;
  1139. }
  1140. this.Canvas.fillStyle=barColor;
  1141. if (isHScreen)
  1142. {
  1143. if (Math.abs(yOpen-y)<1)
  1144. {
  1145. this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  1146. }
  1147. else
  1148. {
  1149. if (drawType==3) //空心柱
  1150. {
  1151. this.Canvas.beginPath();
  1152. this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth));
  1153. this.Canvas.stroke();
  1154. }
  1155. else
  1156. {
  1157. this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth));
  1158. }
  1159. }
  1160. }
  1161. else
  1162. {
  1163. if (Math.abs(yOpen-y)<1)
  1164. {
  1165. this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1
  1166. }
  1167. else
  1168. {
  1169. if (drawType==3) //空心柱
  1170. {
  1171. this.Canvas.beginPath();
  1172. this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y));
  1173. this.Canvas.stroke();
  1174. }
  1175. else
  1176. {
  1177. this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y)));
  1178. }
  1179. }
  1180. }
  1181. if (data.Open>data.Low) //下影线
  1182. {
  1183. this.Canvas.beginPath();
  1184. if (isHScreen)
  1185. {
  1186. this.Canvas.moveTo(ToFixedPoint(drawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x));
  1187. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  1188. }
  1189. else
  1190. {
  1191. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(drawType==3?Math.max(yClose,yOpen):y));
  1192. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  1193. }
  1194. this.Canvas.stroke();
  1195. }
  1196. }
  1197. else
  1198. {
  1199. this.Canvas.beginPath();
  1200. if (isHScreen)
  1201. {
  1202. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  1203. this.Canvas.lineTo(yLow,ToFixedPoint(x));
  1204. }
  1205. else
  1206. {
  1207. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  1208. this.Canvas.lineTo(ToFixedPoint(x),yLow);
  1209. }
  1210. this.Canvas.strokeStyle=barColor;
  1211. this.Canvas.stroke();
  1212. }
  1213. }
  1214. //绘制自定义K线
  1215. this.DrawColorKBar=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  1216. {
  1217. if (Math.abs(yClose-yOpen)<1)
  1218. this.DrawColorKBar_Line(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  1219. else if (colorData.Border || colorData.Type===0)
  1220. this.DrawColorKBar_Border(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  1221. else
  1222. this.DrawColorKBar_NoBorder(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  1223. }
  1224. //带边框柱子
  1225. this.DrawColorKBar_Border=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  1226. {
  1227. if (dataWidth>=this.MinColorBarWidth)
  1228. {
  1229. if ((dataWidth%2)!=0) dataWidth-=1;
  1230. var topPrice=Math.max(data.Close,data.Open);
  1231. var bottomPrice=Math.min(data.Close,data.Open);
  1232. if (isHScreen)
  1233. {
  1234. var yBarTop=Math.max(yClose,yOpen);
  1235. var yBarBottom=Math.min(yClose,yOpen);
  1236. }
  1237. else
  1238. {
  1239. var yBarTop=Math.min(yClose,yOpen);
  1240. var yBarBottom=Math.max(yClose,yOpen);
  1241. }
  1242. var yBarHeight=Math.abs(yClose-yOpen);
  1243. //上影线
  1244. if (data.High>topPrice && colorData.Line)
  1245. {
  1246. this.Canvas.strokeStyle=colorData.Line.Color;
  1247. this.Canvas.beginPath();
  1248. if (isHScreen)
  1249. {
  1250. this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x));
  1251. this.Canvas.lineTo(ToFixedPoint(yBarTop),ToFixedPoint(x));
  1252. }
  1253. else
  1254. {
  1255. var xFixed=left+dataWidth/2;
  1256. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yHigh));
  1257. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yBarTop));
  1258. }
  1259. this.Canvas.stroke();
  1260. }
  1261. //下影线
  1262. if (bottomPrice>data.Low && colorData.Line)
  1263. {
  1264. this.Canvas.strokeStyle=colorData.Line.Color;
  1265. this.Canvas.beginPath();
  1266. if (isHScreen)
  1267. {
  1268. this.Canvas.moveTo(ToFixedPoint(yBarBottom),ToFixedPoint(x));
  1269. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  1270. }
  1271. else
  1272. {
  1273. var xFixed=left+dataWidth/2;
  1274. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yBarBottom));
  1275. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow));
  1276. }
  1277. this.Canvas.stroke();
  1278. }
  1279. //中心柱子
  1280. this.Canvas.beginPath();
  1281. if (isHScreen)
  1282. {
  1283. this.Canvas.rect(ToFixedPoint(yBarBottom),ToFixedPoint(left),ToFixedRect(yBarHeight),ToFixedRect(dataWidth));
  1284. }
  1285. else
  1286. {
  1287. this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarHeight));
  1288. }
  1289. this.Canvas.closePath();
  1290. if (colorData.Type==0) //空心柱子
  1291. {
  1292. if (colorData.BarColor) //边框
  1293. {
  1294. this.Canvas.strokeStyle=colorData.BarColor;
  1295. this.Canvas.stroke();
  1296. }
  1297. if (colorData.Border)
  1298. {
  1299. this.Canvas.strokeStyle=colorData.Border.Color;
  1300. this.Canvas.stroke();
  1301. }
  1302. }
  1303. else if (colorData.Type==1) //实心
  1304. {
  1305. if (colorData.BarColor) //内部填充
  1306. {
  1307. this.Canvas.fillStyle=colorData.BarColor;
  1308. this.Canvas.fill();
  1309. }
  1310. if (colorData.Border) //边框
  1311. {
  1312. this.Canvas.strokeStyle=colorData.Border.Color;
  1313. this.Canvas.stroke();
  1314. }
  1315. }
  1316. }
  1317. else
  1318. {
  1319. this.DrawColorKBar_MinBar(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  1320. }
  1321. }
  1322. //不带边框柱子
  1323. this.DrawColorKBar_NoBorder=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  1324. {
  1325. if (dataWidth>=this.MinColorBarWidth)
  1326. {
  1327. var topPrice=Math.max(data.Close,data.Open);
  1328. var bottomPrice=Math.min(data.Close,data.Open);
  1329. if (isHScreen)
  1330. {
  1331. var yBarTop=Math.max(yClose,yOpen);
  1332. var yBarBottom=Math.min(yClose,yOpen);
  1333. }
  1334. else
  1335. {
  1336. var yBarTop=Math.min(yClose,yOpen);
  1337. var yBarBottom=Math.max(yClose,yOpen);
  1338. }
  1339. var yBarHeight=Math.abs(yClose-yOpen);
  1340. //上影线
  1341. if (data.High>topPrice && colorData.Line)
  1342. {
  1343. this.Canvas.strokeStyle=colorData.Line.Color;
  1344. this.Canvas.beginPath();
  1345. if (isHScreen)
  1346. {
  1347. this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x));
  1348. this.Canvas.lineTo(ToFixedPoint(yBarTop),ToFixedPoint(x));
  1349. }
  1350. else
  1351. {
  1352. var xFixed=left+dataWidth/2;
  1353. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yHigh));
  1354. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yBarTop));
  1355. }
  1356. this.Canvas.stroke();
  1357. }
  1358. //下影线
  1359. if (bottomPrice>data.Low && colorData.Line)
  1360. {
  1361. this.Canvas.strokeStyle=colorData.Line.Color;
  1362. this.Canvas.beginPath();
  1363. if (isHScreen)
  1364. {
  1365. this.Canvas.moveTo(ToFixedPoint(yBarBottom),ToFixedPoint(x));
  1366. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  1367. }
  1368. else
  1369. {
  1370. var xFixed=left+dataWidth/2;
  1371. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(yBarBottom));
  1372. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow));
  1373. }
  1374. this.Canvas.stroke();
  1375. }
  1376. //中心柱子
  1377. this.Canvas.beginPath();
  1378. if (isHScreen)
  1379. {
  1380. this.Canvas.rect(ToFixedPoint(yBarBottom),ToFixedPoint(left),ToFixedRect(yBarHeight),ToFixedRect(dataWidth));
  1381. }
  1382. else
  1383. {
  1384. this.Canvas.rect(ToFixedRect(left),ToFixedRect(yBarTop),ToFixedRect(dataWidth),ToFixedRect(yBarHeight));
  1385. }
  1386. this.Canvas.closePath();
  1387. if (colorData.Type==1) //实心
  1388. {
  1389. if (colorData.BarColor) //内部填充
  1390. {
  1391. this.Canvas.fillStyle=colorData.BarColor;
  1392. this.Canvas.fill();
  1393. }
  1394. }
  1395. }
  1396. else
  1397. {
  1398. this.DrawColorKBar_MinBar(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  1399. }
  1400. }
  1401. this.DrawColorKBar_MinBar=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  1402. {
  1403. if (colorData.Line)
  1404. {
  1405. this.Canvas.strokeStyle=colorData.Line.Color;
  1406. this.Canvas.beginPath();
  1407. if (isHScreen)
  1408. {
  1409. this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x));
  1410. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  1411. }
  1412. else
  1413. {
  1414. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh));
  1415. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  1416. }
  1417. this.Canvas.stroke();
  1418. }
  1419. /*
  1420. var barColor;
  1421. if (colorData.Type==0) //空心柱子
  1422. {
  1423. if (colorData.Border) barColor=colorData.Border.Color;
  1424. else if (colorData.BarColor) barColor=colorData.BarColor;
  1425. }
  1426. else if (colorData.Type==1) //实心
  1427. {
  1428. if (colorData.Border) barColor=colorData.Border.Color;
  1429. else if (colorData.BarColor) barColor=colorData.BarColor;
  1430. }
  1431. if (barColor)
  1432. {
  1433. this.Canvas.strokeStyle=barColor;
  1434. this.Canvas.beginPath();
  1435. if (isHScreen)
  1436. {
  1437. this.Canvas.moveTo(ToFixedPoint(yOpen),ToFixedPoint(x));
  1438. this.Canvas.lineTo(ToFixedPoint(yClose),ToFixedPoint(x));
  1439. }
  1440. else
  1441. {
  1442. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yOpen));
  1443. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose));
  1444. }
  1445. this.Canvas.stroke();
  1446. }
  1447. */
  1448. }
  1449. //十字线
  1450. this.DrawColorKBar_Line=function(data, colorData, dataWidth, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  1451. {
  1452. if (dataWidth>=this.MinColorBarWidth)
  1453. {
  1454. if (colorData.Line)
  1455. {
  1456. this.Canvas.strokeStyle=colorData.Line.Color;
  1457. this.Canvas.beginPath();
  1458. if (isHScreen)
  1459. {
  1460. this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x));
  1461. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  1462. }
  1463. else
  1464. {
  1465. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh));
  1466. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  1467. }
  1468. this.Canvas.stroke();
  1469. }
  1470. var barColor;
  1471. if (colorData.Type==0) //空心柱子
  1472. {
  1473. if (colorData.Border) barColor=colorData.Border.Color;
  1474. else if (colorData.BarColor) barColor=colorData.BarColor;
  1475. }
  1476. else if (colorData.Type==1) //实心
  1477. {
  1478. if (colorData.Border) barColor=colorData.Border.Color;
  1479. else if (colorData.BarColor) barColor=colorData.BarColor;
  1480. }
  1481. if (barColor)
  1482. {
  1483. this.Canvas.strokeStyle=barColor;
  1484. this.Canvas.beginPath();
  1485. if (isHScreen)
  1486. {
  1487. this.Canvas.moveTo(ToFixedPoint(yOpen),ToFixedPoint(left));
  1488. this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(right));
  1489. }
  1490. else
  1491. {
  1492. this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(yOpen));
  1493. this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(yOpen));
  1494. }
  1495. this.Canvas.stroke();
  1496. }
  1497. }
  1498. else
  1499. {
  1500. if (colorData.Line)
  1501. {
  1502. var xFixed=left+dataWidth/2;
  1503. this.Canvas.strokeStyle=colorData.Line.Color;
  1504. this.Canvas.beginPath();
  1505. if (isHScreen)
  1506. {
  1507. this.Canvas.moveTo(ToFixedPoint(yHigh),ToFixedPoint(x));
  1508. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  1509. }
  1510. else
  1511. {
  1512. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(yHigh));
  1513. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  1514. }
  1515. this.Canvas.stroke();
  1516. }
  1517. }
  1518. }
  1519. this.ClearCustomKLine=function()
  1520. {
  1521. this.CustomKLine=null;
  1522. }
  1523. this.GetCustomKLine=function(kItem)
  1524. {
  1525. if (!this.CustomKLine) return null;
  1526. if (!kItem) return null;
  1527. var key=kItem.Date*1000000;
  1528. if (IFrameSplitOperator.IsNumber(kItem.Time)) key+=kItem.Time;
  1529. if (!this.CustomKLine.has(key)) return null;
  1530. var value=this.CustomKLine.get(key);
  1531. return value;
  1532. }
  1533. this.DrawTrade = function () //交易系统
  1534. {
  1535. if (!this.TradeData) return;
  1536. var isHScreen = (this.ChartFrame.IsHScreen === true);
  1537. var dataWidth = this.ChartFrame.DataWidth;
  1538. var distanceWidth = this.ChartFrame.DistanceWidth;
  1539. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  1540. var chartright = this.ChartBorder.GetRight();
  1541. var xPointCount = this.ChartFrame.XPointCount;
  1542. if (isHScreen) {
  1543. xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  1544. chartright = this.ChartBorder.GetBottom();
  1545. }
  1546. var sellData = this.TradeData.Sell;
  1547. var buyData = this.TradeData.Buy;
  1548. var arrowWidth = dataWidth;
  1549. if (arrowWidth > 10) arrowWidth = 10;
  1550. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth)) {
  1551. var data = this.Data.Data[i];
  1552. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  1553. var buy = false, sell = false;
  1554. if (sellData && i < sellData.length) sell = sellData[i] > 0;
  1555. if (buyData && i < buyData.length) buy = buyData[i] > 0;
  1556. if (!sell && !buy) continue;
  1557. var left = xOffset;
  1558. var right = xOffset + dataWidth;
  1559. if (right > chartright) break;
  1560. var x = left + (right - left) / 2;
  1561. var yLow = this.ChartFrame.GetYFromData(data.Low);
  1562. var yHigh = this.ChartFrame.GetYFromData(data.High);
  1563. var yOpen = this.ChartFrame.GetYFromData(data.Open);
  1564. var yClose = this.ChartFrame.GetYFromData(data.Close);
  1565. var y = yHigh;
  1566. if (buy) {
  1567. this.Canvas.fillStyle = this.UpColor;
  1568. this.Canvas.strokeStyle = this.UnchagneColor;
  1569. this.Canvas.beginPath();
  1570. if (isHScreen) {
  1571. this.Canvas.moveTo(yLow - 1, x);
  1572. this.Canvas.lineTo(yLow - arrowWidth - 1, x - arrowWidth / 2);
  1573. this.Canvas.lineTo(yLow - arrowWidth - 1, x + arrowWidth / 2);
  1574. }
  1575. else {
  1576. this.Canvas.moveTo(x, yLow + 1);
  1577. this.Canvas.lineTo(x - arrowWidth / 2, yLow + arrowWidth + 1);
  1578. this.Canvas.lineTo(x + arrowWidth / 2, yLow + arrowWidth + 1);
  1579. }
  1580. this.Canvas.closePath();
  1581. this.Canvas.fill();
  1582. this.Canvas.stroke();
  1583. }
  1584. if (sell) {
  1585. this.Canvas.fillStyle = this.DownColor;
  1586. this.Canvas.strokeStyle = this.UnchagneColor;
  1587. this.Canvas.beginPath();
  1588. if (isHScreen) {
  1589. this.Canvas.moveTo(yHigh + 1, x);
  1590. this.Canvas.lineTo(yHigh + arrowWidth + 1, x - arrowWidth / 2);
  1591. this.Canvas.lineTo(yHigh + arrowWidth + 1, x + arrowWidth / 2);
  1592. }
  1593. else {
  1594. this.Canvas.moveTo(x, yHigh - 1);
  1595. this.Canvas.lineTo(x - arrowWidth / 2, yHigh - arrowWidth - 1);
  1596. this.Canvas.lineTo(x + arrowWidth / 2, yHigh - arrowWidth - 1);
  1597. }
  1598. this.Canvas.closePath();
  1599. this.Canvas.fill();
  1600. this.Canvas.stroke();
  1601. }
  1602. }
  1603. }
  1604. this.Draw = function ()
  1605. {
  1606. this.PtMax = { X: null, Y: null, Value: null, Align: 'left' }; //清空最大
  1607. this.PtMin = { X: null, Y: null, Value: null, Align: 'left' }; //清空最小
  1608. this.ChartFrame.ChartKLine = { Max: null, Min: null }; //保存K线上 显示最大最小值坐标
  1609. this.DrawKRange={ Start:null, End:null };
  1610. this.AryPriceGapCache=[];
  1611. if (this.IsShow == false) return;
  1612. if (this.DrawType == 1)
  1613. {
  1614. this.DrawCloseLine();
  1615. if (this.PriceGap.Enable) this.DrawPriceGap();
  1616. return;
  1617. }
  1618. else if (this.DrawType == 2)
  1619. {
  1620. this.DrawAKLine();
  1621. }
  1622. else if (this.DrawType == 4)
  1623. {
  1624. this.DrawCloseArea();
  1625. }
  1626. else if (this.DrawType==9)
  1627. {
  1628. this.DrawKBar();
  1629. }
  1630. else
  1631. {
  1632. this.DrawKBar();
  1633. }
  1634. this.DrawTrade();
  1635. if (this.PriceGap.Enable) this.DrawPriceGap();
  1636. if (this.IsShowMaxMinPrice) //标注最大值最小值
  1637. {
  1638. if (this.ChartFrame.IsHScreen === true) this.HScreenDrawMaxMinPrice(this.PtMax, this.PtMin);
  1639. else this.DrawMaxMinPrice(this.PtMax, this.PtMin);
  1640. }
  1641. }
  1642. this.OnFormatHighLowTitle=function(ptMax, ptMin)
  1643. {
  1644. if (!ptMax || !ptMin) return null;
  1645. if (!IFrameSplitOperator.IsNumber(ptMax.Value) || !IFrameSplitOperator.IsNumber(ptMin.Value)) return null;
  1646. var defaultfloatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol); //小数位数
  1647. var title=
  1648. {
  1649. High:ptMax.Value.toFixed(defaultfloatPrecision),
  1650. Low:ptMin.Value.toFixed(defaultfloatPrecision)
  1651. };
  1652. if (!this.GetEventCallback) return title;
  1653. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_FORMAT_KLINE_HIGH_LOW_TITLE);
  1654. if (!event || !event.Callback) return title;
  1655. var data={ Max:ptMax, Min:ptMin, Symbol:this.Symbol, Title:{ High:title.High, Low:title.Low }, Decimal:defaultfloatPrecision, PreventDefault:false };
  1656. event.Callback(event, data, this);
  1657. if (data.PreventDefault) return data.Title; //使用外部回调的数值
  1658. return title;
  1659. }
  1660. this.DrawMaxMinPrice = function (ptMax, ptMin)
  1661. {
  1662. if (ptMax.X == null || ptMax.Y == null || ptMax.Value == null) return;
  1663. if (ptMin.X == null || ptMin.Y == null || ptMin.Value == null) return;
  1664. var title=this.OnFormatHighLowTitle(ptMax,ptMin);
  1665. if (!title) return;
  1666. var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow;
  1667. var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow;
  1668. var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset;
  1669. var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset;
  1670. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
  1671. this.Canvas.font = this.TextFont;
  1672. this.Canvas.textAlign = ptMax.Align;
  1673. this.Canvas.textBaseline = 'bottom';
  1674. var left = ptMax.X;
  1675. if (IFrameSplitOperator.IsNumber(highYOffset)) ptMax.Y+=highYOffset;
  1676. //var text = ptMax.Value.toFixed(defaultfloatPrecision);
  1677. var text=title.High;
  1678. var textColor=this.TextColor;
  1679. if (title.HighColor) textColor=title.HighColor;
  1680. this.Canvas.fillStyle = textColor;
  1681. if (ptMax.Align == 'left') text = leftArrow + text;
  1682. else text = text + rightArrow;
  1683. this.Canvas.fillText(text, left, ptMax.Y);
  1684. this.ChartFrame.ChartKLine.Max = { X: left, Y: ptMax.Y, Text: { BaseLine: 'bottom' } };
  1685. this.Canvas.textAlign = ptMin.Align;
  1686. this.Canvas.textBaseline = 'top';
  1687. var left = ptMin.X;
  1688. if (IFrameSplitOperator.IsNumber(lowYOffset)) ptMin.Y+=lowYOffset;
  1689. //text = ptMin.Value.toFixed(defaultfloatPrecision);
  1690. var text=title.Low;
  1691. var textColor=this.TextColor;
  1692. if (title.LowColor) textColor=title.LowColor;
  1693. this.Canvas.fillStyle = textColor;
  1694. if (ptMin.Align == 'left') text = leftArrow + text;
  1695. else text = text + rightArrow;
  1696. this.Canvas.fillText(text, left, ptMin.Y);
  1697. this.ChartFrame.ChartKLine.Min = { X: left, Y: ptMin.Y, Text: { BaseLine: 'top' } };
  1698. }
  1699. this.HScreenDrawMaxMinPrice = function (ptMax, ptMin) //横屏模式下显示最大最小值
  1700. {
  1701. if (ptMax.X == null || ptMax.Y == null || ptMax.Value == null) return;
  1702. if (ptMin.X == null || ptMin.Y == null || ptMin.Value == null) return;
  1703. var title=this.OnFormatHighLowTitle(ptMax,ptMin);
  1704. if (!title) return;
  1705. var leftArrow=g_JSChartResource.KLine.MaxMin.LeftArrow;
  1706. var rightArrow=g_JSChartResource.KLine.MaxMin.RightArrow;
  1707. var highYOffset=g_JSChartResource.KLine.MaxMin.HighYOffset;
  1708. var lowYOffset=g_JSChartResource.KLine.MaxMin.LowYOffset;
  1709. var defaultfloatPrecision = JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
  1710. var xText = ptMax.Y;
  1711. var yText = ptMax.X;
  1712. if (IFrameSplitOperator.IsNumber(highYOffset)) xText+=highYOffset;
  1713. this.Canvas.save();
  1714. this.Canvas.translate(xText, yText);
  1715. this.Canvas.rotate(90 * Math.PI / 180);
  1716. this.Canvas.font = this.TextFont;
  1717. if (title.HighColor) this.Canvas.fillStyle=title.HighColor;
  1718. else this.Canvas.fillStyle=this.TextColor;
  1719. this.Canvas.textAlign = ptMax.Align;
  1720. this.Canvas.textBaseline = 'bottom';
  1721. var text=title.High;
  1722. //var text = ptMax.Value.toFixed(defaultfloatPrecision);
  1723. if (ptMax.Align == 'left') text = leftArrow + text;
  1724. else text = text + rightArrow;
  1725. this.Canvas.fillText(text, 0, 0);
  1726. this.Canvas.restore();
  1727. var xText = ptMin.Y;
  1728. var yText = ptMin.X;
  1729. if (IFrameSplitOperator.IsNumber(lowYOffset)) xText+=lowYOffset;
  1730. this.Canvas.save();
  1731. this.Canvas.translate(xText, yText);
  1732. this.Canvas.rotate(90 * Math.PI / 180);
  1733. this.Canvas.font = this.TextFont;
  1734. if (title.LowColor) this.Canvas.fillStyle=title.LowColor;
  1735. else this.Canvas.fillStyle=this.TextColor;
  1736. this.Canvas.textAlign = ptMin.Align;
  1737. this.Canvas.textBaseline = 'top';
  1738. var text=title.Low;
  1739. //var text = ptMin.Value.toFixed(defaultfloatPrecision);
  1740. if (ptMin.Align == 'left') text = leftArrow + text;
  1741. else text = text + rightArrow;
  1742. this.Canvas.fillText(text, 0, 0);
  1743. this.Canvas.restore();
  1744. }
  1745. //画某一天的信息地雷 画在底部
  1746. this.DrawInfoDiv = function (item) {
  1747. if (!this.InfoData || this.InfoData.size <= 0) return;
  1748. var dataWidth = this.ChartFrame.DataWidth;
  1749. var distanceWidth = this.ChartFrame.DistanceWidth;
  1750. var infoData = this.InfoData.get(item.DayData.Date.toString());
  1751. if (!infoData || infoData.Data.length <= 0) return;
  1752. var bHScreen = (this.ChartFrame.IsHScreen === true);
  1753. if (this.InfoDrawType === 1) {
  1754. this.Canvas.font = this.GetDynamicFont(dataWidth);
  1755. this.Canvas.fillStyle = this.InfoPointColor2;
  1756. this.Canvas.textAlign = 'center';
  1757. this.Canvas.textBaseline = 'top';
  1758. if (bHScreen) {
  1759. var xText = item.YMin;
  1760. var yText = item.X;
  1761. this.Canvas.save();
  1762. this.Canvas.translate(xText, yText);
  1763. this.Canvas.rotate(90 * Math.PI / 180);
  1764. this.Canvas.fillText('▲', 0, 0);
  1765. this.Canvas.restore();
  1766. }
  1767. else {
  1768. var left = ToFixedPoint(item.X);
  1769. this.Canvas.fillText('▲', left, item.YMin);
  1770. }
  1771. }
  1772. else {
  1773. var dataWidth = this.ChartFrame.DataWidth;
  1774. var radius = dataWidth / 2;
  1775. if (radius > 3) radius = 3;
  1776. var x = item.X;
  1777. var y = this.ChartFrame.ChartBorder.GetBottom() - 2 - radius;
  1778. if (bHScreen) y = this.ChartFrame.ChartBorder.GetLeft() + 2 + radius;
  1779. this.Canvas.fillStyle = this.InfoPointColor;
  1780. this.Canvas.beginPath();
  1781. if (bHScreen) this.Canvas.arc(y, x, radius, 0, Math.PI * 2, true);
  1782. else this.Canvas.arc(ToFixedPoint(x), y, radius, 0, Math.PI * 2, true);
  1783. this.Canvas.closePath();
  1784. this.Canvas.fill();
  1785. }
  1786. }
  1787. this.GetTooltipData = function (x, y, tooltip) {
  1788. return false;
  1789. }
  1790. this.GetMaxMin = function () //计算当天显示数据的最大最小值
  1791. {
  1792. var xPointCount = this.ChartFrame.XPointCount;
  1793. var range = {};
  1794. range.Max = null;
  1795. range.Min = null;
  1796. if (this.IsShow == false) return range;
  1797. if (this.DrawType==1 || this.DrawType==4 ) // 1=收盘价线 4=收盘价面积图
  1798. {
  1799. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  1800. {
  1801. var data=this.Data.Data[i];
  1802. if (!IFrameSplitOperator.IsNumber(data.Close)) continue;
  1803. if (range.Max==null) range.Max=data.Close;
  1804. if (range.Min==null) range.Min=data.Close;
  1805. if (range.Max<data.Close) range.Max=data.Close;
  1806. if (range.Min>data.Close) range.Min=data.Close;
  1807. }
  1808. }
  1809. else
  1810. {
  1811. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  1812. {
  1813. var data = this.Data.Data[i];
  1814. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  1815. if (range.Max == null) range.Max = data.High;
  1816. if (range.Min == null) range.Min = data.Low;
  1817. if (range.Max < data.High) range.Max = data.High;
  1818. if (range.Min > data.Low) range.Min = data.Low;
  1819. }
  1820. }
  1821. return range;
  1822. }
  1823. this.DrawLastPointEvent=function(ptLast)
  1824. {
  1825. if (!this.GetEventCallback) return;
  1826. //通知外部绘制最后一个点
  1827. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_DRAW_KLINE_LAST_POINT);
  1828. if (event)
  1829. {
  1830. var kWidth={ Data: this.ChartFrame.DataWidth, Distance:this.ChartFrame.DistanceWidth };
  1831. if (ptLast) var data={ LastPoint:{ X:ptLast.X, Y:ptLast.Y, XLeft:ptLast.XLeft, XRight:ptLast.XRight }, KItem:ptLast.KItem, DrawType:this.DrawType, KWidth:kWidth, ChartRight:ptLast.ChartRight };
  1832. else var data={ LastPoint:null, KItem:null, KWidth:kWidth };
  1833. event.Callback(event,data,this);
  1834. }
  1835. }
  1836. //////////////////////////////////////////////////////////////
  1837. // 标识缺口
  1838. /////////////////////////////////////////////////////////////
  1839. this.DrawPriceGap=function()
  1840. {
  1841. if (!IFrameSplitOperator.IsNonEmptyArray(this.AryPriceGapCache)) return;
  1842. if (this.PriceGap.Count<=0) return;
  1843. var index=this.AryPriceGapCache.length-this.PriceGap.Count;
  1844. if (index<0) index=0;
  1845. var isHScreen=(this.ChartFrame.IsHScreen===true);
  1846. var border=null;
  1847. if (isHScreen) border=this.ChartBorder.GetHScreenBorder();
  1848. else border=this.ChartBorder.GetBorder();
  1849. this.Canvas.font=this.PriceGapStyple.Text.Font;
  1850. this.Canvas.textAlign = 'left';
  1851. this.Canvas.textBaseline = 'bottom';
  1852. var textHeight=this.Canvas.measureText("擎").width;
  1853. var decNum=JSCommonCoordinateData.GetfloatPrecision(this.Symbol);
  1854. for(var i=index;i<this.AryPriceGapCache.length;++i)
  1855. {
  1856. var item=this.AryPriceGapCache[i];
  1857. var start=item.Data[0];
  1858. var end=item.Data[1];
  1859. var rect=null, rtText=null, text=null;
  1860. if (item.Type==1) //上缺口
  1861. {
  1862. if (isHScreen)
  1863. {
  1864. rect={ Left:start.Coordinate.High, Right:end.Coordinate.Low, Top:start.Coordinate.X, Bottom: border.Bottom };
  1865. rect.Width=rect.Right-rect.Left;
  1866. rect.Height=rect.Bottom-rect.Top;
  1867. rtText={ Left:start.Coordinate.High-textHeight-2, Top:start.Coordinate.Right+2, Height:textHeight };
  1868. rtText.Bottom=rtText.Top+rtText.Height;
  1869. }
  1870. else
  1871. {
  1872. rect={ Left:start.Coordinate.X, Right:border.Right, Top:end.Coordinate.Low, Bottom:start.Coordinate.High };
  1873. rect.Width=rect.Right-rect.Left;
  1874. rect.Height=rect.Bottom-rect.Top;
  1875. rtText={ Left:start.Coordinate.Right+2, Top:rect.Bottom+2, Right:rect.Right, Height:textHeight };
  1876. rtText.Bottom=rtText.Top+rtText.Height;
  1877. }
  1878. text=`${start.Data.High.toFixed(decNum)}-${end.Data.Low.toFixed(decNum)}`;
  1879. }
  1880. else if (item.Type==2) //下缺口
  1881. {
  1882. if (isHScreen)
  1883. {
  1884. rect={ Left:start.Coordinate.Low, Right:end.Coordinate.High, Top:start.Coordinate.X, Bottom: border.Bottom };
  1885. rect.Width=rect.Right-rect.Left;
  1886. rect.Height=rect.Bottom-rect.Top;
  1887. rtText={ Left:start.Coordinate.Low+2, Top:start.Coordinate.Right+2, Height:textHeight };
  1888. rtText.Bottom=rtText.Top+rtText.Height;
  1889. }
  1890. else
  1891. {
  1892. rect={ Left:start.Coordinate.X, Right:border.Right, Top:start.Coordinate.Low, Bottom:end.Coordinate.High };
  1893. rect.Width=rect.Right-rect.Left;
  1894. rect.Height=rect.Bottom-rect.Top;
  1895. rtText={ Left:start.Coordinate.Right+2, Bottom:rect.Top, Right:rect.Right, Height:textHeight };
  1896. rtText.Top=rtText.Bottom-rtText.Height;
  1897. }
  1898. text=`${start.Data.Low.toFixed(decNum)}-${end.Data.High.toFixed(decNum)}`;
  1899. }
  1900. else
  1901. {
  1902. continue;
  1903. }
  1904. if (!rect) return;
  1905. this.Canvas.fillStyle=this.PriceGapStyple.Line.Color;
  1906. this.Canvas.fillRect(rect.Left, rect.Top,rect.Width, rect.Height);
  1907. if (rtText)
  1908. {
  1909. var textWidth=this.Canvas.measureText(text).width;
  1910. rtText.Width=textWidth;
  1911. rtText.Right=rtText.Left+rtText.Width;
  1912. this.Canvas.fillStyle=this.PriceGapStyple.Text.Color;
  1913. if (isHScreen)
  1914. {
  1915. this.Canvas.save();
  1916. this.Canvas.translate(rtText.Left, rtText.Top);
  1917. this.Canvas.rotate(90 * Math.PI / 180);
  1918. this.Canvas.fillText(text,0,0);
  1919. this.Canvas.restore();
  1920. }
  1921. else
  1922. {
  1923. if (rtText.Right>rect.Right)
  1924. {
  1925. rtText.Right=rect.Right;
  1926. rtText.Left=rtText.Right-rtText.Width;
  1927. }
  1928. this.Canvas.fillStyle=this.PriceGapStyple.Text.Color;
  1929. this.Canvas.fillText(text,rtText.Left,rtText.Bottom);
  1930. }
  1931. //this.Canvas.fillStyle="rgb(250,250,250)"
  1932. //this.Canvas.fillRect(rtText.Left, rtText.Top, rtText.Width, rtText.Height);
  1933. }
  1934. }
  1935. }
  1936. //是否有缺口
  1937. this.IsPriceGap=function(item, preItem)
  1938. {
  1939. if (!preItem || !item) return 0;
  1940. if (preItem.Data.Low>item.Data.High) return 2; //下缺口
  1941. if (preItem.Data.High<item.Data.Low) return 1; //上缺口
  1942. return -1;
  1943. }
  1944. //检测缺口是不回补了
  1945. this.CheckPriceGap=function(kItemInfo)
  1946. {
  1947. var kItem=kItemInfo.Data;
  1948. for(var i=0;i<this.AryPriceGapCache.length;++i)
  1949. {
  1950. var item=this.AryPriceGapCache[i];
  1951. var start=item.Data[0];
  1952. var end=item.Data[1];
  1953. if (item.Type==1) //上缺口
  1954. {
  1955. if (kItem.Low<=start.Data.High)
  1956. {
  1957. this.AryPriceGapCache.splice(i,1);
  1958. --i;
  1959. continue;
  1960. }
  1961. if (kItem.Low<end.Data.Low) item.Data[1]=kItemInfo;
  1962. }
  1963. else if (item.Type==2) //下缺口
  1964. {
  1965. if (kItem.High>=start.Data.Low)
  1966. {
  1967. this.AryPriceGapCache.splice(i,1);
  1968. --i;
  1969. continue;
  1970. }
  1971. if (kItem.High>end.Data.High) item.Data[1]=kItemInfo;
  1972. }
  1973. }
  1974. }
  1975. }
  1976. function ChartColorKline()
  1977. {
  1978. this.newMethod=IChartPainting; //派生
  1979. this.newMethod();
  1980. delete this.newMethod;
  1981. this.ClassName='ChartColorKline'; //类名
  1982. this.Symbol; //股票代码
  1983. this.Color='rgb(0,255,44)';
  1984. this.IsEmptyBar=false;
  1985. this.DrawType=0; //0=实心K线柱子 3=空心K线柱子
  1986. this.KLineColor; //Map key=K线索引 value=设置
  1987. this.DrawName;
  1988. this.Draw=function()
  1989. {
  1990. if (!this.IsShow) return;
  1991. if (this.DrawName=="DRAWCOLORKLINE")
  1992. {
  1993. this.DrawColorBar();
  1994. }
  1995. else
  1996. {
  1997. if (!this.KLineColor) return;
  1998. this.DrawBar();
  1999. }
  2000. }
  2001. this.DrawUpBarItem=function(data, xOffset, dataWidth, option)
  2002. {
  2003. var isHScreen=(this.ChartFrame.IsHScreen===true);
  2004. var left=xOffset;
  2005. var right=xOffset+dataWidth;
  2006. var x=left+(right-left)/2;
  2007. var yLow=this.ChartFrame.GetYFromData(data.Low);
  2008. var yHigh=this.ChartFrame.GetYFromData(data.High);
  2009. var yOpen=this.ChartFrame.GetYFromData(data.Open);
  2010. var yClose=this.ChartFrame.GetYFromData(data.Close);
  2011. var y=yHigh;
  2012. if (dataWidth>=4)
  2013. {
  2014. if (data.High>data.Close) //上影线
  2015. {
  2016. this.Canvas.beginPath();
  2017. if (isHScreen)
  2018. {
  2019. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  2020. this.Canvas.lineTo(ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):yClose),ToFixedPoint(x));
  2021. }
  2022. else
  2023. {
  2024. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  2025. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):yClose));
  2026. }
  2027. this.Canvas.stroke();
  2028. y=yClose;
  2029. }
  2030. else
  2031. {
  2032. y=yClose;
  2033. }
  2034. if (isHScreen)
  2035. {
  2036. if (Math.abs(yOpen-y)<1)
  2037. {
  2038. this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  2039. }
  2040. else
  2041. {
  2042. if (this.DrawType==3) //空心柱
  2043. {
  2044. this.Canvas.beginPath();
  2045. this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth));
  2046. this.Canvas.stroke();
  2047. }
  2048. else
  2049. {
  2050. this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth));
  2051. }
  2052. }
  2053. }
  2054. else
  2055. {
  2056. if (Math.abs(yOpen-y)<1)
  2057. {
  2058. this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1
  2059. }
  2060. else
  2061. {
  2062. if (this.DrawType==3) //空心柱
  2063. {
  2064. this.Canvas.beginPath();
  2065. this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y));
  2066. this.Canvas.stroke();
  2067. }
  2068. else
  2069. {
  2070. this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y)));
  2071. }
  2072. }
  2073. }
  2074. if (data.Open>data.Low) //下影线
  2075. {
  2076. this.Canvas.beginPath();
  2077. if (isHScreen)
  2078. {
  2079. this.Canvas.moveTo(ToFixedPoint(this.DrawType==3?Math.min(yClose,yOpen):y),ToFixedPoint(x));
  2080. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  2081. }
  2082. else
  2083. {
  2084. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(this.DrawType==3?Math.max(yClose,yOpen):y));
  2085. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  2086. }
  2087. this.Canvas.stroke();
  2088. }
  2089. }
  2090. else
  2091. {
  2092. this.Canvas.beginPath();
  2093. if (isHScreen)
  2094. {
  2095. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  2096. this.Canvas.lineTo(yLow,ToFixedPoint(x));
  2097. }
  2098. else
  2099. {
  2100. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  2101. this.Canvas.lineTo(ToFixedPoint(x),yLow);
  2102. }
  2103. this.Canvas.stroke();
  2104. }
  2105. }
  2106. this.DrawDownBarItem=function(data, xOffset, dataWidth, option)
  2107. {
  2108. var isHScreen=(this.ChartFrame.IsHScreen===true);
  2109. var left=xOffset;
  2110. var right=xOffset+dataWidth;
  2111. var x=left+(right-left)/2;
  2112. var yLow=this.ChartFrame.GetYFromData(data.Low);
  2113. var yHigh=this.ChartFrame.GetYFromData(data.High);
  2114. var yOpen=this.ChartFrame.GetYFromData(data.Open);
  2115. var yClose=this.ChartFrame.GetYFromData(data.Close);
  2116. var y=yHigh;
  2117. if (dataWidth>=4)
  2118. {
  2119. if (data.High>data.Close) //上影线
  2120. {
  2121. this.Canvas.beginPath();
  2122. if (isHScreen)
  2123. {
  2124. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  2125. this.Canvas.lineTo(ToFixedPoint(yOpen),ToFixedPoint(x));
  2126. }
  2127. else
  2128. {
  2129. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  2130. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yOpen));
  2131. }
  2132. this.Canvas.stroke();
  2133. y=yOpen;
  2134. }
  2135. else
  2136. {
  2137. y=yOpen
  2138. }
  2139. if (isHScreen)
  2140. {
  2141. if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  2142. else this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yClose-y),ToFixedRect(dataWidth));
  2143. }
  2144. else
  2145. {
  2146. if (Math.abs(yClose-y)<1) this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1
  2147. else this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yClose)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yClose-y)));
  2148. }
  2149. if (data.Open>data.Low) //下影线
  2150. {
  2151. this.Canvas.beginPath();
  2152. if (isHScreen)
  2153. {
  2154. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  2155. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  2156. }
  2157. else
  2158. {
  2159. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  2160. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  2161. }
  2162. this.Canvas.stroke();
  2163. }
  2164. }
  2165. else
  2166. {
  2167. this.Canvas.beginPath();
  2168. if (isHScreen)
  2169. {
  2170. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  2171. this.Canvas.lineTo(yLow,ToFixedPoint(x));
  2172. }
  2173. else
  2174. {
  2175. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  2176. this.Canvas.lineTo(ToFixedPoint(x),yLow);
  2177. }
  2178. this.Canvas.stroke();
  2179. }
  2180. }
  2181. this.DrawUnChangeBarItem=function(data, xOffset, dataWidth, option)
  2182. {
  2183. var isHScreen=(this.ChartFrame.IsHScreen===true);
  2184. var left=xOffset;
  2185. var right=xOffset+dataWidth;
  2186. var x=left+(right-left)/2;
  2187. var yLow=this.ChartFrame.GetYFromData(data.Low);
  2188. var yHigh=this.ChartFrame.GetYFromData(data.High);
  2189. var yOpen=this.ChartFrame.GetYFromData(data.Open);
  2190. var yClose=this.ChartFrame.GetYFromData(data.Close);
  2191. var y=yHigh;
  2192. if (dataWidth>=4)
  2193. {
  2194. this.Canvas.beginPath();
  2195. if (data.High>data.Close) //上影线
  2196. {
  2197. if (isHScreen)
  2198. {
  2199. this.Canvas.moveTo(y,ToFixedPoint(x));
  2200. this.Canvas.lineTo(yOpen,ToFixedPoint(x));
  2201. }
  2202. else
  2203. {
  2204. this.Canvas.moveTo(ToFixedPoint(x),y);
  2205. this.Canvas.lineTo(ToFixedPoint(x),yOpen);
  2206. }
  2207. y=yOpen;
  2208. }
  2209. else
  2210. {
  2211. y=yOpen;
  2212. }
  2213. if (isHScreen)
  2214. {
  2215. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left));
  2216. this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right));
  2217. }
  2218. else
  2219. {
  2220. this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y));
  2221. this.Canvas.lineTo(ToFixedPoint(right),ToFixedPoint(y));
  2222. }
  2223. if (data.Open>data.Low) //下影线
  2224. {
  2225. if (isHScreen)
  2226. {
  2227. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  2228. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  2229. }
  2230. else
  2231. {
  2232. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  2233. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  2234. }
  2235. }
  2236. this.Canvas.stroke();
  2237. }
  2238. else
  2239. {
  2240. this.Canvas.beginPath();
  2241. if (isHScreen)
  2242. {
  2243. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  2244. this.Canvas.lineTo(yLow,ToFixedPoint(x));
  2245. }
  2246. else
  2247. {
  2248. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  2249. this.Canvas.lineTo(ToFixedPoint(x),yLow);
  2250. }
  2251. this.Canvas.stroke();
  2252. }
  2253. }
  2254. this.DrawBar=function()
  2255. {
  2256. var dataWidth=this.ChartFrame.DataWidth;
  2257. var distanceWidth=this.ChartFrame.DistanceWidth;
  2258. var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+2.0;
  2259. var chartright=this.ChartBorder.GetRight();
  2260. var xPointCount=this.ChartFrame.XPointCount;
  2261. if (this.IsHScreen)
  2262. {
  2263. xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+2.0;
  2264. chartright=this.ChartBorder.GetBottom();
  2265. }
  2266. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  2267. {
  2268. var data=this.Data.Data[i];
  2269. if (data.Open==null || data.High==null || data.Low==null || data.Close==null) continue;
  2270. if (!this.KLineColor.has(i)) continue;
  2271. var itemOption=this.KLineColor.get(i);
  2272. var left=xOffset;
  2273. var right=xOffset+dataWidth;
  2274. if (right>chartright) break;
  2275. if (itemOption.Color)
  2276. {
  2277. this.Canvas.strokeStyle=itemOption.Color;
  2278. this.Canvas.fillStyle=itemOption.Color;
  2279. }
  2280. else
  2281. {
  2282. this.Canvas.strokeStyle=this.Color;
  2283. this.Canvas.fillStyle=this.Color;
  2284. }
  2285. if (data.Open<data.Close) //阳线
  2286. {
  2287. this.DrawUpBarItem(data,xOffset,dataWidth,itemOption);
  2288. }
  2289. else if (data.Open>data.Close) //阴线
  2290. {
  2291. this.DrawDownBarItem(data,xOffset,dataWidth,itemOption);
  2292. }
  2293. else //平线
  2294. {
  2295. this.DrawUnChangeBarItem(data,xOffset,dataWidth,itemOption);
  2296. }
  2297. }
  2298. }
  2299. this.DrawColorBar=function()
  2300. {
  2301. var isHScreen=(this.ChartFrame.IsHScreen===true);
  2302. var dataWidth=this.ChartFrame.DataWidth;
  2303. var distanceWidth=this.ChartFrame.DistanceWidth;
  2304. var border=this.ChartBorder.GetBorder();
  2305. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  2306. var chartright=border.RightEx;
  2307. var xPointCount=this.ChartFrame.XPointCount;
  2308. if (isHScreen)
  2309. {
  2310. var border=this.ChartBorder.GetHScreenBorder();
  2311. xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  2312. chartright=border.BottomEx;
  2313. }
  2314. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  2315. {
  2316. var data=this.Data.Data[i];
  2317. if (!data) continue;
  2318. if (!IFrameSplitOperator.IsNumber(data.Open) || !IFrameSplitOperator.IsNumber(data.High) ||
  2319. !IFrameSplitOperator.IsNumber(data.Low) || !IFrameSplitOperator.IsNumber(data.Close)) continue;
  2320. var left=xOffset;
  2321. var right=xOffset+dataWidth;
  2322. if (right>chartright) break;
  2323. var x=left+(right-left)/2;
  2324. var yLow=this.GetYFromData(data.Low, false);
  2325. var yHigh=this.GetYFromData(data.High, false);
  2326. var yOpen=this.GetYFromData(data.Open, false);
  2327. var yClose=this.GetYFromData(data.Close, false);
  2328. var y=yHigh;
  2329. if (data.Open==data.Close)
  2330. this.DrawKBar_Unchagne(data, dataWidth, this.Color, this.IsEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  2331. else
  2332. this.DrawKBar_Custom(data, dataWidth, this.Color, this.IsEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen);
  2333. }
  2334. }
  2335. this.DrawKBar_Unchagne=function(data, dataWidth, unchagneColor, drawType, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  2336. {
  2337. if (dataWidth>=4)
  2338. {
  2339. if ((dataWidth%2)!=0) dataWidth-=1;
  2340. this.Canvas.strokeStyle=unchagneColor;
  2341. this.Canvas.beginPath();
  2342. if (data.High>data.Close) //上影线
  2343. {
  2344. if (isHScreen)
  2345. {
  2346. this.Canvas.moveTo(y,ToFixedPoint(x));
  2347. this.Canvas.lineTo(yOpen,ToFixedPoint(x));
  2348. }
  2349. else
  2350. {
  2351. var xFixed=ToFixedPoint(left+dataWidth/2);
  2352. this.Canvas.moveTo(xFixed,y);
  2353. this.Canvas.lineTo(xFixed,yOpen);
  2354. }
  2355. y=yOpen;
  2356. }
  2357. else
  2358. {
  2359. y=yOpen;
  2360. }
  2361. if (isHScreen)
  2362. {
  2363. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(left));
  2364. this.Canvas.lineTo(ToFixedPoint(y),ToFixedPoint(right));
  2365. }
  2366. else
  2367. {
  2368. this.Canvas.moveTo(ToFixedPoint(left),ToFixedPoint(y));
  2369. this.Canvas.lineTo(ToFixedPoint(left+dataWidth),ToFixedPoint(y));
  2370. }
  2371. if (data.Open>data.Low) //下影线
  2372. {
  2373. if (isHScreen)
  2374. {
  2375. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  2376. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  2377. }
  2378. else
  2379. {
  2380. var xFixed=ToFixedPoint(left+dataWidth/2);
  2381. this.Canvas.moveTo(xFixed,ToFixedPoint(y));
  2382. this.Canvas.lineTo(xFixed,ToFixedPoint(yLow));
  2383. }
  2384. }
  2385. this.Canvas.stroke();
  2386. }
  2387. else
  2388. {
  2389. this.Canvas.beginPath();
  2390. if (isHScreen)
  2391. {
  2392. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  2393. this.Canvas.lineTo(yLow,ToFixedPoint(x));
  2394. }
  2395. else
  2396. {
  2397. if (data.High==data.Low)
  2398. {
  2399. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  2400. this.Canvas.lineTo(ToFixedPoint(x),yLow+1);
  2401. }
  2402. else
  2403. {
  2404. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  2405. this.Canvas.lineTo(ToFixedPoint(x),yLow);
  2406. }
  2407. }
  2408. this.Canvas.strokeStyle=unchagneColor;
  2409. this.Canvas.stroke();
  2410. }
  2411. }
  2412. this.DrawKBar_Custom=function(data, dataWidth, barColor, isEmptyBar, x, y, left, right, yLow, yHigh, yOpen, yClose, isHScreen)
  2413. {
  2414. if (isEmptyBar)
  2415. {
  2416. if ((dataWidth%2)!=0) dataWidth-=1;
  2417. }
  2418. if (dataWidth>=4)
  2419. {
  2420. this.Canvas.strokeStyle=barColor;
  2421. if (data.High>data.Close) //上影线
  2422. {
  2423. this.Canvas.beginPath();
  2424. if (isHScreen)
  2425. {
  2426. this.Canvas.moveTo(ToFixedPoint(y),ToFixedPoint(x));
  2427. this.Canvas.lineTo(ToFixedPoint(isEmptyBar?Math.max(yClose,yOpen):yClose),ToFixedPoint(x));
  2428. }
  2429. else
  2430. {
  2431. if (isEmptyBar)
  2432. {
  2433. var xFixed=left+dataWidth/2;
  2434. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(y));
  2435. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(Math.min(yClose,yOpen)));
  2436. }
  2437. else
  2438. {
  2439. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  2440. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yClose));
  2441. }
  2442. }
  2443. this.Canvas.stroke();
  2444. y=yClose;
  2445. }
  2446. else
  2447. {
  2448. y=yClose;
  2449. }
  2450. this.Canvas.fillStyle=barColor;
  2451. if (isHScreen)
  2452. {
  2453. if (Math.abs(yOpen-y)<1)
  2454. {
  2455. this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),1,ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  2456. }
  2457. else
  2458. {
  2459. if (isEmptyBar) //空心柱
  2460. {
  2461. this.Canvas.beginPath();
  2462. this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth));
  2463. this.Canvas.stroke();
  2464. }
  2465. else
  2466. {
  2467. this.Canvas.fillRect(ToFixedRect(y),ToFixedRect(left),ToFixedRect(yOpen-y),ToFixedRect(dataWidth));
  2468. }
  2469. }
  2470. }
  2471. else
  2472. {
  2473. if (Math.abs(yOpen-y)<1)
  2474. {
  2475. this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(y),ToFixedRect(dataWidth),1); //高度小于1,统一使用高度1
  2476. }
  2477. else
  2478. {
  2479. if (isEmptyBar) //空心柱
  2480. {
  2481. this.Canvas.beginPath();
  2482. this.Canvas.rect(ToFixedPoint(left),ToFixedPoint(y),ToFixedRect(dataWidth),ToFixedRect(yOpen-y));
  2483. this.Canvas.stroke();
  2484. }
  2485. else
  2486. {
  2487. this.Canvas.fillRect(ToFixedRect(left),ToFixedRect(Math.min(y,yOpen)),ToFixedRect(dataWidth),ToFixedRect(Math.abs(yOpen-y)));
  2488. }
  2489. }
  2490. }
  2491. if (data.Open>data.Low) //下影线
  2492. {
  2493. this.Canvas.beginPath();
  2494. if (isHScreen)
  2495. {
  2496. this.Canvas.moveTo(ToFixedPoint(isEmptyBar?Math.min(yClose,yOpen):y),ToFixedPoint(x));
  2497. this.Canvas.lineTo(ToFixedPoint(yLow),ToFixedPoint(x));
  2498. }
  2499. else
  2500. {
  2501. if (isEmptyBar)
  2502. {
  2503. var xFixed=left+dataWidth/2;
  2504. this.Canvas.moveTo(ToFixedPoint(xFixed),ToFixedPoint(Math.max(yClose,yOpen)));
  2505. this.Canvas.lineTo(ToFixedPoint(xFixed),ToFixedPoint(yLow));
  2506. }
  2507. else
  2508. {
  2509. this.Canvas.moveTo(ToFixedPoint(x),ToFixedPoint(y));
  2510. this.Canvas.lineTo(ToFixedPoint(x),ToFixedPoint(yLow));
  2511. }
  2512. }
  2513. this.Canvas.stroke();
  2514. }
  2515. }
  2516. else
  2517. {
  2518. this.Canvas.beginPath();
  2519. if (isHScreen)
  2520. {
  2521. this.Canvas.moveTo(yHigh,ToFixedPoint(x));
  2522. this.Canvas.lineTo(yLow,ToFixedPoint(x));
  2523. }
  2524. else
  2525. {
  2526. this.Canvas.moveTo(ToFixedPoint(x),yHigh);
  2527. this.Canvas.lineTo(ToFixedPoint(x),yLow);
  2528. }
  2529. this.Canvas.strokeStyle=barColor;
  2530. this.Canvas.stroke();
  2531. }
  2532. }
  2533. this.GetMaxMin=function()
  2534. {
  2535. var range={Max:null,Min:null };
  2536. if (this.DrawName=="DRAWCOLORKLINE")
  2537. {
  2538. var xPointCount=this.ChartFrame.XPointCount;
  2539. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  2540. {
  2541. var data=this.Data.Data[i];
  2542. if (!data) continue;
  2543. if (data.Open==null || data.High==null || data.Low==null || data.Close==null) continue;
  2544. if (range.Max==null) range.Max=data.High;
  2545. if (range.Min==null) range.Min=data.Low;
  2546. if (range.Max<data.High) range.Max=data.High;
  2547. if (range.Min>data.Low) range.Min=data.Low;
  2548. }
  2549. }
  2550. return range;
  2551. }
  2552. }
  2553. function ChartDrawIcon()
  2554. {
  2555. this.newMethod = IChartPainting; //派生
  2556. this.newMethod();
  2557. delete this.newMethod;
  2558. this.ClassName="ChartDrawIcon";
  2559. this.IsHScreen=false; //是否横屏
  2560. this.DrawCallback; //function(op, obj) op:1=开始 2=绘制 4=销毁
  2561. this.IsDestroy=false; //是否已销毁
  2562. this.TextAlign = 'left';
  2563. this.TextBaseline="middle";
  2564. this.IconID;
  2565. this.Color;
  2566. this.FixedIconSize;
  2567. this.DrawItem=[];
  2568. this.Identify;
  2569. this.Draw=function()
  2570. {
  2571. this.DrawItem=[];
  2572. if (this.DrawCallback) this.DrawCallback(1, {Self:this} );
  2573. this.DrawAllText();
  2574. if (this.DrawCallback) this.DrawCallback(2, { Self:this, Draw:this.DrawItem } );
  2575. }
  2576. this.DrawAllText=function()
  2577. {
  2578. var isHScreen = (this.ChartFrame.IsHScreen === true)
  2579. var dataWidth = this.ChartFrame.DataWidth;
  2580. var distanceWidth = this.ChartFrame.DistanceWidth;
  2581. var chartright = this.ChartBorder.GetRight();
  2582. var top = this.ChartBorder.GetTopEx();
  2583. var bottom = this.ChartBorder.GetBottomEx();
  2584. if (isHScreen)
  2585. {
  2586. chartright = this.ChartBorder.GetBottom();
  2587. top = this.ChartBorder.GetRightEx();
  2588. bottom = this.ChartBorder.GetLeftEx();
  2589. }
  2590. var xPointCount = this.ChartFrame.XPointCount;
  2591. var isArrayText = Array.isArray(this.Text);
  2592. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  2593. {
  2594. var value = this.Data.Data[i];
  2595. if (value == null) continue;
  2596. var x = this.ChartFrame.GetXFromIndex(j);
  2597. var y = this.ChartFrame.GetYFromData(value);
  2598. if (x > chartright) break;
  2599. var drawTextInfo=
  2600. {
  2601. Text:
  2602. {
  2603. Color:this.Color,
  2604. Align:this.TextAlign,
  2605. Baseline:this.TextBaseline,
  2606. },
  2607. X:x, Y:y,
  2608. IconID:this.IconID
  2609. };
  2610. this.DrawItem.push(drawTextInfo);
  2611. }
  2612. }
  2613. this.OnDestroy=function()
  2614. {
  2615. this.IsDestroy=true;
  2616. if (this.DrawCallback) this.DrawCallback(4, { Self:this } );
  2617. }
  2618. }
  2619. /*
  2620. 文字输出 支持横屏
  2621. 数组不为null的数据中输出 this.Text文本
  2622. */
  2623. function ChartSingleText()
  2624. {
  2625. this.newMethod = IChartPainting; //派生
  2626. this.newMethod();
  2627. delete this.newMethod;
  2628. this.Color = "rgb(255,193,37)"; //线段颜色
  2629. this.TextFont = "14px 微软雅黑"; //字体
  2630. this.Text;
  2631. this.TextAlign = 'left';
  2632. this.Direction = 0; //0=middle 1=bottom 2=top
  2633. this.FixedFontSize=-1; //固定字体大小
  2634. this.YOffset = 0;
  2635. this.Position; //指定输出位置
  2636. this.TextBG; //{ Color:"rgb(0,0,92)", Border:"rgb(205,0,92)", Margin:[0,1,1,1], } // { Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] }
  2637. this.ShowOffset={ X:0, Y:0 }; //显示偏移
  2638. this.TextSize=
  2639. {
  2640. Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值
  2641. Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数
  2642. FontName:g_JSChartResource.DRAWICON.Text.FontName
  2643. }
  2644. this.ReloadResource=function(resource)
  2645. {
  2646. if (this.Name=="DRAWTEXT")
  2647. {
  2648. this.TextSize=
  2649. {
  2650. Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值
  2651. Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数
  2652. FontName:g_JSChartResource.DRAWTEXT.FontName
  2653. }
  2654. }
  2655. else if (this.Name=="DRAWNUMBER")
  2656. {
  2657. this.TextSize=
  2658. {
  2659. Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值
  2660. Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数
  2661. FontName:g_JSChartResource.DRAWNUMBER.FontName
  2662. }
  2663. }
  2664. }
  2665. this.Draw = function ()
  2666. {
  2667. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  2668. if (this.NotSupportMessage)
  2669. {
  2670. this.DrawNotSupportmessage();
  2671. return;
  2672. }
  2673. if (this.Name=="DRAWTEXTREL" || this.Name=="DRAWTEXTABS")
  2674. {
  2675. this.DrawRectText();
  2676. return;
  2677. }
  2678. if (this.Position)
  2679. {
  2680. this.DrawPosition();
  2681. return;
  2682. }
  2683. if (!this.Data || !this.Data.Data) return;
  2684. var isHScreen = (this.ChartFrame.IsHScreen === true)
  2685. var dataWidth = this.ChartFrame.DataWidth;
  2686. var distanceWidth = this.ChartFrame.DistanceWidth;
  2687. var chartright = this.ChartBorder.GetRight();
  2688. var top = this.ChartBorder.GetTopEx();
  2689. var bottom = this.ChartBorder.GetBottomEx();
  2690. if (isHScreen)
  2691. {
  2692. chartright = this.ChartBorder.GetBottom();
  2693. top = this.ChartBorder.GetRightEx();
  2694. bottom = this.ChartBorder.GetLeftEx();
  2695. }
  2696. var xPointCount = this.ChartFrame.XPointCount;
  2697. var isArrayText = Array.isArray(this.Text);
  2698. var text;
  2699. var drawTextInfo={ Text:{ }, Font:{ } };
  2700. //上下位置
  2701. if (this.Direction == 1)
  2702. {
  2703. this.Canvas.textBaseline = 'bottom';
  2704. drawTextInfo.Text={ Baseline: 'bottom'};
  2705. }
  2706. else if (this.Direction == 2)
  2707. {
  2708. this.Canvas.textBaseline = 'top';
  2709. drawTextInfo.Text={ Baseline: 'top'};
  2710. }
  2711. else
  2712. {
  2713. this.Canvas.textBaseline = 'middle';
  2714. drawTextInfo.Text={ Baseline: 'middle'};
  2715. }
  2716. //字体大小
  2717. if (this.FixedFontSize>0)
  2718. this.TextFont=`${this.FixedFontSize}px ${this.TextSize.FontName}`;
  2719. else
  2720. this.TextFont = this.GetDynamicFontEx(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName);
  2721. drawTextInfo.Font={ Height:this.GetFontHeight(this.TextFont) };
  2722. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  2723. {
  2724. var value = this.Data.Data[i];
  2725. if (value == null) continue;
  2726. var x = this.ChartFrame.GetXFromIndex(j);
  2727. var y = this.ChartFrame.GetYFromData(value);
  2728. if (x > chartright) break;
  2729. y+=this.ShowOffset.Y;
  2730. x+=this.ShowOffset.X;
  2731. this.Canvas.textAlign = this.TextAlign;
  2732. this.Canvas.fillStyle = this.Color;
  2733. this.Canvas.font = this.TextFont;
  2734. drawTextInfo.Text.Color=this.Color;
  2735. drawTextInfo.Text.Align=this.TextAlign;
  2736. drawTextInfo.X=x;
  2737. drawTextInfo.Y=y;
  2738. if (this.YOffset > 0 && this.Direction > 0)
  2739. {
  2740. var yPrice = y;
  2741. this.Canvas.save();
  2742. this.Canvas.setLineDash([5, 10]);
  2743. this.Canvas.strokeStyle = this.Color;
  2744. this.Canvas.beginPath();
  2745. if (isHScreen)
  2746. {
  2747. if (this.Direction == 1)
  2748. {
  2749. y = top - this.YOffset;
  2750. yPrice += 5;
  2751. }
  2752. else
  2753. {
  2754. y = bottom + this.YOffset;
  2755. yPrice -= 5;
  2756. }
  2757. this.Canvas.moveTo(ToFixedPoint(yPrice), ToFixedPoint(x));
  2758. this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(x));
  2759. }
  2760. else
  2761. {
  2762. if (this.Direction == 1)
  2763. {
  2764. y = top + this.YOffset;
  2765. yPrice += 5;
  2766. }
  2767. else
  2768. {
  2769. y = bottom - this.YOffset;
  2770. yPrice -= 5;
  2771. }
  2772. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(yPrice));
  2773. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(y));
  2774. }
  2775. this.Canvas.stroke();
  2776. this.Canvas.restore();
  2777. }
  2778. if (isArrayText)
  2779. {
  2780. text = this.Text[i];
  2781. if (!text) continue;
  2782. if (isHScreen)
  2783. {
  2784. if (this.Name=='DRAWNUMBER')
  2785. {
  2786. if (this.Direction==1) y+=g_JSChartResource.DRAWABOVE.YOffset;
  2787. else if (this.Direction==2) y-=4;
  2788. }
  2789. }
  2790. else
  2791. {
  2792. if (this.Name=='DRAWNUMBER')
  2793. {
  2794. if (this.Direction==1) y-=g_JSChartResource.DRAWABOVE.YOffset;
  2795. else if (this.Direction==2) y+=4;
  2796. }
  2797. }
  2798. if (this.Name=="DRAWTEXT")
  2799. this.DrawTextV2(text,drawTextInfo,isHScreen);
  2800. else
  2801. this.DrawText(text, x, y, isHScreen);
  2802. }
  2803. else
  2804. {
  2805. if (this.Name=="DRAWTEXT")
  2806. {
  2807. this.DrawTextV2(this.Text,drawTextInfo,isHScreen);
  2808. }
  2809. else
  2810. {
  2811. this.DrawText(this.Text, x, y, isHScreen);
  2812. }
  2813. }
  2814. }
  2815. }
  2816. this.DrawPosition=function() //绘制在指定位置上
  2817. {
  2818. if (!this.Text) return;
  2819. var isHScreen=(this.ChartFrame.IsHScreen===true)
  2820. if (isHScreen)
  2821. {
  2822. var y=this.ChartBorder.GetRightEx()-this.ChartBorder.GetWidthEx()*this.Position.Y;
  2823. var x=this.ChartBorder.GetTop()+this.ChartBorder.GetHeight()*this.Position.X;
  2824. }
  2825. else
  2826. {
  2827. var x=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*this.Position.X;
  2828. var y=this.ChartBorder.GetTopEx()+this.ChartBorder.GetHeight()*this.Position.Y;
  2829. }
  2830. this.Canvas.fillStyle=this.Color;
  2831. //TYPE:0为左对齐,1为右对齐.
  2832. if (this.Position.Type==0) this.Canvas.textAlign='left';
  2833. else if (this.Position.Type==1) this.Canvas.textAlign='right';
  2834. else this.Canvas.textAlign='center';
  2835. if (this.Direction==1) this.Canvas.textBaseline='bottom';
  2836. else if (this.Direction==2) this.Canvas.textBaseline='top';
  2837. else this.Canvas.textBaseline='middle';
  2838. this.DrawText(this.Text,x,y,isHScreen);
  2839. }
  2840. this.DrawText = function (text, x, y, isHScreen)
  2841. {
  2842. if (isHScreen)
  2843. {
  2844. this.Canvas.save();
  2845. this.Canvas.translate(y, x);
  2846. this.Canvas.rotate(90 * Math.PI / 180);
  2847. this.Canvas.fillText(text, 0, 0);
  2848. this.Canvas.restore();
  2849. }
  2850. else
  2851. {
  2852. this.Canvas.fillText(text, x, y);
  2853. }
  2854. }
  2855. this.DrawTextV2=function(text, drawInfo, isHScreen)
  2856. {
  2857. var textWidth=this.Canvas.measureText(text).width;
  2858. if (isHScreen)
  2859. {
  2860. var x=drawInfo.Y;
  2861. var y=drawInfo.X;
  2862. if (drawInfo.Text.Align=="right") y=y-textWidth;
  2863. else if (drawInfo.Text.Align=="center") y=y-textWidth/2;
  2864. if (drawInfo.Text.Baseline=="top") x-=drawInfo.Font.Height;
  2865. else if (drawInfo.Text.Baseline=="middle") x-=drawInfo.Font.Height/2;
  2866. if (this.TextBG && (this.TextBG.Color || this.TextBG.Border))
  2867. {
  2868. var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右
  2869. var xRect=x-margin[0];
  2870. var yRect=y-margin[2];
  2871. var bgWidth=textWidth+margin[2]+margin[3];
  2872. var bgHeight=drawInfo.Font.Height+margin[0]+margin[1];
  2873. if (this.TextBG.Color)
  2874. {
  2875. this.Canvas.fillStyle=this.TextBG.Color;
  2876. this.Canvas.fillRect(xRect,yRect,bgHeight,bgWidth);
  2877. }
  2878. if (this.TextBG.Border)
  2879. {
  2880. this.Canvas.strokeStyle=this.TextBG.Border;
  2881. this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgHeight),ToFixedRect(bgWidth));
  2882. }
  2883. }
  2884. this.Canvas.textBaseline="bottom";
  2885. this.Canvas.textAlign="left";
  2886. this.Canvas.fillStyle=drawInfo.Text.Color;
  2887. this.Canvas.save();
  2888. this.Canvas.translate(x, y);
  2889. this.Canvas.rotate(90 * Math.PI / 180);
  2890. this.Canvas.fillText(text,0,0);
  2891. this.Canvas.restore();
  2892. }
  2893. else
  2894. {
  2895. var x=drawInfo.X;
  2896. var y=drawInfo.Y;
  2897. if (drawInfo.Text.Align=="right") x=x-textWidth;
  2898. else if (drawInfo.Text.Align=="center") x=x-textWidth/2;
  2899. if (drawInfo.Text.Baseline=="top") y+=drawInfo.Font.Height;
  2900. else if (drawInfo.Text.Baseline=="middle") y+=drawInfo.Font.Height/2;
  2901. if (this.TextBG && (this.TextBG.Color || this.TextBG.Border))
  2902. {
  2903. var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右
  2904. var xRect=x-margin[2];
  2905. var yRect=y-drawInfo.Font.Height-margin[1];
  2906. var bgWidth=textWidth+margin[2]+margin[3];
  2907. var bgHeight=drawInfo.Font.Height+margin[0]+margin[1];
  2908. if (this.TextBG.Color)
  2909. {
  2910. this.Canvas.fillStyle=this.TextBG.Color;
  2911. this.Canvas.fillRect(xRect,yRect,bgWidth,bgHeight);
  2912. }
  2913. if (this.TextBG.Border)
  2914. {
  2915. this.Canvas.strokeStyle=this.TextBG.Border;
  2916. this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgWidth),ToFixedRect(bgHeight));
  2917. }
  2918. }
  2919. this.Canvas.textBaseline="bottom";
  2920. this.Canvas.textAlign="left";
  2921. this.Canvas.fillStyle=drawInfo.Text.Color;
  2922. this.Canvas.fillText(text,x,y);
  2923. }
  2924. }
  2925. this.DrawRectText=function()
  2926. {
  2927. if (!this.DrawData) return;
  2928. var isHScreen=(this.ChartFrame.IsHScreen===true)
  2929. var border=this.ChartFrame.GetBorder();
  2930. if (this.Name=="DRAWTEXTREL")
  2931. {
  2932. if (isHScreen)
  2933. {
  2934. var height=border.RightTitle-border.LeftEx;
  2935. var width=border.BottomEx-border.TopEx;
  2936. var x=this.DrawData.Point.X/1000*width+border.TopEx;
  2937. var y=border.RightTitle-this.DrawData.Point.Y/1000*width;
  2938. }
  2939. else
  2940. {
  2941. var width=border.RightEx-border.LeftEx;
  2942. var height=border.BottomEx-border.TopTitle;
  2943. var x=this.DrawData.Point.X/1000*width+border.LeftEx;
  2944. var y=this.DrawData.Point.Y/1000*height+border.TopTitle;
  2945. }
  2946. }
  2947. else if (this.Name=="DRAWTEXTABS")
  2948. {
  2949. if (isHScreen)
  2950. {
  2951. var x=this.DrawData.Point.X+border.TopEx;
  2952. var y=border.RightTitle-this.DrawData.Point.Y;
  2953. }
  2954. else
  2955. {
  2956. var x=this.DrawData.Point.X+border.LeftEx;
  2957. var y=this.DrawData.Point.Y+border.TopTitle;
  2958. }
  2959. }
  2960. else
  2961. {
  2962. return;
  2963. }
  2964. if (this.Direction==1) this.Canvas.textBaseline='bottom';
  2965. else if (this.Direction==2) this.Canvas.textBaseline='top';
  2966. else this.Canvas.textBaseline='middle';
  2967. this.Canvas.textAlign=this.TextAlign;
  2968. this.Canvas.font=this.TextFont;
  2969. this.Canvas.fillStyle=this.Color;
  2970. this.DrawText(this.DrawData.Text,x,y,isHScreen);
  2971. }
  2972. this.SuperGetMaxMin=this.GetMaxMin;
  2973. this.GetMaxMin=function()
  2974. {
  2975. if (this.Name=="DRAWTEXTREL" || this.Name=="DRAWTEXTABS")
  2976. {
  2977. return { Min:null,Max:null };
  2978. }
  2979. else
  2980. {
  2981. return this.SuperGetMaxMin();
  2982. }
  2983. }
  2984. }
  2985. function ChartDrawText()
  2986. {
  2987. this.newMethod=IChartPainting; //派生
  2988. this.newMethod();
  2989. delete this.newMethod;
  2990. this.ClassName='ChartDrawText'; //类名
  2991. this.Color = "rgb(255,193,37)"; //线段颜色
  2992. this.TextFont = "14px 微软雅黑"; //字体
  2993. this.Text;
  2994. this.TextAlign = 'left';
  2995. this.TextBaseline="middle";
  2996. this.FixedFontSize=-1; //固定字体大小
  2997. this.YOffset = 0;
  2998. this.FixedPosition=-1; //固定位置输出 1顶部, 2底部
  2999. this.TextBG; //{ Color:"rgb(0,0,92)", Border:"rgb(205,0,92)", Margin:[0,1,1,1], } // { Color:背景色, Border:边框颜色, Margin=[上,下,左, 右] }
  3000. this.VerticalLine; //垂直线
  3001. this.ShowOffset={ X:0, Y:0 }; //显示偏移
  3002. this.TextSize=
  3003. {
  3004. Max: g_JSChartResource.DRAWICON.Text.MaxSize, Min:g_JSChartResource.DRAWICON.Text.MinSize, //字体的最大最小值
  3005. Zoom:{ Type:g_JSChartResource.DRAWICON.Text.Zoom.Type , Value:g_JSChartResource.DRAWICON.Text.Zoom.Value }, //放大倍数
  3006. FontName:g_JSChartResource.DRAWICON.Text.FontName
  3007. }
  3008. this.ReloadResource=function(resource)
  3009. {
  3010. this.TextSize=
  3011. {
  3012. Max: g_JSChartResource.DRAWTEXT.MaxSize, Min:g_JSChartResource.DRAWTEXT.MinSize, //字体的最大最小值
  3013. Zoom:{ Type:g_JSChartResource.DRAWTEXT.Zoom.Type , Value:g_JSChartResource.DRAWTEXT.Zoom.Value }, //放大倍数
  3014. FontName:g_JSChartResource.DRAWTEXT.FontName
  3015. }
  3016. }
  3017. this.Draw = function ()
  3018. {
  3019. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  3020. if (this.NotSupportMessage)
  3021. {
  3022. this.DrawNotSupportmessage();
  3023. return;
  3024. }
  3025. if (!this.Data || !this.Data.Data) return;
  3026. var isHScreen = (this.ChartFrame.IsHScreen === true)
  3027. var dataWidth = this.ChartFrame.DataWidth;
  3028. var distanceWidth = this.ChartFrame.DistanceWidth;
  3029. var chartright = this.ChartBorder.GetRight();
  3030. var top = this.ChartBorder.GetTopEx();
  3031. var bottom = this.ChartBorder.GetBottomEx();
  3032. if (isHScreen)
  3033. {
  3034. chartright = this.ChartBorder.GetBottom();
  3035. top = this.ChartBorder.GetRightEx();
  3036. bottom = this.ChartBorder.GetLeftEx();
  3037. }
  3038. var xPointCount = this.ChartFrame.XPointCount;
  3039. var isArrayText = Array.isArray(this.Text);
  3040. var text;
  3041. var drawTextInfo={ Text:{ Color:this.Color, Align:this.TextAlign, Baseline:this.TextBaseline }, Font:{ } };
  3042. //字体大小
  3043. if (this.FixedFontSize>0)
  3044. this.TextFont=`${this.FixedFontSize}px ${this.TextSize.FontName}`;
  3045. else
  3046. this.TextFont = this.GetDynamicFontEx(dataWidth,distanceWidth,this.TextSize.Max,this.TextSize.Min,this.TextSize.Zoom,this.TextSize.FontName);
  3047. drawTextInfo.Font={ Height:this.GetFontHeight(this.TextFont) };
  3048. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  3049. {
  3050. var value = this.Data.Data[i];
  3051. if (value == null) continue;
  3052. var x = this.ChartFrame.GetXFromIndex(j);
  3053. var y;
  3054. if (this.FixedPosition===1) y=top;
  3055. else if (this.FixedPosition===2) y=bottom;
  3056. else y=this.ChartFrame.GetYFromData(value);
  3057. if (x > chartright) break;
  3058. y+=this.ShowOffset.Y;
  3059. x+=this.ShowOffset.X;
  3060. drawTextInfo.X=x;
  3061. drawTextInfo.Y=y;
  3062. if (isArrayText)
  3063. {
  3064. text = this.Text[i];
  3065. if (!text) continue;
  3066. this.DrawText(text,drawTextInfo,isHScreen);
  3067. }
  3068. else
  3069. {
  3070. this.DrawText(this.Text,drawTextInfo,isHScreen);
  3071. }
  3072. this.DrawVerticalLine(i, drawTextInfo, isHScreen);
  3073. }
  3074. }
  3075. this.DrawText=function(text, drawInfo, isHScreen)
  3076. {
  3077. var textWidth=this.Canvas.measureText(text).width;
  3078. if (isHScreen)
  3079. {
  3080. var x=drawInfo.Y;
  3081. var y=drawInfo.X;
  3082. if (drawInfo.Text.Align=="right") y=y-textWidth;
  3083. else if (drawInfo.Text.Align=="center") y=y-textWidth/2;
  3084. if (drawInfo.Text.Baseline=="top") x-=drawInfo.Font.Height;
  3085. else if (drawInfo.Text.Baseline=="middle") x-=drawInfo.Font.Height/2;
  3086. if (this.TextBG && (this.TextBG.Color || this.TextBG.Border))
  3087. {
  3088. var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右
  3089. var xRect=x-margin[0];
  3090. var yRect=y-margin[2];
  3091. var bgWidth=textWidth+margin[2]+margin[3];
  3092. var bgHeight=drawInfo.Font.Height+margin[0]+margin[1];
  3093. if (this.TextBG.Color)
  3094. {
  3095. this.Canvas.fillStyle=this.TextBG.Color;
  3096. this.Canvas.fillRect(xRect,yRect,bgHeight,bgWidth);
  3097. }
  3098. if (this.TextBG.Border)
  3099. {
  3100. this.Canvas.strokeStyle=this.TextBG.Border;
  3101. this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgHeight),ToFixedRect(bgWidth));
  3102. }
  3103. drawInfo.Rect={Bottom:xRect, Top:xRect+bgHeight };
  3104. }
  3105. else
  3106. {
  3107. var xRect=x;
  3108. var bgHeight=drawInfo.Font.Height;
  3109. drawInfo.Rect={Bottom:xRect, Top:xRect+bgHeight };
  3110. }
  3111. this.Canvas.textBaseline="bottom";
  3112. this.Canvas.textAlign="left";
  3113. this.Canvas.fillStyle=drawInfo.Text.Color;
  3114. this.Canvas.save();
  3115. this.Canvas.translate(x, y);
  3116. this.Canvas.rotate(90 * Math.PI / 180);
  3117. this.Canvas.fillText(text,0,0);
  3118. this.Canvas.restore();
  3119. }
  3120. else
  3121. {
  3122. var x=drawInfo.X;
  3123. var y=drawInfo.Y;
  3124. if (drawInfo.Text.Align=="right") x=x-textWidth;
  3125. else if (drawInfo.Text.Align=="center") x=x-textWidth/2;
  3126. if (drawInfo.Text.Baseline=="top") y+=drawInfo.Font.Height;
  3127. else if (drawInfo.Text.Baseline=="middle") y+=drawInfo.Font.Height/2;
  3128. if (this.TextBG && (this.TextBG.Color || this.TextBG.Border))
  3129. {
  3130. var margin=this.TextBG.Margin; //0=上 1=下 2=左 3=右
  3131. var xRect=x-margin[2];
  3132. var yRect=y-drawInfo.Font.Height-margin[1];
  3133. var bgWidth=textWidth+margin[2]+margin[3];
  3134. var bgHeight=drawInfo.Font.Height+margin[0]+margin[1];
  3135. if (this.TextBG.Color)
  3136. {
  3137. this.Canvas.fillStyle=this.TextBG.Color;
  3138. this.Canvas.fillRect(xRect,yRect,bgWidth,bgHeight);
  3139. }
  3140. if (this.TextBG.Border)
  3141. {
  3142. this.Canvas.strokeStyle=this.TextBG.Border;
  3143. this.Canvas.strokeRect(ToFixedPoint(xRect),ToFixedPoint(yRect),ToFixedRect(bgWidth),ToFixedRect(bgHeight));
  3144. }
  3145. drawInfo.Rect={Top:yRect, Bottom:yRect+bgHeight };
  3146. }
  3147. else
  3148. {
  3149. var yRect=y-drawInfo.Font.Height;
  3150. var bgHeight=drawInfo.Font.Height;
  3151. drawInfo.Rect={Top:yRect, Bottom:yRect+bgHeight };
  3152. }
  3153. this.Canvas.textBaseline="bottom";
  3154. this.Canvas.textAlign="left";
  3155. this.Canvas.fillStyle=drawInfo.Text.Color;
  3156. this.Canvas.fillText(text,x,y);
  3157. }
  3158. }
  3159. //画连线
  3160. this.DrawVerticalLine=function(index, drawTextInfo, isHScreen)
  3161. {
  3162. if (!this.VerticalLine) return;
  3163. var item=this.VerticalLine.Data[index];
  3164. if (!item) return;
  3165. if (!IFrameSplitOperator.IsNumber(item.High)) return;
  3166. if (!IFrameSplitOperator.IsNumber(item.Low)) return;
  3167. var yHigh=this.ChartFrame.GetYFromData(item.High);
  3168. var yLow=this.ChartFrame.GetYFromData(item.Low);
  3169. var yLine, yLine2;
  3170. if (isHScreen)
  3171. {
  3172. if (drawTextInfo.Rect.Bottom>yHigh)
  3173. {
  3174. yLine=drawTextInfo.Rect.Bottom-1;
  3175. yLine2=yHigh+1;
  3176. }
  3177. else if (drawTextInfo.Rect.Top<yLow)
  3178. {
  3179. yLine=drawTextInfo.Rect.Top-1;
  3180. yLine2=yLow-1;
  3181. }
  3182. else
  3183. {
  3184. return;
  3185. }
  3186. }
  3187. else
  3188. {
  3189. if (drawTextInfo.Rect.Bottom<yHigh)
  3190. {
  3191. yLine=drawTextInfo.Rect.Bottom+1;
  3192. yLine2=yHigh-1;
  3193. }
  3194. else if (drawTextInfo.Rect.Top>yLow)
  3195. {
  3196. yLine=drawTextInfo.Rect.Top-1;
  3197. yLine2=yLow+1;
  3198. }
  3199. else
  3200. {
  3201. return;
  3202. }
  3203. }
  3204. this.Canvas.save();
  3205. var pixelTatio =1;
  3206. var xLine=drawTextInfo.X;
  3207. if (this.VerticalLine.LineType==1)
  3208. {
  3209. if (this.VerticalLine.LineDotted)
  3210. this.Canvas.setLineDash(this.VerticalLine.LineDotted);
  3211. else
  3212. this.Canvas.setLineDash([3,3]);
  3213. }
  3214. if (IFrameSplitOperator.IsPlusNumber(this.VerticalLine.LineWidth))
  3215. {
  3216. this.Canvas.lineWidth=this.VerticalLine.LineWidth*pixelTatio;
  3217. }
  3218. this.Canvas.strokeStyle=this.VerticalLine.Color;
  3219. this.Canvas.beginPath();
  3220. if (isHScreen)
  3221. {
  3222. this.Canvas.moveTo(ToFixedPoint(yLine),ToFixedPoint(xLine));
  3223. this.Canvas.lineTo(ToFixedPoint(yLine2),ToFixedPoint(xLine));
  3224. }
  3225. else
  3226. {
  3227. this.Canvas.moveTo(ToFixedPoint(xLine),ToFixedPoint(yLine));
  3228. this.Canvas.lineTo(ToFixedPoint(xLine),ToFixedPoint(yLine2));
  3229. }
  3230. this.Canvas.stroke();
  3231. this.Canvas.restore();
  3232. }
  3233. }
  3234. function ChartDrawNumber()
  3235. {
  3236. this.newMethod=ChartDrawText; //派生
  3237. this.newMethod();
  3238. delete this.newMethod;
  3239. this.ClassName='ChartDrawNumber'; //类名
  3240. this.ReloadResource=function(resource)
  3241. {
  3242. this.TextSize=
  3243. {
  3244. Max: g_JSChartResource.DRAWNUMBER.MaxSize, Min:g_JSChartResource.DRAWNUMBER.MinSize, //字体的最大最小值
  3245. Zoom:{ Type:g_JSChartResource.DRAWNUMBER.Zoom.Type , Value:g_JSChartResource.DRAWNUMBER.Zoom.Value }, //放大倍数
  3246. FontName:g_JSChartResource.DRAWNUMBER.FontName
  3247. }
  3248. }
  3249. }
  3250. function ChartDrawText_Fix()
  3251. {
  3252. this.newMethod=IChartPainting; //派生
  3253. this.newMethod();
  3254. delete this.newMethod;
  3255. this.ClassName='ChartDrawText_Fix'; //类名
  3256. this.Color="rgb(255,193,37)"; //字颜色
  3257. this.TextFont=g_JSChartResource.DRAWTEXT_FIX.Font;
  3258. this.PtPercentage=null; //{ X:, Y: } 百分比坐标
  3259. this.TextBaseline="top";
  3260. this.TextAlign='center';
  3261. this.ShowOffset={ X:0, Y:0 }; //显示偏移
  3262. this.MapCache;
  3263. this.HQChart;
  3264. this.AryText;
  3265. this.BuildCacheData=function(kData, data)
  3266. {
  3267. var mapData=new Map();
  3268. this.MapCache=mapData;
  3269. if (!kData || !IFrameSplitOperator.IsNonEmptyArray(kData.Data)) return;
  3270. if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Value) || !IFrameSplitOperator.IsNonEmptyArray(data.Text)) return;
  3271. for(var i=0;i<kData.Data.length;++i)
  3272. {
  3273. var value=data.Value[i];
  3274. if (value!==1) continue;
  3275. var text=data.Text[i];
  3276. if (!text) continue;
  3277. var kItem=kData.Data[i];
  3278. var item={ Value:value, Text:text, Date:kItem.Date, Time:kItem.Time };
  3279. var key=this.BuildKey(item);
  3280. /* //测试
  3281. item.Text=
  3282. [
  3283. { Name:`日期`, Text:`${item.Date}`, Margin:{ Bottom:10 }},
  3284. { Name:`日期2`, Text:`${item.Date}-2`},
  3285. ]
  3286. */
  3287. mapData.set(key,item);
  3288. }
  3289. }
  3290. this.ReloadResource=function(resource)
  3291. {
  3292. this.TextFont=g_JSChartResource.DRAWTEXT_FIX.Font;
  3293. }
  3294. this.Draw=function()
  3295. {
  3296. this.AryText=null;
  3297. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  3298. if (this.IsHideScriptIndex()) return;
  3299. if (!this.MapCache || this.MapCache.size<=0) return;
  3300. if (!this.PtPercentage || !IFrameSplitOperator.IsNumber(this.PtPercentage.X) || !IFrameSplitOperator.IsNumber(this.PtPercentage.Y)) return;
  3301. if (!this.IsDrawText()) return;
  3302. var bHScreen=(this.ChartFrame.IsHScreen===true)
  3303. this.Canvas.save();
  3304. this.ClipClient(bHScreen);
  3305. this.DrawText();
  3306. this.Canvas.restore();
  3307. this.AryText=null;
  3308. }
  3309. //当前屏是否要绘制文字
  3310. this.IsDrawText=function()
  3311. {
  3312. if (!this.HQChart) return false;
  3313. var kData=this.HQChart.GetKData();
  3314. if (!kData || !IFrameSplitOperator.IsNonEmptyArray(kData.Data)) return false;
  3315. var bHScreen=(this.ChartFrame.IsHScreen===true)
  3316. var dataWidth=this.ChartFrame.DataWidth;
  3317. var distanceWidth=this.ChartFrame.DistanceWidth;
  3318. var xPointCount=this.ChartFrame.XPointCount;
  3319. var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3320. var chartright=this.ChartBorder.GetRight();
  3321. var top=this.ChartBorder.GetTopEx();
  3322. var bottom=this.ChartBorder.GetBottomEx();
  3323. if (bHScreen)
  3324. {
  3325. chartright=this.ChartBorder.GetBottom();
  3326. top=this.ChartBorder.GetRightEx();
  3327. bottom=this.ChartBorder.GetLeftEx();
  3328. xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3329. }
  3330. for(var i=kData.DataOffset,j=0;i<kData.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  3331. {
  3332. var kItem=kData.Data[i];
  3333. if (kItem==null) continue;
  3334. var key=this.BuildKey(kItem);
  3335. if (!this.MapCache.has(key)) continue;
  3336. var item=this.MapCache.get(key);
  3337. if (Array.isArray(item.Text)) this.AryText=item.Text;
  3338. else this.AryText=[{ Name:item.Text }];
  3339. return true;
  3340. }
  3341. return false;
  3342. }
  3343. this.DrawText=function()
  3344. {
  3345. var bHScreen=(this.ChartFrame.IsHScreen===true);
  3346. if (bHScreen)
  3347. {
  3348. var x=this.ChartBorder.GetRightEx()-this.ChartBorder.GetWidthEx()*this.PtPercentage.Y;
  3349. var y=this.ChartBorder.GetTop()+this.ChartBorder.GetHeight()*this.PtPercentage.X;
  3350. }
  3351. else
  3352. {
  3353. var x=this.ChartBorder.GetLeft()+this.ChartBorder.GetWidth()*this.PtPercentage.X;
  3354. var y=this.ChartBorder.GetTopEx()+this.ChartBorder.GetHeightEx()*this.PtPercentage.Y;
  3355. }
  3356. var drawInfo=this.CalculateComplexTextSize(this.AryText, { Font:this.TextFont, Color:this.Color });
  3357. if (!drawInfo) return;
  3358. drawInfo.IsHScreen=bHScreen;
  3359. if (bHScreen)
  3360. {
  3361. if (this.TextBaseline=="middle") x=x-drawInfo.Height/2; //上下居中
  3362. else if (this.TextBaseline=="bottom") x=x-drawInfo.Height; //底部
  3363. if (this.TextAlign=="center") y=y-drawInfo.Width/2; //左右居中
  3364. else if (this.TextAlign=='right') y=y-drawInfo.Width; //右对齐
  3365. this.DrawComplexText(x,y, drawInfo);
  3366. }
  3367. else
  3368. {
  3369. if (this.TextBaseline=="middle") y=y-drawInfo.Height/2; //上下居中
  3370. else if (this.TextBaseline=="bottom") y=y-drawInfo.Height; //底部
  3371. if (this.TextAlign=="center") x=x-drawInfo.Width/2; //左右居中
  3372. else if (this.TextAlign=='right') x=x-drawInfo.Width; //右对齐
  3373. this.DrawComplexText(x,y, drawInfo);
  3374. }
  3375. }
  3376. this.DrawComplexText=function(x, y, drawInfo)
  3377. {
  3378. var left=x;
  3379. var lineTop=y;
  3380. if (drawInfo.IsHScreen)
  3381. {
  3382. left=0;
  3383. lineTop=0;
  3384. this.Canvas.save();
  3385. this.Canvas.translate(x, y);
  3386. this.Canvas.rotate(90 * Math.PI / 180);
  3387. }
  3388. this.Canvas.textBaseline="bottom";
  3389. this.Canvas.textAlign="left";
  3390. for(var i=0;i<drawInfo.AryData.length;++i)
  3391. {
  3392. var item=drawInfo.AryData[i];
  3393. var margin=item.Margin;
  3394. var xText=left+margin.Left;
  3395. var yText=lineTop+item.Height-margin.Bottom;
  3396. if (item.Name)
  3397. {
  3398. this.Canvas.font=item.Font;
  3399. this.Canvas.fillStyle=item.NameColor;
  3400. this.Canvas.fillText(item.Name,xText,yText);
  3401. xText+=item.NameWidth+item.Space;
  3402. }
  3403. if (item.Text)
  3404. {
  3405. this.Canvas.font=item.Font;
  3406. this.Canvas.fillStyle=item.TextColor;
  3407. this.Canvas.fillText(item.Text,xText,yText);
  3408. xText+=item.TextWidth;
  3409. }
  3410. lineTop+=item.Height;
  3411. }
  3412. if (drawInfo.IsHScreen) this.Canvas.restore();
  3413. }
  3414. //计算复杂文本长度高度 defaultOption:{ Font:, }
  3415. this.CalculateComplexTextSize=function(aryText, defaultOption)
  3416. {
  3417. if (!defaultOption) return null;
  3418. if (!aryText || !IFrameSplitOperator.IsNonEmptyArray(aryText)) return null;
  3419. this.Canvas.font=defaultOption.Font;
  3420. var lineHeight=this.Canvas.measureText("擎").width;
  3421. var maxNameWidth=0, maxTextWidth=0;
  3422. var result={ AryData:[], Width:0, Height:0 }
  3423. for(var i=0;i<aryText.length;++i)
  3424. {
  3425. var item=aryText[i];
  3426. var newItem={ NameWidth:0, TextWidth:0, Margin:{ Left:0, Top:0, Right:0, Bottom:0 }, Font:defaultOption.Font, Space:0, YOffset:0, Width:0, Height:0 };
  3427. if (item.Name)
  3428. {
  3429. newItem.NameWidth=this.Canvas.measureText(item.Name).width;
  3430. newItem.Name=item.Name;
  3431. if (maxNameWidth<item.NameWidth) maxNameWidth=newItem.NameWidth;
  3432. if (IFrameSplitOperator.IsNumber(item.Space)) newItem.Space=item.Space;
  3433. if (item.NameColor) newItem.NameColor=item.NameColor;
  3434. else newItem.NameColor=defaultOption.Color;
  3435. }
  3436. if (item.Text)
  3437. {
  3438. newItem.TextWidth=this.Canvas.measureText(item.Text).width;
  3439. newItem.Text=item.Text;
  3440. if (maxTextWidth<item.TextWidth) maxTextWidth=newItem.TextWidth;
  3441. if (item.TextColor) newItem.TextColor=item.TextColor;
  3442. else newItem.TextColor=defaultOption.Color;
  3443. }
  3444. JSChartResource.CopyMarginConfig(newItem.Margin, item.Margin);
  3445. if (IFrameSplitOperator.IsNumber(item.YOffset)) newItem.YOffset=item.YOffset;
  3446. newItem.Width=newItem.NameWidth+newItem.TextWidth;
  3447. newItem.Width+=newItem.Margin.Left+newItem.Margin.Right+newItem.Space;
  3448. newItem.Height=(lineHeight+newItem.Margin.Top+newItem.Margin.Bottom);
  3449. result.AryData.push(newItem);
  3450. result.Height+=newItem.Height;
  3451. if (result.Width<newItem.Width) result.Width=newItem.Width;
  3452. }
  3453. return result;
  3454. }
  3455. }
  3456. function ChartDrawNumber_Fix()
  3457. {
  3458. this.newMethod=ChartDrawText_Fix; //派生
  3459. this.newMethod();
  3460. delete this.newMethod;
  3461. this.ClassName='ChartDrawNumber_Fix'; //类名
  3462. this.TextFont=g_JSChartResource.DRAWNUMBER_FIX.Font;
  3463. this.BuildCacheData=function(kData, data)
  3464. {
  3465. var mapData=new Map();
  3466. this.MapCache=mapData;
  3467. if (!kData || !IFrameSplitOperator.IsNonEmptyArray(kData.Data)) return;
  3468. if (!data || !IFrameSplitOperator.IsNonEmptyArray(data.Value) || !IFrameSplitOperator.IsNonEmptyArray(data.Text)) return;
  3469. for(var i=0;i<kData.Data.length;++i)
  3470. {
  3471. var value=data.Value[i];
  3472. var text=data.Text[i];
  3473. if (!text) continue;
  3474. var kItem=kData.Data[i];
  3475. var item={ Value:value, Text:text, Date:kItem.Date, Time:kItem.Time };
  3476. var key=this.BuildKey(item);
  3477. mapData.set(key,item);
  3478. }
  3479. }
  3480. this.ReloadResource=function(resource)
  3481. {
  3482. this.TextFont=g_JSChartResource.DRAWNUMBER_FIX.Font;
  3483. }
  3484. }
  3485. //线段
  3486. function ChartLine()
  3487. {
  3488. this.newMethod = IChartPainting; //派生
  3489. this.newMethod();
  3490. delete this.newMethod;
  3491. this.ClassName ='ChartLine';
  3492. this.Color = "rgb(255,193,37)"; //线段颜色
  3493. this.LineWidth; //线段宽度
  3494. this.DrawType = 0; //画图方式 0=无效数平滑 1=无效数不画断开
  3495. this.IsDotLine = false; //虚线
  3496. this.LineDash=g_JSChartResource.DOTLINE.LineDash;
  3497. this.Draw = function ()
  3498. {
  3499. if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return;
  3500. if (this.IsHideScriptIndex()) return;
  3501. if (this.NotSupportMessage)
  3502. {
  3503. this.DrawNotSupportmessage();
  3504. return;
  3505. }
  3506. if (!this.Data || !this.Data.Data) return;
  3507. switch (this.DrawType)
  3508. {
  3509. case 0:
  3510. return this.DrawLine();
  3511. case 1:
  3512. return this.DrawStraightLine();
  3513. }
  3514. }
  3515. this.DrawLine = function ()
  3516. {
  3517. var bHScreen = (this.ChartFrame.IsHScreen === true);
  3518. var dataWidth = this.ChartFrame.DataWidth;
  3519. var distanceWidth = this.ChartFrame.DistanceWidth;
  3520. var chartright = this.ChartBorder.GetRight();
  3521. if (bHScreen) chartright = this.ChartBorder.GetBottom();
  3522. var xPointCount = this.ChartFrame.XPointCount;
  3523. this.Canvas.save();
  3524. if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth;
  3525. var bFirstPoint = true;
  3526. var drawCount = 0;
  3527. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  3528. {
  3529. var value = this.Data.Data[i];
  3530. if (value == null) continue;
  3531. var x = this.ChartFrame.GetXFromIndex(j);
  3532. var y = this.GetYFromData(value);
  3533. if (x > chartright) break;
  3534. if (bFirstPoint)
  3535. {
  3536. this.Canvas.strokeStyle = this.Color;
  3537. this.Canvas.beginPath();
  3538. if (bHScreen) this.Canvas.moveTo(y, x); //横屏坐标轴对调
  3539. else this.Canvas.moveTo(x, y);
  3540. bFirstPoint = false;
  3541. }
  3542. else
  3543. {
  3544. if (bHScreen) this.Canvas.lineTo(y, x);
  3545. else this.Canvas.lineTo(x, y);
  3546. }
  3547. ++drawCount;
  3548. }
  3549. if (drawCount > 0) this.Canvas.stroke();
  3550. this.Canvas.restore();
  3551. }
  3552. //无效数不画
  3553. this.DrawStraightLine = function ()
  3554. {
  3555. var bHScreen = (this.ChartFrame.IsHScreen === true);
  3556. var isMinute=this.IsMinuteFrame();
  3557. var dataWidth = this.ChartFrame.DataWidth;
  3558. var distanceWidth = this.ChartFrame.DistanceWidth;
  3559. var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3560. var chartright = this.ChartBorder.GetRight();
  3561. if (bHScreen) chartright = this.ChartBorder.GetBottom();
  3562. if (bHScreen) xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3563. var xPointCount = this.ChartFrame.XPointCount;
  3564. var lockRect=this.GetLockRect();
  3565. if (lockRect)
  3566. {
  3567. if (bHScreen) chartright=lockRect.Top;
  3568. else chartright=lockRect.Left;
  3569. }
  3570. this.Canvas.save();
  3571. if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth;
  3572. this.Canvas.strokeStyle = this.Color;
  3573. if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线
  3574. var bFirstPoint = true;
  3575. var drawCount = 0;
  3576. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  3577. //for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  3578. {
  3579. var value = this.Data.Data[i];
  3580. if (value == null)
  3581. {
  3582. if (drawCount > 0) this.Canvas.stroke();
  3583. bFirstPoint = true;
  3584. drawCount = 0;
  3585. continue;
  3586. }
  3587. if (isMinute)
  3588. {
  3589. var x = this.ChartFrame.GetXFromIndex(j);
  3590. }
  3591. else
  3592. {
  3593. var left=xOffset;
  3594. var right=xOffset+dataWidth;
  3595. if (right>chartright) break;
  3596. var x=left+(right-left)/2;
  3597. }
  3598. var y = this.GetYFromData(value);
  3599. if (x > chartright) break;
  3600. if (bFirstPoint)
  3601. {
  3602. this.Canvas.beginPath();
  3603. if (bHScreen) this.Canvas.moveTo(y, x); //横屏坐标轴对调
  3604. else this.Canvas.moveTo(x, y);
  3605. bFirstPoint = false;
  3606. }
  3607. else
  3608. {
  3609. if (bHScreen) this.Canvas.lineTo(y, x);
  3610. else this.Canvas.lineTo(x, y);
  3611. }
  3612. ++drawCount;
  3613. }
  3614. if (drawCount > 0) this.Canvas.stroke();
  3615. this.Canvas.restore();
  3616. }
  3617. this.GetYFromData = function (value)
  3618. {
  3619. return this.ChartFrame.GetYFromData(value);
  3620. }
  3621. }
  3622. //独立线段
  3623. //独立线段
  3624. function ChartSingleLine()
  3625. {
  3626. this.newMethod=ChartLine; //派生
  3627. this.newMethod();
  3628. delete this.newMethod;
  3629. this.ClassName='ChartSingleLine'; //类名
  3630. this.MaxMin=null; //当前的显示范围
  3631. this.Draw=function()
  3632. {
  3633. this.MaxMin=null;
  3634. if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return;
  3635. if (this.IsHideScriptIndex()) return;
  3636. if (!this.Data || !this.Data.Data) return;
  3637. this.MaxMin=this.GetCurrentMaxMin();
  3638. if (!this.MaxMin) return;
  3639. if (!IFrameSplitOperator.IsNumber(this.MaxMin.Max) || !IFrameSplitOperator.IsNumber(this.MaxMin.Min)) return;
  3640. switch(this.DrawType)
  3641. {
  3642. default:
  3643. return this.DrawStraightLine();
  3644. }
  3645. }
  3646. //获取当前页的最大最小值
  3647. this.GetCurrentMaxMin=function()
  3648. {
  3649. var xPointCount=this.ChartFrame.XPointCount;
  3650. var range={ Max:null, Min:null };
  3651. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  3652. {
  3653. var value=this.Data.Data[i];
  3654. if (!IFrameSplitOperator.IsNumber(value)) continue;
  3655. if (range.Max==null) range.Max=value;
  3656. if (range.Min==null) range.Min=value;
  3657. if (range.Max<value) range.Max=value;
  3658. if (range.Min>value) range.Min=value;
  3659. }
  3660. return range;
  3661. }
  3662. this.GetMaxMin=function()
  3663. {
  3664. return { Max:null, Min:null };
  3665. }
  3666. this.GetYFromData=function(value)
  3667. {
  3668. var bHScreen = (this.ChartFrame.IsHScreen === true);
  3669. if (bHScreen)
  3670. {
  3671. if (value <= this.MaxMin.Min) return this.ChartBorder.GetLeftEx();
  3672. if (value >= this.MaxMin.Max) return this.ChartBorder.GetRightEx();
  3673. var width = this.ChartBorder.GetWidthEx() * (value - this.MaxMin.Min) / (this.MaxMin.Max - this.MaxMin.Min);
  3674. return this.ChartBorder.GetLeftEx() + width;
  3675. }
  3676. else
  3677. {
  3678. if(value<=this.MaxMin.Min) return this.ChartBorder.GetBottomEx();
  3679. if(value>=this.MaxMin.Max) return this.ChartBorder.GetTopEx();
  3680. var height=this.ChartBorder.GetHeightEx()*(value-this.MaxMin.Min)/(this.MaxMin.Max-this.MaxMin.Min);
  3681. return this.ChartBorder.GetBottomEx()-height;
  3682. }
  3683. }
  3684. }
  3685. //彩色线段
  3686. function ChartPartLine()
  3687. {
  3688. this.newMethod=IChartPainting; //派生
  3689. this.newMethod();
  3690. delete this.newMethod;
  3691. this.ClassName='ChartPartLine'; //类名
  3692. this.LineWidth; //线段宽度
  3693. this.IsDotLine=false; //虚线
  3694. this.LineDash=[3,5]; //虚线设置
  3695. this.Draw=function()
  3696. {
  3697. if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return;
  3698. if (this.IsHideScriptIndex()) return;
  3699. if (!this.Data || !this.Data.Data) return;
  3700. this.DrawLine();
  3701. }
  3702. this.DrawLine=function()
  3703. {
  3704. var bHScreen=(this.ChartFrame.IsHScreen===true);
  3705. var dataWidth=this.ChartFrame.DataWidth;
  3706. var distanceWidth=this.ChartFrame.DistanceWidth;
  3707. if (bHScreen)
  3708. {
  3709. var border=this.ChartBorder.GetHScreenBorder();
  3710. var chartright=border.BottomEx;
  3711. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3712. }
  3713. else
  3714. {
  3715. var border=this.ChartBorder.GetBorder();
  3716. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3717. var chartright=border.RightEx;
  3718. }
  3719. var xPointCount=this.ChartFrame.XPointCount;
  3720. var isMinute=this.IsMinuteFrame();
  3721. this.Canvas.save();
  3722. if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth;
  3723. if (this.IsDotLine) this.Canvas.setLineDash(this.LineDash); //画虚线
  3724. var drawCount=0;
  3725. var lastColor;
  3726. var lastPoint={X:null,Y:null};
  3727. var isPerNull=false;
  3728. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  3729. {
  3730. var item=this.Data.Data[i];
  3731. if (item==null || item.Value==null)
  3732. {
  3733. lastPoint.X=null;
  3734. lastPoint.Y=null;
  3735. isPerNull=true;
  3736. continue;
  3737. }
  3738. if (isMinute)
  3739. {
  3740. var x=this.ChartFrame.GetXFromIndex(j);
  3741. }
  3742. else
  3743. {
  3744. var left=xOffset;
  3745. var right=xOffset+dataWidth;
  3746. if (right>chartright) break;
  3747. var x=left+(right-left)/2;
  3748. }
  3749. var value=item.Value;
  3750. var color=item.RGB;
  3751. var y=this.ChartFrame.GetYFromData(value);
  3752. if (x>chartright) break;
  3753. if (color!=lastColor || isPerNull==true)
  3754. {
  3755. if (lastColor && drawCount>0) this.Canvas.stroke();
  3756. drawCount=0;
  3757. lastColor=color;
  3758. this.Canvas.strokeStyle=color;
  3759. this.Canvas.beginPath();
  3760. if (lastPoint.X!=null && lastPoint.Y!=null) //接着上一个点连线
  3761. {
  3762. if (bHScreen) this.Canvas.moveTo(lastPoint.Y,lastPoint.X); //横屏坐标轴对调
  3763. else this.Canvas.moveTo(lastPoint.X,lastPoint.Y);
  3764. if (bHScreen) this.Canvas.lineTo(y,x);
  3765. else this.Canvas.lineTo(x,y);
  3766. ++drawCount;
  3767. }
  3768. else
  3769. {
  3770. if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调
  3771. else this.Canvas.moveTo(x,y);
  3772. }
  3773. }
  3774. else
  3775. {
  3776. if (bHScreen) this.Canvas.lineTo(y,x);
  3777. else this.Canvas.lineTo(x,y);
  3778. ++drawCount;
  3779. }
  3780. lastPoint.X=x;
  3781. lastPoint.Y=y;
  3782. isPerNull=false;
  3783. }
  3784. if (drawCount>0) this.Canvas.stroke();
  3785. this.Canvas.restore();
  3786. }
  3787. this.GetMaxMin=function()
  3788. {
  3789. var xPointCount=this.ChartFrame.XPointCount;
  3790. var range={};
  3791. range.Min=null;
  3792. range.Max=null;
  3793. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  3794. {
  3795. var item = this.Data.Data[i];
  3796. if (!item || !item.Value) continue;
  3797. if (range.Max == null || range.Max<item.Value) range.Max = item.Value;
  3798. if (range.Min == null || range.Min>item.Value) range.Min = item.Value;
  3799. }
  3800. return range;
  3801. }
  3802. }
  3803. //面积图 支持横屏
  3804. function ChartArea()
  3805. {
  3806. this.newMethod=IChartPainting; //派生
  3807. this.newMethod();
  3808. delete this.newMethod;
  3809. this.ClassName='ChartArea'; //类名
  3810. this.Color="rgb(255,193,37)"; //线段颜色
  3811. this.AreaColor; //面积颜色
  3812. this.LineWidth; //线段宽度
  3813. this.LineDash; //虚线
  3814. this.AreaDirection=0 //0=向下 1=向上
  3815. this.DrawSelectedStatus=this.DrawLinePoint;
  3816. this.PtInChart=this.PtInLine;
  3817. this.ExportData=this.ExportArrayData;
  3818. this.GetItemData=this.GetArrayItemData;
  3819. this.Draw=function()
  3820. {
  3821. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  3822. if (this.NotSupportMessage)
  3823. {
  3824. this.DrawNotSupportmessage();
  3825. return;
  3826. }
  3827. if (!this.Data || !this.Data.Data) return;
  3828. this.DrawArea();
  3829. }
  3830. //无效数不画
  3831. this.DrawArea=function()
  3832. {
  3833. var bHScreen=(this.ChartFrame.IsHScreen===true);
  3834. var isMinute=this.IsMinuteFrame();
  3835. var dataWidth=this.ChartFrame.DataWidth;
  3836. var distanceWidth=this.ChartFrame.DistanceWidth;
  3837. var xPointCount=this.ChartFrame.XPointCount;
  3838. if (bHScreen)
  3839. {
  3840. var border=this.ChartBorder.GetHScreenBorder();
  3841. var chartright=border.BottomEx;
  3842. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3843. }
  3844. else
  3845. {
  3846. var border=this.ChartBorder.GetBorder();
  3847. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  3848. var chartright=border.RightEx;
  3849. }
  3850. var lockRect=this.GetLockRect();
  3851. if (lockRect)
  3852. {
  3853. if (bHScreen) chartright=lockRect.Top;
  3854. else chartright=lockRect.Left;
  3855. }
  3856. this.Canvas.save();
  3857. if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth;
  3858. this.Canvas.strokeStyle=this.Color;
  3859. if (this.AreaColor) this.Canvas.fillStyle=this.AreaColor;
  3860. else this.Canvas.fillStyle=ColorToRGBA(this.Color,0.6);
  3861. if (IFrameSplitOperator.IsNonEmptyArray(this.LineDash)) this.Canvas.setLineDash(this.LineDas); //画虚线
  3862. var bFirstPoint=true;
  3863. var ptFirst=null, ptEnd=null //起始结束点
  3864. var drawCount=0;
  3865. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  3866. {
  3867. var value=this.Data.Data[i];
  3868. if (!IFrameSplitOperator.IsNumber(value))
  3869. {
  3870. if (drawCount>0) this.Canvas.stroke();
  3871. if (ptFirst && ptEnd)
  3872. {
  3873. if (bHScreen)
  3874. {
  3875. if (this.AreaDirection==1)
  3876. {
  3877. this.Canvas.lineTo(border.RightEx,ptEnd.X);
  3878. this.Canvas.lineTo(border.RightEx,ptFirst.X);
  3879. }
  3880. else
  3881. {
  3882. this.Canvas.lineTo(border.LeftEx,ptEnd.X);
  3883. this.Canvas.lineTo(border.LeftEx,ptFirst.X);
  3884. }
  3885. this.Canvas.closePath();
  3886. this.Canvas.fill();
  3887. }
  3888. else
  3889. {
  3890. if (this.AreaDirection==1)
  3891. {
  3892. this.Canvas.lineTo(ptEnd.X, border.TopEx);
  3893. this.Canvas.lineTo(ptFirst.X, border.TopEx);
  3894. }
  3895. else
  3896. {
  3897. this.Canvas.lineTo(ptEnd.X, border.BottomEx);
  3898. this.Canvas.lineTo(ptFirst.X, border.BottomEx);
  3899. }
  3900. this.Canvas.closePath();
  3901. this.Canvas.fill();
  3902. }
  3903. }
  3904. bFirstPoint=true;
  3905. drawCount=0;
  3906. ptFirst=null;
  3907. ptEnd=null;
  3908. continue;
  3909. }
  3910. if (isMinute)
  3911. {
  3912. var x=this.ChartFrame.GetXFromIndex(j);
  3913. }
  3914. else
  3915. {
  3916. var left=xOffset;
  3917. var right=xOffset+dataWidth;
  3918. if (right>chartright) break;
  3919. var x=left+(right-left)/2;
  3920. }
  3921. var y=this.GetYFromData(value,false);
  3922. if (x>chartright) break;
  3923. if (bFirstPoint)
  3924. {
  3925. this.Canvas.beginPath();
  3926. if (bHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调
  3927. else this.Canvas.moveTo(x,y);
  3928. bFirstPoint=false;
  3929. ptFirst={ X:x, Y:y };
  3930. }
  3931. else
  3932. {
  3933. if (bHScreen) this.Canvas.lineTo(y,x);
  3934. else this.Canvas.lineTo(x,y);
  3935. ptEnd={ X:x, Y:y };
  3936. }
  3937. ++drawCount;
  3938. }
  3939. if (drawCount>0)
  3940. {
  3941. if (drawCount==1 && ptFirst) //如果只有1个点, 画一个像素的横线
  3942. {
  3943. if (bHScreen) this.Canvas.lineTo(ptFirst.Y,ptFirst.X+1*GetDevicePixelRatio());
  3944. else this.Canvas.lineTo(ptFirst.X+1*GetDevicePixelRatio(),ptFirst.Y);
  3945. }
  3946. this.Canvas.stroke();
  3947. if (ptFirst && ptEnd)
  3948. {
  3949. if (bHScreen)
  3950. {
  3951. if (this.AreaDirection==1)
  3952. {
  3953. this.Canvas.lineTo(border.RightEx,ptEnd.X);
  3954. this.Canvas.lineTo(border.RightEx,ptFirst.X);
  3955. }
  3956. else
  3957. {
  3958. this.Canvas.lineTo(border.LeftEx,ptEnd.X);
  3959. this.Canvas.lineTo(border.LeftEx,ptFirst.X);
  3960. }
  3961. this.Canvas.closePath();
  3962. this.Canvas.fill();
  3963. }
  3964. else
  3965. {
  3966. if (this.AreaDirection==1)
  3967. {
  3968. this.Canvas.lineTo(ptEnd.X, border.TopEx);
  3969. this.Canvas.lineTo(ptFirst.X, border.TopEx);
  3970. }
  3971. else
  3972. {
  3973. this.Canvas.lineTo(ptEnd.X, border.BottomEx);
  3974. this.Canvas.lineTo(ptFirst.X, border.BottomEx);
  3975. }
  3976. this.Canvas.closePath();
  3977. this.Canvas.fill();
  3978. }
  3979. }
  3980. }
  3981. this.Canvas.restore();
  3982. }
  3983. }
  3984. //子线段
  3985. function ChartSubLine()
  3986. {
  3987. this.newMethod = ChartLine; //派生
  3988. this.newMethod();
  3989. delete this.newMethod;
  3990. this.ClassName = 'ChartSubLine'; //类名
  3991. this.Color = "rgb(255,193,37)"; //线段颜色
  3992. this.LineWidth; //线段宽度
  3993. this.DrawType = 0; //画图方式 0=无效数平滑 1=无效数不画断开
  3994. this.IsDotLine = false; //虚线
  3995. this.SubFrame = { Max: null, Min: null };
  3996. this.Draw = function ()
  3997. {
  3998. if (!this.IsShow) return;
  3999. if (!this.Data || !this.Data.Data) return;
  4000. this.CalculateDataMaxMin();
  4001. switch (this.DrawType)
  4002. {
  4003. case 0:
  4004. return this.DrawLine();
  4005. case 1:
  4006. return this.DrawStraightLine();
  4007. }
  4008. }
  4009. this.GetYFromData = function (value)
  4010. {
  4011. var bHScreen = (this.ChartFrame.IsHScreen === true);
  4012. if (bHScreen)
  4013. {
  4014. if (value <= this.SubFrame.Min) return this.ChartBorder.GetLeftEx();
  4015. if (value >= this.SubFrame.Max) return this.ChartBorder.GetRightEx();
  4016. var width = this.ChartBorder.GetWidthEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min);
  4017. return this.ChartBorder.GetLeftEx() + width;
  4018. }
  4019. else
  4020. {
  4021. if (value <= this.SubFrame.Min) return this.ChartBorder.GetBottomEx();
  4022. if (value >= this.SubFrame.Max) return this.ChartBorder.GetTopEx();
  4023. var height = this.ChartBorder.GetHeightEx() * (value - this.SubFrame.Min) / (this.SubFrame.Max - this.SubFrame.Min);
  4024. return this.ChartBorder.GetBottomEx() - height;
  4025. }
  4026. }
  4027. this.CalculateDataMaxMin = function ()
  4028. {
  4029. this.SubFrame = { Max: null, Min: null };
  4030. var bHScreen = (this.ChartFrame.IsHScreen === true);
  4031. var chartright = this.ChartBorder.GetRight();
  4032. if (bHScreen) chartright = this.ChartBorder.GetBottom();
  4033. var xPointCount = this.ChartFrame.XPointCount;
  4034. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  4035. {
  4036. var value = this.Data.Data[i];
  4037. if (value == null) continue;
  4038. var x = this.ChartFrame.GetXFromIndex(j);
  4039. if (x > chartright) break;
  4040. if (this.SubFrame.Min == null || this.SubFrame.Min > value) this.SubFrame.Min = value;
  4041. if (this.SubFrame.Max == null || this.SubFrame.Max < value) this.SubFrame.Max = value;
  4042. }
  4043. }
  4044. this.GetMaxMin = function () //数据不参与坐标轴最大最小值计算
  4045. {
  4046. var range = { Min: null, Max: null };
  4047. return range;
  4048. }
  4049. }
  4050. //POINTDOT 圆点 支持横屏
  4051. function ChartPointDot()
  4052. {
  4053. this.newMethod = IChartPainting; //派生
  4054. this.newMethod();
  4055. delete this.newMethod;
  4056. this.Color = "rgb(255,193,37)"; //线段颜色
  4057. this.Radius = 1; //点半径
  4058. this.ClassName = 'ChartPointDot';
  4059. this.EnableUpDownColor=false; //是否是红绿点
  4060. this.UpColor=g_JSChartResource.ChartPointDot.UpColor;
  4061. this.DownColor=g_JSChartResource.ChartPointDot.DownColor;
  4062. this.HistoryData;
  4063. this.Draw = function ()
  4064. {
  4065. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  4066. if (this.NotSupportMessage)
  4067. {
  4068. this.DrawNotSupportmessage();
  4069. return;
  4070. }
  4071. if (!this.Data || !this.Data.Data) return;
  4072. var bHScreen = (this.ChartFrame.IsHScreen === true);
  4073. var dataWidth = this.ChartFrame.DataWidth;
  4074. var distanceWidth = this.ChartFrame.DistanceWidth;
  4075. var chartright = this.ChartBorder.GetRight();
  4076. if (bHScreen === true) chartright = this.ChartBorder.GetBottom();
  4077. var xPointCount = this.ChartFrame.XPointCount;
  4078. this.Canvas.save();
  4079. this.Canvas.fillStyle = this.Color;
  4080. var colorDot;
  4081. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  4082. {
  4083. var value = this.Data.Data[i];
  4084. if (value == null) continue;
  4085. var x = this.ChartFrame.GetXFromIndex(j);
  4086. var y = this.ChartFrame.GetYFromData(value);
  4087. if (x > chartright) break;
  4088. if (this.EnableUpDownColor)
  4089. {
  4090. var kItem=this.HistoryData.Data[i];
  4091. if (kItem.Close>value) colorDot=this.UpColor
  4092. else colorDot=this.DownColor;
  4093. this.Canvas.fillStyle=colorDot;
  4094. }
  4095. this.Canvas.beginPath();
  4096. if (bHScreen) this.Canvas.arc(y, x, this.Radius, 0, Math.PI * 2, true);
  4097. else this.Canvas.arc(x, y, this.Radius, 0, Math.PI * 2, true);
  4098. this.Canvas.closePath();
  4099. this.Canvas.fill();
  4100. }
  4101. this.Canvas.restore();
  4102. }
  4103. }
  4104. //通达信语法 STICK 支持横屏
  4105. function ChartStick()
  4106. {
  4107. this.newMethod = IChartPainting; //派生
  4108. this.newMethod();
  4109. delete this.newMethod;
  4110. this.Color = "rgb(255,193,37)"; //线段颜色
  4111. this.LineWidth; //线段宽度
  4112. this.ClassName = 'ChartStick';
  4113. this.DrawLine = function ()
  4114. {
  4115. if (this.ChartFrame.IsMinSize) return;
  4116. if (this.IsHideScriptIndex()) return;
  4117. if (!this.Data || !this.Data.Data) return;
  4118. var isHScreen = (this.ChartFrame.IsHScreen === true);
  4119. var dataWidth = this.ChartFrame.DataWidth;
  4120. var distanceWidth = this.ChartFrame.DistanceWidth;
  4121. var chartright = this.ChartBorder.GetRight();
  4122. if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
  4123. var xPointCount = this.ChartFrame.XPointCount;
  4124. this.Canvas.save();
  4125. if (this.LineWidth > 0) this.Canvas.lineWidth = this.LineWidth;
  4126. var bFirstPoint = true;
  4127. var drawCount = 0;
  4128. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  4129. {
  4130. var value = this.Data.Data[i];
  4131. if (value == null) continue;
  4132. var x = this.ChartFrame.GetXFromIndex(j);
  4133. var y = this.ChartFrame.GetYFromData(value);
  4134. if (x > chartright) break;
  4135. if (bFirstPoint)
  4136. {
  4137. this.Canvas.strokeStyle = this.Color;
  4138. this.Canvas.beginPath();
  4139. if (isHScreen) this.Canvas.moveTo(y, x);
  4140. else this.Canvas.moveTo(x, y);
  4141. bFirstPoint = false;
  4142. }
  4143. else
  4144. {
  4145. if (isHScreen) this.Canvas.lineTo(y, x);
  4146. else this.Canvas.lineTo(x, y);
  4147. }
  4148. ++drawCount;
  4149. }
  4150. if (drawCount > 0) this.Canvas.stroke();
  4151. this.Canvas.restore();
  4152. }
  4153. this.DrawStick = function ()
  4154. {
  4155. if (!this.Data || !this.Data.Data) return;
  4156. var bHScreen = (this.ChartFrame.IsHScreen === true);
  4157. var chartright = this.ChartBorder.GetRight();
  4158. if (bHScreen) chartright = this.ChartBorder.GetBottom();
  4159. var xPointCount = this.ChartFrame.XPointCount;
  4160. var yBottom = this.ChartBorder.GetBottom();
  4161. var xLeft = this.ChartBorder.GetLeft();
  4162. this.Canvas.save();
  4163. this.Canvas.strokeStyle = this.Color;
  4164. if (this.LineWidth) this.Canvas.lineWidth = this.LineWidth;
  4165. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  4166. {
  4167. var value = this.Data.Data[i];
  4168. if (value == null) continue;
  4169. var x = this.ChartFrame.GetXFromIndex(j);
  4170. var y = this.ChartFrame.GetYFromData(value);
  4171. if (x > chartright) break;
  4172. this.Canvas.beginPath();
  4173. if (bHScreen)
  4174. {
  4175. this.Canvas.moveTo(xLeft, x);
  4176. this.Canvas.lineTo(y, x);
  4177. this.Canvas.stroke();
  4178. }
  4179. else
  4180. {
  4181. var xFix = parseInt(x.toString()) + 0.5;
  4182. this.Canvas.moveTo(xFix, y);
  4183. this.Canvas.lineTo(xFix, yBottom);
  4184. }
  4185. this.Canvas.stroke();
  4186. }
  4187. this.Canvas.restore();
  4188. }
  4189. this.Draw = function ()
  4190. {
  4191. if (!this.IsShow) return;
  4192. if (this.NotSupportMessage)
  4193. {
  4194. this.DrawNotSupportmessage();
  4195. return;
  4196. }
  4197. this.DrawStick();
  4198. }
  4199. }
  4200. //通达信语法 LINESTICK 支持横屏
  4201. function ChartLineStick()
  4202. {
  4203. this.newMethod = ChartStick; //派生
  4204. this.newMethod();
  4205. delete this.newMethod;
  4206. this.ClassName = 'ChartLineStick';
  4207. this.Draw = function ()
  4208. {
  4209. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  4210. if (this.IsHideScriptIndex()) return;
  4211. if (this.NotSupportMessage)
  4212. {
  4213. this.DrawNotSupportmessage();
  4214. return;
  4215. }
  4216. this.DrawStick();
  4217. this.DrawLine();
  4218. }
  4219. }
  4220. //柱子 支持横屏
  4221. function ChartStickLine()
  4222. {
  4223. this.newMethod = IChartPainting; //派生
  4224. this.newMethod();
  4225. delete this.newMethod;
  4226. this.ClassName ='ChartStickLine';
  4227. this.Color = "rgb(255,193,37)"; //线段颜色
  4228. this.BarType = 0; //柱子类型 0=实心 1=空心 -1=画虚线空心柱
  4229. this.LineDotted=[3,3]; //虚线设置
  4230. this.Width=0; //柱子宽度 0=1 3,50=k线宽度 101=K线宽度+间距宽度
  4231. this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度
  4232. this.IsHScreen=false;
  4233. this.BarCache={ Type:0 }; //Type:1=线段 2=柱子
  4234. this.SetEmptyBar=function() //设置空心柱子
  4235. {
  4236. if (this.BarType!=1 && this.BarType!=-1) return false;
  4237. this.Canvas.lineWidth=1;
  4238. this.Canvas.strokeStyle=this.Color;
  4239. var emptyBGColor=g_JSChartResource.EmptyBarBGColor;
  4240. if (emptyBGColor) this.BarCache.EmptyBGColor=emptyBGColor;
  4241. if (this.BarType==-1) this.BarCache.LineDotted=this.LineDotted; //虚线
  4242. return true;
  4243. }
  4244. this.IsEmptyBar=function()
  4245. {
  4246. return (this.BarType==1 || this.BarType==-1);
  4247. }
  4248. this.Draw = function ()
  4249. {
  4250. if (this.ChartFrame.IsMinSize) return;
  4251. if (this.NotSupportMessage)
  4252. {
  4253. this.DrawNotSupportmessage();
  4254. return;
  4255. }
  4256. if (!this.Data || !this.Data.Data) return;
  4257. this.BarCache={ Color:this.Color, EmptyBGColor:null, Width:1, Type:0, LineDotted:null };
  4258. this.IsHScreen = (this.ChartFrame.IsHScreen === true);
  4259. var dataWidth = this.ChartFrame.DataWidth;
  4260. var distanceWidth = this.ChartFrame.DistanceWidth;
  4261. var chartright = this.ChartBorder.GetRight();
  4262. var xPointCount = this.ChartFrame.XPointCount;
  4263. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
  4264. var isMinute=this.IsMinuteFrame();
  4265. if (this.IsHScreen)
  4266. {
  4267. chartright = this.ChartBorder.GetBottom();
  4268. xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + g_JSChartResource.FrameLeftMargin;
  4269. }
  4270. if (isMinute)
  4271. {
  4272. if (this.Width>1) this.BarCache.Width=2;
  4273. this.BarCache.Type=1;
  4274. }
  4275. else if(this.Width==0)
  4276. {
  4277. this.BarCache.Type=1;
  4278. this.SetEmptyBar();
  4279. }
  4280. else if (this.Width==50 || this.Width==3) //3和50 K线宽度
  4281. {
  4282. this.BarCache.Type=1;
  4283. if (dataWidth >= this.MinBarWidth)
  4284. {
  4285. this.BarCache.Type=2;
  4286. this.BarCache.Width=dataWidth;
  4287. this.SetEmptyBar();
  4288. }
  4289. }
  4290. else if (this.Width==101) //柱子+间距
  4291. {
  4292. var lineWidth=dataWidth+distanceWidth+1;
  4293. this.BarCache.Type=1;
  4294. if (lineWidth >= this.MinBarWidth)
  4295. {
  4296. this.BarCache.Type=2;
  4297. this.BarCache.Width=lineWidth;
  4298. }
  4299. }
  4300. else if (this.Width <=3)
  4301. {
  4302. var minWidth=2;
  4303. var barWidth=dataWidth*(this.Width/3);
  4304. if (barWidth<minWidth) barWidth=minWidth;
  4305. this.BarCache.Type=1;
  4306. if (barWidth >= this.MinBarWidth)
  4307. {
  4308. this.BarCache.Type=2;
  4309. this.BarCache.Width=barWidth;
  4310. this.SetEmptyBar();
  4311. }
  4312. }
  4313. else
  4314. {
  4315. var barWidth=this.Width;
  4316. this.BarCache.Type=2;
  4317. this.BarCache.Width=barWidth;
  4318. this.SetEmptyBar();
  4319. }
  4320. this.Canvas.save();
  4321. this.Canvas.strokeStyle=this.BarCache.Color;
  4322. if (this.BarCache.EmptyBGColor) this.Canvas.fillStyle=this.BarCache.EmptyBGColor; //空心柱子
  4323. else this.Canvas.fillStyle=this.BarCache.Color;
  4324. if (IFrameSplitOperator.IsNonEmptyArray(this.BarCache.LineDotted)) this.Canvas.setLineDash(this.BarCache.LineDotted); //虚线
  4325. if (this.BarCache.Type==1) this.Canvas.lineWidth=this.BarCache.Width;
  4326. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  4327. {
  4328. var value = this.Data.Data[i];
  4329. if (!value) continue;
  4330. if (!IFrameSplitOperator.IsNumber(value.Value)) continue;
  4331. var price = value.Value;
  4332. var price2 =0;
  4333. if (IFrameSplitOperator.IsNumber(value.Value2)) price2=value.Value2;
  4334. if (isMinute)
  4335. {
  4336. var x=this.ChartFrame.GetXFromIndex(j);
  4337. }
  4338. else
  4339. {
  4340. var left=xOffset;
  4341. var right=xOffset+dataWidth;
  4342. var x=left+(right-left)/2;
  4343. }
  4344. var y = this.ChartFrame.GetYFromData(price);
  4345. var y2 = this.ChartFrame.GetYFromData(price2);
  4346. if (x > chartright) break;
  4347. var xCenter=x;
  4348. var yTop=Math.min(y,y2);
  4349. var barHeight=Math.abs(y-y2); //柱子高度
  4350. this.DrawBar(xCenter, yTop, barHeight);
  4351. }
  4352. this.Canvas.restore();
  4353. }
  4354. this.DrawBar=function(xCenter, ytop, barHeight)
  4355. {
  4356. if (barHeight<1) barHeight=1;
  4357. if (this.BarCache.Type==1) //线段
  4358. {
  4359. if (this.IsHScreen)
  4360. {
  4361. this.Canvas.beginPath();
  4362. this.Canvas.moveTo(ytop,ToFixedPoint(xCenter));
  4363. this.Canvas.lineTo(ytop+barHeight,ToFixedPoint(xCenter));
  4364. this.Canvas.stroke();
  4365. }
  4366. else
  4367. {
  4368. this.Canvas.beginPath();
  4369. this.Canvas.moveTo(ToFixedPoint(xCenter),ytop);
  4370. this.Canvas.lineTo(ToFixedPoint(xCenter),ytop+barHeight);
  4371. this.Canvas.stroke();
  4372. }
  4373. }
  4374. else if (this.BarCache.Type==2) //柱子
  4375. {
  4376. if (this.IsHScreen)
  4377. {
  4378. var xLeft=xCenter-this.BarCache.Width/2;
  4379. if (this.IsEmptyBar()) //空心
  4380. {
  4381. if (this.BarCache.EmptyBGColor) //背景色填充
  4382. this.Canvas.fillRect(ToFixedRect(ytop),ToFixedRect(xLeft),ToFixedRect(barHeight),ToFixedRect(this.BarCache.Width));
  4383. this.Canvas.beginPath();
  4384. this.Canvas.rect(ToFixedPoint(ytop),ToFixedPoint(xLeft),ToFixedRect(barHeight),ToFixedRect(this.BarCache.Width));
  4385. this.Canvas.stroke();
  4386. }
  4387. else
  4388. {
  4389. this.Canvas.fillRect(ToFixedRect(ytop),ToFixedRect(xLeft),ToFixedRect(barHeight),ToFixedRect(this.BarCache.Width));
  4390. }
  4391. }
  4392. else
  4393. {
  4394. var xLeft=xCenter-this.BarCache.Width/2;
  4395. if (this.IsEmptyBar()) //空心
  4396. {
  4397. if (this.BarCache.EmptyBGColor) //背景色填充
  4398. this.Canvas.fillRect(ToFixedRect(xLeft),ToFixedRect(ytop),ToFixedRect(this.BarCache.Width),ToFixedRect(barHeight));
  4399. this.Canvas.beginPath();
  4400. this.Canvas.rect(ToFixedPoint(xLeft),ToFixedPoint(ytop),ToFixedRect(this.BarCache.Width),ToFixedRect(barHeight));
  4401. this.Canvas.stroke();
  4402. }
  4403. else
  4404. {
  4405. this.Canvas.fillRect(ToFixedRect(xLeft),ToFixedRect(ytop),ToFixedRect(this.BarCache.Width),ToFixedRect(barHeight));
  4406. }
  4407. }
  4408. }
  4409. }
  4410. this.GetMaxMin = function ()
  4411. {
  4412. var xPointCount = this.ChartFrame.XPointCount;
  4413. var range = {};
  4414. range.Min = null;
  4415. range.Max = null;
  4416. if (!this.Data || !this.Data.Data) return range;
  4417. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  4418. {
  4419. var data = this.Data.Data[i];
  4420. if (data == null) continue;
  4421. var value2 = data.Value2;
  4422. if (value2 == null) value2 = 0;
  4423. if (data == null || isNaN(data.Value) || isNaN(value2)) continue;
  4424. var valueMax = Math.max(data.Value, value2);
  4425. var valueMin = Math.min(data.Value, value2);
  4426. if (range.Max == null) range.Max = valueMax;
  4427. if (range.Min == null) range.Min = valueMin;
  4428. if (range.Max < valueMax) range.Max = valueMax;
  4429. if (range.Min > valueMin) range.Min = valueMin;
  4430. }
  4431. return range;
  4432. }
  4433. }
  4434. //画矩形
  4435. function ChartRectangle()
  4436. {
  4437. this.newMethod = IChartPainting; //派生
  4438. this.newMethod();
  4439. delete this.newMethod;
  4440. this.ClassName ='ChartRectangle';
  4441. this.Color = [];
  4442. this.Rect;
  4443. this.BorderColor = g_JSChartResource.FrameBorderPen;
  4444. this.Draw = function ()
  4445. {
  4446. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  4447. if (!this.Color || !this.Rect) return;
  4448. if (this.Color.length <= 0) return;
  4449. this.Canvas.strokeStyle = this.BorderColor;
  4450. var bFill = false;
  4451. if (this.Color.length == 2)
  4452. {
  4453. /* TODO 渐变下次做吧
  4454. if (this.ColorAngle==0)
  4455. {
  4456. var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
  4457. var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() };
  4458. }
  4459. else
  4460. {
  4461. var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
  4462. var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() };
  4463. }
  4464. let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y);
  4465. gradient.addColorStop(0, this.Color[0]);
  4466. gradient.addColorStop(1, this.Color[1]);
  4467. this.Canvas.fillStyle=gradient;
  4468. */
  4469. this.Canvas.fillStyle = this.Color[0];
  4470. bFill = true;
  4471. }
  4472. else if (this.Color.length == 1)
  4473. {
  4474. if (this.Color[0])
  4475. {
  4476. this.Canvas.fillStyle = this.Color[0];
  4477. bFill = true;
  4478. }
  4479. }
  4480. else
  4481. {
  4482. return;
  4483. }
  4484. var chartWidth = this.ChartBorder.GetWidth();
  4485. var chartHeight = this.ChartBorder.GetHeightEx();
  4486. var left = this.Rect.Left / 1000 * chartWidth;
  4487. var top = this.Rect.Top / 1000 * chartHeight;
  4488. var right = this.Rect.Right / 1000 * chartWidth;
  4489. var bottom = this.Rect.Bottom / 1000 * chartHeight;
  4490. left = this.ChartBorder.GetLeft() + left
  4491. top = this.ChartBorder.GetTopEx() + top;
  4492. right = this.ChartBorder.GetLeft() + right;
  4493. bottom = this.ChartBorder.GetTopEx() + bottom;
  4494. var width = Math.abs(left - right);
  4495. var height = Math.abs(top - bottom);
  4496. if (bFill) this.Canvas.fillRect(left, top, width, height);
  4497. this.Canvas.beginPath();
  4498. this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(top), ToFixedRect(width), ToFixedRect(height));
  4499. this.Canvas.stroke();
  4500. }
  4501. }
  4502. //K线叠加
  4503. function ChartOverlayKLine()
  4504. {
  4505. this.newMethod = IChartPainting; //派生
  4506. this.newMethod();
  4507. delete this.newMethod;
  4508. this.Color = "rgb(65,105,225)";
  4509. this.MainData; //主图K线数据
  4510. this.SourceData; //叠加的原始数据
  4511. this.Name = "ChartOverlayKLine";
  4512. this.Title;
  4513. this.DrawType = 0;
  4514. this.ClassName ='ChartOverlayKLine';
  4515. this.CustomDrawType = null; //图形类型
  4516. this.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID;
  4517. this.ShowRange={ }; //K线显示范围 { Start:, End:, DataCount:, ShowCount: }
  4518. this.DrawKRange={ Start:null, End:null }; //当前屏K线的索引{ Start: , End:}
  4519. this.YInfoType=4;
  4520. this.SetOption = function (option)
  4521. {
  4522. if (!option) return;
  4523. if (IFrameSplitOperator.IsNumber(option.DrawType)) this.CustomDrawType = option.DrawType;
  4524. if (IFrameSplitOperator.IsNumber(option.YInfoType)) this.YInfoType=option.YInfoType;
  4525. }
  4526. this.DrawKBar = function (firstOpen) //firstOpen 当前屏第1个显示数据
  4527. {
  4528. var isHScreen = (this.ChartFrame.IsHScreen === true);
  4529. var dataWidth = this.ChartFrame.DataWidth;
  4530. var distanceWidth = this.ChartFrame.DistanceWidth;
  4531. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  4532. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  4533. var chartright = this.ChartBorder.GetRight();
  4534. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  4535. var xPointCount = this.ChartFrame.XPointCount;
  4536. var isFristDraw = true;
  4537. var firstOverlayOpen = null;
  4538. this.ShowRange.Start=this.Data.DataOffset;
  4539. this.ShowRange.End=this.ShowRange.Start;
  4540. this.ShowRange.DataCount=0;
  4541. this.ShowRange.ShowCount=xPointCount;
  4542. this.ShowRange.FirstOpen=firstOpen;
  4543. this.DrawKRange.Start=this.Data.DataOffset;
  4544. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount)
  4545. {
  4546. var data = this.Data.Data[i];
  4547. if (!data || data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  4548. if (firstOverlayOpen == null)
  4549. {
  4550. firstOverlayOpen = data.Open;
  4551. this.ShowRange.FirstOverlayOpen=data.Open;
  4552. }
  4553. if (isFristDraw)
  4554. {
  4555. this.Canvas.strokeStyle = this.Color;
  4556. this.Canvas.fillStyle = this.Color;
  4557. this.Canvas.beginPath();
  4558. isFristDraw = false;
  4559. }
  4560. var left = xOffset;
  4561. var right = xOffset + dataWidth;
  4562. if (right > chartright) break;
  4563. var x = left + (right - left) / 2;
  4564. var yLow = this.ChartFrame.GetYFromData(data.Low / firstOverlayOpen * firstOpen);
  4565. var yHigh = this.ChartFrame.GetYFromData(data.High / firstOverlayOpen * firstOpen);
  4566. var yOpen = this.ChartFrame.GetYFromData(data.Open / firstOverlayOpen * firstOpen);
  4567. var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen);
  4568. var y = yHigh;
  4569. this.DrawKRange.End=i;
  4570. if (data.Open < data.Close) //阳线
  4571. {
  4572. if (dataWidth >= 4)
  4573. {
  4574. if (data.High > data.Close) //上影线
  4575. {
  4576. if (isHScreen)
  4577. {
  4578. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  4579. this.Canvas.lineTo(ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : yClose), ToFixedPoint(x));
  4580. }
  4581. else
  4582. {
  4583. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  4584. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : yClose));
  4585. }
  4586. y = yClose;
  4587. }
  4588. else
  4589. {
  4590. y = yClose;
  4591. }
  4592. if (isHScreen) {
  4593. if (Math.abs(yOpen - y) < 1)
  4594. {
  4595. this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  4596. }
  4597. else
  4598. {
  4599. if (this.DrawType == 3) this.Canvas.rect(ToFixedPoint(y), ToFixedPoint(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth)); //空心柱
  4600. else this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yOpen - y), ToFixedRect(dataWidth));
  4601. }
  4602. }
  4603. else
  4604. {
  4605. if (Math.abs(yOpen - y) < 1)
  4606. {
  4607. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
  4608. }
  4609. else
  4610. {
  4611. if (this.DrawType == 3) this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y)); //空心柱
  4612. else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yOpen - y));
  4613. }
  4614. }
  4615. if (data.Open > data.Low)
  4616. {
  4617. if (isHScreen)
  4618. {
  4619. this.Canvas.moveTo(ToFixedPoint(this.DrawType == 3 ? Math.min(yClose, yOpen) : y), ToFixedPoint(x));
  4620. this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
  4621. }
  4622. else
  4623. {
  4624. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(this.DrawType == 3 ? Math.max(yClose, yOpen) : y));
  4625. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
  4626. }
  4627. }
  4628. }
  4629. else
  4630. {
  4631. if (isHScreen)
  4632. {
  4633. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  4634. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  4635. }
  4636. else
  4637. {
  4638. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  4639. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  4640. }
  4641. }
  4642. }
  4643. else if (data.Open > data.Close) //阴线
  4644. {
  4645. if (dataWidth >= 4)
  4646. {
  4647. if (data.High > data.Close) //上影线
  4648. {
  4649. if (isHScreen)
  4650. {
  4651. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  4652. this.Canvas.lineTo(ToFixedPoint(yOpen), ToFixedPoint(x));
  4653. }
  4654. else
  4655. {
  4656. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  4657. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yOpen));
  4658. }
  4659. y = yOpen;
  4660. }
  4661. else
  4662. {
  4663. y = yOpen
  4664. }
  4665. if (isHScreen)
  4666. {
  4667. if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), 1, ToFixedRect(dataWidth)); //高度小于1,统一使用高度1
  4668. else this.Canvas.fillRect(ToFixedRect(y), ToFixedRect(left), ToFixedRect(yClose - y), ToFixedRect(dataWidth));
  4669. }
  4670. else
  4671. {
  4672. if (Math.abs(yClose - y) < 1) this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), 1); //高度小于1,统一使用高度1
  4673. else this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(y), ToFixedRect(dataWidth), ToFixedRect(yClose - y));
  4674. }
  4675. if (data.Open > data.Low) //下影线
  4676. {
  4677. if (isHScreen)
  4678. {
  4679. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  4680. this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
  4681. }
  4682. else
  4683. {
  4684. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  4685. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
  4686. }
  4687. }
  4688. }
  4689. else
  4690. {
  4691. if (isHScreen)
  4692. {
  4693. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  4694. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  4695. }
  4696. else
  4697. {
  4698. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  4699. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  4700. }
  4701. }
  4702. }
  4703. else // 平线
  4704. {
  4705. if (dataWidth >= 4)
  4706. {
  4707. if (data.High > data.Close) //上影线
  4708. {
  4709. if (isHScreen)
  4710. {
  4711. this.Canvas.moveTo(y, ToFixedPoint(x));
  4712. this.Canvas.lineTo(yOpen, ToFixedPoint(x));
  4713. }
  4714. else
  4715. {
  4716. this.Canvas.moveTo(ToFixedPoint(x), y);
  4717. this.Canvas.lineTo(ToFixedPoint(x), yOpen);
  4718. }
  4719. y = yOpen;
  4720. }
  4721. else
  4722. {
  4723. y = yOpen;
  4724. }
  4725. if (isHScreen)
  4726. {
  4727. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(left));
  4728. this.Canvas.lineTo(ToFixedPoint(y), ToFixedPoint(right));
  4729. }
  4730. else
  4731. {
  4732. this.Canvas.moveTo(ToFixedPoint(left), ToFixedPoint(y));
  4733. this.Canvas.lineTo(ToFixedPoint(right), ToFixedPoint(y));
  4734. }
  4735. if (data.Open > data.Low) //下影线
  4736. {
  4737. if (isHScreen)
  4738. {
  4739. this.Canvas.moveTo(ToFixedPoint(y), ToFixedPoint(x));
  4740. this.Canvas.lineTo(ToFixedPoint(yLow), ToFixedPoint(x));
  4741. }
  4742. else
  4743. {
  4744. this.Canvas.moveTo(ToFixedPoint(x), ToFixedPoint(y));
  4745. this.Canvas.lineTo(ToFixedPoint(x), ToFixedPoint(yLow));
  4746. }
  4747. }
  4748. }
  4749. else
  4750. {
  4751. if (isHScreen)
  4752. {
  4753. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  4754. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  4755. }
  4756. else
  4757. {
  4758. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  4759. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  4760. }
  4761. }
  4762. }
  4763. }
  4764. if (isFristDraw == false) this.Canvas.stroke();
  4765. }
  4766. this.DrawAKLine = function (firstOpen) //美国线
  4767. {
  4768. var isHScreen = (this.ChartFrame.IsHScreen === true);
  4769. var dataWidth = this.ChartFrame.DataWidth;
  4770. var distanceWidth = this.ChartFrame.DistanceWidth;
  4771. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  4772. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  4773. var chartright = this.ChartBorder.GetRight();
  4774. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  4775. var xPointCount = this.ChartFrame.XPointCount;
  4776. var firstOverlayOpen = null;
  4777. this.Canvas.strokeStyle = this.Color;
  4778. this.ShowRange.Start=this.Data.DataOffset;
  4779. this.ShowRange.End=this.ShowRange.Start;
  4780. this.ShowRange.DataCount=0;
  4781. this.ShowRange.ShowCount=xPointCount;
  4782. this.ShowRange.FirstOpen=firstOpen;
  4783. this.DrawKRange.Start=this.Data.DataOffset;
  4784. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount)
  4785. {
  4786. var data = this.Data.Data[i];
  4787. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  4788. if (firstOverlayOpen == null)
  4789. {
  4790. firstOverlayOpen = data.Open;
  4791. this.ShowRange.FirstOverlayOpen=data.Open;
  4792. }
  4793. var left = xOffset;
  4794. var right = xOffset + dataWidth;
  4795. if (right > chartright) break;
  4796. var x = left + (right - left) / 2;
  4797. var yLow = this.ChartFrame.GetYFromData(data.Low / firstOverlayOpen * firstOpen);
  4798. var yHigh = this.ChartFrame.GetYFromData(data.High / firstOverlayOpen * firstOpen);
  4799. var yOpen = this.ChartFrame.GetYFromData(data.Open / firstOverlayOpen * firstOpen);
  4800. var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen);
  4801. this.DrawKRange.End=i;
  4802. this.Canvas.beginPath(); //最高-最低
  4803. if (isHScreen)
  4804. {
  4805. this.Canvas.moveTo(yHigh, ToFixedPoint(x));
  4806. this.Canvas.lineTo(yLow, ToFixedPoint(x));
  4807. }
  4808. else
  4809. {
  4810. this.Canvas.moveTo(ToFixedPoint(x), yHigh);
  4811. this.Canvas.lineTo(ToFixedPoint(x), yLow);
  4812. }
  4813. this.Canvas.stroke();
  4814. if (dataWidth >= 4)
  4815. {
  4816. this.Canvas.beginPath(); //开盘
  4817. if (isHScreen)
  4818. {
  4819. this.Canvas.moveTo(ToFixedPoint(yOpen), left);
  4820. this.Canvas.lineTo(ToFixedPoint(yOpen), x);
  4821. }
  4822. else
  4823. {
  4824. this.Canvas.moveTo(left, ToFixedPoint(yOpen));
  4825. this.Canvas.lineTo(x, ToFixedPoint(yOpen));
  4826. }
  4827. this.Canvas.stroke();
  4828. this.Canvas.beginPath(); //收盘
  4829. if (isHScreen)
  4830. {
  4831. this.Canvas.moveTo(ToFixedPoint(yClose), right);
  4832. this.Canvas.lineTo(ToFixedPoint(yClose), x);
  4833. }
  4834. else
  4835. {
  4836. this.Canvas.moveTo(right, ToFixedPoint(yClose));
  4837. this.Canvas.lineTo(x, ToFixedPoint(yClose));
  4838. }
  4839. this.Canvas.stroke();
  4840. }
  4841. }
  4842. }
  4843. this.DrawCloseLine = function (firstOpen) //收盘价线
  4844. {
  4845. var isHScreen = (this.ChartFrame.IsHScreen === true);
  4846. var dataWidth = this.ChartFrame.DataWidth;
  4847. var distanceWidth = this.ChartFrame.DistanceWidth;
  4848. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  4849. if (isHScreen) xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  4850. var chartright = this.ChartBorder.GetRight();
  4851. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  4852. var xPointCount = this.ChartFrame.XPointCount;
  4853. var firstOverlayOpen = null;
  4854. var bFirstPoint = true;
  4855. this.ShowRange.Start=this.Data.DataOffset;
  4856. this.ShowRange.End=this.ShowRange.Start;
  4857. this.ShowRange.DataCount=0;
  4858. this.ShowRange.ShowCount=xPointCount;
  4859. this.ShowRange.FirstOpen=firstOpen;
  4860. this.DrawKRange.Start=this.Data.DataOffset;
  4861. this.Canvas.strokeStyle = this.Color;
  4862. this.Canvas.beginPath();
  4863. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth),++this.ShowRange.DataCount)
  4864. {
  4865. var data = this.Data.Data[i];
  4866. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  4867. if (firstOverlayOpen == null)
  4868. {
  4869. firstOverlayOpen = data.Open;
  4870. this.ShowRange.FirstOverlayOpen=data.Open;
  4871. }
  4872. var left = xOffset;
  4873. var right = xOffset + dataWidth;
  4874. if (right > chartright) break;
  4875. var x = left + (right - left) / 2;
  4876. var yClose = this.ChartFrame.GetYFromData(data.Close / firstOverlayOpen * firstOpen);
  4877. this.DrawKRange.End=i;
  4878. if (bFirstPoint)
  4879. {
  4880. if (isHScreen) this.Canvas.moveTo(yClose, x);
  4881. else this.Canvas.moveTo(x, yClose);
  4882. bFirstPoint = false;
  4883. }
  4884. else
  4885. {
  4886. if (isHScreen) this.Canvas.lineTo(yClose, x);
  4887. else this.Canvas.lineTo(x, yClose);
  4888. }
  4889. }
  4890. if (bFirstPoint == false) this.Canvas.stroke();
  4891. }
  4892. this.GetFirstOpen=function()
  4893. {
  4894. var xPointCount = this.ChartFrame.XPointCount;
  4895. var firstOpen = null; //主线数据第1个开盘价
  4896. for (var i = this.Data.DataOffset, j = 0; i < this.MainData.Data.length && j < xPointCount; ++i, ++j)
  4897. {
  4898. var data = this.MainData.Data[i];
  4899. if (data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  4900. firstOpen = data.Open;
  4901. break;
  4902. }
  4903. return firstOpen;
  4904. }
  4905. this.Draw = function ()
  4906. {
  4907. this.TooltipRect = [];
  4908. this.DrawKRange={ Start:null, End:null };
  4909. if (!this.MainData || !this.Data) return;
  4910. var firstOpen = this.GetFirstOpen(); //主线数据第1个开盘价
  4911. if (firstOpen == null) return;
  4912. var drawTypeBackup = this.DrawType; //备份下线段类型
  4913. if (this.CustomDrawType != null) this.DrawType = this.CustomDrawType;
  4914. if (this.DrawType == 1) this.DrawCloseLine(firstOpen);
  4915. else if (this.DrawType == 2) this.DrawAKLine(firstOpen);
  4916. else this.DrawKBar(firstOpen);
  4917. this.DrawType = drawTypeBackup; //还原线段类型
  4918. }
  4919. this.GetMaxMin = function ()
  4920. {
  4921. var xPointCount = this.ChartFrame.XPointCount;
  4922. var range = {};
  4923. range.Max = null;
  4924. range.Min = null;
  4925. if (!this.MainData || !this.Data) return range;
  4926. var firstOpen = this.GetFirstOpen(); //主线数据第1个收盘价
  4927. if (firstOpen == null) return range;
  4928. var firstOverlayOpen = null;
  4929. var high, low;
  4930. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  4931. {
  4932. var data = this.Data.Data[i];
  4933. if (!data || data.Open == null || data.High == null || data.Low == null || data.Close == null) continue;
  4934. if (firstOverlayOpen == null) firstOverlayOpen = data.Open;
  4935. high = data.High / firstOverlayOpen * firstOpen;
  4936. low = data.Low / firstOverlayOpen * firstOpen;
  4937. if (range.Max == null) range.Max = high;
  4938. if (range.Min == null) range.Min = low;
  4939. if (range.Max < high) range.Max = high;
  4940. if (range.Min > low) range.Min = low;
  4941. }
  4942. return range;
  4943. }
  4944. }
  4945. // 多文本集合2.0 支持横屏
  4946. function ChartMultiText()
  4947. {
  4948. this.newMethod = IChartPainting; //派生
  4949. this.newMethod();
  4950. delete this.newMethod;
  4951. this.ClassName ='ChartMultiText';
  4952. this.Texts = []; //[ {Date, Time:, Value:, Text:, Color:, Font: , Baseline:, Line:{ Color:, Dash:[虚线点], KData:"H/L", Offset:[5,10], Width:线粗细 } } ]
  4953. this.Font = g_JSChartResource.DefaultTextFont;
  4954. this.Color = g_JSChartResource.DefaultTextColor;
  4955. this.IsHScreen = false; //是否横屏
  4956. this.MapCache=null; //key=date/date-time value={ Data:[] }
  4957. this.GetKValue=ChartData.GetKValue;
  4958. this.BuildCacheData=function()
  4959. {
  4960. var mapData=new Map();
  4961. this.MapCache=mapData;
  4962. if (!IFrameSplitOperator.IsNonEmptyArray(this.Texts)) return;
  4963. for(var i=0;i<this.Texts.length;++i)
  4964. {
  4965. var item=this.Texts[i];
  4966. var key=this.BuildKey(item);
  4967. if (mapData.has(key))
  4968. {
  4969. var mapItem=mapData.get(key);
  4970. mapItem.Data.push(item);
  4971. }
  4972. else
  4973. {
  4974. mapData.set(key,{ Data:[item] });
  4975. }
  4976. }
  4977. }
  4978. this.Draw = function ()
  4979. {
  4980. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  4981. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; //k线数据
  4982. if (!IFrameSplitOperator.IsNonEmptyArray(this.Texts)) return;
  4983. if (!this.MapCache || this.MapCache.size<=0) return;
  4984. this.IsHScreen = (this.ChartFrame.IsHScreen === true);
  4985. this.Canvas.save();
  4986. this.ClipClient(this.IsHScreen);
  4987. this.DrawAllText();
  4988. this.Canvas.restore();
  4989. }
  4990. this.DrawAllText=function()
  4991. {
  4992. var bHScreen=(this.ChartFrame.IsHScreen===true);
  4993. var isMinute=this.IsMinuteFrame();
  4994. var dataWidth=this.ChartFrame.DataWidth;
  4995. var distanceWidth=this.ChartFrame.DistanceWidth;
  4996. var xPointCount=this.ChartFrame.XPointCount;
  4997. if (bHScreen)
  4998. {
  4999. var border=this.ChartBorder.GetHScreenBorder();
  5000. var chartright=border.BottomEx;
  5001. var chartleft=border.TopEx;
  5002. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  5003. var left=this.ChartBorder.GetTop();
  5004. var right=this.ChartBorder.GetBottom();
  5005. var top=border.RightEx;
  5006. var bottom=border.LeftEx;
  5007. }
  5008. else
  5009. {
  5010. var border=this.ChartBorder.GetBorder();
  5011. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  5012. var chartright=border.RightEx;
  5013. var chartleft=border.LeftEx;
  5014. var left=this.ChartBorder.GetLeft();
  5015. var right=this.ChartBorder.GetRight();
  5016. var top=border.TopEx;
  5017. var bottom=border.BottomEx;
  5018. }
  5019. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  5020. {
  5021. var kItem=this.Data.Data[i];
  5022. if (!kItem) continue;
  5023. var key=this.BuildKey(kItem);
  5024. if (!this.MapCache.has(key)) continue;
  5025. var mapItem=this.MapCache.get(key);
  5026. if (!IFrameSplitOperator.IsNonEmptyArray(mapItem.Data)) continue;
  5027. if (isMinute)
  5028. {
  5029. var x=this.ChartFrame.GetXFromIndex(j);
  5030. }
  5031. else
  5032. {
  5033. var left=xOffset;
  5034. var right=xOffset+dataWidth;
  5035. if (right>chartright) break;
  5036. var x=left+(right-left)/2;
  5037. }
  5038. for(var k=0;k<mapItem.Data.length;++k)
  5039. {
  5040. var item=mapItem.Data[k];
  5041. var y=top;
  5042. if (item.Value=="TOP") y=top;
  5043. else if (item.Value=="BOTTOM") y=bottom;
  5044. else
  5045. {
  5046. var price=item.Value;
  5047. if (IFrameSplitOperator.IsString(item.Value)) price=this.GetKValue(kItem,item.Value);
  5048. y=this.ChartFrame.GetYFromData(price, false);
  5049. }
  5050. if (item.Color) this.Canvas.fillStyle = item.Color;
  5051. else this.Canvas.fillStyle = this.Color;
  5052. if (item.Font) this.Canvas.font = item.Font;
  5053. else this.Canvas.font=this.Font;
  5054. var textWidth=this.Canvas.measureText(item.Text).width;
  5055. this.Canvas.textAlign='center';
  5056. if (x+textWidth/2>=chartright)
  5057. {
  5058. this.Canvas.textAlign='right';
  5059. x=chartright;
  5060. }
  5061. else if (x-textWidth/2<chartleft)
  5062. {
  5063. this.Canvas.textAlign = 'left';
  5064. x=chartleft;
  5065. }
  5066. if (item.Baseline==1) this.Canvas.textBaseline='top';
  5067. else if (item.Baseline==2) this.Canvas.textBaseline='bottom';
  5068. else this.Canvas.textBaseline = 'middle';
  5069. if (this.IsHScreen)
  5070. {
  5071. this.Canvas.save();
  5072. this.Canvas.translate(y, x);
  5073. this.Canvas.rotate(90 * Math.PI / 180);
  5074. this.Canvas.fillText(item.Text,0,0);
  5075. this.Canvas.restore();
  5076. }
  5077. else
  5078. {
  5079. if (IFrameSplitOperator.IsNumber(item.YMove)) y+=item.YMove;
  5080. this.Canvas.fillText(item.Text, x, y);
  5081. }
  5082. if (item.Line)
  5083. {
  5084. var price=item.Line.KData=="H"? kItem.High:kItem.Low;
  5085. var yPrice=this.ChartFrame.GetYFromData(price, false);
  5086. var yText=y;
  5087. if (Array.isArray(item.Line.Offset) && item.Line.Offset.length==2)
  5088. {
  5089. if (yText>yPrice) //文字在下方
  5090. {
  5091. yText-=item.Line.Offset[1];
  5092. yPrice+=item.Line.Offset[0]
  5093. }
  5094. else if (yText<yPrice)
  5095. {
  5096. yText+=item.Line.Offset[1];
  5097. yPrice-=item.Line.Offset[0]
  5098. }
  5099. }
  5100. this.Canvas.save();
  5101. if (item.Line.Dash) this.Canvas.setLineDash(item.Line.Dash); //虚线
  5102. if (item.Line.Width>0) this.Canvas.lineWidth=item.Line.Width; //线宽
  5103. this.Canvas.strokeStyle = item.Line.Color;
  5104. this.Canvas.beginPath();
  5105. if (this.IsHScreen)
  5106. {
  5107. this.Canvas.moveTo(yText, ToFixedPoint(x));
  5108. this.Canvas.lineTo(yPrice,ToFixedPoint(x));
  5109. }
  5110. else
  5111. {
  5112. this.Canvas.moveTo(ToFixedPoint(x),yText);
  5113. this.Canvas.lineTo(ToFixedPoint(x),yPrice);
  5114. }
  5115. this.Canvas.stroke();
  5116. this.Canvas.restore();
  5117. }
  5118. }
  5119. }
  5120. }
  5121. this.GetMaxMin = function ()
  5122. {
  5123. var range = { Min: null, Max: null };
  5124. if (!this.Texts) return range;
  5125. var xPointCount = this.ChartFrame.XPointCount;
  5126. var start = this.Data.DataOffset;
  5127. var end = start + xPointCount;
  5128. for (var i in this.Texts)
  5129. {
  5130. var item = this.Texts[i];
  5131. if (item.Index >= start && item.Index < end)
  5132. {
  5133. if (range.Max == null) range.Max = item.Value;
  5134. else if (range.Max < item.Value) range.Max = item.Value;
  5135. if (range.Min == null) range.Min = item.Value;
  5136. else if (range.Min > item.Value) range.Min = item.Value;
  5137. }
  5138. }
  5139. return range;
  5140. }
  5141. }
  5142. // 多dom节点
  5143. function ChartMultiHtmlDom()
  5144. {
  5145. this.newMethod=IChartPainting; //派生
  5146. this.newMethod();
  5147. delete this.newMethod;
  5148. this.ClassName="ChartMultiHtmlDom";
  5149. this.Texts=[]; //[ {Index:, Value:, Text: ] Text=dom内容
  5150. this.IsHScreen=false; //是否横屏
  5151. this.DrawCallback; //function(op, obj) op:1=开始 2=结束 3=绘制单个数据 4=销毁
  5152. this.DrawItem=[];
  5153. this.IsDestroy=false; //是否已销毁
  5154. this.Draw=function()
  5155. {
  5156. this.DrawItem=[];
  5157. if (this.DrawCallback) this.DrawCallback(1, {Self:this} );
  5158. this.DrawDom();
  5159. if (this.DrawCallback) this.DrawCallback(2, { Self:this, Draw:this.DrawItem } );
  5160. }
  5161. this.OnDestroy=function()
  5162. {
  5163. this.IsDestroy=true;
  5164. if (this.DrawCallback) this.DrawCallback(4, { Self:this } );
  5165. }
  5166. this.DrawDom=function()
  5167. {
  5168. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  5169. if (!this.Data || this.Data.length<=0) return;
  5170. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  5171. var xPointCount=this.ChartFrame.XPointCount;
  5172. var offset=this.Data.DataOffset;
  5173. for(var i in this.Texts)
  5174. {
  5175. var item=this.Texts[i];
  5176. if (!item.Text) continue;
  5177. if (!IFrameSplitOperator.IsNumber(item.Index)) continue;
  5178. var index=item.Index-offset;
  5179. var kItem=this.Data.Data[item.Index]; //K线数据
  5180. var obj={ KData:kItem, Item:item, IsShow:false, Self:this };
  5181. if (index>=0 && index<xPointCount)
  5182. {
  5183. var x=this.ChartFrame.GetXFromIndex(index);
  5184. var y=this.ChartFrame.GetYFromData(item.Value);
  5185. obj.X=x;
  5186. obj.Y=y;
  5187. obj.IsShow=true;
  5188. }
  5189. this.DrawItem.push(obj);
  5190. if (this.DrawCallback) this.DrawCallback(3, obj);
  5191. }
  5192. }
  5193. this.GetMaxMin=function()
  5194. {
  5195. var range={ Min:null, Max:null };
  5196. var xPointCount=this.ChartFrame.XPointCount;
  5197. var start=this.Data.DataOffset;
  5198. var end=start+xPointCount;
  5199. for(var i in this.Texts)
  5200. {
  5201. var item=this.Texts[i];
  5202. if (!IFrameSplitOperator.IsNumber(item.Index)) continue;
  5203. if (item.Index>=start && item.Index<end)
  5204. {
  5205. if (range.Max==null) range.Max=item.Value;
  5206. else if (range.Max<item.Value) range.Max=item.Value;
  5207. if (range.Min==null) range.Min=item.Value;
  5208. else if (range.Min>item.Value) range.Min=item.Value;
  5209. }
  5210. }
  5211. return range;
  5212. }
  5213. }
  5214. // 线段集合 支持横屏
  5215. function ChartMultiLine()
  5216. {
  5217. this.newMethod = IChartPainting; //派生
  5218. this.newMethod();
  5219. delete this.newMethod;
  5220. this.ClassName="ChartMultiLine";
  5221. this.Lines = []; // [ {Point:[ {Index, Value }, ], Color: }, ]
  5222. this.IsHScreen = false;
  5223. this.LineWidth=1;
  5224. this.LineDash;
  5225. //箭头配置
  5226. this.ArrawAngle=35; //三角斜边一直线夹角
  5227. this.ArrawLength=10; //三角斜边长度
  5228. this.ArrawLineWidth=5; //箭头粗细
  5229. this.Arrow={ Start:false, End:false }; //Start=是否绘制开始箭头 <- End=是否绘制结束箭头 ->
  5230. this.Draw = function ()
  5231. {
  5232. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  5233. if (!this.Data || this.Data.length <= 0) return;
  5234. this.IsHScreen = (this.ChartFrame.IsHScreen === true);
  5235. var xPointCount = this.ChartFrame.XPointCount;
  5236. var offset = this.Data.DataOffset;
  5237. var drawLines = [];
  5238. var arrowLines=[];
  5239. for (var i=0; i<this.Lines.length; ++i)
  5240. {
  5241. var line = this.Lines[i];
  5242. var drawPoints = { Point: [], Color: line.Color };
  5243. var drawArrowPoints={ Start:[], End:[] };
  5244. if (line.BGColor) drawPoints.BGColor=line.BGColor;
  5245. for (var j=0;j<line.Point.length; ++j)
  5246. {
  5247. var point = line.Point[j];
  5248. if (!IFrameSplitOperator.IsNumber(point.Index)) continue;
  5249. var index = point.Index - offset;
  5250. if (index >= 0 && index < xPointCount)
  5251. {
  5252. var x = this.ChartFrame.GetXFromIndex(index);
  5253. var y = this.ChartFrame.GetYFromData(point.Value);
  5254. var pointItem={X:x, Y:y, End:false };
  5255. drawPoints.Point.push({ X: x, Y: y });
  5256. if (j==0 || j==1) drawArrowPoints.Start.push(pointItem); //起始点
  5257. if (j==line.Point.length-1 || j==line.Point.length-2) drawArrowPoints.End.push(pointItem); //结束点
  5258. }
  5259. else
  5260. {
  5261. if (drawPoints.Point.length>0) drawPoints.Point[drawPoints.Point.length-1].End=true; //点断开
  5262. }
  5263. }
  5264. if (drawPoints.Point.length >= 2)
  5265. {
  5266. drawLines.push(drawPoints);
  5267. arrowLines.push(drawArrowPoints);
  5268. }
  5269. }
  5270. this.Canvas.save();
  5271. for (var i=0; i<drawLines.length; ++i)
  5272. {
  5273. if (this.LineDash) this.Canvas.setLineDash(this.LineDash);
  5274. if (IFrameSplitOperator.IsPlusNumber(this.LineWidth)) this.Canvas.lineWidth=this.LineWidth;
  5275. else this.Canvas.lineWidth=1;
  5276. var item = drawLines[i];
  5277. this.DrawLine(item, arrowLines[i]);
  5278. }
  5279. this.Canvas.restore();
  5280. }
  5281. this.DrawLine = function (line, arrow)
  5282. {
  5283. if (line.BGColor) //背景色
  5284. {
  5285. this.Canvas.fillStyle=line.BGColor;
  5286. for(var i=0; i<line.Point.length; ++i)
  5287. {
  5288. var item=line.Point[i];
  5289. if (i==0)
  5290. {
  5291. this.Canvas.beginPath();
  5292. if (this.IsHScreen) this.Canvas.moveTo(item.Y,item.X);
  5293. else this.Canvas.moveTo(item.X,item.Y);
  5294. }
  5295. else
  5296. {
  5297. if (this.IsHScreen) this.Canvas.lineTo(item.Y,item.X);
  5298. else this.Canvas.lineTo(item.X,item.Y);
  5299. }
  5300. }
  5301. this.Canvas.closePath();
  5302. this.Canvas.fill();
  5303. }
  5304. this.Canvas.strokeStyle = line.Color;
  5305. var drawCount=0;
  5306. for (var i=0; i<line.Point.length; ++i)
  5307. {
  5308. var item = line.Point[i];
  5309. if (drawCount==0)
  5310. {
  5311. this.Canvas.beginPath();
  5312. if (this.IsHScreen) this.Canvas.moveTo(item.Y, item.X);
  5313. else this.Canvas.moveTo(item.X, item.Y);
  5314. ++drawCount;
  5315. }
  5316. else
  5317. {
  5318. if (this.IsHScreen) this.Canvas.lineTo(item.Y, item.X);
  5319. else this.Canvas.lineTo(item.X, item.Y);
  5320. ++drawCount;
  5321. }
  5322. if (item.End==true) //点断了 要重新画
  5323. {
  5324. if (drawCount>0) this.Canvas.stroke();
  5325. drawCount=0;
  5326. }
  5327. }
  5328. if (drawCount>0) this.Canvas.stroke();
  5329. //绘制箭头
  5330. if (arrow.End.length==2 && this.Arrow.End==true)
  5331. this.DrawArrow(arrow.End[0],arrow.End[1]);
  5332. if (arrow.Start.length==2 && this.Arrow.Start==true)
  5333. this.DrawArrow(arrow.Start[1],arrow.Start[0]);
  5334. }
  5335. this.DrawArrow=function(ptStart,ptEnd)
  5336. {
  5337. //计算箭头
  5338. var theta=this.ArrawAngle; //三角斜边一直线夹角
  5339. var headlen=this.ArrawLength; //三角斜边长度
  5340. var angle = Math.atan2(ptStart.Y - ptEnd.Y, ptStart.X - ptEnd.X) * 180 / Math.PI,
  5341. angle1 = (angle + theta) * Math.PI / 180,
  5342. angle2 = (angle - theta) * Math.PI / 180,
  5343. topX = headlen * Math.cos(angle1),
  5344. topY = headlen * Math.sin(angle1),
  5345. botX = headlen * Math.cos(angle2),
  5346. botY = headlen * Math.sin(angle2);
  5347. this.Canvas.beginPath();
  5348. var arrowX = ptEnd.X + topX;
  5349. var arrowY = ptEnd.Y + topY;
  5350. this.Canvas.moveTo(arrowX,arrowY);
  5351. this.Canvas.lineTo(ptEnd.X, ptEnd.Y);
  5352. arrowX = ptEnd.X + botX;
  5353. arrowY = ptEnd.Y + botY;
  5354. this.Canvas.lineTo(arrowX,arrowY);
  5355. this.Canvas.setLineDash([]);
  5356. this.Canvas.lineWidth=this.ArrawLineWidth;
  5357. this.Canvas.stroke();
  5358. }
  5359. this.GetMaxMin = function ()
  5360. {
  5361. var range = { Min: null, Max: null };
  5362. var xPointCount = this.ChartFrame.XPointCount;
  5363. var start = this.Data.DataOffset;
  5364. var end = start + xPointCount;
  5365. for (var i in this.Lines)
  5366. {
  5367. var line = this.Lines[i];
  5368. for (var j in line.Point)
  5369. {
  5370. var point = line.Point[j];
  5371. if (point.Index >= start && point.Index < end)
  5372. {
  5373. if (range.Max == null) range.Max = point.Value;
  5374. else if (range.Max < point.Value) range.Max = point.Value;
  5375. if (range.Min == null) range.Min = point.Value;
  5376. else if (range.Min > point.Value) range.Min = point.Value;
  5377. }
  5378. }
  5379. }
  5380. return range;
  5381. }
  5382. }
  5383. // 多个点集合2.0 支持横屏
  5384. function ChartMultiPoint()
  5385. {
  5386. this.newMethod=IChartPainting; //派生
  5387. this.newMethod();
  5388. delete this.newMethod;
  5389. this.ClassName="ChartMultiPoint";
  5390. this.PointGroup=[]; // [ {Point:[ { {Date, Time, Value } }, ], Color: }, ]
  5391. this.IsHScreen=false;
  5392. this.LineWidth=1;
  5393. this.PointRadius=5;
  5394. this.MapCache=null; //key=date/date-time value={ Data:[] }
  5395. this.GetKValue=ChartData.GetKValue;
  5396. this.GetItem=function(kItem)
  5397. {
  5398. if (!this.MapCache || this.MapCache.size<=0) return null;
  5399. var key=this.BuildKey(kItem);
  5400. if (!this.MapCache.has(key)) return null;
  5401. return this.MapCache.get(key);
  5402. }
  5403. this.BuildCacheData=function()
  5404. {
  5405. var mapData=new Map();
  5406. this.MapCache=mapData;
  5407. if (!IFrameSplitOperator.IsNonEmptyArray(this.PointGroup)) return;
  5408. for(var i=0; i<this.PointGroup.length; ++i)
  5409. {
  5410. var groupItem=this.PointGroup[i];
  5411. if (!groupItem || !IFrameSplitOperator.IsNonEmptyArray(groupItem.Point)) continue;
  5412. var clrConfig= { Color:groupItem.Color, BGColor:groupItem.BGColor, LineWidth:this.LineWidth, Radius:this.PointRadius, Name:groupItem.Name };
  5413. if (IFrameSplitOperator.IsNumber(groupItem.PointRadius)) clrConfig.Radius=groupItem.PointRadius;
  5414. if (IFrameSplitOperator.IsNumber(groupItem.LineWidth)) clrConfig.LineWidth=groupItem.LineWidth;
  5415. for(var j=0; j<groupItem.Point.length; ++j)
  5416. {
  5417. var point=groupItem.Point[j];
  5418. var key=this.BuildKey(point);
  5419. var item={ Data:point, ColorConfig:clrConfig }
  5420. if (mapData.has(key))
  5421. {
  5422. var mapItem=mapData.get(key);
  5423. mapItem.Data.push(item);
  5424. }
  5425. else
  5426. {
  5427. mapData.set(key,{ Data:[item] });
  5428. }
  5429. }
  5430. }
  5431. }
  5432. this.Draw=function()
  5433. {
  5434. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  5435. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; //k线数据
  5436. if (!IFrameSplitOperator.IsNonEmptyArray(this.PointGroup)) return;
  5437. if (!this.MapCache || this.MapCache.size<=0) return;
  5438. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  5439. var xPointCount=this.ChartFrame.XPointCount;
  5440. var dataWidth=this.ChartFrame.DataWidth;
  5441. var distanceWidth=this.ChartFrame.DistanceWidth;
  5442. var isMinute=this.IsMinuteFrame();
  5443. var border=this.GetBorder();
  5444. if (this.IsHScreen)
  5445. {
  5446. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  5447. var chartright=border.BottomEx;
  5448. var chartLeft=border.TopEx;
  5449. }
  5450. else
  5451. {
  5452. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  5453. var chartright=border.RightEx;
  5454. var chartLeft=border.LeftEx;
  5455. }
  5456. //计算所有的点位置
  5457. var mapPoint=new Map();
  5458. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  5459. {
  5460. var kItem=this.Data.Data[i];
  5461. var key=this.BuildKey(kItem);
  5462. if (!this.MapCache.has(key)) continue;
  5463. var mapItem=this.MapCache.get(key);
  5464. if (!IFrameSplitOperator.IsNonEmptyArray(mapItem.Data)) continue;
  5465. if (isMinute)
  5466. {
  5467. var x=this.ChartFrame.GetXFromIndex(j);
  5468. }
  5469. else
  5470. {
  5471. var left=xOffset;
  5472. var right=xOffset+dataWidth;
  5473. if (right>chartright) break;
  5474. var x=left+(right-left)/2;
  5475. }
  5476. this.CalculateItem(mapItem, kItem, x, mapPoint);
  5477. }
  5478. if (mapPoint.size<=0) return;
  5479. this.Canvas.save();
  5480. this.DrawAllPoint(mapPoint);
  5481. this.Canvas.restore();
  5482. }
  5483. this.CalculateItem=function(groupItem, kItem, x, mapPoint)
  5484. {
  5485. for(var i=0; i<groupItem.Data.length; ++i)
  5486. {
  5487. var item=groupItem.Data[i];
  5488. var value=item.Data.Value;
  5489. if (IFrameSplitOperator.IsString(item.Data.Value)) value=this.GetKValue(kItem,item.Data.Value);
  5490. if (!IFrameSplitOperator.IsNumber(value)) continue;
  5491. var y=this.ChartFrame.GetYFromData(value,false);
  5492. var strConfig=JSON.stringify(item.ColorConfig);
  5493. if (!mapPoint.has(strConfig)) mapPoint.set(strConfig, { AryPoint:[]});
  5494. var mapItem=mapPoint.get(strConfig);
  5495. mapItem.AryPoint.push({ X:x, Y:y, Data:item });
  5496. }
  5497. }
  5498. this.DrawAllPoint=function(mapPoint)
  5499. {
  5500. for(var mapItem of mapPoint)
  5501. {
  5502. var aryPoint=mapItem[1].AryPoint;
  5503. if (!IFrameSplitOperator.IsNonEmptyArray(aryPoint)) continue;
  5504. var config=null;
  5505. this.Canvas.beginPath();
  5506. var count=0;
  5507. for(var i=0;i<aryPoint.length;++i)
  5508. {
  5509. var item=aryPoint[i];
  5510. if (!config) config=item.Data.ColorConfig;
  5511. if (this.IsHScreen)
  5512. {
  5513. this.Canvas.moveTo(item.Y+config.Radius,item.X);
  5514. this.Canvas.arc(item.Y,item.X,config.Radius,0,360,false);
  5515. }
  5516. else
  5517. {
  5518. this.Canvas.moveTo(item.X+config.Radius,item.Y);
  5519. this.Canvas.arc(item.X,item.Y,config.Radius,0,360,false);
  5520. }
  5521. ++count;
  5522. }
  5523. if (count>0 && config)
  5524. {
  5525. if (config.BGColor)
  5526. {
  5527. this.Canvas.fillStyle=config.BGColor; //背景填充颜色
  5528. this.Canvas.fill();
  5529. }
  5530. if (config.Color)
  5531. {
  5532. this.Canvas.lineWidth=config.LineWidth;
  5533. this.Canvas.strokeStyle=config.Color;
  5534. this.Canvas.stroke();
  5535. }
  5536. }
  5537. }
  5538. }
  5539. this.GetMaxMin=function()
  5540. {
  5541. var range={ Min:null, Max:null };
  5542. if(!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return range;
  5543. if (!this.MapCache || this.MapCache.size<=0) return;
  5544. var xPointCount=this.ChartFrame.XPointCount;
  5545. for(var i=this.Data.DataOffset,j=0, k=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  5546. {
  5547. var kItem=this.Data.Data[i];
  5548. var key=this.BuildKey(kItem);
  5549. if (!this.MapCache.has(key)) continue;
  5550. var mapItem=this.MapCache.get(key);
  5551. if (!IFrameSplitOperator.IsNonEmptyArray(mapItem.Data)) continue;
  5552. for(k=0;k<mapItem.Data.length;++k)
  5553. {
  5554. var item=mapItem.Data[k];
  5555. var value=item.Data.Value;
  5556. if (IFrameSplitOperator.IsString(item.Data.Value)) value=this.GetKValue(kItem,item.Data.Value);
  5557. if (!IFrameSplitOperator.IsNumber(value)) continue;
  5558. if (range.Max==null) range.Max=value;
  5559. else if (range.Max<value) range.Max=value;
  5560. if (range.Min==null) range.Min=value;
  5561. else if (range.Min>value) range.Min=value;
  5562. }
  5563. }
  5564. return range;
  5565. }
  5566. }
  5567. // 柱子集合2.0 支持横屏
  5568. function ChartMultiBar()
  5569. {
  5570. this.newMethod = IChartPainting; //派生
  5571. this.newMethod();
  5572. delete this.newMethod;
  5573. this.Bars = []; // [ {Point:[ {Date, Time, Value, Value2 }, ], Color:, Width: , Type: 0 实心 1 空心 }, ]
  5574. this.IsHScreen = false;
  5575. this.MapCache=null; //key=date/date-time value={ Data:[] }
  5576. this.GetKValue=ChartData.GetKValue;
  5577. this.GetItem=function(kItem)
  5578. {
  5579. if (!this.MapCache || this.MapCache.size<=0) return null;
  5580. var key=this.BuildKey(kItem);
  5581. if (!this.MapCache.has(key)) return null;
  5582. return this.MapCache.get(key);
  5583. }
  5584. this.BuildCacheData=function()
  5585. {
  5586. var mapData=new Map();
  5587. this.MapCache=mapData;
  5588. if (!IFrameSplitOperator.IsNonEmptyArray(this.Bars)) return;
  5589. for(var i=0; i<this.Bars.length; ++i)
  5590. {
  5591. var groupItem=this.Bars[i];
  5592. if (!groupItem || !IFrameSplitOperator.IsNonEmptyArray(groupItem.Point)) continue;
  5593. var clrConfig= { Color:groupItem.Color, Width:5, Name:groupItem.Name, Type:0 };
  5594. if (IFrameSplitOperator.IsNumber(groupItem.Width)) clrConfig.Width=groupItem.Width;
  5595. if (IFrameSplitOperator.IsNumber(groupItem.Type)) clrConfig.Type=groupItem.Type;
  5596. for(var j=0; j<groupItem.Point.length; ++j)
  5597. {
  5598. var point=groupItem.Point[j];
  5599. var key=this.BuildKey(point);
  5600. var item={ Data:point, ColorConfig:clrConfig }
  5601. if (mapData.has(key))
  5602. {
  5603. var mapItem=mapData.get(key);
  5604. mapItem.Data.push(item);
  5605. }
  5606. else
  5607. {
  5608. mapData.set(key,{ Data:[item] });
  5609. }
  5610. }
  5611. }
  5612. }
  5613. this.Draw = function ()
  5614. {
  5615. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  5616. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; //k线数据
  5617. if (!IFrameSplitOperator.IsNonEmptyArray(this.Bars)) return;
  5618. if (!this.MapCache || this.MapCache.size<=0) return;
  5619. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  5620. var xPointCount=this.ChartFrame.XPointCount;
  5621. var dataWidth=this.ChartFrame.DataWidth;
  5622. var distanceWidth=this.ChartFrame.DistanceWidth;
  5623. var isMinute=this.IsMinuteFrame();
  5624. var border=this.GetBorder();
  5625. if (this.IsHScreen)
  5626. {
  5627. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  5628. var chartright=border.BottomEx;
  5629. var chartLeft=border.TopEx;
  5630. }
  5631. else
  5632. {
  5633. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  5634. var chartright=border.RightEx;
  5635. var chartLeft=border.LeftEx;
  5636. }
  5637. //计算所有柱子位置
  5638. var mapBar=new Map();
  5639. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  5640. {
  5641. var kItem=this.Data.Data[i];
  5642. var key=this.BuildKey(kItem);
  5643. if (!this.MapCache.has(key)) continue;
  5644. var mapItem=this.MapCache.get(key);
  5645. if (!IFrameSplitOperator.IsNonEmptyArray(mapItem.Data)) continue;
  5646. if (isMinute)
  5647. {
  5648. var x=this.ChartFrame.GetXFromIndex(j);
  5649. }
  5650. else
  5651. {
  5652. var left=xOffset;
  5653. var right=xOffset+dataWidth;
  5654. if (right>chartright) break;
  5655. var x=left+(right-left)/2;
  5656. }
  5657. this.CalculateItem(mapItem, kItem, x, mapBar);
  5658. }
  5659. if (mapBar.size<=0) return;
  5660. this.Canvas.save();
  5661. this.ClipClient(this.IsHScreen);
  5662. this.DrawAllBar(mapBar);
  5663. this.Canvas.restore();
  5664. }
  5665. this.CalculateItem=function(groupItem, kItem, x, mapBar)
  5666. {
  5667. for(var i=0; i<groupItem.Data.length; ++i)
  5668. {
  5669. var item=groupItem.Data[i];
  5670. var value=item.Data.Value;
  5671. if (IFrameSplitOperator.IsString(item.Data.Value)) value=this.GetKValue(kItem,item.Data.Value);
  5672. if (!IFrameSplitOperator.IsNumber(value)) continue;
  5673. var value2=item.Data.Value2;
  5674. if (IFrameSplitOperator.IsString(item.Data.Value2)) value2=this.GetKValue(kItem,item.Data.Value2);
  5675. if (!IFrameSplitOperator.IsNumber(value2)) continue;
  5676. var y=this.ChartFrame.GetYFromData(value, false);
  5677. var y2=this.ChartFrame.GetYFromData(value2, false);
  5678. var strConfig=JSON.stringify(item.ColorConfig);
  5679. if (!mapBar.has(strConfig)) mapBar.set(strConfig, { AryBar:[]});
  5680. var mapItem=mapBar.get(strConfig);
  5681. mapItem.AryBar.push({ X:x, Y:y, Y2:y2, Data:item });
  5682. }
  5683. }
  5684. this.DrawAllBar=function(mapBar)
  5685. {
  5686. var dataWidth=this.ChartFrame.DataWidth;
  5687. for(var mapItem of mapBar)
  5688. {
  5689. var aryBar=mapItem[1].AryBar;
  5690. if (!IFrameSplitOperator.IsNonEmptyArray(aryBar)) continue;
  5691. var config=null;
  5692. var count=0;
  5693. var drawType=-1; //1=直线 2=实心 3=空心
  5694. var barWidth=dataWidth;
  5695. this.Canvas.beginPath();
  5696. for(var i=0;i<aryBar.length;++i)
  5697. {
  5698. var item=aryBar[i];
  5699. if (!config)
  5700. {
  5701. barWidth=dataWidth;
  5702. config=item.Data.ColorConfig;
  5703. if (IFrameSplitOperator.IsNumber(config.Width)) barWidth=config.Width;
  5704. if (barWidth>4)
  5705. {
  5706. if (config.Type==0) drawType=2; //实心
  5707. else if (config.Type==1) drawType=3; //空心
  5708. else continue;
  5709. }
  5710. else //太细了, 直线
  5711. {
  5712. drawType=1;
  5713. }
  5714. }
  5715. if (drawType<=0) continue;
  5716. if (drawType==1)
  5717. {
  5718. if (this.IsHScreen)
  5719. {
  5720. this.Canvas.moveTo(ToFixedPoint(item.Y),ToFixedPoint(item.X));
  5721. this.Canvas.lineTo(ToFixedPoint(item.Y2),ToFixedPoint(item.X));
  5722. }
  5723. else
  5724. {
  5725. this.Canvas.moveTo(ToFixedPoint(item.X),ToFixedPoint(item.Y));
  5726. this.Canvas.lineTo(ToFixedPoint(item.X),ToFixedPoint(item.Y2));
  5727. }
  5728. ++count;
  5729. }
  5730. else if (drawType==2) //实心
  5731. {
  5732. var x=item.X-(barWidth/2);
  5733. var y=Math.min(item.Y,item.Y2);
  5734. var barWidth=barWidth;
  5735. var barHeight=Math.abs(item.Y-item.Y2);
  5736. if (this.IsHScreen)
  5737. this.Canvas.rect(ToFixedRect(y),ToFixedRect(x),ToFixedRect(barHeight),ToFixedRect(barWidth))
  5738. else
  5739. this.Canvas.rect(ToFixedRect(x),ToFixedRect(y),ToFixedRect(barWidth),ToFixedRect(barHeight))
  5740. ++count;
  5741. }
  5742. else if (drawType==3) //空心
  5743. {
  5744. var x=item.X-(barWidth/2);
  5745. var y=Math.min(item.Y,item.Y2);
  5746. var barWidth=barWidth;
  5747. var barHeight=Math.abs(item.Y-item.Y2);
  5748. if (this.IsHScreen)
  5749. this.Canvas.rect(ToFixedPoint(y),ToFixedPoint(x),ToFixedPoint(barHeight),ToFixedPoint(barWidth))
  5750. else
  5751. this.Canvas.rect(ToFixedPoint(x),ToFixedPoint(y),ToFixedPoint(barWidth),ToFixedPoint(barHeight))
  5752. ++count;
  5753. }
  5754. }
  5755. if (count>0 && drawType>0 && config)
  5756. {
  5757. if (drawType==1)
  5758. {
  5759. this.Canvas.lineWidth=1;
  5760. this.Canvas.strokeStyle=config.Color;
  5761. this.Canvas.stroke();
  5762. }
  5763. else if (drawType==2)
  5764. {
  5765. this.Canvas.fillStyle=config.Color; //背景填充颜色
  5766. this.Canvas.fill();
  5767. }
  5768. else if (drawType==3)
  5769. {
  5770. this.Canvas.lineWidth=1;
  5771. this.Canvas.strokeStyle=config.Color;
  5772. this.Canvas.stroke();
  5773. }
  5774. }
  5775. }
  5776. }
  5777. this.GetMaxMin = function ()
  5778. {
  5779. var range={ Min:null, Max:null };
  5780. if(!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return range;
  5781. if (!this.MapCache || this.MapCache.size<=0) return range;
  5782. var xPointCount=this.ChartFrame.XPointCount;
  5783. for(var i=this.Data.DataOffset,j=0, k=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  5784. {
  5785. var kItem=this.Data.Data[i];
  5786. var key=this.BuildKey(kItem);
  5787. if (!this.MapCache.has(key)) continue;
  5788. var mapItem=this.MapCache.get(key);
  5789. if (!IFrameSplitOperator.IsNonEmptyArray(mapItem.Data)) continue;
  5790. for(k=0;k<mapItem.Data.length;++k)
  5791. {
  5792. var item=mapItem.Data[k];
  5793. var value=item.Data.Value;
  5794. if (IFrameSplitOperator.IsString(item.Data.Value)) value=this.GetKValue(kItem,item.Data.Value);
  5795. if (!IFrameSplitOperator.IsNumber(value)) continue;
  5796. var value2=item.Data.Value2;
  5797. if (IFrameSplitOperator.IsString(item.Data.Value2)) value2=this.GetKValue(kItem,item.Data.Value2);
  5798. if (!IFrameSplitOperator.IsNumber(value2)) continue;
  5799. var minValue=Math.min(value, value2);
  5800. var maxValue=Math.max(value, value2);
  5801. if (range.Max==null) range.Max=maxValue;
  5802. else if (range.Max<maxValue) range.Max=maxValue;
  5803. if (range.Min==null) range.Min=minValue;
  5804. else if (range.Min>minValue) range.Min=minValue;
  5805. }
  5806. }
  5807. return range;
  5808. }
  5809. }
  5810. //分钟信息地雷 支持横屏
  5811. function ChartMinuteInfo()
  5812. {
  5813. this.newMethod = IChartPainting; //派生
  5814. this.newMethod();
  5815. delete this.newMethod;
  5816. this.ClassName = "ChartMinuteInfo";
  5817. this.Data = new Map() //Map key=date-time, value=[{Date, Time, Title, Type, ID:}]
  5818. this.SourceData;
  5819. this.ChartMinutePrice;
  5820. this.YClose;
  5821. this.TextColor = g_JSChartResource.MinuteInfo.TextColor;
  5822. this.Font = g_JSChartResource.MinuteInfo.Font;
  5823. this.PointColor = g_JSChartResource.MinuteInfo.PointColor;
  5824. this.PointRadius=g_JSChartResource.MinuteInfo.PointRadius;
  5825. this.LineColor = g_JSChartResource.MinuteInfo.LineColor;
  5826. this.TextBGColor = g_JSChartResource.MinuteInfo.TextBGColor;
  5827. this.TextHeight = 18;
  5828. this.TextRectCache = [];
  5829. this.InfoDrawCache = [];
  5830. this.FrameBottom;
  5831. this.FrameTop;
  5832. this.FrameLeft;
  5833. this.FrameRight;
  5834. this.YOffset = 5;
  5835. this.IsHScreen = false;
  5836. this.SetOption = function (option)
  5837. {
  5838. if (option.TextColor) this.TextColor = option.TextColor;
  5839. if (option.TextBGColor) this.TextBGColor = option.TextBGColor;
  5840. if (option.Font) this.Font = option.Font;
  5841. if (option.PointColor) this.PointColor = option.PointColor;
  5842. if (option.LineColor) this.LineColor = option.LineColor;
  5843. if (option.TextHeight > 0) this.TextHeight = option.TextHeight;
  5844. }
  5845. this.Draw = function ()
  5846. {
  5847. if (!this.ChartMinutePrice) return;
  5848. if (!this.Data || this.Data.size <= 0) return;
  5849. this.TextRectCache = [];
  5850. this.InfoDrawCache = [];
  5851. this.IsHScreen = (this.ChartFrame.IsHScreen === true);
  5852. var xPointCount = this.ChartFrame.XPointCount;
  5853. var minuteCount = this.ChartFrame.MinuteCount;
  5854. this.FrameBottom = this.ChartBorder.GetBottom();
  5855. this.FrameTop = this.ChartBorder.GetTop();
  5856. this.FrameLeft = this.ChartBorder.GetLeft();
  5857. this.FrameRight = this.ChartBorder.GetRight();
  5858. if (this.IsHScreen)
  5859. {
  5860. this.FrameRight = this.ChartBorder.GetBottom();
  5861. this.FrameLeft = this.ChartBorder.GetTop();
  5862. this.FrameBottom = this.ChartBorder.GetLeft();
  5863. this.FrameTop = this.ChartBorder.GetRight();
  5864. }
  5865. this.YClose = this.ChartMinutePrice.YClose;
  5866. var data = this.ChartMinutePrice.Data;
  5867. var isBeforeData = false;
  5868. if (this.ChartMinutePrice.SourceData)
  5869. {
  5870. data = this.ChartMinutePrice.SourceData;
  5871. isBeforeData = true;
  5872. }
  5873. this.Canvas.font = this.Font;
  5874. for (var i = data.DataOffset, j = 0; i < data.Data.length && j < xPointCount; ++i, ++j)
  5875. {
  5876. var item = this.SourceData.Data[i];
  5877. if (isBeforeData && item.Before) continue;
  5878. if (!item) continue;
  5879. var dateTime = item.DateTime;
  5880. if (!this.Data.has(dateTime)) continue;
  5881. if (this.IsHScreen)
  5882. this.CalcuateInfoHScreenPosition(this.Data.get(dateTime), j, item);
  5883. else
  5884. this.CalcuateInfoPosition(this.Data.get(dateTime), j, item);
  5885. }
  5886. for (var i in this.InfoDrawCache)
  5887. {
  5888. var item = this.InfoDrawCache[i];
  5889. this.DrawInfoLines(item);
  5890. }
  5891. for (var i in this.InfoDrawCache)
  5892. {
  5893. var item = this.InfoDrawCache[i];
  5894. this.DrawInfoText(item);
  5895. }
  5896. this.TextRectCache = [];
  5897. this.InfoDrawCache = [];
  5898. }
  5899. this.CalcuateInfoPosition = function (infoItem, index, minuteItem)
  5900. {
  5901. if (!infoItem || !infoItem.Data || infoItem.Data.length <= 0) return;
  5902. var showItem = infoItem.Data[0];
  5903. var textWidth = this.Canvas.measureText(showItem.Title).width + 4;
  5904. var textHeight = this.TextHeight;
  5905. var x = this.ChartFrame.GetXFromIndex(index);
  5906. var y = this.ChartFrame.GetYFromData(minuteItem.Close);
  5907. x = ToFixedPoint(x);
  5908. var isDrawLeft = x < (this.FrameLeft + Math.abs(this.FrameLeft - this.FrameRight) / 2);
  5909. var ARRAY_OFFSET = [2, 4, 3, 2, 3, 3, 2];
  5910. var offset = textHeight + ARRAY_OFFSET[index % ARRAY_OFFSET.length];
  5911. var yData =
  5912. {
  5913. Y:
  5914. [
  5915. { Value: y + (textHeight + this.YOffset), Offset: offset },
  5916. { Value: y - (2 * textHeight + this.YOffset), Offset: -offset }
  5917. ]
  5918. };
  5919. if (minuteItem.Close < this.YClose)
  5920. yData.Y = yData.Y.reverse();
  5921. var rtBorder = { X: x, Y: null, Width: textWidth, Height: textHeight };
  5922. if (!isDrawLeft) rtBorder.X -= rtBorder.Width;
  5923. this.FixTextRect(rtBorder, yData);
  5924. var InfoDrawItem = { Border: rtBorder, Start: { X: x, Y: y }, IsLeft: isDrawLeft, Title: showItem.Title };
  5925. if (showItem.Content) InfoDrawItem.Content=showItem.Content;
  5926. if (showItem.Link) InfoDrawItem.Link=showItem.Link;
  5927. if (showItem.Color) InfoDrawItem.Color=showItem.Color;
  5928. if (showItem.BGColor) InfoDrawItem.BGColor=showItem.BGColor;
  5929. this.InfoDrawCache.push(InfoDrawItem);
  5930. this.TextRectCache.push(rtBorder);
  5931. }
  5932. this.CalcuateInfoHScreenPosition = function (infoItem, index, minuteItem)
  5933. {
  5934. if (!infoItem || !infoItem.Data || infoItem.Data.length <= 0) return;
  5935. var showItem = infoItem.Data[0];
  5936. var textHeight = this.Canvas.measureText(showItem.Title).width + 4;
  5937. var textWidth = this.TextHeight;
  5938. var y = this.ChartFrame.GetXFromIndex(index);
  5939. var x = this.ChartFrame.GetYFromData(minuteItem.Close);
  5940. y = ToFixedPoint(y);
  5941. var isDrawLeft = y < (this.FrameLeft + Math.abs(this.FrameLeft - this.FrameRight) / 2);
  5942. var ARRAY_OFFSET = [2, 4, 3, 2, 3, 3, 2];
  5943. var offset = textWidth + ARRAY_OFFSET[index % ARRAY_OFFSET.length];
  5944. var xData =
  5945. {
  5946. X:
  5947. [
  5948. { Value: x + (textWidth + this.YOffset), Offset: offset },
  5949. { Value: x - (2 * textWidth + this.YOffset), Offset: -offset }
  5950. ]
  5951. };
  5952. if (minuteItem.Close > this.YClose)
  5953. xData.X = xData.X.reverse();
  5954. var rtBorder = { X: null, Y: y, Width: textWidth, Height: textHeight };
  5955. if (!isDrawLeft) rtBorder.Y -= rtBorder.Height;
  5956. this.FixHScreenTextRect(rtBorder, xData);
  5957. var InfoDrawItem = { Border: rtBorder, Start: { X: x, Y: y }, IsLeft: isDrawLeft, Title: showItem.Title };
  5958. if (showItem.Content) InfoDrawItem.Content=showItem.Content;
  5959. if (showItem.Link) InfoDrawItem.Link=showItem.Link;
  5960. if (showItem.Color) InfoDrawItem.Color=showItem.Color;
  5961. if (showItem.BGColor) InfoDrawItem.BGColor=showItem.BGColor;
  5962. this.InfoDrawCache.push(InfoDrawItem);
  5963. this.TextRectCache.push(rtBorder);
  5964. }
  5965. this.DrawInfoLines = function (item)
  5966. {
  5967. var rtBorder = item.Border;
  5968. var isDrawLeft = item.IsLeft;
  5969. this.Canvas.strokeStyle = this.LineColor;
  5970. this.Canvas.beginPath();
  5971. this.Canvas.moveTo(item.Start.X, item.Start.Y);
  5972. if (isDrawLeft)
  5973. {
  5974. this.Canvas.lineTo(rtBorder.X, rtBorder.Y);
  5975. }
  5976. else
  5977. {
  5978. if (this.IsHScreen) this.Canvas.lineTo(rtBorder.X, rtBorder.Y + rtBorder.Height);
  5979. else this.Canvas.lineTo(rtBorder.X + rtBorder.Width, rtBorder.Y);
  5980. }
  5981. this.Canvas.stroke();
  5982. this.Canvas.fillStyle = this.PointColor;
  5983. this.Canvas.beginPath();
  5984. this.Canvas.arc(item.Start.X, item.Start.Y, this.PointRadius, 0, 2 * Math.PI);
  5985. this.Canvas.closePath();
  5986. this.Canvas.fill();
  5987. }
  5988. this.DrawInfoText = function (item)
  5989. {
  5990. var rtBorder = item.Border;
  5991. var x = rtBorder.X, y = rtBorder.Y;
  5992. if (item.BGColor) this.Canvas.fillStyle=item.BGColor
  5993. else this.Canvas.fillStyle = this.TextBGColor;
  5994. this.Canvas.fillRect(x, y, rtBorder.Width, rtBorder.Height);
  5995. this.Canvas.strokeStyle = this.LineColor;
  5996. this.Canvas.beginPath();
  5997. this.Canvas.rect(x, y, rtBorder.Width, rtBorder.Height);
  5998. this.Canvas.stroke();
  5999. if (this.IsHScreen)
  6000. {
  6001. this.Canvas.save();
  6002. this.Canvas.translate(rtBorder.X, rtBorder.Y);
  6003. this.Canvas.rotate(90 * Math.PI / 180);
  6004. x = 0; y = 0;
  6005. }
  6006. this.Canvas.textAlign = 'left'
  6007. this.Canvas.textBaseline = 'middle';
  6008. if (item.Color) this.Canvas.fillStyle=item.Color;
  6009. else this.Canvas.fillStyle = this.TextColor;
  6010. this.Canvas.font = this.Font;
  6011. if (this.IsHScreen) this.Canvas.fillText(item.Title, x + 2, y - rtBorder.Width / 2);
  6012. else this.Canvas.fillText(item.Title, x+2, y + rtBorder.Height / 2);
  6013. if (this.IsHScreen) this.Canvas.restore();
  6014. }
  6015. this.FixTextRect = function (rect, yData)
  6016. {
  6017. for (var k in yData.Y)
  6018. {
  6019. var yItem = yData.Y[k];
  6020. rect.Y = yItem.Value;
  6021. var y;
  6022. for (var j = 0; j < 10; ++j)
  6023. {
  6024. var isOverlap = false;
  6025. for (var i in this.TextRectCache)
  6026. {
  6027. var item = this.TextRectCache[i];
  6028. if (this.IsOverlap(item, rect))
  6029. {
  6030. isOverlap = true;
  6031. break;
  6032. }
  6033. }
  6034. if (isOverlap == false) return;
  6035. y = rect.Y;
  6036. y += yItem.Offset;
  6037. if (y + rect.Height > this.FrameBottom || y < this.FrameTop) break;
  6038. rect.Y = y;
  6039. }
  6040. }
  6041. }
  6042. this.FixHScreenTextRect = function (rect, xData)
  6043. {
  6044. for (var k in xData.X)
  6045. {
  6046. var xItem = xData.X[k];
  6047. rect.X = xItem.Value;
  6048. var x;
  6049. for (var j = 0; j < 10; ++j)
  6050. {
  6051. var isOverlap = false;
  6052. for (var i in this.TextRectCache)
  6053. {
  6054. var item = this.TextRectCache[i];
  6055. if (this.IsOverlap(item, rect))
  6056. {
  6057. isOverlap = true;
  6058. break;
  6059. }
  6060. }
  6061. if (isOverlap == false) return;
  6062. x = rect.X;
  6063. x += xItem.Offset;
  6064. if (x + rect.Width < this.FrameBottom || x > this.FrameTop) break;
  6065. rect.X = x;
  6066. }
  6067. }
  6068. }
  6069. this.IsOverlap = function (rc1, rc2)
  6070. {
  6071. if (rc1.X + rc1.Width > rc2.X && rc2.X + rc2.Width > rc1.X && rc1.Y + rc1.Height > rc2.Y && rc2.Y + rc2.Height > rc1.Y)
  6072. return true;
  6073. else
  6074. return false;
  6075. }
  6076. this.GetMaxMin = function ()
  6077. {
  6078. var range = { Min: null, Max: null };
  6079. return range;
  6080. }
  6081. }
  6082. //买卖盘
  6083. function ChartBuySell()
  6084. {
  6085. this.newMethod = ChartSingleText; //派生
  6086. this.newMethod();
  6087. delete this.newMethod;
  6088. this.ClassName = "ChartBuySell";
  6089. this.TextFont = g_JSChartResource.KLineTrain.Font; //"bold 14px arial"; //买卖信息字体
  6090. this.LastDataIcon = g_JSChartResource.KLineTrain.LastDataIcon; //{Color:'rgb(0,0,205)',Text:'↓'};
  6091. this.BuyIcon = g_JSChartResource.KLineTrain.BuyIcon; //{Color:'rgb(0,0,205)',Text:'B'};
  6092. this.SellIcon = g_JSChartResource.KLineTrain.SellIcon; //{Color:'rgb(0,0,205)',Text:'S'};
  6093. this.BuySellData = new Map(); //Key=数据索引index Value:Data:[ { Op: 买/卖 0=buy 1=sell, Date:, Time, Price: Vol:}, ]
  6094. this.LastDataDrawType=0; //0=画在最后一个数据上 1=画在指定索引上
  6095. this.LastDataIndex=-1;
  6096. this.AddTradeItem = function (tradeItem)
  6097. {
  6098. if (this.BuySellData.has(tradeItem.Key))
  6099. {
  6100. var Trade = this.BuySellData.get(tradeItem.Key);
  6101. Trade.Data.push(tradeItem);
  6102. }
  6103. else
  6104. {
  6105. this.BuySellData.set(tradeItem.Key, { Data: [tradeItem] });
  6106. }
  6107. }
  6108. this.ClearTradeData = function ()
  6109. {
  6110. this.BuySellData = new Map();
  6111. }
  6112. this.Draw = function ()
  6113. {
  6114. if (!this.Data || !this.Data.Data) return;
  6115. var isHScreen = (this.ChartFrame.IsHScreen === true);
  6116. var dataWidth = this.ChartFrame.DataWidth;
  6117. var distanceWidth = this.ChartFrame.DistanceWidth;
  6118. var chartright = this.ChartBorder.GetRight();
  6119. if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
  6120. var xPointCount = this.ChartFrame.XPointCount;
  6121. var bottom = this.ChartBorder.GetBottomEx();
  6122. var top = this.ChartBorder.GetTopEx();
  6123. var height = this.ChartBorder.GetHeightEx();
  6124. if (isHScreen)
  6125. {
  6126. top = this.ChartBorder.GetRightEx();
  6127. bottom = this.ChartBorder.GetLeftEx();
  6128. height = this.ChartBorder.GetWidthEx();
  6129. }
  6130. this.Canvas.font = this.TextFont;
  6131. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  6132. {
  6133. var value = this.Data.Data[i];
  6134. if (value == null) continue;
  6135. if (x > chartright) break;
  6136. var bDrawLastData=false;
  6137. if (this.LastDataDrawType==1)
  6138. {
  6139. if (i==this.LastDataIndex) bDrawLastData=true;
  6140. }
  6141. else
  6142. {
  6143. if (i==this.Data.Data.length-1) bDrawLastData=true;
  6144. }
  6145. if (bDrawLastData)
  6146. {
  6147. var x = this.ChartFrame.GetXFromIndex(j);
  6148. var yHigh = this.ChartFrame.GetYFromData(value.High);
  6149. if (this.LastDataIcon.Text)
  6150. {
  6151. this.Canvas.textAlign = 'center';
  6152. this.Canvas.textBaseline = 'bottom';
  6153. this.Canvas.fillStyle = this.LastDataIcon.Color;
  6154. this.Canvas.font = this.TextFont;
  6155. this.DrawText(this.LastDataIcon.Text, x, yHigh, isHScreen);
  6156. }
  6157. else
  6158. {
  6159. var obj =
  6160. {
  6161. X: x, Top: top, Bottom: bottom, Height: height,
  6162. DataWidth: dataWidth, Color: this.LastDataIcon.Color, IsHScreen: isHScreen,
  6163. };
  6164. this.DrawLastData(obj);
  6165. }
  6166. }
  6167. var key = i;
  6168. if (!this.BuySellData.has(key)) continue;
  6169. var trade = this.BuySellData.get(key);
  6170. var x = this.ChartFrame.GetXFromIndex(j);
  6171. var yHigh = this.ChartFrame.GetYFromData(value.High);
  6172. var yLow = this.ChartFrame.GetYFromData(value.Low);
  6173. var drawInfo = [false, false]; //0=buy 1=sell
  6174. for (var k in trade.Data)
  6175. {
  6176. if (drawInfo[0] == true && drawInfo[1] == true) break; //买卖图标只画一次
  6177. var bsItem = trade.Data[k];
  6178. if (bsItem.Op == 0 && drawInfo[0] == false) //买 标识在最低价上
  6179. {
  6180. this.Canvas.textAlign = 'center';
  6181. this.Canvas.textBaseline = 'top';
  6182. this.Canvas.fillStyle = this.BuyIcon.Color;
  6183. this.DrawText(this.BuyIcon.Text, x, yLow, isHScreen);
  6184. drawInfo[0] = true;
  6185. }
  6186. else if (bsItem.Op == 1 && drawInfo[1] == false) //卖 标识在最高价上
  6187. {
  6188. this.Canvas.textAlign = 'center';
  6189. this.Canvas.textBaseline = 'bottom';
  6190. this.Canvas.fillStyle = this.SellIcon.Color;
  6191. this.DrawText(this.SellIcon.Text, x, yHigh, isHScreen);
  6192. drawInfo[1] = true;
  6193. }
  6194. }
  6195. }
  6196. }
  6197. this.DrawLastData=function(obj)
  6198. {
  6199. this.Canvas.fillStyle = obj.Color;
  6200. var width = obj.DataWidth;
  6201. if (this.LastDataIcon.Width >= 2 && this.LastDataIcon.Width < obj.DataWidth)
  6202. width = this.LastDataIcon.Width;
  6203. var left = obj.X - width / 2;
  6204. if (obj.IsHScreen)
  6205. {
  6206. this.Canvas.fillRect(ToFixedRect(obj.Bottom), ToFixedRect(left), ToFixedRect(obj.Height), ToFixedRect(width));
  6207. }
  6208. else
  6209. {
  6210. var left = obj.X - width/2;
  6211. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(obj.Top), ToFixedRect(width), ToFixedRect(obj.Height));
  6212. }
  6213. }
  6214. }
  6215. //分钟成交量
  6216. function ChartMinuteVolumBar()
  6217. {
  6218. this.newMethod = IChartPainting; //派生
  6219. this.newMethod();
  6220. delete this.newMethod;
  6221. this.UpColor = g_JSChartResource.UpBarColor;
  6222. this.DownColor = g_JSChartResource.DownBarColor;
  6223. this.UnchangeColor=g_JSChartResource.UnchagneBarColor; //平盘
  6224. this.BarColorType=1; //柱子颜色显示类型 0=红绿 1=红绿白
  6225. this.CustomColor=g_JSChartResource.Minute.VolBarColor;
  6226. this.YClose; //前收盘
  6227. this.Symbol;
  6228. this.GetVolUnit=function()
  6229. {
  6230. var upperSymbol=this.Symbol?this.Symbol.toUpperCase():null;
  6231. var unit=MARKET_SUFFIX_NAME.GetVolUnit(upperSymbol);
  6232. return unit;
  6233. }
  6234. this.Draw = function ()
  6235. {
  6236. var isHScreen = (this.ChartFrame.IsHScreen === true)
  6237. var chartright = this.ChartBorder.GetRight();
  6238. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  6239. var xPointCount = this.ChartFrame.XPointCount;
  6240. var yBottom = this.ChartFrame.GetYFromData(0);
  6241. var yPrice = this.YClose; //上一分钟的价格
  6242. var unit=this.GetVolUnit();
  6243. if (this.CustomColor) this.Canvas.strokeStyle=this.CustomColor;
  6244. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  6245. {
  6246. var item = this.Data.Data[i];
  6247. if (!item || !item.Vol) continue;
  6248. var y = this.ChartFrame.GetYFromData(item.Vol/unit);
  6249. var x = this.ChartFrame.GetXFromIndex(i);
  6250. if (x > chartright) break;
  6251. //价格>=上一分钟价格 红色 否则绿色
  6252. if (!this.CustomColor) this.Canvas.strokeStyle = this.GetMinuteBarColor(item.Close, yPrice);
  6253. this.Canvas.beginPath();
  6254. if (isHScreen)
  6255. {
  6256. this.Canvas.moveTo(y, ToFixedPoint(x));
  6257. this.Canvas.lineTo(yBottom, ToFixedPoint(x));
  6258. }
  6259. else
  6260. {
  6261. this.Canvas.moveTo(ToFixedPoint(x), y);
  6262. this.Canvas.lineTo(ToFixedPoint(x), yBottom);
  6263. }
  6264. this.Canvas.stroke();
  6265. yPrice = item.Close;
  6266. }
  6267. }
  6268. //连续交易成交量柱子颜色
  6269. this.GetMinuteBarColor=function(price, yPrice)
  6270. {
  6271. if (this.BarColorType==1) //通达信模式
  6272. {
  6273. if (price>yPrice) return this.UpColor;
  6274. else if (price<yPrice) return this.DownColor;
  6275. else return this.UnchangeColor;
  6276. }
  6277. else //东方财富模式
  6278. {
  6279. return price >= yPrice ? this.UpColor:this.DownColor;
  6280. }
  6281. }
  6282. this.GetMaxMin = function ()
  6283. {
  6284. var unit=this.GetVolUnit();
  6285. var xPointCount = this.ChartFrame.XPointCount;
  6286. var range = {};
  6287. range.Min = 0;
  6288. range.Max = null;
  6289. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  6290. {
  6291. var item = this.Data.Data[i];
  6292. if (!item || !item.Vol) continue;
  6293. var value=item.Vol/unit;
  6294. if (range.Max == null || range.Max < value) range.Max = value;
  6295. }
  6296. return range;
  6297. }
  6298. }
  6299. //MACD森林线 支持横屏
  6300. function ChartMACD()
  6301. {
  6302. this.newMethod = IChartPainting; //派生
  6303. this.newMethod();
  6304. delete this.newMethod;
  6305. this.ClassName ='ChartMACD';
  6306. this.UpColor = g_JSChartResource.UpBarColor;
  6307. this.DownColor = g_JSChartResource.DownBarColor;
  6308. this.LineWidth=1;
  6309. this.Draw = function ()
  6310. {
  6311. if (this.ChartFrame.IsMinSize || !this.IsVisible) return;
  6312. if (this.IsHideScriptIndex()) return;
  6313. if (this.NotSupportMessage)
  6314. {
  6315. this.DrawNotSupportmessage();
  6316. return;
  6317. }
  6318. if (this.ChartFrame.IsHScreen === true)
  6319. {
  6320. this.HScreenDraw();
  6321. return;
  6322. }
  6323. var isMinute=this.IsMinuteFrame();
  6324. var dataWidth = this.ChartFrame.DataWidth;
  6325. var distanceWidth = this.ChartFrame.DistanceWidth;
  6326. var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6327. var chartright = this.ChartBorder.GetRight();
  6328. var xPointCount = this.ChartFrame.XPointCount;
  6329. var lineWidth=this.LineWidth;
  6330. if (this.LineWidth==50) lineWidth=dataWidth;
  6331. else if (lineWidth>dataWidth) lineWidth=dataWidth;
  6332. this.Canvas.save();
  6333. this.Canvas.lineWidth=lineWidth;
  6334. var bFirstPoint = true;
  6335. var drawCount = 0;
  6336. var yBottom = this.ChartFrame.GetYFromData(0);
  6337. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  6338. //for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  6339. {
  6340. var value = this.Data.Data[i];
  6341. if (value == null) continue;
  6342. if (isMinute)
  6343. {
  6344. var x = this.ChartFrame.GetXFromIndex(j);
  6345. }
  6346. else
  6347. {
  6348. var left=xOffset;
  6349. var right=xOffset+dataWidth;
  6350. if (right>chartright) break;
  6351. var x=left+(right-left)/2;
  6352. }
  6353. var y = this.ChartFrame.GetYFromData(value);
  6354. if (x > chartright) break;
  6355. var xFix = parseInt(x.toString()) + 0.5; //毛边修正
  6356. this.Canvas.beginPath();
  6357. this.Canvas.moveTo(xFix, yBottom);
  6358. this.Canvas.lineTo(xFix, y);
  6359. if (value >= 0) this.Canvas.strokeStyle = this.UpColor;
  6360. else this.Canvas.strokeStyle = this.DownColor;
  6361. this.Canvas.stroke();
  6362. this.Canvas.closePath();
  6363. }
  6364. this.Canvas.restore();
  6365. }
  6366. this.HScreenDraw = function ()
  6367. {
  6368. var isMinute=this.IsMinuteFrame();
  6369. var dataWidth = this.ChartFrame.DataWidth;
  6370. var distanceWidth = this.ChartFrame.DistanceWidth;
  6371. var xOffset=this.ChartBorder.GetTop()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6372. var chartright = this.ChartBorder.GetBottom();
  6373. var xPointCount = this.ChartFrame.XPointCount;
  6374. var yBottom = this.ChartFrame.GetYFromData(0);
  6375. var lineWidth=this.LineWidth;
  6376. if (this.LineWidth==50) lineWidth=dataWidth;
  6377. else if (lineWidth>dataWidth) lineWidth=dataWidth;
  6378. this.Canvas.save();
  6379. this.Canvas.lineWidth=lineWidth;
  6380. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  6381. //for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  6382. {
  6383. var value = this.Data.Data[i];
  6384. if (value == null) continue;
  6385. if (isMinute)
  6386. {
  6387. var x = this.ChartFrame.GetXFromIndex(j);
  6388. }
  6389. else
  6390. {
  6391. var left=xOffset;
  6392. var right=xOffset+dataWidth;
  6393. if (right>chartright) break;
  6394. var x=left+(right-left)/2;
  6395. }
  6396. var y = this.ChartFrame.GetYFromData(value);
  6397. if (x > chartright) break;
  6398. this.Canvas.beginPath();
  6399. this.Canvas.moveTo(yBottom, ToFixedPoint(x));
  6400. this.Canvas.lineTo(y, ToFixedPoint(x));
  6401. if (value >= 0) this.Canvas.strokeStyle = this.UpColor;
  6402. else this.Canvas.strokeStyle = this.DownColor;
  6403. this.Canvas.stroke();
  6404. this.Canvas.closePath();
  6405. }
  6406. this.Canvas.restore();
  6407. }
  6408. }
  6409. //堆积柱状图
  6410. function ChartStackedBar()
  6411. {
  6412. this.newMethod=IChartPainting; //派生
  6413. this.newMethod();
  6414. delete this.newMethod;
  6415. this.ClassName="ChartStackedBar";
  6416. this.Data; //{ Data:[ [bar1, bar2], [bar1,bar2 ] ] };
  6417. this.BarName=[];
  6418. this.BarColor=['rgb(255,165,0)',"rgb(95,158,160)"];
  6419. this.LineWidth=1;
  6420. this.BarType=0; //0=线段 1=K线宽度一致
  6421. this.IsHScreen;
  6422. this.Draw=function()
  6423. {
  6424. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  6425. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return;
  6426. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  6427. var dataWidth=this.ChartFrame.DataWidth;
  6428. var distanceWidth=this.ChartFrame.DistanceWidth;
  6429. var xPointCount=this.ChartFrame.XPointCount;
  6430. if (this.IsHScreen)
  6431. {
  6432. var border=this.ChartBorder.GetHScreenBorder();
  6433. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6434. var chartright=border.BottomEx;
  6435. var top=border.RightEx;
  6436. var bottom=border.LeftEx;
  6437. }
  6438. else
  6439. {
  6440. var border=this.ChartFrame.GetBorder();
  6441. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6442. var chartright=border.RightEx;
  6443. var top=border.TopEx;
  6444. var bottom=border.BottomEx;
  6445. }
  6446. var isMinute=this.IsMinuteFrame();
  6447. this.Canvas.save();
  6448. if (this.BarType==1)
  6449. {
  6450. }
  6451. else
  6452. {
  6453. if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth;
  6454. var lineWidth=this.Canvas.lineWidth;
  6455. }
  6456. var yZero=this.ChartFrame.GetYFromData(0);
  6457. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  6458. {
  6459. var bars=this.Data.Data[i];
  6460. if (!IFrameSplitOperator.IsNonEmptyArray(bars)) continue;
  6461. if (isMinute)
  6462. {
  6463. var x=this.ChartFrame.GetXFromIndex(j);
  6464. }
  6465. else
  6466. {
  6467. var left=xOffset;
  6468. var right=xOffset+dataWidth;
  6469. if (right>chartright) break;
  6470. var x=left+(right-left)/2;
  6471. }
  6472. if (x>chartright) break;
  6473. if (this.BarType==1)
  6474. {
  6475. if (dataWidth>=4) //柱子太细就直接画竖线
  6476. this.DrawKBarItem(bars, x, left, right, top, bottom, yZero, dataWidth);
  6477. else
  6478. this.DrawBarItem(bars, x, top, bottom, yZero, lineWidth);
  6479. }
  6480. else
  6481. {
  6482. this.DrawBarItem(bars, x, top, bottom, yZero, lineWidth);
  6483. }
  6484. }
  6485. this.Canvas.restore();
  6486. }
  6487. this.DrawKBarItem=function(aryBar, x, left, right, top, bottom,yZero, barWidth)
  6488. {
  6489. var plusValue=0, yPlus=yZero; //正数
  6490. var negativeValue=0, yNegative= yZero; //负数
  6491. for(var i=0;i<aryBar.length;++i)
  6492. {
  6493. var item=aryBar[i];
  6494. if (!IFrameSplitOperator.IsNumber(item)) continue;
  6495. if(item==0) continue;
  6496. this.Canvas.fillStyle=this.BarColor[i];
  6497. if (item>0)
  6498. {
  6499. plusValue+=item;
  6500. var y=this.ChartFrame.GetYFromData(plusValue);
  6501. var rtBar={Left: left, Top:y, Width:barWidth, Height:(yPlus-y)};
  6502. yPlus=y;
  6503. }
  6504. else
  6505. {
  6506. negativeValue+=item;
  6507. var y=this.ChartFrame.GetYFromData(negativeValue);
  6508. var rtBar={Left:left, Top:y, Width:barWidth, Height:(yNegative-y)};
  6509. yNegative=y;
  6510. }
  6511. if (this.IsHScreen)
  6512. this.Canvas.fillRect(rtBar.Top,rtBar.Left, rtBar.Height, rtBar.Width);
  6513. else
  6514. this.Canvas.fillRect(rtBar.Left, rtBar.Top, rtBar.Width, rtBar.Height);
  6515. }
  6516. }
  6517. this.DrawBarItem=function(aryBar,x, top, bottom, yZero, lineWidth)
  6518. {
  6519. var x=ToFixedPoint(x);
  6520. var plusValue=0, yPlus=yZero; //正数
  6521. var negativeValue=0, yNegative=yZero; //负数
  6522. for(var i=0;i<aryBar.length;++i)
  6523. {
  6524. var item=aryBar[i];
  6525. if (!IFrameSplitOperator.IsNumber(item)) continue;
  6526. if(item==0) continue;
  6527. var line={};
  6528. if (item>0)
  6529. {
  6530. plusValue+=item;
  6531. var y=this.ChartFrame.GetYFromData(plusValue);
  6532. var line={X:x, Y:yPlus, X2:x, Y2:y};
  6533. yPlus=y;
  6534. }
  6535. else
  6536. {
  6537. negativeValue+=item;
  6538. var y=this.ChartFrame.GetYFromData(negativeValue);
  6539. var line={X:x, Y:yNegative, X2:x, Y2:y};
  6540. yNegative=y;
  6541. }
  6542. this.Canvas.beginPath();
  6543. if (this.IsHScreen)
  6544. {
  6545. this.Canvas.moveTo(line.Y,line.X);
  6546. this.Canvas.lineTo(line.Y2,line.X2);
  6547. }
  6548. else
  6549. {
  6550. this.Canvas.moveTo(line.X,line.Y);
  6551. this.Canvas.lineTo(line.X2,line.Y2);
  6552. }
  6553. this.Canvas.strokeStyle=this.BarColor[i];
  6554. this.Canvas.stroke();
  6555. }
  6556. }
  6557. this.GetMaxMin=function()
  6558. {
  6559. var xPointCount=this.ChartFrame.XPointCount;
  6560. var range={};
  6561. range.Min=null;
  6562. range.Max=null;
  6563. if(!this.Data || !this.Data.Data) return range;
  6564. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  6565. {
  6566. var bars=this.Data.Data[i];
  6567. if (!bars || !IFrameSplitOperator.IsNonEmptyArray(bars)) continue;
  6568. var plusValue=0; //正数
  6569. var negativeValue=0; //负数
  6570. for(var k=0;k<bars.length;++k)
  6571. {
  6572. var barValue=bars[k];
  6573. if (!IFrameSplitOperator.IsNumber(barValue)) continue;
  6574. if (barValue==0) continue;
  6575. if (barValue>0) plusValue+=barValue;
  6576. else if (barValue<0) negativeValue+=barValue;
  6577. }
  6578. if (range.Max==null)
  6579. {
  6580. range.Max=plusValue;
  6581. range.Min=negativeValue;
  6582. }
  6583. if (range.Max<plusValue) range.Max=plusValue;
  6584. if (range.Min>negativeValue) range.Min=negativeValue;
  6585. }
  6586. return range;
  6587. }
  6588. }
  6589. function ChartStepLine()
  6590. {
  6591. this.newMethod=IChartPainting; //派生
  6592. this.newMethod();
  6593. delete this.newMethod;
  6594. this.ClassName='ChartStepLine'; //类名
  6595. this.LineWidth=1; //线段宽度
  6596. this.DotLine;
  6597. this.IsHScreen;
  6598. this.IsDotLine=false; //虚线
  6599. this.Draw=function()
  6600. {
  6601. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  6602. if (this.NotSupportMessage)
  6603. {
  6604. this.DrawNotSupportmessage();
  6605. return;
  6606. }
  6607. if (!this.Data || !this.Data.Data) return;
  6608. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  6609. this.Canvas.save();
  6610. this.DrawLine();
  6611. this.Canvas.restore();
  6612. }
  6613. this.DrawLine=function()
  6614. {
  6615. var isMinute=this.IsMinuteFrame();
  6616. var dataWidth=this.ChartFrame.DataWidth;
  6617. var distanceWidth=this.ChartFrame.DistanceWidth;
  6618. var xPointCount=this.ChartFrame.XPointCount;
  6619. var lockRect=this.GetLockRect();
  6620. if (this.IsHScreen)
  6621. {
  6622. var border=this.ChartBorder.GetHScreenBorder();
  6623. var chartright=border.BottomEx;
  6624. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6625. if (lockRect) chartright=lockRect.Top;
  6626. }
  6627. else
  6628. {
  6629. var border=this.ChartBorder.GetBorder();
  6630. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6631. var chartright=border.RightEx;
  6632. if (lockRect) chartright=lockRect.Left;
  6633. }
  6634. if (this.LineWidth>0) this.Canvas.lineWidth=this.LineWidth;
  6635. if (this.IsDotLine) this.Canvas.setLineDash(g_JSChartResource.DOTLINE.LineDash); //画虚线
  6636. if (this.DotLine) this.Canvas.setLineDash(this.DotLine); //画虚线
  6637. this.Canvas.strokeStyle=this.Color;
  6638. var bFirstPoint=true;
  6639. var drawCount=0;
  6640. var prePoint={ X:null, Y:null };
  6641. for(var i=this.Data.DataOffset; i>=0; --i)
  6642. {
  6643. var value=this.Data.Data[i];
  6644. if (!IFrameSplitOperator.IsNumber(value)) continue;
  6645. var y=this.GetYFromData(value,false);
  6646. var x=null;
  6647. if (isMinute) x=this.ChartFrame.GetXFromIndex(0);
  6648. else x=xOffset;
  6649. this.Canvas.beginPath();
  6650. if (this.IsHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调
  6651. else this.Canvas.moveTo(x,y);
  6652. bFirstPoint=false;
  6653. prePoint.Y=y;
  6654. prePoint.X=x;
  6655. }
  6656. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  6657. {
  6658. if (isMinute)
  6659. {
  6660. var x=this.ChartFrame.GetXFromIndex(j);
  6661. }
  6662. else
  6663. {
  6664. var left=xOffset;
  6665. var right=xOffset+dataWidth;
  6666. if (right>chartright) break;
  6667. var x=left+(right-left)/2;
  6668. }
  6669. if (x>chartright) break;
  6670. var value=this.Data.Data[i];
  6671. if (!IFrameSplitOperator.IsNumber(value)) continue;
  6672. var y=this.GetYFromData(value,false);
  6673. if (bFirstPoint)
  6674. {
  6675. this.Canvas.beginPath();
  6676. if (this.IsHScreen) this.Canvas.moveTo(y,x); //横屏坐标轴对调
  6677. else this.Canvas.moveTo(x,y);
  6678. bFirstPoint=false;
  6679. prePoint.X=x;
  6680. prePoint.Y=y;
  6681. }
  6682. else
  6683. {
  6684. if (this.IsHScreen)
  6685. {
  6686. this.Canvas.lineTo(prePoint.Y,x)
  6687. this.Canvas.lineTo(y,x);
  6688. }
  6689. else
  6690. {
  6691. this.Canvas.lineTo(x,prePoint.Y)
  6692. this.Canvas.lineTo(x,y);
  6693. }
  6694. prePoint.X=x;
  6695. prePoint.Y=y;
  6696. }
  6697. ++drawCount;
  6698. }
  6699. if (drawCount>0) this.Canvas.stroke();
  6700. }
  6701. }
  6702. ////////////////////////////////////////////////////////////////////////////////
  6703. // 等待提示
  6704. function ChartSplashPaint()
  6705. {
  6706. this.newMethod = IChartPainting; //派生
  6707. this.newMethod();
  6708. delete this.newMethod;
  6709. this.Font = g_JSChartResource.DefaultTextFont; //字体
  6710. this.TextColor = g_JSChartResource.DefaultTextColor; //文本颜色
  6711. this.IsEnableSplash = false;
  6712. this.SplashTitle = '数据加载中.....';
  6713. this.HQChart;
  6714. this.EnableSplash=function(bEnable)
  6715. {
  6716. this.IsEnableSplash=bEnable;
  6717. if (this.HQChart)
  6718. {
  6719. var event=this.HQChart.GetEnableSplashEvent();
  6720. if (event)
  6721. {
  6722. var data={ Enable:bEnable };
  6723. event.Callback(event,data,this);
  6724. }
  6725. }
  6726. }
  6727. this.SetTitle=function(title)
  6728. {
  6729. this.SplashTitle=title;
  6730. }
  6731. this.Draw = function ()
  6732. {
  6733. if (!this.IsEnableSplash) return;
  6734. if (this.Frame.IsHScreen === true)
  6735. {
  6736. this.HScreenDraw();
  6737. return;
  6738. }
  6739. var xCenter = (this.Frame.ChartBorder.GetLeft() + this.Frame.ChartBorder.GetRight()) / 2;
  6740. var yCenter = (this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.GetBottom()) / 2;
  6741. this.Canvas.textAlign = 'center';
  6742. this.Canvas.textBaseline = 'middle';
  6743. this.Canvas.fillStyle = this.TextColor;
  6744. this.Canvas.font = this.Font;
  6745. this.Canvas.fillText(this.SplashTitle, xCenter, yCenter);
  6746. }
  6747. this.HScreenDraw = function () //横屏
  6748. {
  6749. var xCenter = (this.Frame.ChartBorder.GetLeft() + this.Frame.ChartBorder.GetRight()) / 2;
  6750. var yCenter = (this.Frame.ChartBorder.GetTop() + this.Frame.ChartBorder.GetBottom()) / 2;
  6751. this.Canvas.save();
  6752. this.Canvas.translate(xCenter, yCenter);
  6753. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  6754. this.Canvas.textAlign = 'center';
  6755. this.Canvas.textBaseline = 'middle';
  6756. this.Canvas.fillStyle = this.TextColor;
  6757. this.Canvas.font = this.Font;
  6758. this.Canvas.fillText(this.SplashTitle, 0, 0);
  6759. this.Canvas.restore();
  6760. }
  6761. }
  6762. //填充背景 支持横屏
  6763. function ChartBackground()
  6764. {
  6765. this.newMethod=IChartPainting; //派生
  6766. this.newMethod();
  6767. delete this.newMethod;
  6768. this.ClassName="ChartBackground";
  6769. this.Color=null;
  6770. this.ColorAngle=0; //0 竖向 1 横向
  6771. this.IsDrawFirst = true; //面积图在K线前面画,否则回挡住K线的
  6772. this.IsHScreen=false;
  6773. this.Draw=function()
  6774. {
  6775. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  6776. if (!this.Color) return;
  6777. if (this.Color.length<=0) return;
  6778. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  6779. if (this.Color.length==2)
  6780. {
  6781. if (this.IsHScreen)
  6782. {
  6783. if (this.ColorAngle==0)
  6784. {
  6785. var ptStart={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() };
  6786. var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
  6787. }
  6788. else
  6789. {
  6790. var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
  6791. var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() };
  6792. }
  6793. }
  6794. else
  6795. {
  6796. if (this.ColorAngle==0)
  6797. {
  6798. var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
  6799. var ptEnd={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetBottomEx() };
  6800. }
  6801. else
  6802. {
  6803. var ptStart={ X:this.ChartBorder.GetLeft(), Y:this.ChartBorder.GetTopEx() };
  6804. var ptEnd={ X:this.ChartBorder.GetRight(), Y:this.ChartBorder.GetTopEx() };
  6805. }
  6806. }
  6807. let gradient = this.Canvas.createLinearGradient(ptStart.X,ptStart.Y, ptEnd.X,ptEnd.Y);
  6808. gradient.addColorStop(0, this.Color[0]);
  6809. gradient.addColorStop(1, this.Color[1]);
  6810. this.Canvas.fillStyle=gradient;
  6811. }
  6812. else if (this.Color.length==1)
  6813. {
  6814. this.Canvas.fillStyle=this.Color[0];
  6815. }
  6816. else
  6817. {
  6818. return;
  6819. }
  6820. if (this.Name=="DRAWGBK2" || this.Name=="KLINE_BG")
  6821. {
  6822. this.DrawRegion();
  6823. return;
  6824. }
  6825. if (this.IsHScreen)
  6826. {
  6827. var left=this.ChartBorder.GetLeftEx();
  6828. var top=this.ChartBorder.GetTop();
  6829. var width=this.ChartBorder.GetWidthEx();
  6830. var height=this.ChartBorder.GetHeight();
  6831. }
  6832. else
  6833. {
  6834. var left=this.ChartBorder.GetLeft();
  6835. var top=this.ChartBorder.GetTopEx();
  6836. var width=this.ChartBorder.GetWidth();
  6837. var height=this.ChartBorder.GetHeightEx();
  6838. }
  6839. this.Canvas.fillRect(left, top,width, height);
  6840. }
  6841. this.DrawRegion=function()
  6842. {
  6843. var xPointCount=this.ChartFrame.XPointCount;
  6844. var xOffset=this.ChartBorder.GetLeft()+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6845. var dataWidth=this.ChartFrame.DataWidth;
  6846. var distanceWidth=this.ChartFrame.DistanceWidth;
  6847. var top=this.ChartBorder.GetTopEx();
  6848. var bottom=this.ChartBorder.GetBottomEx();
  6849. if (this.IsHScreen)
  6850. {
  6851. top=this.ChartBorder.GetRightEx();
  6852. bottom=this.ChartBorder.GetLeftEx();
  6853. }
  6854. var aryPoint=[]; //点坐标
  6855. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  6856. {
  6857. var value=this.Data.Data[i];
  6858. aryPoint[i]=null;
  6859. if (!IFrameSplitOperator.IsNumber(value) || value<=0) continue;
  6860. var x=this.ChartFrame.GetXFromIndex(j);
  6861. var y=this.ChartFrame.GetYFromData(value.Value);
  6862. if (this.IsHScreen)
  6863. aryPoint[i]={ Line:{ X:bottom, Y:x }, Line2:{ X:top, Y:x } };
  6864. else
  6865. aryPoint[i]={ Line:{ X:x, Y:top }, Line2:{ X:x, Y:bottom } };
  6866. }
  6867. this.DrawBG(aryPoint);
  6868. }
  6869. this.DrawBG=function(aryPoint)
  6870. {
  6871. var dataWidth=this.ChartFrame.DataWidth;
  6872. var distanceWidth=this.ChartFrame.DistanceWidth;
  6873. var halfWidth=(distanceWidth+dataWidth)/2;
  6874. var firstPoint=true;
  6875. var pointCount=0;
  6876. var aryLine2=[];
  6877. var color=null;
  6878. for(var i in aryPoint)
  6879. {
  6880. var item=aryPoint[i];
  6881. if (!item || (color && item.Color!=color) )
  6882. {
  6883. if (pointCount>0)
  6884. {
  6885. for(var j=aryLine2.length-1; j>=0; --j)
  6886. {
  6887. var item2=aryLine2[j];
  6888. if (this.IsHScreen)
  6889. {
  6890. this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth);
  6891. this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth);
  6892. }
  6893. else
  6894. {
  6895. this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y);
  6896. this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y);
  6897. }
  6898. }
  6899. this.Canvas.closePath();
  6900. this.Canvas.fill();
  6901. }
  6902. firstPoint=true;
  6903. pointCount=0;
  6904. aryLine2=[];
  6905. color=null;
  6906. }
  6907. if (!item) continue;
  6908. if (firstPoint)
  6909. {
  6910. this.Canvas.beginPath();
  6911. if (this.IsHScreen)
  6912. {
  6913. this.Canvas.moveTo(item.Line.X, item.Line.Y-halfWidth);
  6914. this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth);
  6915. }
  6916. else
  6917. {
  6918. this.Canvas.moveTo(item.Line.X-halfWidth, item.Line.Y);
  6919. this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y);
  6920. }
  6921. firstPoint=false;
  6922. color=item.Color;
  6923. }
  6924. else
  6925. {
  6926. if (this.IsHScreen)
  6927. {
  6928. this.Canvas.lineTo(item.Line.X, item.Line.Y-halfWidth);
  6929. this.Canvas.lineTo(item.Line.X, item.Line.Y+halfWidth);
  6930. }
  6931. else
  6932. {
  6933. this.Canvas.lineTo(item.Line.X-halfWidth, item.Line.Y);
  6934. this.Canvas.lineTo(item.Line.X+halfWidth, item.Line.Y);
  6935. }
  6936. }
  6937. aryLine2.push(item);
  6938. ++pointCount;
  6939. }
  6940. if (pointCount>0)
  6941. {
  6942. for(var j=aryLine2.length-1; j>=0; --j)
  6943. {
  6944. var item2=aryLine2[j];
  6945. if (this.IsHScreen)
  6946. {
  6947. this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y+halfWidth);
  6948. this.Canvas.lineTo(item2.Line2.X, item2.Line2.Y-halfWidth);
  6949. }
  6950. else
  6951. {
  6952. this.Canvas.lineTo(item2.Line2.X+halfWidth, item2.Line2.Y);
  6953. this.Canvas.lineTo(item2.Line2.X-halfWidth, item2.Line2.Y);
  6954. }
  6955. }
  6956. this.Canvas.closePath();
  6957. this.Canvas.fill();
  6958. }
  6959. }
  6960. this.GetMaxMin=function()
  6961. {
  6962. return { Min:null, Max:null };
  6963. }
  6964. }
  6965. //填充部分背景 支持横屏
  6966. function ChartBackgroundDiv()
  6967. {
  6968. this.newMethod=IChartPainting; //派生
  6969. this.newMethod();
  6970. delete this.newMethod;
  6971. this.ClassName="ChartBackgroundDiv";
  6972. this.AryColor;
  6973. this.ColorType=0;
  6974. this.Draw=function()
  6975. {
  6976. if (!this.IsShow || this.ChartFrame.IsMinSize) return;
  6977. if (!IFrameSplitOperator.IsNonEmptyArray(this.AryColor)) return;
  6978. if (!this.Data || !this.Data.Data) return;
  6979. var bHScreen=(this.ChartFrame.IsHScreen===true);
  6980. var dataWidth=this.ChartFrame.DataWidth;
  6981. var distanceWidth=this.ChartFrame.DistanceWidth;
  6982. var xPointCount=this.ChartFrame.XPointCount;
  6983. var border,xOffset, chartright, yTop, yBottom;
  6984. if (bHScreen)
  6985. {
  6986. border=this.ChartBorder.GetHScreenBorder();
  6987. xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6988. chartright=border.BottomEx;
  6989. yTop=border.LeftEx;
  6990. yBottom=border.RightEx;
  6991. }
  6992. else
  6993. {
  6994. border=this.ChartBorder.GetBorder();
  6995. xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  6996. chartright=border.RightEx;
  6997. yTop=border.TopEx;
  6998. yBottom=border.BottomEx;
  6999. }
  7000. var rtBG=null //{ Left:null, Top:null, Right:null, Bottom:null };
  7001. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  7002. {
  7003. var item=this.Data.Data[i];
  7004. var left=xOffset;
  7005. var right=xOffset+dataWidth;
  7006. if (right>chartright) break;
  7007. if (!item)
  7008. {
  7009. if (rtBG) this.DrawDiv(rtBG,bHScreen);
  7010. rtBG=null;
  7011. }
  7012. else
  7013. {
  7014. var y=yTop;
  7015. var y2=yBottom;
  7016. if (IFrameSplitOperator.IsNonEmptyArray(item.AryValue))
  7017. {
  7018. var value=this.ChartFrame.GetYFromData(item.AryValue[0]);
  7019. var value2=this.ChartFrame.GetYFromData(item.AryValue[1]);
  7020. y=Math.min(value, value2);
  7021. y2=Math.max(value, value2);
  7022. }
  7023. if (bHScreen)
  7024. {
  7025. if (!rtBG)
  7026. {
  7027. rtBG={ Left:y, Right:y2, Top:left, Bottom:right };
  7028. }
  7029. else
  7030. {
  7031. rtBG.Bottom=right;
  7032. if (rtBG.Left>y) rtBG.Left=y;
  7033. if (rtBG.Right<y2) rtBG.Right=y2;
  7034. }
  7035. }
  7036. else
  7037. {
  7038. if (!rtBG)
  7039. {
  7040. rtBG={ Left:left, Right:right, Top:y, Bottom:y2 };
  7041. }
  7042. else
  7043. {
  7044. rtBG.Right=right;
  7045. if (rtBG.Top>y) rtBG.Top=y;
  7046. if (rtBG.Bottom<y2) rtBG.Bottom=y2;
  7047. }
  7048. }
  7049. }
  7050. }
  7051. }
  7052. this.DrawDiv=function(rtBG, bHScreen)
  7053. {
  7054. if (this.ColorType==2) //2=用COLOR1画框线
  7055. {
  7056. this.Canvas.strokeStyle = this.AryColor[0];
  7057. this.Canvas.strokeRect(ToFixedPoint(rtBG.Left),ToFixedPoint(rtBG.Top),ToFixedRect(rtBG.Right-rtBG.Left),ToFixedRect(rtBG.Bottom-rtBG.Top));
  7058. }
  7059. else if (this.ColorType==3) //3=用COLOR1画框线,用COLOR2填充
  7060. {
  7061. this.Canvas.fillStyle=this.AryColor[1];
  7062. this.Canvas.fillRect(ToFixedRect(rtBG.Left),ToFixedRect(rtBG.Top),ToFixedRect(rtBG.Right-rtBG.Left),ToFixedRect(rtBG.Bottom-rtBG.Top));
  7063. this.Canvas.strokeStyle = this.AryColor[0];
  7064. this.Canvas.strokeRect(ToFixedPoint(rtBG.Left),ToFixedPoint(rtBG.Top),ToFixedRect(rtBG.Right-rtBG.Left),ToFixedRect(rtBG.Bottom-rtBG.Top));
  7065. }
  7066. else if (this.ColorType==0 || this.ColorType==1) //0=上下渐进 1=左右渐进
  7067. {
  7068. var gradient=null;
  7069. if (bHScreen)
  7070. {
  7071. if (this.ColorType==0)
  7072. gradient = this.Canvas.createLinearGradient(rtBG.Left,rtBG.Top, rtBG.Right,rtBG.Top);
  7073. else
  7074. gradient = this.Canvas.createLinearGradient(rtBG.Left,rtBG.Top, rtBG.Left,rtBG.Bottom);
  7075. }
  7076. else
  7077. {
  7078. if (this.ColorType==0)
  7079. gradient = this.Canvas.createLinearGradient(rtBG.Left,rtBG.Top, rtBG.Left,rtBG.Bottom);
  7080. else
  7081. gradient = this.Canvas.createLinearGradient(rtBG.Left,rtBG.Top, rtBG.Right,rtBG.Top);
  7082. }
  7083. gradient.addColorStop(0.5, this.AryColor[0]);
  7084. gradient.addColorStop(1, this.AryColor[1]);
  7085. this.Canvas.fillStyle=gradient;
  7086. this.Canvas.fillRect(ToFixedRect(rtBG.Left),ToFixedRect(rtBG.Top),ToFixedRect(rtBG.Right-rtBG.Left),ToFixedRect(rtBG.Bottom-rtBG.Top));
  7087. }
  7088. else
  7089. {
  7090. return;
  7091. }
  7092. }
  7093. }
  7094. //锁 支持横屏
  7095. function ChartLock()
  7096. {
  7097. this.newMethod=IChartPainting; //派生
  7098. this.newMethod();
  7099. delete this.newMethod;
  7100. this.ClassName="ChartLock";
  7101. this.AryData=null;
  7102. this.LockRect=null; //上锁区域
  7103. this.LockCount = 20; // 锁最新的几个数据
  7104. this.BGColor = g_JSChartResource.IndexLock.BGColor;
  7105. this.TextColor = g_JSChartResource.IndexLock.TextColor;
  7106. this.Font = g_JSChartResource.IndexLock.Font;
  7107. this.Title = g_JSChartResource.IndexLock.Title;
  7108. this.LockID; //锁ID
  7109. this.Callback; //回调
  7110. this.IndexName; //指标名字
  7111. this.IndexID; //指标ID
  7112. this.MinWidthText=" 付费指标 "
  7113. this.SetData=function(aryData)
  7114. {
  7115. this.AryData=aryData;
  7116. if (IFrameSplitOperator.IsNonEmptyArray(this.AryData))
  7117. {
  7118. var item=this.AryData[0].Data; //取第一个锁
  7119. this.LockCount = item.LockCount;
  7120. this.BGColor = item.BGColor
  7121. this.TextColor = item.TextColor
  7122. this.Font = item.Font
  7123. this.Title = item.Title
  7124. this.LockID=item.LockID; //锁ID
  7125. this.Callback=item.Callback; //回调
  7126. this.IndexName=item.IndexName; //指标名字
  7127. this.IndexID=item.IndexID; //指标ID
  7128. }
  7129. }
  7130. this.CalculateTextSize=function(aryText, defaultFont, out)
  7131. {
  7132. if (!out || !IFrameSplitOperator.IsNonEmptyArray(aryText)) return false;
  7133. this.Canvas.font=defaultFont;
  7134. var defaultLineHeight=this.Canvas.measureText("擎").width; //行高
  7135. var lineHeight=defaultLineHeight;
  7136. var height=0, width=0;
  7137. out.AryText=[];
  7138. for(var i=0;i<aryText.length;++i)
  7139. {
  7140. var item=aryText[i];
  7141. if (!item || (!item.Text && !item.Image)) continue;
  7142. if (item.Image)
  7143. {
  7144. textWidth=item.Image.Width;
  7145. lineHeight=item.Image.Height;
  7146. }
  7147. else
  7148. {
  7149. if (item.Font)
  7150. {
  7151. this.Canvas.font=item.Font;
  7152. lineHeight=this.Canvas.measureText("擎").width;
  7153. }
  7154. else
  7155. {
  7156. this.Canvas.font=defaultFont;
  7157. lineHeight=defaultLineHeight;
  7158. }
  7159. var textWidth=this.Canvas.measureText(item.Text).width;
  7160. }
  7161. var lineItem={ Text:item.Text, Width:textWidth, Height:lineHeight, Color:item.Color, TextMargin:{ Top:0, Bottom:0, Left:0, Right:0 }, YOffset:0 };
  7162. if (IFrameSplitOperator.IsNumber(item.YOffset)) lineItem.YOffset=item.YOffset;
  7163. if (item.Font) lineItem.Font=item.Font;
  7164. if (IFrameSplitOperator.IsNumber(item.Align)) lineItem.Align=item.Align; //左右对齐 0=左 1=中 2=右
  7165. if (item.Image) lineItem.Image=item.Image;
  7166. if (item.TextMargin)
  7167. {
  7168. var margin=item.TextMargin;
  7169. if (IFrameSplitOperator.IsNumber(margin.Top)) lineItem.TextMargin.Top=margin.Top;
  7170. if (IFrameSplitOperator.IsNumber(margin.Bottom)) lineItem.TextMargin.Bottom=margin.Bottom;
  7171. if (IFrameSplitOperator.IsNumber(margin.Left)) lineItem.TextMargin.Left=margin.Left;
  7172. if (IFrameSplitOperator.IsNumber(margin.Right)) lineItem.TextMargin.Right=margin.Right;
  7173. }
  7174. lineItem.Height+=lineItem.TextMargin.Top+lineItem.TextMargin.Bottom;
  7175. lineItem.Width+=lineItem.TextMargin.Left+lineItem.TextMargin.Right;
  7176. if (width<lineItem.Width) width=lineItem.Width;
  7177. out.AryText.push(lineItem);
  7178. height+=lineItem.Height;
  7179. }
  7180. out.Width=width;
  7181. out.Height=height;
  7182. return true;
  7183. }
  7184. this.Draw=function(bDraw)
  7185. {
  7186. this.LockRect=null;
  7187. if (!IFrameSplitOperator.IsNonEmptyArray(this.AryData)) return;
  7188. var bHScreen=this.ChartFrame.IsHScreen;
  7189. var bMinute=this.IsMinuteFrame();
  7190. var dataWidth=this.ChartFrame.DataWidth;
  7191. var distanceWidth=this.ChartFrame.DistanceWidth;
  7192. var xPointCount=this.ChartFrame.XPointCount;
  7193. var border=this.ChartFrame.GetBorder();
  7194. if (bHScreen)
  7195. {
  7196. var chartright=border.BottomEx;
  7197. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  7198. }
  7199. else
  7200. {
  7201. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  7202. var chartright=border.RightEx;
  7203. }
  7204. var kData=this.ChartFrame.Data;
  7205. var left=xOffset;
  7206. if (kData && IFrameSplitOperator.IsNonEmptyArray(kData.Data))
  7207. {
  7208. for(var i=kData.DataOffset,j=0;i<kData.Data.length-this.LockCount && j<xPointCount-this.LockCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  7209. {
  7210. var kItem=kData.Data[i];
  7211. if (kItem.Open==null || kItem.High==null || kItem.Low==null || kItem.Close==null) continue;
  7212. if (bMinute)
  7213. {
  7214. left=this.ChartFrame.GetXFromIndex(j);
  7215. }
  7216. else
  7217. {
  7218. left=xOffset;
  7219. var right=xOffset+dataWidth;
  7220. if (right>chartright) break;
  7221. }
  7222. }
  7223. }
  7224. this.Canvas.font=this.Font;
  7225. var minWidth=this.Canvas.measureText(this.MinWidthText).width;
  7226. var aryText=null;
  7227. if (Array.isArray(this.Title)) aryText=this.Title;
  7228. else aryText=[{Text:this.Title}];
  7229. var outSize={ };
  7230. if (!this.CalculateTextSize(aryText, this.Font, outSize)) outSize=null;;
  7231. if (outSize && outSize.Width+8>minWidth) minWidth=outSize.Width+4; //确保文字可以显示
  7232. if (bHScreen)
  7233. {
  7234. var rtBG={ Left:border.Left, Right:border.RightEx, Top:left, Bottom:border.Bottom };
  7235. rtBG.Width=rtBG.Right-rtBG.Left;
  7236. rtBG.Height=rtBG.Bottom-rtBG.Top;
  7237. if (rtBG.Height<minWidth)
  7238. {
  7239. rtBG.Height=minWidth;
  7240. rtBG.Top=rtBG.Bottom-rtBG.Height;
  7241. }
  7242. this.LockRect=rtBG; //保存上锁区域
  7243. if (bDraw)
  7244. {
  7245. var bgColor=this.SetFillStyle(this.BGColor, rtBG.Left, rtBG.Top, rtBG.Right, rtBG.Top);
  7246. this.Canvas.fillStyle =bgColor;
  7247. this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height);
  7248. }
  7249. }
  7250. else
  7251. {
  7252. var rtBG={ Left:left, Right:border.RightEx, Top:border.TopTitle, Bottom:border.Bottom };
  7253. rtBG.Width=rtBG.Right-rtBG.Left;
  7254. rtBG.Height=rtBG.Bottom-rtBG.Top;
  7255. if (rtBG.Width<minWidth)
  7256. {
  7257. rtBG.Width=minWidth;
  7258. rtBG.Left=rtBG.Right-rtBG.Width;
  7259. }
  7260. this.LockRect=rtBG; //保存上锁区域
  7261. if (bDraw)
  7262. {
  7263. var bgColor=this.SetFillStyle(this.BGColor, rtBG.Left, rtBG.Top, rtBG.Left, rtBG.Bottom); //上下渐变
  7264. this.Canvas.fillStyle =bgColor;
  7265. this.Canvas.fillRect(rtBG.Left, rtBG.Top, rtBG.Width, rtBG.Height);
  7266. }
  7267. }
  7268. if (!bDraw) return;
  7269. if (!outSize) return;
  7270. this.Canvas.textAlign='left';
  7271. this.Canvas.textBaseline='bottom';
  7272. this.Canvas.font = this.Font;
  7273. if (bHScreen)
  7274. {
  7275. var top=rtBG.Top+(rtBG.Height-outSize.Width)/2;
  7276. if (outSize.Width>rtBG.Height) top=rtBG.Bottom-outSize.Width;
  7277. var left=rtBG.Left+(rtBG.Width-outSize.Height)/2;
  7278. this.Canvas.save();
  7279. this.Canvas.translate(left, top);
  7280. this.Canvas.rotate(90 * Math.PI / 180);
  7281. var left=0,top=0;
  7282. }
  7283. else
  7284. {
  7285. var left=rtBG.Left+(rtBG.Width-outSize.Width)/2;
  7286. if (outSize.Width>rtBG.Width) left=rtBG.Right-outSize.Width;
  7287. var top=rtBG.Top+(rtBG.Height-outSize.Height)/2;
  7288. }
  7289. var yText=top, xText=left;
  7290. for(var i=0;i<outSize.AryText.length;++i)
  7291. {
  7292. var item=outSize.AryText[i];
  7293. xText=left;
  7294. if (item.Image)
  7295. {
  7296. if (item.Align===1)
  7297. {
  7298. if (outSize.Width>item.Width) xText+=(outSize.Width-item.Width)/2;
  7299. }
  7300. this.Canvas.drawImage(item.Image.Data, xText, yText, item.Image.Width, item.Image.Height);
  7301. yText+=item.Height;
  7302. }
  7303. else
  7304. {
  7305. if (item.Color) this.Canvas.fillStyle=item.Color;
  7306. else this.Canvas.fillStyle=this.TextColor;
  7307. if (item.Font) this.Canvas.font = item.Font;
  7308. else this.Canvas.font = this.Font;
  7309. yText+=item.Height;
  7310. if (item.Align===1)
  7311. {
  7312. if (outSize.Width>item.Width) xText+=(outSize.Width-item.Width)/2;
  7313. }
  7314. this.Canvas.fillText(item.Text, xText, yText+item.YOffset);
  7315. }
  7316. }
  7317. if (bHScreen) this.Canvas.restore();
  7318. }
  7319. //x,y是否在上锁区域
  7320. this.GetTooltipData=function(x,y,tooltip)
  7321. {
  7322. if (!this.LockRect) return false;
  7323. if (Path2DHelper.PtInRect(x,y,this.LockRect))
  7324. {
  7325. tooltip.Data={ ID:this.LockID, Callback:this.Callback, IndexName:this.IndexName, IndexID:this.IndexID, Data:this.AryData };
  7326. tooltip.ChartPaint=this;
  7327. return true;
  7328. }
  7329. return false;
  7330. }
  7331. }
  7332. //通达信语法 VOLSTICK 支持横屏
  7333. function ChartVolStick()
  7334. {
  7335. this.newMethod = IChartPainting; //派生
  7336. this.newMethod();
  7337. delete this.newMethod;
  7338. this.UpColor = g_JSChartResource.UpBarColor;
  7339. this.DownColor = g_JSChartResource.DownBarColor;
  7340. this.HistoryData; //历史数据
  7341. this.KLineDrawType = 0;
  7342. this.BarType; //柱子状态 1=实心 0=空心 2=涨实跌空 如果设置了这个属性, 属性KLineDrawType无效
  7343. this.ClassName = 'ChartVolStick';
  7344. this.MinBarWidth=g_JSChartResource.MinKLineBarWidth; //最小的柱子宽度
  7345. this.Draw = function ()
  7346. {
  7347. if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return;
  7348. if (this.IsHideScriptIndex()) return;
  7349. if (this.ChartFrame.IsHScreen === true)
  7350. {
  7351. this.HScreenDraw();
  7352. return;
  7353. }
  7354. var dataWidth = this.ChartFrame.DataWidth;
  7355. var distanceWidth = this.ChartFrame.DistanceWidth;
  7356. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  7357. var chartright = this.ChartBorder.GetRight();
  7358. var xPointCount = this.ChartFrame.XPointCount;
  7359. var yBottom = this.ChartFrame.GetYFromData(0);
  7360. var isMinute=this.IsMinuteFrame();
  7361. this.Canvas.save();
  7362. if (dataWidth >= this.MinBarWidth)
  7363. { //只有K线, 分时图dataWidth=1
  7364. yBottom = ToFixedRect(yBottom);
  7365. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  7366. {
  7367. var value = this.Data.Data[i];
  7368. var kItem = this.HistoryData.Data[i];
  7369. if (value == null || kItem == null) continue;
  7370. if (value===0) continue;
  7371. var left = xOffset;
  7372. var right = xOffset + dataWidth;
  7373. if (right > chartright) break;
  7374. var y = this.ChartFrame.GetYFromData(value);
  7375. var barColor=this.GetBarColor(kItem);
  7376. var bUp = barColor.IsUp;
  7377. //高度调整为整数
  7378. var height = ToFixedRect(Math.abs(yBottom - y)>=1 ? yBottom - y : 1);
  7379. y = yBottom - height;
  7380. var bSolidBar=this.IsSolidBar(bUp); //实心柱子
  7381. if (bSolidBar)
  7382. {
  7383. this.Canvas.fillStyle=barColor.Color;
  7384. this.Canvas.fillRect(ToFixedRect(left), y, ToFixedRect(dataWidth), height);
  7385. }
  7386. else
  7387. {
  7388. this.Canvas.strokeStyle=barColor.Color;
  7389. this.Canvas.beginPath();
  7390. this.Canvas.rect(ToFixedPoint(left), ToFixedPoint(y), ToFixedRect(dataWidth), height);
  7391. this.Canvas.stroke();
  7392. }
  7393. }
  7394. }
  7395. else //太细了直接话线
  7396. {
  7397. var preKItem=null;
  7398. var barColor=null;
  7399. this.Canvas.lineWidth=1;
  7400. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  7401. {
  7402. var value = this.Data.Data[i];
  7403. var kItem = this.HistoryData.Data[i];
  7404. if (value == null || kItem == null) continue;
  7405. var y = this.ChartFrame.GetYFromData(value);
  7406. if (isMinute)
  7407. {
  7408. var x=this.ChartFrame.GetXFromIndex(j);
  7409. }
  7410. else
  7411. {
  7412. var left=xOffset;
  7413. var right=xOffset+dataWidth;
  7414. var x=left+(right-left)/2;
  7415. }
  7416. if (x > chartright) break;
  7417. if (isMinute) barColor=this.GetMinuteBarColor(kItem,preKItem); //分时图颜色单独计算
  7418. else barColor=this.GetBarColor(kItem);
  7419. this.Canvas.strokeStyle=barColor.Color;
  7420. //var x = this.ChartFrame.GetXFromIndex(j);
  7421. this.Canvas.beginPath();
  7422. this.Canvas.moveTo(ToFixedPoint(x), y);
  7423. this.Canvas.lineTo(ToFixedPoint(x), yBottom);
  7424. this.Canvas.stroke();
  7425. preKItem=kItem;
  7426. }
  7427. }
  7428. this.Canvas.restore();
  7429. }
  7430. this.GetBarColor=function(kItem)
  7431. {
  7432. if (kItem.Close>=kItem.Open) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨
  7433. else return { Color:this.DownColor, IsUp:false };
  7434. }
  7435. this.GetMinuteBarColor=function(kItem, preItem)
  7436. {
  7437. var prePrice=kItem.YClose;
  7438. if (preItem) prePrice=preItem.Close;
  7439. if (kItem.Close>=prePrice) return { Color:this.UpColor, IsUp:true }; //颜色, 是否是上涨
  7440. else return { Color:this.DownColor, IsUp:false };
  7441. }
  7442. //true=实心 false=空心
  7443. this.IsSolidBar=function(bUp)
  7444. {
  7445. var bSolidBar=true; //实心柱子
  7446. if (this.BarType===0 || this.BarType===1 || this.BarType===2)
  7447. {
  7448. if (this.BarType===0) //空心
  7449. bSolidBar=false;
  7450. else if (this.BarType===2) //涨实跌空
  7451. bSolidBar=bUp;
  7452. }
  7453. else
  7454. {
  7455. if (this.KLineDrawType==6) //完全空心柱
  7456. bSolidBar=false;
  7457. else if (bUp && (this.KLineDrawType==1 || this.KLineDrawType==2 || this.KLineDrawType==3)) //空心柱子
  7458. bSolidBar=false;
  7459. }
  7460. return bSolidBar;
  7461. }
  7462. this.HScreenDraw = function () //横屏画法
  7463. {
  7464. var dataWidth = this.ChartFrame.DataWidth;
  7465. var distanceWidth = this.ChartFrame.DistanceWidth;
  7466. var xOffset = this.ChartBorder.GetTop() + distanceWidth / 2.0 + 2.0;
  7467. var chartBottom = this.ChartBorder.GetBottom();
  7468. var xPointCount = this.ChartFrame.XPointCount;
  7469. var isMinute=this.IsMinuteFrame();
  7470. var yBottom = this.ChartFrame.GetYFromData(0);
  7471. if (dataWidth >= this.MinBarWidth)
  7472. {
  7473. yBottom = ToFixedRect(yBottom);
  7474. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  7475. {
  7476. var value = this.Data.Data[i];
  7477. var kItem = this.HistoryData.Data[i];
  7478. if (value == null || kItem == null) continue;
  7479. var left = xOffset;
  7480. var right = xOffset + dataWidth;
  7481. if (right > chartBottom) break;
  7482. var y = this.ChartFrame.GetYFromData(value);
  7483. var barColor=this.GetBarColor(kItem);
  7484. var bUp=barColor.IsUp;
  7485. //高度调整为整数
  7486. var height = ToFixedRect(y - yBottom);
  7487. var bSolidBar=this.IsSolidBar(bUp); //实心柱子
  7488. if (bSolidBar)
  7489. {
  7490. this.Canvas.fillStyle=barColor.Color;
  7491. this.Canvas.fillRect(yBottom, ToFixedRect(left), height, ToFixedRect(dataWidth));
  7492. }
  7493. else
  7494. {
  7495. this.Canvas.strokeStyle=barColor.Color;
  7496. this.Canvas.beginPath();
  7497. this.Canvas.rect(ToFixedPoint(yBottom), ToFixedPoint(left), height, ToFixedRect(dataWidth));
  7498. this.Canvas.stroke();
  7499. }
  7500. }
  7501. }
  7502. else //太细了直接话线
  7503. {
  7504. var preKItem=null;
  7505. var barColor=null;
  7506. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  7507. {
  7508. var value = this.Data.Data[i];
  7509. var kItem = this.HistoryData.Data[i];
  7510. if (value == null || kItem == null) continue;
  7511. var y = this.ChartFrame.GetYFromData(value);
  7512. if (isMinute)
  7513. {
  7514. var x=this.ChartFrame.GetXFromIndex(j);
  7515. }
  7516. else
  7517. {
  7518. var left=xOffset;
  7519. var right=xOffset+dataWidth;
  7520. var x=left+(right-left)/2;
  7521. }
  7522. if (x > chartBottom) break;
  7523. if (isMinute) barColor=this.GetMinuteBarColor(kItem,preKItem); //分时图颜色单独计算
  7524. else barColor=this.GetBarColor(kItem);
  7525. this.Canvas.strokeStyle=barColor.Color;
  7526. //var x = this.ChartFrame.GetXFromIndex(j);
  7527. this.Canvas.beginPath();
  7528. this.Canvas.moveTo(y, ToFixedPoint(x));
  7529. this.Canvas.lineTo(yBottom, ToFixedPoint(x));
  7530. this.Canvas.stroke();
  7531. preKItem=kItem;
  7532. }
  7533. }
  7534. }
  7535. this.GetMaxMin = function ()
  7536. {
  7537. var xPointCount = this.ChartFrame.XPointCount;
  7538. var range = { Min:null, Max:null };
  7539. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  7540. {
  7541. var value = this.Data.Data[i];
  7542. if (!IFrameSplitOperator.IsNumber(range.Max) || range.Max<value) range.Max=value;
  7543. if (!IFrameSplitOperator.IsNumber(range.Min) || range.Min>value) range.Min=value
  7544. }
  7545. if (range.Max>0 && range.Min>0) range.Min=0;
  7546. else if (range.Max<0 && range.Min<0) range.Max=0;
  7547. return range;
  7548. }
  7549. }
  7550. function ChartText()
  7551. {
  7552. this.newMethod = IChartPainting; //派生
  7553. this.newMethod();
  7554. delete this.newMethod;
  7555. this.TextFont = "14px 微软雅黑";
  7556. this.Draw = function ()
  7557. {
  7558. if (this.ChartFrame.IsMinSize) return;
  7559. if (this.NotSupportMessage)
  7560. {
  7561. this.DrawNotSupportmessage();
  7562. return;
  7563. }
  7564. if (!this.Data || !this.Data.Data) return;
  7565. var dataWidth = this.ChartFrame.DataWidth;
  7566. var distanceWidth = this.ChartFrame.DistanceWidth;
  7567. var chartright = this.ChartBorder.GetRight();
  7568. var xPointCount = this.ChartFrame.XPointCount;
  7569. for (var i in this.Data.Data)
  7570. {
  7571. var value = this.Data.Data[i];
  7572. if (value == null) continue;
  7573. var price = value.Value;
  7574. var position = value.Position;
  7575. if (position == 'Left') {
  7576. var x = this.ChartFrame.GetXFromIndex(0);
  7577. var y = this.ChartFrame.GetYFromData(price);
  7578. if (x > chartright) continue;
  7579. this.Canvas.textAlign = 'left';
  7580. this.Canvas.textBaseline = 'middle';
  7581. this.Canvas.fillStyle = value.Color;
  7582. this.Canvas.font = this.TextFont;
  7583. this.Canvas.fillText(value.Message, x, y);
  7584. }
  7585. }
  7586. }
  7587. this.GetMaxMin = function ()
  7588. {
  7589. var xPointCount = this.ChartFrame.XPointCount;
  7590. var range = {};
  7591. range.Min = null;
  7592. range.Max = null;
  7593. if (!this.Data || !this.Data.Data) return range;
  7594. for (var i in this.Data.Data)
  7595. {
  7596. var data = this.Data.Data[i];
  7597. if (data == null || isNaN(data.Value)) continue;
  7598. var value = data.Value;
  7599. if (range.Max == null) range.Max = value;
  7600. if (range.Min == null) range.Min = value;
  7601. if (range.Max < value) range.Max = value;
  7602. if (range.Min > value) range.Min = value;
  7603. }
  7604. return range;
  7605. }
  7606. }
  7607. /* 水平面积 只有1个数据
  7608. Data 数据结构
  7609. Value, Value2 区间最大最小值
  7610. Color=面积的颜色
  7611. Title=标题 TitleColor=标题颜色
  7612. 支持横屏
  7613. */
  7614. function ChartStraightArea()
  7615. {
  7616. this.newMethod = IChartPainting; //派生
  7617. this.newMethod();
  7618. delete this.newMethod;
  7619. this.Color = "rgb(255,193,37)"; //线段颜色
  7620. this.Font = '11px 微软雅黑';
  7621. this.Draw = function ()
  7622. {
  7623. if (this.ChartFrame.IsMinSize) return;
  7624. if (this.NotSupportMessage)
  7625. {
  7626. this.DrawNotSupportmessage();
  7627. return;
  7628. }
  7629. if (!this.Data || !this.Data.Data) return;
  7630. if (this.ChartFrame.IsHScreen === true)
  7631. {
  7632. this.HScreenDraw();
  7633. return;
  7634. }
  7635. var dataWidth = this.ChartFrame.DataWidth;
  7636. var distanceWidth = this.ChartFrame.DistanceWidth;
  7637. var chartright = this.ChartBorder.GetRight();
  7638. var bottom = this.ChartBorder.GetBottom();
  7639. var left = this.ChartBorder.GetLeft();
  7640. var xPointCount = this.ChartFrame.XPointCount;
  7641. var xRight = this.ChartFrame.GetXFromIndex(xPointCount - 1);
  7642. //画背景
  7643. for (let i in this.Data.Data)
  7644. {
  7645. let item = this.Data.Data[i];
  7646. if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
  7647. if (item.Color == null) continue;
  7648. let valueMax = Math.max(item.Value, item.Value2);
  7649. let valueMin = Math.min(item.Value, item.Value2);
  7650. let yTop = this.ChartFrame.GetYFromData(valueMax);
  7651. let yBottom = this.ChartFrame.GetYFromData(valueMin);
  7652. this.Canvas.fillStyle = item.Color;
  7653. this.Canvas.fillRect(ToFixedRect(left), ToFixedRect(yTop), ToFixedRect(xRight - left), ToFixedRect(yBottom - yTop));
  7654. }
  7655. for (let i in this.Data.Data)
  7656. {
  7657. let item = this.Data.Data[i];
  7658. if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
  7659. if (item.Color == null) continue;
  7660. let valueMax = Math.max(item.Value, item.Value2);
  7661. let valueMin = Math.min(item.Value, item.Value2);
  7662. let yTop = this.ChartFrame.GetYFromData(valueMax);
  7663. let yBottom = this.ChartFrame.GetYFromData(valueMin);
  7664. if (item.Title && item.TitleColor)
  7665. {
  7666. let x = xRight;
  7667. if (item.Align == 'left')
  7668. {
  7669. this.Canvas.textAlign = 'left';
  7670. x = left;
  7671. }
  7672. else
  7673. {
  7674. this.Canvas.textAlign = 'right';
  7675. x = xRight;
  7676. }
  7677. this.Canvas.textBaseline = 'middle';
  7678. this.Canvas.fillStyle = item.TitleColor;
  7679. this.Canvas.font = this.Font;
  7680. let y = yTop + (yBottom - yTop) / 2;
  7681. this.Canvas.fillText(item.Title, x, y);
  7682. }
  7683. }
  7684. }
  7685. this.HScreenDraw = function ()
  7686. {
  7687. var bottom = this.ChartBorder.GetBottom();
  7688. var top = this.ChartBorder.GetTop();
  7689. var height = this.ChartBorder.GetHeight();
  7690. for (let i in this.Data.Data)
  7691. {
  7692. let item = this.Data.Data[i];
  7693. if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
  7694. if (item.Color == null) continue;
  7695. let valueMax = Math.max(item.Value, item.Value2);
  7696. let valueMin = Math.min(item.Value, item.Value2);
  7697. var yTop = this.ChartFrame.GetYFromData(valueMax);
  7698. var yBottom = this.ChartFrame.GetYFromData(valueMin);
  7699. this.Canvas.fillStyle = item.Color;
  7700. this.Canvas.fillRect(ToFixedRect(yBottom), ToFixedRect(top), ToFixedRect(yTop - yBottom), ToFixedRect(height));
  7701. if (item.Title && item.TitleColor)
  7702. {
  7703. var xText = yTop + (yBottom - yTop) / 2;
  7704. var yText = bottom;
  7705. this.Canvas.save();
  7706. this.Canvas.translate(xText, yText);
  7707. this.Canvas.rotate(90 * Math.PI / 180);
  7708. this.Canvas.textAlign = 'right';
  7709. this.Canvas.textBaseline = 'middle';
  7710. this.Canvas.fillStyle = item.TitleColor;
  7711. this.Canvas.font = this.Font;
  7712. this.Canvas.fillText(item.Title, 0, -2);
  7713. this.Canvas.restore();
  7714. }
  7715. }
  7716. }
  7717. this.GetMaxMin = function ()
  7718. {
  7719. var xPointCount = this.ChartFrame.XPointCount;
  7720. var range = {};
  7721. range.Min = null;
  7722. range.Max = null;
  7723. if (!this.Data || !this.Data.Data) return range;
  7724. for (let i in this.Data.Data)
  7725. {
  7726. let item = this.Data.Data[i];
  7727. if (item == null || isNaN(item.Value) || isNaN(item.Value2)) continue;
  7728. let valueMax = Math.max(item.Value, item.Value2);
  7729. let valueMin = Math.min(item.Value, item.Value2);
  7730. if (range.Max == null) range.Max = valueMax;
  7731. if (range.Min == null) range.Min = valueMin;
  7732. if (range.Max < valueMax) range.Max = valueMax;
  7733. if (range.Min > valueMin) range.Min = valueMin;
  7734. }
  7735. return range;
  7736. }
  7737. }
  7738. // DRAWBAND 面积图 支持横屏
  7739. function ChartBand()
  7740. {
  7741. this.newMethod = IChartPainting; //派生
  7742. this.newMethod();
  7743. delete this.newMethod;
  7744. this.IsDrawFirst = true;
  7745. this.ClassName="ChartBand";
  7746. this.FirstColor = g_JSChartResource.Index.LineColor[0];
  7747. this.SecondColor = g_JSChartResource.Index.LineColor[1];
  7748. this.Draw = function ()
  7749. {
  7750. if (this.ChartFrame.IsMinSize) return;
  7751. if (this.NotSupportMessage)
  7752. {
  7753. this.DrawNotSupportmessage();
  7754. return;
  7755. }
  7756. var isHScreen=this.ChartFrame.IsHScreen;
  7757. var dataWidth = this.ChartFrame.DataWidth;
  7758. var distanceWidth = this.ChartFrame.DistanceWidth;
  7759. var xPointCount = this.ChartFrame.XPointCount;
  7760. var xOffset = this.ChartBorder.GetLeft() + distanceWidth / 2.0 + 2.0;
  7761. var x = 0;
  7762. var y = 0;
  7763. var y2 = 0;
  7764. var firstlinePoints = [];
  7765. var secondlinePoints = [];
  7766. var lIndex = 0;
  7767. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j, xOffset += (dataWidth + distanceWidth))
  7768. {
  7769. var value = this.Data.Data[i];
  7770. if (value == null || value.Value == null || value.Value2 == null) continue;
  7771. x = this.ChartFrame.GetXFromIndex(j);
  7772. y = this.ChartFrame.GetYFromData(value.Value);
  7773. y2 = this.ChartFrame.GetYFromData(value.Value2);
  7774. if (isHScreen)
  7775. {
  7776. firstlinePoints[lIndex] = { x: y, y: x };
  7777. secondlinePoints[lIndex] = { x: y2, y: x };
  7778. }
  7779. else
  7780. {
  7781. firstlinePoints[lIndex] = { x: x, y: y };
  7782. secondlinePoints[lIndex] = { x: x, y: y2 };
  7783. }
  7784. lIndex++;
  7785. }
  7786. if (firstlinePoints.length>1 && secondlinePoints.length>1)
  7787. {
  7788. this.DrawBand(firstlinePoints, secondlinePoints);
  7789. }
  7790. }
  7791. this.ClipTop=function(aryFrist)
  7792. {
  7793. var isHScreen=this.ChartFrame.IsHScreen;
  7794. this.Canvas.beginPath();
  7795. for(var i=0;i<aryFrist.length;++i)
  7796. {
  7797. if (i == 0)
  7798. this.Canvas.moveTo(aryFrist[i].x, aryFrist[i].y);
  7799. else
  7800. this.Canvas.lineTo(aryFrist[i].x, aryFrist[i].y);
  7801. }
  7802. var ptStart=aryFrist[0];
  7803. var ptEnd=aryFrist[aryFrist.length-1];
  7804. if (isHScreen)
  7805. {
  7806. var xLeft=this.ChartBorder.GetRightEx();
  7807. this.Canvas.lineTo(xLeft, ptEnd.y);
  7808. this.Canvas.lineTo(xLeft, ptStart.y);
  7809. }
  7810. else
  7811. {
  7812. var yTop=this.ChartBorder.GetTopEx();
  7813. this.Canvas.lineTo(ptEnd.x, yTop);
  7814. this.Canvas.lineTo(ptStart.x, yTop);
  7815. }
  7816. this.Canvas.closePath();
  7817. this.Canvas.clip();
  7818. }
  7819. this.ClipBottom=function(aryFrist)
  7820. {
  7821. var isHScreen=this.ChartFrame.IsHScreen;
  7822. this.Canvas.beginPath();
  7823. for(var i=0;i<aryFrist.length;++i)
  7824. {
  7825. if (i == 0)
  7826. this.Canvas.moveTo(aryFrist[i].x, aryFrist[i].y);
  7827. else
  7828. this.Canvas.lineTo(aryFrist[i].x, aryFrist[i].y);
  7829. }
  7830. var ptStart=aryFrist[0];
  7831. var ptEnd=aryFrist[aryFrist.length-1];
  7832. if (isHScreen)
  7833. {
  7834. var xLeft=this.ChartBorder.GetLeftEx();
  7835. this.Canvas.lineTo(xLeft, ptEnd.y);
  7836. this.Canvas.lineTo(xLeft, ptStart.y);
  7837. }
  7838. else
  7839. {
  7840. var yBottom=this.ChartBorder.GetBottomEx();
  7841. this.Canvas.lineTo(ptEnd.x, yBottom);
  7842. this.Canvas.lineTo(ptStart.x, yBottom);
  7843. }
  7844. this.Canvas.closePath();
  7845. //this.Canvas.fillStyle = "rgb(255,0,0)";
  7846. //this.Canvas.fill();
  7847. this.Canvas.clip();
  7848. }
  7849. this.DrawArea=function(aryFrist, arySecond, clrArea)
  7850. {
  7851. this.Canvas.beginPath();
  7852. for(var i=0;i<aryFrist.length;++i)
  7853. {
  7854. if (i == 0)
  7855. this.Canvas.moveTo(aryFrist[i].x, aryFrist[i].y);
  7856. else
  7857. this.Canvas.lineTo(aryFrist[i].x, aryFrist[i].y);
  7858. }
  7859. for (var i = arySecond.length-1; i >= 0; --i)
  7860. {
  7861. this.Canvas.lineTo(arySecond[i].x, arySecond[i].y);
  7862. }
  7863. this.Canvas.closePath();
  7864. this.Canvas.fillStyle = clrArea;
  7865. this.Canvas.fill();
  7866. }
  7867. this.DrawBand=function(aryFrist, arySecond)
  7868. {
  7869. if (this.FirstColor)
  7870. {
  7871. this.Canvas.save();
  7872. this.ClipTop(aryFrist);
  7873. this.DrawArea(aryFrist, arySecond, this.FirstColor);
  7874. this.Canvas.restore();
  7875. }
  7876. if (this.SecondColor)
  7877. {
  7878. this.Canvas.save();
  7879. this.ClipBottom(aryFrist);
  7880. this.DrawArea(aryFrist, arySecond, this.SecondColor);
  7881. this.Canvas.restore();
  7882. }
  7883. }
  7884. this.GetMaxMin = function ()
  7885. {
  7886. var xPointCount = this.ChartFrame.XPointCount;
  7887. var range = {};
  7888. range.Min = null;
  7889. range.Max = null;
  7890. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  7891. {
  7892. var value = this.Data.Data[i];
  7893. if (value == null || value.Value == null || value.Value2 == null) continue;
  7894. var maxData = value.Value > value.Value2 ? value.Value : value.Value2;
  7895. var minData = value.Value < value.Value2 ? value.Value : value.Value2;
  7896. if (range.Max == null)
  7897. range.Max = maxData;
  7898. else if (range.Max < maxData)
  7899. range.Max = maxData;
  7900. if (range.Min == null)
  7901. range.Min = minData;
  7902. else if (range.Min > minData)
  7903. range.Min = minData;
  7904. }
  7905. return range;
  7906. }
  7907. }
  7908. //分钟线叠加 支持横屏
  7909. function ChartOverlayMinutePriceLine()
  7910. {
  7911. this.newMethod = IChartPainting; //派生
  7912. this.newMethod();
  7913. delete this.newMethod;
  7914. this.Color = "rgb(65,105,225)";
  7915. this.MainData; //主图数据
  7916. this.Name = "ChartOverlayMinutePriceLine";
  7917. this.Title;
  7918. this.Symbol; //叠加的股票代码
  7919. this.YClose; //叠加的股票前收盘
  7920. this.Status=OVERLAY_STATUS_ID.STATUS_NONE_ID;
  7921. this.OverlayType=0; //叠加方式 0=百分比叠加 1=绝对叠加
  7922. this.Draw = function ()
  7923. {
  7924. if (this.NotSupportMessage)
  7925. {
  7926. this.DrawNotSupportmessage();
  7927. return;
  7928. }
  7929. var isHScreen = (this.ChartFrame.IsHScreen === true);
  7930. var dataWidth = this.ChartFrame.DataWidth;
  7931. var distanceWidth = this.ChartFrame.DistanceWidth;
  7932. var chartright = this.ChartBorder.GetRight();
  7933. if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
  7934. var xPointCount = this.ChartFrame.XPointCount;
  7935. var minuteCount = this.ChartFrame.MinuteCount;
  7936. var yClose=null, mainYClose=null;
  7937. var bFirstPoint = true;
  7938. var drawCount = 0, showValue=0, pointCount=0;
  7939. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  7940. {
  7941. var item=this.Data.Data[i];
  7942. if (item && IFrameSplitOperator.IsNumber(item.Close))
  7943. {
  7944. if (bFirstPoint) //百分比使用每天的昨收计算
  7945. {
  7946. yClose=item.YClose;
  7947. var minItem=this.MainData.Data[i];
  7948. mainYClose=minItem.YClose;
  7949. }
  7950. var value=item.Close;
  7951. showValue=value; //绝对叠加
  7952. if (this.OverlayType==0) showValue=value/yClose*mainYClose; //百分比
  7953. var x = this.ChartFrame.GetXFromIndex(j);
  7954. var y = this.ChartFrame.GetYFromData(showValue, false);
  7955. if (bFirstPoint)
  7956. {
  7957. this.Canvas.strokeStyle = this.Color;
  7958. this.Canvas.beginPath();
  7959. if (isHScreen) this.Canvas.moveTo(y, x);
  7960. else this.Canvas.moveTo(x, y);
  7961. bFirstPoint = false;
  7962. }
  7963. else
  7964. {
  7965. if (isHScreen) this.Canvas.lineTo(y, x);
  7966. else this.Canvas.lineTo(x, y);
  7967. }
  7968. ++drawCount;
  7969. }
  7970. ++pointCount;
  7971. if (pointCount>=minuteCount) //上一天的数据和这天地数据线段要断开
  7972. {
  7973. bFirstPoint=true;
  7974. pointCount=0;
  7975. if (drawCount>0) this.Canvas.stroke();
  7976. drawCount=0;
  7977. }
  7978. }
  7979. if (drawCount > 0) this.Canvas.stroke();
  7980. }
  7981. this.GetMaxMin = function ()
  7982. {
  7983. var xPointCount = this.ChartFrame.XPointCount;
  7984. var range={ Min:null, Max:null };
  7985. var minuteCount=this.ChartFrame.MinuteCount;
  7986. var yClose=null, mainYClose=null;
  7987. var bFirstPoint=true;
  7988. var pointCount=0;
  7989. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  7990. {
  7991. var item=this.Data.Data[i];
  7992. if (!item || !IFrameSplitOperator.IsNumber(item.Close))
  7993. {
  7994. ++pointCount;
  7995. continue;
  7996. }
  7997. if (bFirstPoint)
  7998. {
  7999. yClose=item.YClose;
  8000. var minItem=this.MainData.Data[i];
  8001. mainYClose=minItem.YClose;
  8002. bFirstPoint=false;
  8003. }
  8004. var value=item.Close;
  8005. if (this.OverlayType==0) value=value/yClose*mainYClose;
  8006. if (range.Max==null) range.Max=value;
  8007. if (range.Min==null) range.Min=value;
  8008. if (range.Max<value) range.Max=value;
  8009. if (range.Min>value) range.Min=value;
  8010. ++pointCount;
  8011. if (pointCount>=minuteCount)
  8012. {
  8013. bFirstPoint=true;
  8014. pointCount=0;
  8015. }
  8016. }
  8017. return range;
  8018. }
  8019. }
  8020. //线段 多数据(一个X点有多条Y数据) 支持横屏
  8021. function ChartLineMultiData()
  8022. {
  8023. this.newMethod = IChartPainting; //派生
  8024. this.newMethod();
  8025. delete this.newMethod;
  8026. this.Color = "rgb(255,193,37)"; //线段颜色
  8027. this.Draw = function ()
  8028. {
  8029. if (this.NotSupportMessage)
  8030. {
  8031. this.DrawNotSupportmessage();
  8032. return;
  8033. }
  8034. if (!this.Data || !this.Data.Data) return;
  8035. var isHScreen = (this.ChartFrame.IsHScreen === true);
  8036. var dataWidth = this.ChartFrame.DataWidth;
  8037. var distanceWidth = this.ChartFrame.DistanceWidth;
  8038. var chartright = this.ChartBorder.GetRight();
  8039. if (isHScreen) chartright = this.ChartBorder.GetBottom();
  8040. var xPointCount = this.ChartFrame.XPointCount;
  8041. var bFirstPoint = true;
  8042. var drawCount = 0;
  8043. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  8044. {
  8045. var aryValue = this.Data.Data[i];
  8046. if (aryValue == null) continue;
  8047. var x = this.ChartFrame.GetXFromIndex(j);
  8048. if (x > chartright) break;
  8049. for (var index in aryValue)
  8050. {
  8051. var value = aryValue[index].Value;
  8052. var y = this.ChartFrame.GetYFromData(value);
  8053. if (bFirstPoint)
  8054. {
  8055. this.Canvas.strokeStyle = this.Color;
  8056. this.Canvas.beginPath();
  8057. if (isHScreen) this.Canvas.moveTo(y, x);
  8058. else this.Canvas.moveTo(x, y);
  8059. bFirstPoint = false;
  8060. }
  8061. else
  8062. {
  8063. if (isHScreen) this.Canvas.lineTo(y, x);
  8064. else this.Canvas.lineTo(x, y);
  8065. }
  8066. ++drawCount;
  8067. }
  8068. }
  8069. if (drawCount > 0) this.Canvas.stroke();
  8070. }
  8071. this.GetMaxMin = function ()
  8072. {
  8073. var xPointCount = this.ChartFrame.XPointCount;
  8074. var range = {};
  8075. range.Min = null;
  8076. range.Max = null;
  8077. if (!this.Data || !this.Data.Data) return range;
  8078. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  8079. {
  8080. var aryValue = this.Data.Data[i];
  8081. if (aryValue == null) continue;
  8082. for (var index in aryValue)
  8083. {
  8084. var value = aryValue[index].Value;
  8085. if (range.Max == null) range.Max = value;
  8086. if (range.Min == null) range.Min = value;
  8087. if (range.Max < value) range.Max = value;
  8088. if (range.Min > value) range.Min = value;
  8089. }
  8090. }
  8091. return range;
  8092. }
  8093. }
  8094. //直线 水平直线 只有1个数据 支持横屏
  8095. function ChartStraightLine()
  8096. {
  8097. this.newMethod = IChartPainting; //派生
  8098. this.newMethod();
  8099. delete this.newMethod;
  8100. this.Color = "rgb(255,193,37)"; //线段颜色
  8101. this.Draw = function ()
  8102. {
  8103. if (!this.Data || !this.Data.Data) return;
  8104. if (this.Data.Data.length != 1) return;
  8105. var isHScreen = this.ChartFrame.IsHScreen;
  8106. var dataWidth = this.ChartFrame.DataWidth;
  8107. var distanceWidth = this.ChartFrame.DistanceWidth;
  8108. var chartright = this.ChartBorder.GetRight();
  8109. if (isHScreen) chartright = this.ChartBorder.GetTop();
  8110. var xPointCount = this.ChartFrame.XPointCount;
  8111. var yValue = this.Data.Data[0];
  8112. var y = this.ChartFrame.GetYFromData(yValue);
  8113. var xLeft = this.ChartFrame.GetXFromIndex(0);
  8114. var xRight = this.ChartFrame.GetXFromIndex(xPointCount - 1);
  8115. var yFix = parseInt(y.toString()) + 0.5;
  8116. this.Canvas.beginPath();
  8117. if (isHScreen)
  8118. {
  8119. this.Canvas.moveTo(yFix, xLeft);
  8120. this.Canvas.lineTo(yFix, xRight);
  8121. }
  8122. else
  8123. {
  8124. this.Canvas.moveTo(xLeft, yFix);
  8125. this.Canvas.lineTo(xRight, yFix);
  8126. }
  8127. this.Canvas.strokeStyle = this.Color;
  8128. this.Canvas.stroke();
  8129. }
  8130. this.GetMaxMin = function ()
  8131. {
  8132. var xPointCount = this.ChartFrame.XPointCount;
  8133. var range = {};
  8134. range.Min = null;
  8135. range.Max = null;
  8136. if (!this.Data || !this.Data.Data) return range;
  8137. if (this.Data.Data.length != 1) return range;
  8138. range.Min = this.Data.Data[0];
  8139. range.Max = this.Data.Data[0];
  8140. return range;
  8141. }
  8142. }
  8143. //图标集合(2.0) 支持横屏
  8144. function ChartMultiSVGIconV2()
  8145. {
  8146. this.newMethod=IChartPainting; //派生
  8147. this.newMethod();
  8148. delete this.newMethod;
  8149. this.ClassName="ChartMultiSVGIconV2";
  8150. this.AryIcon; //[ {Index:, Value:, Baseline:, Line:{ Color:, Dash:[虚线点], KData:"H/L", Offset:[5,10], Width:线粗细 }, Image:{ Data:Image图片, Width, Height } } ]
  8151. this.IsHScreen=false;
  8152. this.MapCache=null; //key=date/date-time value={ Data:[] }
  8153. this.BuildKey=function(item)
  8154. {
  8155. if (IFrameSplitOperator.IsNumber(item.Time)) return `${item.Date}-${item.Time}`;
  8156. else return item.Date;
  8157. }
  8158. this.BuildCacheData=function()
  8159. {
  8160. var mapData=new Map();
  8161. this.MapCache=mapData;
  8162. if (!IFrameSplitOperator.IsNonEmptyArray(this.AryIcon)) return;
  8163. for(var i=0;i<this.AryIcon.length;++i)
  8164. {
  8165. var item=this.AryIcon[i];
  8166. var key=this.BuildKey(item);
  8167. if (mapData.has(key))
  8168. {
  8169. var mapItem=mapData.get(key);
  8170. mapItem.Data.push(item);
  8171. }
  8172. else
  8173. {
  8174. mapData.set(key,{ Data:[item] });
  8175. }
  8176. }
  8177. }
  8178. this.ClipClient=function(isHScreen) //裁剪客户端
  8179. {
  8180. if (isHScreen==true)
  8181. {
  8182. var left=this.ChartBorder.GetLeft();
  8183. var right=this.ChartBorder.GetRight();
  8184. var top=this.ChartBorder.GetTop();
  8185. var bottom=this.ChartBorder.GetBottom();
  8186. }
  8187. else
  8188. {
  8189. var left=this.ChartBorder.GetLeft();
  8190. var right=this.ChartBorder.GetRight();
  8191. var top=this.ChartBorder.GetTop();
  8192. var bottom=this.ChartBorder.GetBottom();
  8193. }
  8194. this.Canvas.beginPath();
  8195. this.Canvas.rect(left,top,(right-left),(bottom-top));
  8196. //this.Canvas.stroke(); //调试用
  8197. this.Canvas.clip();
  8198. }
  8199. this.Draw=function()
  8200. {
  8201. if (!this.IsShow || this.ChartFrame.IsMinSize || !this.IsVisible) return;
  8202. if (this.IsHideScriptIndex()) return;
  8203. if (!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return; //k线数据
  8204. if (!this.Family) return;
  8205. if (!this.MapCache || this.MapCache.size<=0) return;
  8206. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  8207. var xPointCount=this.ChartFrame.XPointCount;
  8208. var dataWidth=this.ChartFrame.DataWidth;
  8209. var distanceWidth=this.ChartFrame.DistanceWidth;
  8210. var isMinute=this.IsMinuteFrame();
  8211. var border=this.GetBorder();
  8212. if (this.IsHScreen)
  8213. {
  8214. var xOffset=border.TopEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  8215. var chartright=border.BottomEx;
  8216. var chartLeft=border.TopEx;
  8217. }
  8218. else
  8219. {
  8220. var xOffset=border.LeftEx+distanceWidth/2.0+g_JSChartResource.FrameLeftMargin;
  8221. var chartright=border.RightEx;
  8222. var chartLeft=border.LeftEx;
  8223. }
  8224. this.Canvas.save();
  8225. this.ClipClient(this.ChartFrame.IsHScreen);
  8226. var drawInfo={ Left:chartLeft, Right:chartright, DataWidth:dataWidth, DistanceWidth:distanceWidth };
  8227. for(var i=this.Data.DataOffset,j=0;i<this.Data.Data.length && j<xPointCount;++i,++j,xOffset+=(dataWidth+distanceWidth))
  8228. {
  8229. var kItem=this.Data.Data[i];
  8230. var key=this.BuildKey(kItem);
  8231. if (!this.MapCache.has(key)) continue;
  8232. var mapItem=this.MapCache.get(key);
  8233. if (isMinute)
  8234. {
  8235. var x=this.ChartFrame.GetXFromIndex(j);
  8236. }
  8237. else
  8238. {
  8239. var left=xOffset;
  8240. var right=xOffset+dataWidth;
  8241. if (right>chartright) break;
  8242. var x=left+(right-left)/2;
  8243. }
  8244. this.DrawItem(mapItem, kItem, x, drawInfo);
  8245. }
  8246. this.Canvas.restore();
  8247. }
  8248. this.GetKValue=function(kItem, valueName)
  8249. {
  8250. switch(valueName)
  8251. {
  8252. case "HIGH":
  8253. case "H":
  8254. return kItem.High;
  8255. case "L":
  8256. case "LOW":
  8257. return kItem.Low;
  8258. case "C":
  8259. case "CLOSE":
  8260. return kItem.Close;
  8261. case "O":
  8262. case "OPEN":
  8263. return KItem.Open;
  8264. default:
  8265. return null;
  8266. }
  8267. }
  8268. this.DrawItem=function(groupItem, kItem, x, drawInfo)
  8269. {
  8270. if (!IFrameSplitOperator.IsNonEmptyArray(groupItem.Data)) return;
  8271. //var left=drawInfo.Left, right=drawInfo.Right;
  8272. //var dataWidth=drawInfo.DataWidth;
  8273. //var distanceWidth=drawInfo.DistanceWidth;
  8274. for(var i=0;i<groupItem.Data.length;++i)
  8275. {
  8276. var item=groupItem.Data[i];
  8277. var value=item.Value;
  8278. if (IFrameSplitOperator.IsString(item.Value)) value=this.GetKValue(kItem,item.Value);
  8279. if (!IFrameSplitOperator.IsNumber(value)) continue;
  8280. if (!item.Image) continue;
  8281. var y=this.ChartFrame.GetYFromData(item.Value,false);
  8282. var imageHeight=item.Image.Height;
  8283. var imageWidth=item.Image.Width;
  8284. if (this.IsHScreen)
  8285. {
  8286. var xImage=x-imageWidth/2, yImage=y;
  8287. if (item.Baseline==1) yImage=y-imageHeight;
  8288. else if (item.Baseline==2) yImage=y;
  8289. else yImage=y-imageHeight/2;
  8290. if (IFrameSplitOperator.IsNumber(item.YMove))
  8291. {
  8292. yImage-=item.YMove;
  8293. y-=item.YMove;
  8294. }
  8295. //this.Canvas.drawImage(item.Image.Data, yImage, xImage,item.Image.Width, item.Image.Height);
  8296. this.Canvas.save();
  8297. this.Canvas.translate(yImage+imageWidth/2, xImage+imageHeight/2);
  8298. this.Canvas.rotate(90 * Math.PI / 180);
  8299. this.Canvas.drawImage(item.Image.Data, -imageWidth/2, -imageHeight/2, item.Image.Width, item.Image.Height);
  8300. this.Canvas.restore();
  8301. }
  8302. else
  8303. {
  8304. var rtIcon=new RectV2(x-imageWidth/2,y-imageHeight/2,imageWidth,imageHeight);
  8305. if (item.Baseline==1) rtIcon.Y=y;
  8306. else if (item.Baseline==2) rtIcon.Y=y-imageHeight;
  8307. else rtIcon.Y=y-imageHeight/2;
  8308. if (IFrameSplitOperator.IsNumber(item.YMove))
  8309. {
  8310. y+=item.YMove;
  8311. rtIcon.Y+=item.YMove;
  8312. }
  8313. this.Canvas.drawImage(item.Image.Data, rtIcon.X, rtIcon.Y, item.Image.Width, item.Image.Height);
  8314. }
  8315. if (item.Line)
  8316. {
  8317. var price=item.Line.KData=="H"? kItem.High:kItem.Low;
  8318. var yPrice=this.ChartFrame.GetYFromData(price, false);
  8319. var yText=y;
  8320. if (Array.isArray(item.Line.Offset) && item.Line.Offset.length==2)
  8321. {
  8322. if (yText>yPrice) //文字在下方
  8323. {
  8324. yText-=item.Line.Offset[1];
  8325. yPrice+=item.Line.Offset[0]
  8326. }
  8327. else if (yText<yPrice)
  8328. {
  8329. yText+=item.Line.Offset[1];
  8330. yPrice-=item.Line.Offset[0]
  8331. }
  8332. }
  8333. this.Canvas.save();
  8334. if (item.Line.Dash) this.Canvas.setLineDash(item.Line.Dash); //虚线
  8335. if (item.Line.Width>0) this.Canvas.lineWidth=item.Line.Width; //线宽
  8336. this.Canvas.strokeStyle = item.Line.Color;
  8337. this.Canvas.beginPath();
  8338. if (this.IsHScreen)
  8339. {
  8340. this.Canvas.moveTo(yText, ToFixedPoint(x));
  8341. this.Canvas.lineTo(yPrice,ToFixedPoint(x));
  8342. }
  8343. else
  8344. {
  8345. this.Canvas.moveTo(ToFixedPoint(x),yText);
  8346. this.Canvas.lineTo(ToFixedPoint(x),yPrice);
  8347. }
  8348. this.Canvas.stroke();
  8349. this.Canvas.restore();
  8350. }
  8351. }
  8352. }
  8353. this.GetMaxMin=function()
  8354. {
  8355. this.IsHScreen=(this.ChartFrame.IsHScreen===true);
  8356. var range={ Min:null, Max:null };
  8357. if(!this.Data || !IFrameSplitOperator.IsNonEmptyArray(this.Data.Data)) return range;
  8358. if (!this.MapCache || this.MapCache.size<=0) return;
  8359. var xPointCount=this.ChartFrame.XPointCount;
  8360. for(var i=this.Data.DataOffset,j=0, k=0;i<this.Data.Data.length && j<xPointCount;++i,++j)
  8361. {
  8362. var kItem=this.Data.Data[i];
  8363. var key=this.BuildKey(kItem);
  8364. if (!this.MapCache.has(key)) continue;
  8365. var mapItem=this.MapCache.get(key);
  8366. if (!IFrameSplitOperator.IsNonEmptyArray(mapItem.Data)) continue;
  8367. for(k=0;k<mapItem.Data.length;++k)
  8368. {
  8369. var item=mapItem.Data[k];
  8370. var value=item.Value;
  8371. if (IFrameSplitOperator.IsString(item.Value)) value=this.GetKValue(kItem,item.Value);
  8372. if (!IFrameSplitOperator.IsNumber(value)) continue;
  8373. if (range.Max==null) range.Max=value;
  8374. else if (range.Max<value) range.Max=value;
  8375. if (range.Min==null) range.Min=value;
  8376. else if (range.Min>value) range.Min=value;
  8377. }
  8378. }
  8379. return range;
  8380. }
  8381. }
  8382. ///////////////////////////////////////////////////////////////////////////////////////////////////
  8383. //十字光标
  8384. function ChartCorssCursor()
  8385. {
  8386. this.Frame;
  8387. this.Canvas; //画布
  8388. this.HPenColor = g_JSChartResource.CorssCursorHPenColor; //水平线颜色
  8389. this.HPenType = 0; //水平线样式 0=虚线 1=实线
  8390. this.VPenColor = g_JSChartResource.CorssCursorVPenColor; //垂直线颜色
  8391. this.VPenType = 0; //垂直线颜色 0=虚线 1=实线 2=K线宽度
  8392. this.Font = g_JSChartResource.CorssCursorTextFont; //字体
  8393. this.TextColor = g_JSChartResource.CorssCursorTextColor; //文本颜色
  8394. this.TextBGColor = g_JSChartResource.CorssCursorBGColor; //文本背景色
  8395. this.LineDash=g_JSChartResource.CorssCursorLineDash.slice(); //虚线
  8396. this.TextHeight = 15; //文本字体高度
  8397. this.LastPoint;
  8398. this.CursorIndex; //当前数据的位置
  8399. this.PointX;
  8400. this.PointY;
  8401. this.StringFormatX;
  8402. this.StringFormatY;
  8403. this.IsShow = true; //是否显示
  8404. this.ShowTextMode = { Left: 1, Right: 1, Bottom: 1 }; //0=不显示 1=显示在框架外 2=显示在框架内
  8405. this.TextFormat= { Right:0 }; //0=默认 1=价格显示(分时图才有用)
  8406. this.IsShowCorss = true; //是否显示十字光标
  8407. this.IsShowClose = false; //Y轴始终显示收盘价
  8408. this.IsOnlyDrawMinute=false; //是否只能画在走势图价格线上
  8409. this.IsFixXLastTime=false; //是否修正X轴,超出当前时间的,X轴调整到当前最后的时间.
  8410. this.CorssPointConfig=
  8411. {
  8412. Enable:false,
  8413. Center:CloneData(g_JSChartResource.CorssCursor.CorssPoint.Center),
  8414. Border:CloneData(g_JSChartResource.CorssCursor.CorssPoint.Border)
  8415. }
  8416. this.BottomConfig=CloneData(g_JSChartResource.CorssCursor.BottomText); //底部输出配置
  8417. this.LeftConfig=CloneData(g_JSChartResource.CorssCursor.LeftText);
  8418. this.RightConfig=CloneData(g_JSChartResource.CorssCursor.RightText); //右侧输出配置
  8419. this.BottomButton={ Enable:false, Rect:null }; //底部按钮
  8420. //内部使用
  8421. this.Close = null; //收盘价格
  8422. this.Status=0; //当前状态 0=隐藏 1=显示
  8423. this.GetCloseYPoint = function (index)
  8424. {
  8425. this.Close = null;
  8426. if (!this.StringFormatX.Data) return null;
  8427. var data = this.StringFormatX.Data;
  8428. if (!data.Data || data.Data.length <= 0) return null;
  8429. var dataIndex = data.DataOffset + index;
  8430. if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1;
  8431. if (dataIndex < 0) return null;
  8432. var klineData = data.Data[dataIndex];
  8433. if (!klineData) return null;
  8434. this.Close = klineData.Close;
  8435. var yPoint = this.Frame.GetYFromData(this.Close);
  8436. return yPoint;
  8437. }
  8438. this.GetMinuteCloseYPoint=function(index)
  8439. {
  8440. if (!IFrameSplitOperator.IsNumber(index)) return null;
  8441. index=parseInt(index.toFixed(0));
  8442. if (!this.StringFormatX.Data) return null;
  8443. var data = this.StringFormatX.Data;
  8444. if (!data.Data || data.Data.length <= 0) return null;
  8445. var dataIndex = data.DataOffset + index;
  8446. if (dataIndex >= data.Data.length) dataIndex = data.Data.length - 1;
  8447. if (dataIndex < 0) return null;
  8448. var close = data.Data[dataIndex];
  8449. if (!IFrameSplitOperator.IsNumber(index)) return null;
  8450. this.Close=close;
  8451. var yPoint = this.Frame.GetYFromData(this.Close);
  8452. return yPoint;
  8453. }
  8454. this.FixMinuteLastTimeXPoint=function(index)
  8455. {
  8456. if (!IFrameSplitOperator.IsNumber(index)) return null;
  8457. index=parseInt(index);
  8458. if (!this.StringFormatX.Data) return null;
  8459. var data = this.StringFormatX.Data;
  8460. if (!data.Data || data.Data.length <= 0) return null;
  8461. var dataIndex = data.DataOffset + index;
  8462. if (dataIndex<data.Data.length) return null;
  8463. dataIndex=data.Data.length - 1;
  8464. dataIndex-=data.DataOffset;
  8465. var xPoint=this.Frame.GetXFromIndex(dataIndex);
  8466. return { X:xPoint, Index:dataIndex };
  8467. }
  8468. this.Draw = function ()
  8469. {
  8470. this.Status=JSCHART_CORSSCURSOR_STATUS_ID.NONE_ID;
  8471. this.BottomButton.Rect=null;
  8472. if (!this.LastPoint) return;
  8473. var x = this.LastPoint.X;
  8474. var y = this.LastPoint.Y;
  8475. var isInClient = false;
  8476. var rtClient = new Rect(this.Frame.ChartBorder.GetLeft(), this.Frame.ChartBorder.GetTop(), this.Frame.ChartBorder.GetWidth(), this.Frame.ChartBorder.GetHeight());
  8477. isInClient = rtClient.IsPointIn(x, y);
  8478. this.PointY = null;
  8479. this.PointY == null;
  8480. if (!isInClient) return;
  8481. if (this.Frame.IsHScreen === true)
  8482. {
  8483. this.HScreenDraw();
  8484. return;
  8485. }
  8486. var left = this.Frame.ChartBorder.GetLeft();
  8487. var right = this.Frame.ChartBorder.GetRight();
  8488. var top = this.Frame.ChartBorder.GetTopTitle();
  8489. var bottom = this.Frame.ChartBorder.GetBottom();
  8490. var rightWidth = this.Frame.ChartBorder.Right;
  8491. var chartRight = this.Frame.ChartBorder.GetChartWidth();
  8492. x = this.Frame.GetXFromIndex(this.CursorIndex); //手机端 十字只能画在K线上
  8493. if (this.IsShowClose) //手机端 十字只能画在K线上
  8494. {
  8495. var yPoint = this.GetCloseYPoint(this.CursorIndex);
  8496. if (yPoint != null) y = yPoint;
  8497. }
  8498. else if (this.IsOnlyDrawMinute)
  8499. {
  8500. var yPoint = this.GetMinuteCloseYPoint(this.CursorIndex);
  8501. if (yPoint != null) y=yPoint;
  8502. }
  8503. if (this.IsFixXLastTime)
  8504. {
  8505. var value=this.FixMinuteLastTimeXPoint(this.CursorIndex)
  8506. if (value)
  8507. {
  8508. x=value.X;
  8509. this.CursorIndex=value.Index;
  8510. }
  8511. }
  8512. this.PointY = [[left, y], [right, y]];
  8513. this.PointX = [[x, top], [x, bottom]];
  8514. if (this.IsShowCorss) //十字线
  8515. {
  8516. if (this.HPenType==1 || this.HPenType==0)
  8517. {
  8518. this.Canvas.strokeStyle = this.HPenColor;
  8519. if (this.HPenType == 0) this.Canvas.setLineDash(this.LineDash); //虚线
  8520. //this.Canvas.lineWidth=0.5
  8521. this.Canvas.beginPath();
  8522. this.Canvas.moveTo(left, ToFixedPoint(y));
  8523. this.Canvas.lineTo(right, ToFixedPoint(y));
  8524. this.Canvas.stroke();
  8525. this.Canvas.setLineDash([]);
  8526. }
  8527. this.Canvas.save();
  8528. this.Canvas.strokeStyle = this.VPenColor;
  8529. if (this.VPenType == 0)
  8530. {
  8531. this.Canvas.setLineDash(this.LineDash); //虚线
  8532. }
  8533. else if (this.VPenType == 2)
  8534. {
  8535. let barWidth = this.Frame.SubFrame[0].Frame.DataWidth; //和K线一样宽度
  8536. if (barWidth > 2) this.Canvas.lineWidth = barWidth;
  8537. }
  8538. this.Canvas.beginPath();
  8539. if (this.Frame.SubFrame.length > 0)
  8540. {
  8541. for (var i in this.Frame.SubFrame)
  8542. {
  8543. var frame = this.Frame.SubFrame[i].Frame;
  8544. top = frame.ChartBorder.GetTopTitle();
  8545. bottom = frame.ChartBorder.GetBottom();
  8546. this.Canvas.moveTo(ToFixedPoint(x), top);
  8547. this.Canvas.lineTo(ToFixedPoint(x), bottom);
  8548. }
  8549. }
  8550. else
  8551. {
  8552. this.Canvas.moveTo(ToFixedPoint(x), top);
  8553. this.Canvas.lineTo(ToFixedPoint(x), bottom);
  8554. }
  8555. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.LINE_ID;
  8556. this.Canvas.stroke();
  8557. this.Canvas.restore();
  8558. this.Canvas.save();
  8559. this.DrawCorssPoint(x,y);
  8560. this.Canvas.restore();
  8561. }
  8562. var xValue = this.Frame.GetXData(x);
  8563. var yValueExtend = {};
  8564. var yValue = this.Frame.GetYData(y, yValueExtend);
  8565. this.StringFormatY.RValue = yValueExtend.RightYValue; //右侧子坐标
  8566. if (this.IsShowClose && this.Close != null) yValue = this.Close;
  8567. this.StringFormatX.Value = this.CursorIndex;
  8568. this.StringFormatY.Value = yValue;
  8569. this.StringFormatY.RValue=yValueExtend.RightYValue; //右侧子坐标
  8570. this.StringFormatY.Point={X:x, Y:y};
  8571. this.StringFormatY.FrameID = yValueExtend.FrameID;
  8572. this.Canvas.font = this.Font;
  8573. var textHeight=this.GetFontHeight();
  8574. if (textHeight>this.TextHeight) this.TextHeight=textHeight;
  8575. if (((this.ShowTextMode.Left == 1 && this.Frame.ChartBorder.Left >= 30) || this.ShowTextMode.Left == 2 ||
  8576. (this.ShowTextMode.Right == 1 && this.Frame.ChartBorder.Right >= 30) || this.ShowTextMode.Right == 2) && this.StringFormatY.Operator())
  8577. {
  8578. var text = this.StringFormatY.Text;
  8579. var textWidth = this.Canvas.measureText(text).width; //前后各空2个像素
  8580. var textSize={ Width:textWidth+4, Height:this.TextHeight, Text:[] };
  8581. var margin=this.LeftConfig.Margin;
  8582. var textOffset=this.LeftConfig.TextOffset;
  8583. var rtBG=null;
  8584. if (this.Frame.ChartBorder.Left >= 30 && this.ShowTextMode.Left==1)
  8585. {
  8586. var rtBG={ Right:left, Width:textWidth+margin.Left+margin.Right, YCenter:y, Height:textHeight+margin.Top+margin.Bottom };
  8587. rtBG.Left=rtBG.Right-rtBG.Width;
  8588. rtBG.Top=rtBG.YCenter-rtBG.Height/2;
  8589. rtBG.Bottom=rtBG.Top+rtBG.Height;
  8590. if (rtBG.Left<0)
  8591. {
  8592. rtBG.Left=0;
  8593. rtBG.Right=rtBG.Left+rtBG.Width;
  8594. }
  8595. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.LEFT_TEXT_ID;
  8596. }
  8597. else if (this.ShowTextMode.Left==2) //在框架内显示
  8598. {
  8599. var rtBG={ Left:left, Width:textWidth+margin.Left+margin.Right, YCenter:y, Height:textHeight+margin.Top+margin.Bottom };
  8600. rtBG.Right=rtBG.Left+rtBG.Width;
  8601. rtBG.Top=rtBG.YCenter-rtBG.Height/2;
  8602. rtBG.Bottom=rtBG.Top+rtBG.Height;
  8603. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.LEFT_INTER_TEXT_ID;
  8604. }
  8605. if (rtBG)
  8606. {
  8607. this.DrawTextBGRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height);
  8608. this.Canvas.textAlign="left";
  8609. this.Canvas.textBaseline="bottom";
  8610. this.Canvas.fillStyle=this.TextColor;
  8611. this.Canvas.fillText(text,rtBG.Left+textOffset.X, rtBG.Bottom+textOffset.Y);
  8612. }
  8613. var complexText=
  8614. {
  8615. ShowType:0, //0=单行(默认) 1=多行
  8616. Font:this.Font, Color:this.TextColor,
  8617. Text:[ { Text:text, Margin:this.RightConfig.Margin, TextOffset:this.RightConfig.TextOffset } ],
  8618. };
  8619. var yTop=y-this.TextHeight/2;
  8620. var textSize={ Width:0, Height:0, Text:[] };
  8621. if (this.StringFormatY.PercentageText)
  8622. {
  8623. if (this.TextFormat.Right==0)
  8624. {
  8625. text=this.StringFormatY.PercentageText+'%';
  8626. complexText.Text[0].Text=text;
  8627. }
  8628. }
  8629. if (this.StringFormatY.RText)
  8630. {
  8631. text = this.StringFormatY.RText;
  8632. complexText.Text[0].Text=text;
  8633. }
  8634. if (this.StringFormatY.RComplexText && IFrameSplitOperator.IsNonEmptyArray(this.StringFormatY.RComplexText.Text))
  8635. {
  8636. complexText=this.StringFormatY.RComplexText;
  8637. if (!complexText.Font) complexText.Font=this.Font;
  8638. if (!complexText.Font) complexText.Color=this.TextColor;
  8639. }
  8640. this.CalculateComplexTextSize(complexText, textSize);
  8641. //计算右侧文本输出顶部位置
  8642. function _Temp_CalculateRightTextBGTop(rtBG, complexText, defatulTextHeight)
  8643. {
  8644. if (complexText.ShowType==1)
  8645. {
  8646. var yValue=defatulTextHeight/2;
  8647. if (IFrameSplitOperator.IsNonEmptyArray(textSize.Text) && textSize.Text[0])
  8648. {
  8649. var itemSize=textSize.Text[0];
  8650. if (IFrameSplitOperator.IsNumber(itemSize.Height)) yValue=itemSize.Height/2;
  8651. }
  8652. rtBG.Top=rtBG.YCenter-yValue;
  8653. rtBG.Bottom=rtBG.Top+rtBG.Height;
  8654. }
  8655. else
  8656. {
  8657. rtBG.Top=rtBG.YCenter-rtBG.Height/2;
  8658. rtBG.Bottom=rtBG.Top+rtBG.Height;
  8659. }
  8660. }
  8661. if (this.Frame.ChartBorder.Right >= 30 && this.ShowTextMode.Right == 1)
  8662. {
  8663. var rtBG={ Left:right+1, Width:textSize.Width, YCenter:y, Height:textSize.Height };
  8664. rtBG.Right=rtBG.Left+rtBG.Width;
  8665. _Temp_CalculateRightTextBGTop(rtBG, complexText, this.TextHeight);
  8666. if (rtBG.Right>chartRight)
  8667. {
  8668. rtBG.Right=chartRight;
  8669. rtBG.Left=rtBG.Right-rtBG.Width;
  8670. }
  8671. this.DrawTextBGRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height);
  8672. this.DrawComplexRightText(rtBG,complexText,textSize);
  8673. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.RIGHT_TEXT_ID;
  8674. }
  8675. else if (this.ShowTextMode.Right == 2)
  8676. {
  8677. var rtBG={ Right:right, Width:textSize.Width, YCenter:y, Height:textSize.Height };
  8678. rtBG.Left=rtBG.Right-rtBG.Width;
  8679. _Temp_CalculateRightTextBGTop(rtBG, complexText, this.TextHeight);
  8680. this.Canvas.fillStyle=this.TextBGColor;
  8681. this.DrawTextBGRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height);
  8682. this.DrawComplexRightText(rtBG,complexText,textSize);
  8683. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.RIGHT_INTER_TEXT_ID;
  8684. }
  8685. }
  8686. //Bottom==8 自定义X轴文字位置
  8687. if ((this.ShowTextMode.Bottom == 1 || this.ShowTextMode.Bottom==8) && this.StringFormatX.Operator())
  8688. {
  8689. var text = this.StringFormatX.Text;
  8690. this.Canvas.font = this.Font;
  8691. this.Canvas.fillStyle = this.TextBGColor;
  8692. var textWidth = this.Canvas.measureText(text).width; //前后各空2个像素
  8693. var margin=this.BottomConfig.Margin;
  8694. var textOffset=this.BottomConfig.TextOffset;
  8695. var rtBG=
  8696. {
  8697. Top:bottom, Height:margin.Top+margin.Bottom+textHeight,
  8698. XCenter:x, Width:textWidth+margin.Left+margin.Right
  8699. };
  8700. rtBG.Bottom=rtBG.Top+rtBG.Height;
  8701. rtBG.Left=rtBG.XCenter-rtBG.Width/2;
  8702. rtBG.Right=rtBG.Left+rtBG.Width;
  8703. if (rtBG.Left<=0)
  8704. {
  8705. rtBG.Left=0;
  8706. rtBG.Right=rtBG.Left+rtBG.Width;
  8707. }
  8708. else if (rtBG.Right>=right)
  8709. {
  8710. rtBG.Right=right;
  8711. rtBG.Left=rtBG.Right-rtBG.Width;
  8712. }
  8713. var bShowText=true;
  8714. if (this.ShowTextMode.Bottom==2)
  8715. {
  8716. rtBG.Bottom=bottom;
  8717. rtBG.Top=rtBG.Bottom-rtBG.Height;
  8718. }
  8719. else if (this.ShowTextMode.Bottom==8)
  8720. {
  8721. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_CORSSCURSOR_POSITION);
  8722. if (event && event.Callback)
  8723. {
  8724. var sendData={ RectText:rtBG, IsShowText:bShowText, X:x, Y:y };
  8725. event.Callback(event, sendData, this);
  8726. bShowText=sendData.IsShowText;
  8727. }
  8728. }
  8729. //JSConsole.Chart.Log('[ChartCorssCursor::Draw] ',yCenter);
  8730. if (bShowText)
  8731. {
  8732. this.DrawTextBGRect(rtBG.Left,rtBG.Top,rtBG.Width,rtBG.Height);
  8733. this.Canvas.textAlign="left";
  8734. this.Canvas.textBaseline="bottom";
  8735. this.Canvas.fillStyle=this.TextColor;
  8736. this.Canvas.fillText(text,rtBG.Left+textOffset.X,rtBG.Bottom+textOffset.Y,textWidth);
  8737. var buttonData={X:x, Y:y, XValue:xValue, FrameID:yValueExtend.FrameID };
  8738. if (this.StringFormatX.KItem) buttonData.KItem=this.StringFormatX.KItem;
  8739. this.BottomButton.Rect=rtBG;
  8740. this.BottomButton.Data=buttonData;
  8741. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.BOTTOM_TEXT_ID;
  8742. }
  8743. }
  8744. }
  8745. this.GetFontHeight=function(font)
  8746. {
  8747. if (font) this.Canvas.font=font;
  8748. var textHeight= this.Canvas.measureText("擎").width;
  8749. return textHeight;
  8750. }
  8751. this.DrawTextBGRect=function(x,y, height, width)
  8752. {
  8753. this.Canvas.fillStyle=this.TextBGColor;
  8754. this.Canvas.fillRect(ToFixedPoint(x),ToFixedPoint(y),ToFixedRect(height),ToFixedRect(width));
  8755. //this.Canvas.fillRect(x,y,height,width);
  8756. }
  8757. this.CalculateComplexTextSize=function(complexText, size)
  8758. {
  8759. if (!complexText || !IFrameSplitOperator.IsNonEmptyArray(complexText.Text)) return;
  8760. var showType=0;
  8761. if (complexText.ShowType==1) showType=complexText.ShowType;
  8762. if (showType==1) //多行
  8763. {
  8764. var textWidth=0, textHeight=0;
  8765. for(var i=0; i<complexText.Text.length; ++i)
  8766. {
  8767. var item=complexText.Text[i];
  8768. if (item.Font) this.Canvas.font=item.Font;
  8769. else this.Canvas.font=complexText.Font;
  8770. var itemWidth=this.Canvas.measureText(item.Text).width; //前后各空2个像素
  8771. var itemHeight=this.GetFontHeight();
  8772. if (item.Margin)
  8773. {
  8774. var margin=item.Margin;
  8775. if (IFrameSplitOperator.IsNumber(margin.Left)) itemWidth+=margin.Left;
  8776. if (IFrameSplitOperator.IsNumber(margin.Right)) itemWidth+=margin.Right;
  8777. if (IFrameSplitOperator.IsNumber(margin.Top)) itemHeight+=margin.Top;
  8778. if (IFrameSplitOperator.IsNumber(margin.Bottom)) itemHeight+=margin.Bottom;
  8779. }
  8780. size.Text[i]={ Width:itemWidth, Height:itemHeight }; //保存所有文字的大小信息
  8781. if (textWidth<itemWidth) textWidth=itemWidth;
  8782. textHeight+=itemHeight;
  8783. }
  8784. size.Width=textWidth;
  8785. size.Height=textHeight;
  8786. }
  8787. else //水平 单行
  8788. {
  8789. var textWidth=0, textHeight=this.GetFontHeight();
  8790. for(var i=0; i<complexText.Text.length; ++i)
  8791. {
  8792. var item=complexText.Text[i];
  8793. if (item.Font) this.Canvas.font=item.Font;
  8794. else this.Canvas.font=complexText.Font;
  8795. var itemWidth=this.Canvas.measureText(item.Text).width; //前后各空2个像素
  8796. var itemHeight=this.Canvas.measureText("擎").width;
  8797. if (item.Margin)
  8798. {
  8799. var margin=item.Margin;
  8800. if (IFrameSplitOperator.IsNumber(margin.Left)) itemWidth+=margin.Left;
  8801. if (IFrameSplitOperator.IsNumber(margin.Right)) itemWidth+=margin.Right;
  8802. if (IFrameSplitOperator.IsNumber(margin.Top)) itemHeight+=margin.Top;
  8803. if (IFrameSplitOperator.IsNumber(margin.Bottom)) itemHeight+=margin.Bottom;
  8804. }
  8805. size.Text[i]={ Width:itemWidth, Height:itemHeight }; //保存所有文字的大小信息
  8806. textWidth+=itemWidth;
  8807. if (textHeight<itemHeight) textHeight=itemHeight;
  8808. }
  8809. size.Width=textWidth;
  8810. size.Height=textHeight;
  8811. }
  8812. }
  8813. this.DrawComplexTextV2=function(left, yTop, complexText, size)
  8814. {
  8815. this.Canvas.textAlign="left";
  8816. this.Canvas.textBaseline="bottom";
  8817. var showType=0;
  8818. if (complexText.ShowType==1) showType=complexText.ShowType;
  8819. if (showType==1) //多行
  8820. {
  8821. var xLeft=left;
  8822. var yText=yTop; //顶
  8823. for(var i=0; i<complexText.Text.length; ++i)
  8824. {
  8825. var item=complexText.Text[i];
  8826. var itemSize=size.Text[i];
  8827. if (item.Font) this.Canvas.font=item.Font;
  8828. else this.Canvas.font=complexText.Font;
  8829. if (item.Color) this.Canvas.fillStyle=item.Color;
  8830. else this.Canvas.fillStyle=complexText.Color;
  8831. var y=yText+itemSize.Height;
  8832. var x=xLeft;
  8833. if (item.Margin)
  8834. {
  8835. var margin=item.Margin;
  8836. if (IFrameSplitOperator.IsNumber(margin.Bottom)) y-=margin.Bottom;
  8837. if (IFrameSplitOperator.IsNumber(margin.Left)) x+=margin.Left;
  8838. }
  8839. this.Canvas.fillText(item.Text,x,y,itemSize.Width);
  8840. yText+=itemSize.Height;
  8841. }
  8842. }
  8843. else //水平 单行
  8844. {
  8845. var xText=left;
  8846. var yBottom=yTop+size.Height;
  8847. for(var i=0; i<complexText.Text.length; ++i)
  8848. {
  8849. var item=complexText.Text[i];
  8850. var itemSize=size.Text[i];
  8851. if (item.Font) this.Canvas.font=item.Font;
  8852. else this.Canvas.font=complexText.Font;
  8853. if (item.Color) this.Canvas.fillStyle=item.Color;
  8854. else this.Canvas.fillStyle=complexText.Color;
  8855. var y=yBottom;
  8856. var x=xText;
  8857. if (item.Margin)
  8858. {
  8859. var margin=item.Margin;
  8860. if (IFrameSplitOperator.IsNumber(margin.Bottom)) y-=margin.Bottom;
  8861. if (IFrameSplitOperator.IsNumber(margin.Left)) x+=margin.Left;
  8862. }
  8863. this.Canvas.fillText(item.Text,x,y,itemSize.Width);
  8864. xText+=itemSize.Width;
  8865. }
  8866. }
  8867. }
  8868. this.DrawComplexRightText=function(rtBG, complexText, size)
  8869. {
  8870. this.Canvas.textAlign="left";
  8871. this.Canvas.textBaseline="bottom";
  8872. var showType=0;
  8873. if (complexText.ShowType==1) showType=complexText.ShowType;
  8874. if (showType==1) //多行
  8875. {
  8876. var xLeft=rtBG.Left;
  8877. var yTop=rtBG.Top; //顶
  8878. for(var i=0; i<complexText.Text.length; ++i)
  8879. {
  8880. var item=complexText.Text[i];
  8881. var itemSize=size.Text[i];
  8882. if (item.Font) this.Canvas.font=item.Font;
  8883. else this.Canvas.font=complexText.Font;
  8884. if (item.Color) this.Canvas.fillStyle=item.Color;
  8885. else this.Canvas.fillStyle=complexText.Color;
  8886. var y=yTop+itemSize.Height;
  8887. var x=xLeft;
  8888. if (item.TextOffset)
  8889. {
  8890. var textOffset=item.TextOffset;
  8891. if (IFrameSplitOperator.IsNumber(textOffset.X)) x+=textOffset.X;
  8892. if (IFrameSplitOperator.IsNumber(textOffset.Y)) y+=textOffset.Y;
  8893. }
  8894. this.Canvas.fillText(item.Text,x,y,itemSize.Width);
  8895. yTop+=itemSize.Height;
  8896. }
  8897. }
  8898. else //水平 单行
  8899. {
  8900. var xText=rtBG.Left;
  8901. var yBottom=rtBG.Bottom;
  8902. for(var i=0; i<complexText.Text.length; ++i)
  8903. {
  8904. var item=complexText.Text[i];
  8905. var itemSize=size.Text[i];
  8906. if (item.Font) this.Canvas.font=item.Font;
  8907. else this.Canvas.font=complexText.Font;
  8908. if (item.Color) this.Canvas.fillStyle=item.Color;
  8909. else this.Canvas.fillStyle=complexText.Color;
  8910. var x=xText;
  8911. var y=yBottom;
  8912. if (item.TextOffset)
  8913. {
  8914. var textOffset=item.TextOffset;
  8915. if (IFrameSplitOperator.IsNumber(textOffset.X)) x+=textOffset.X;
  8916. if (IFrameSplitOperator.IsNumber(textOffset.Y)) y+=textOffset.Y;
  8917. }
  8918. this.Canvas.fillText(item.Text,x,y,itemSize.Width);
  8919. xText+=itemSize.Width;
  8920. }
  8921. }
  8922. }
  8923. this.HScreenDraw = function ()
  8924. {
  8925. this.Status=JSCHART_CORSSCURSOR_STATUS_ID.NONE_ID;
  8926. var x = this.LastPoint.X;
  8927. var y = this.LastPoint.Y;
  8928. y = this.Frame.GetXFromIndex(this.CursorIndex); //手机端 十字只能画在K线上
  8929. if (this.IsShowClose) //手机端 十字只能画在K线上
  8930. {
  8931. var yPoint = this.GetCloseYPoint(this.CursorIndex);
  8932. if (yPoint != null) x = yPoint;
  8933. }
  8934. else if (this.IsOnlyDrawMinute)
  8935. {
  8936. var yPoint = this.GetMinuteCloseYPoint(this.CursorIndex);
  8937. if (yPoint != null) x=yPoint;
  8938. }
  8939. var left = this.Frame.ChartBorder.GetLeft();
  8940. var right = this.Frame.ChartBorder.GetRightEx();
  8941. var top = this.Frame.ChartBorder.GetTop();
  8942. var bottom = this.Frame.ChartBorder.GetBottom();
  8943. var bottomWidth = this.Frame.ChartBorder.Bottom;
  8944. this.PointY = [[left, y], [right, y]];
  8945. this.PointX = [[x, top], [x, bottom]];
  8946. if (this.IsShowCorss) //十字线
  8947. {
  8948. this.Canvas.save();
  8949. this.Canvas.strokeStyle = this.HPenColor;
  8950. if (this.HPenType == 0) this.Canvas.setLineDash(this.LineDash); //虚线
  8951. //画竖线
  8952. this.Canvas.beginPath();
  8953. this.Canvas.moveTo(ToFixedPoint(x), top);
  8954. this.Canvas.lineTo(ToFixedPoint(x), bottom);
  8955. this.Canvas.stroke();
  8956. this.Canvas.restore();
  8957. this.Canvas.save();
  8958. this.Canvas.strokeStyle = this.VPenColor;
  8959. if (this.VPenType == 0)
  8960. {
  8961. this.Canvas.setLineDash(this.LineDash); //虚线
  8962. }
  8963. else if (this.VPenType == 2)
  8964. {
  8965. let barWidth = this.Frame.SubFrame[0].Frame.DataWidth; //和K线一样宽度
  8966. if (barWidth > 2) this.Canvas.lineWidth = barWidth;
  8967. }
  8968. this.Canvas.beginPath();
  8969. //画横线
  8970. if (this.Frame.SubFrame.length > 0)
  8971. {
  8972. for (var i in this.Frame.SubFrame)
  8973. {
  8974. var frame = this.Frame.SubFrame[i].Frame;
  8975. this.Canvas.moveTo(frame.ChartBorder.GetLeft(), ToFixedPoint(y));
  8976. this.Canvas.lineTo(frame.ChartBorder.GetRightTitle(), ToFixedPoint(y));
  8977. }
  8978. }
  8979. else
  8980. {
  8981. this.Canvas.moveTo(left, ToFixedPoint(y));
  8982. this.Canvas.lineTo(right, ToFixedPoint(y));
  8983. }
  8984. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.LINE_ID;
  8985. this.Canvas.stroke();
  8986. this.Canvas.restore();
  8987. this.Canvas.save();
  8988. this.DrawCorssPoint(x,y);
  8989. this.Canvas.restore();
  8990. }
  8991. var xValue = this.Frame.GetXData(y);
  8992. var yValueExtend = {};
  8993. var yValue = this.Frame.GetYData(x, yValueExtend);
  8994. this.StringFormatX.Value = xValue;
  8995. this.StringFormatY.Value = yValue;
  8996. this.StringFormatY.RValue=yValueExtend.RightYValue; //右侧子坐标
  8997. this.StringFormatY.Point={X:x, Y:y};
  8998. this.StringFormatY.FrameID = yValueExtend.FrameID;
  8999. if (((this.ShowTextMode.Left == 1 && this.Frame.ChartBorder.Top >= 30) || this.ShowTextMode.Left == 2 ||
  9000. (this.ShowTextMode.Right == 1 && this.Frame.ChartBorder.Bottom >= 30) || this.ShowTextMode.Right == 2) && this.StringFormatY.Operator()) {
  9001. var text = this.StringFormatY.Text;
  9002. this.Canvas.font = this.Font;
  9003. var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
  9004. if (this.Frame.ChartBorder.Top >= 30 && this.ShowTextMode.Left == 1)
  9005. {
  9006. var xText = x, yText = top;
  9007. this.Canvas.save();
  9008. this.Canvas.translate(xText, yText);
  9009. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  9010. this.Canvas.fillStyle = this.TextBGColor;
  9011. if (top >= textWidth)
  9012. {
  9013. this.Canvas.fillRect(-textWidth, -(this.TextHeight / 2), textWidth, this.TextHeight);
  9014. this.Canvas.textAlign = "right";
  9015. this.Canvas.textBaseline = "middle";
  9016. this.Canvas.fillStyle = this.TextColor;
  9017. this.Canvas.fillText(text, -2, 0, textWidth);
  9018. }
  9019. else
  9020. {
  9021. this.Canvas.fillRect((textWidth - top), -(this.TextHeight / 2), -textWidth, this.TextHeight);
  9022. this.Canvas.textAlign = "right";
  9023. this.Canvas.textBaseline = "middle";
  9024. this.Canvas.fillStyle = this.TextColor;
  9025. this.Canvas.fillText(text, (textWidth - top) - 2, 0, textWidth);
  9026. }
  9027. this.Canvas.restore();
  9028. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.LEFT_TEXT_ID;
  9029. }
  9030. else if (this.ShowTextMode.Left == 2)
  9031. {
  9032. var xText = x;
  9033. var yText = top;
  9034. this.Canvas.save();
  9035. this.Canvas.translate(xText, yText);
  9036. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  9037. this.Canvas.fillStyle = this.TextBGColor;
  9038. this.Canvas.fillRect(0, -(this.TextHeight / 2), textWidth, this.TextHeight);
  9039. this.Canvas.textAlign = "left";
  9040. this.Canvas.textBaseline = "middle";
  9041. this.Canvas.fillStyle = this.TextColor;
  9042. this.Canvas.fillText(text, 2, 0, textWidth);
  9043. this.Canvas.restore();
  9044. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.LEFT_INTER_TEXT_ID;
  9045. }
  9046. if (this.StringFormatY.RText)
  9047. {
  9048. text=this.StringFormatY.RText;
  9049. var textWidth=this.Canvas.measureText(text).width+4; //前后各空2个像素
  9050. }
  9051. if (this.Frame.ChartBorder.Bottom >= 30 && this.ShowTextMode.Right == 1)
  9052. {
  9053. var xText = x, yText = bottom;
  9054. this.Canvas.save();
  9055. this.Canvas.translate(xText, yText);
  9056. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  9057. this.Canvas.fillStyle = this.TextBGColor;
  9058. if (bottomWidth > textWidth)
  9059. {
  9060. this.Canvas.fillRect(0, -(this.TextHeight / 2), textWidth, this.TextHeight);
  9061. this.Canvas.textAlign = "left";
  9062. this.Canvas.textBaseline = "middle";
  9063. this.Canvas.fillStyle = this.TextColor;
  9064. this.Canvas.fillText(text, 2, 0, textWidth);
  9065. }
  9066. else
  9067. {
  9068. this.Canvas.fillRect((bottomWidth - textWidth), -(this.TextHeight / 2), textWidth, this.TextHeight);
  9069. this.Canvas.textAlign = "left";
  9070. this.Canvas.textBaseline = "middle";
  9071. this.Canvas.fillStyle = this.TextColor;
  9072. this.Canvas.fillText(text, (bottomWidth - textWidth) + 2, 0, textWidth);
  9073. }
  9074. this.Canvas.restore();
  9075. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.RIGHT_TEXT_ID;
  9076. }
  9077. else if (this.ShowTextMode.Right == 2) {
  9078. var xText = x;
  9079. var yText = bottom;
  9080. this.Canvas.save();
  9081. this.Canvas.translate(xText, yText);
  9082. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  9083. this.Canvas.fillStyle = this.TextBGColor;
  9084. this.Canvas.fillRect(0, -(this.TextHeight / 2), -textWidth, this.TextHeight);
  9085. this.Canvas.textAlign = "right";
  9086. this.Canvas.textBaseline = "middle";
  9087. this.Canvas.fillStyle = this.TextColor;
  9088. this.Canvas.fillText(text, -2, 0, textWidth);
  9089. this.Canvas.restore();
  9090. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.RIGHT_INTER_TEXT_ID;
  9091. }
  9092. }
  9093. if ((this.ShowTextMode.Bottom === 1 ||this.ShowTextMode.Bottom==8) && this.StringFormatX.Operator())
  9094. {
  9095. var text = this.StringFormatX.Text;
  9096. this.Canvas.font = this.Font;
  9097. this.Canvas.fillStyle = this.TextBGColor;
  9098. var textWidth = this.Canvas.measureText(text).width + 4; //前后各空2个像素
  9099. var bShowText=true;
  9100. var yText = y;
  9101. var xText=left;
  9102. if (this.ShowTextMode.Bottom==8)
  9103. {
  9104. var event=this.GetEventCallback(JSCHART_EVENT_ID.ON_CUSTOM_CORSSCURSOR_POSITION);
  9105. if (event && event.Callback)
  9106. {
  9107. var sendData={ XText:xText, Height:this.TextHeight, IsShowText:bShowText };
  9108. event.Callback(event, sendData, this);
  9109. xText=sendData.XText;
  9110. bShowText=sendData.IsShowText;
  9111. }
  9112. }
  9113. if (bShowText)
  9114. {
  9115. if (y - textWidth / 2 < 3) //左边位置不够了, 顶着左边画
  9116. {
  9117. this.Canvas.save();
  9118. this.Canvas.translate(xText, yText);
  9119. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  9120. this.Canvas.fillRect(0, 0, textWidth, this.TextHeight);
  9121. this.Canvas.textAlign = "center";
  9122. this.Canvas.textBaseline = "top";
  9123. this.Canvas.fillStyle = this.TextColor;
  9124. this.Canvas.fillText(text, 0, 0, textWidth);
  9125. this.Canvas.restore();
  9126. }
  9127. else
  9128. {
  9129. this.Canvas.save();
  9130. this.Canvas.translate(xText, yText);
  9131. this.Canvas.rotate(90 * Math.PI / 180); //数据和框子旋转180度
  9132. this.Canvas.fillRect(-(textWidth / 2), 0, textWidth, this.TextHeight);
  9133. this.Canvas.textAlign = "center";
  9134. this.Canvas.textBaseline = "top";
  9135. this.Canvas.fillStyle = this.TextColor;
  9136. this.Canvas.fillText(text, 0, 0, textWidth);
  9137. this.Canvas.restore();
  9138. }
  9139. this.Status|=JSCHART_CORSSCURSOR_STATUS_ID.BOTTOM_TEXT_ID;
  9140. }
  9141. }
  9142. }
  9143. this.DrawCorssPoint=function(x,y)
  9144. {
  9145. var config=this.CorssPointConfig;
  9146. if (!config.Enable) return;
  9147. this.Canvas.beginPath();
  9148. this.Canvas.arc(x,y,config.Center.Radius,0,360,false);
  9149. this.Canvas.closePath();
  9150. if (config.Center && config.Center.Color)
  9151. {
  9152. this.Canvas.fillStyle=config.Center.Color;
  9153. this.Canvas.fill();
  9154. }
  9155. if (config.Border && config.Border.Color)
  9156. {
  9157. this.Canvas.strokeStyle=config.Border.Color;
  9158. if (IFrameSplitOperator.IsNumber(config.Border.Width)) this.Canvas.lineWidth=config.Border.Width;
  9159. this.Canvas.stroke();
  9160. }
  9161. }
  9162. this.PtInButton=function(x,y)
  9163. {
  9164. var item=this.PtInButtomButton(x,y);
  9165. if (item) return item;
  9166. return null;
  9167. }
  9168. this.PtInButtomButton=function(x,y)
  9169. {
  9170. if (!this.BottomButton.Enable) return null;
  9171. if (!this.BottomButton.Rect) return null;
  9172. var rect=this.BottomButton.Rect;
  9173. if (x>=rect.Left && x<=rect.Right && y>=rect.Top && y<=rect.Bottom)
  9174. {
  9175. return { Data:this.BottomButton.Data, Rect:rect , Type:2 }; //Type:1=右侧 2=底部
  9176. }
  9177. return null;
  9178. }
  9179. }
  9180. //分钟线
  9181. function ChartMinutePriceLine()
  9182. {
  9183. this.newMethod = ChartLine; //派生
  9184. this.newMethod();
  9185. delete this.newMethod;
  9186. this.YClose;
  9187. this.IsDrawArea = true; //是否画价格面积图
  9188. this.AreaColor = 'rgba(0,191,255,0.1)';
  9189. this.LastPoint={}; //最后一个点的信息 {X, Y, Data:, Value:, DateTime:YYYYMMDDHHMMSS }
  9190. this.UpdateLastPoint=function(dateTime, x,y, item)
  9191. {
  9192. if (IFrameSplitOperator.IsNumber(this.LastPoint.DateTime) && this.LastPoint.DateTime>dateTime) return;
  9193. this.LastPoint.DateTime=dateTime;
  9194. this.LastPoint.X=x;
  9195. this.LastPoint.Y=y;
  9196. this.LastPoint.Data=item;
  9197. this.LastPoint.Value=item.Value;
  9198. }
  9199. this.Draw = function ()
  9200. {
  9201. this.LastPoint={};
  9202. if (this.NotSupportMessage)
  9203. {
  9204. this.DrawNotSupportmessage();
  9205. return;
  9206. }
  9207. if (!this.IsShow) return;
  9208. if (!this.Data) return;
  9209. var isHScreen = (this.ChartFrame.IsHScreen === true);
  9210. var dataWidth = this.ChartFrame.DataWidth;
  9211. var distanceWidth = this.ChartFrame.DistanceWidth;
  9212. var chartright = this.ChartBorder.GetRight();
  9213. if (isHScreen === true) chartright = this.ChartBorder.GetBottom();
  9214. var xPointCount = this.ChartFrame.XPointCount;
  9215. var minuteCount = this.ChartFrame.MinuteCount;
  9216. var bottom = this.ChartBorder.GetBottom();
  9217. var left = this.ChartBorder.GetLeft();
  9218. var bFirstPoint = true;
  9219. var ptFirst = {}; //第1个点
  9220. var drawCount = 0;
  9221. var pointCount=0;
  9222. this.Canvas.save();
  9223. this.ClipClient(isHScreen); //裁剪区域 防止线段毛刺超出图形
  9224. if (IFrameSplitOperator.IsPlusNumber(this.LineWidth>0)) this.Canvas.lineWidth=this.LineWidth;
  9225. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  9226. {
  9227. var value = this.Data.Data[i];
  9228. ++pointCount;
  9229. if (value == null) continue;
  9230. var x = this.ChartFrame.GetXFromIndex(j);
  9231. var y = this.ChartFrame.GetYFromData(value);
  9232. if (bFirstPoint)
  9233. {
  9234. this.Canvas.strokeStyle = this.Color;
  9235. this.Canvas.beginPath();
  9236. if (isHScreen) this.Canvas.moveTo(y, x);
  9237. else this.Canvas.moveTo(x, y);
  9238. bFirstPoint = false;
  9239. ptFirst = { X: x, Y: y };
  9240. }
  9241. else
  9242. {
  9243. if (isHScreen) this.Canvas.lineTo(y, x);
  9244. else this.Canvas.lineTo(x, y);
  9245. }
  9246. if (this.Source)
  9247. {
  9248. var item=this.Source.Data[i];
  9249. var dateTime=item.Date*1000000+item.Time*100;
  9250. this.UpdateLastPoint(dateTime, x,y, { Value:value, Index:i, Date:item.Date, Time:item.Time, Type:0, Explain:"盘中"});
  9251. }
  9252. ++drawCount;
  9253. if (pointCount >= minuteCount) //上一天的数据和这天地数据线段要断开
  9254. {
  9255. bFirstPoint = true;
  9256. this.Canvas.stroke();
  9257. if (this.IsDrawArea) //画面积
  9258. {
  9259. if (isHScreen)
  9260. {
  9261. this.Canvas.lineTo(left, x);
  9262. this.Canvas.lineTo(left, ptFirst.X);
  9263. this.SetFillStyle(this.AreaColor, this.ChartBorder.GetRight(), bottom, this.ChartBorder.GetLeftEx(), bottom);
  9264. }
  9265. else
  9266. {
  9267. this.Canvas.lineTo(x, bottom);
  9268. this.Canvas.lineTo(ptFirst.X, bottom);
  9269. this.SetFillStyle(this.AreaColor, left, this.ChartBorder.GetTopEx(), left, bottom);
  9270. }
  9271. this.Canvas.fill();
  9272. }
  9273. drawCount = 0;
  9274. pointCount=0;
  9275. }
  9276. }
  9277. if (drawCount > 0)
  9278. {
  9279. if (drawCount==1) //如果线段只有1个点 线段无法画出来 直接画点
  9280. {
  9281. this.Canvas.beginPath();
  9282. if (isHScreen)
  9283. this.Canvas.arc(ptFirst.Y, ptFirst.X, 1,0,360, false);
  9284. else
  9285. this.Canvas.arc(ptFirst.X, ptFirst.Y, 1,0,360, false);
  9286. this.Canvas.closePath();
  9287. this.Canvas.fillStyle=this.Color;
  9288. this.Canvas.fill();
  9289. }
  9290. else
  9291. {
  9292. this.Canvas.stroke();
  9293. if (this.IsDrawArea) //画面积
  9294. {
  9295. if (isHScreen)
  9296. {
  9297. this.Canvas.lineTo(left, x);
  9298. this.Canvas.lineTo(left, ptFirst.X);
  9299. this.SetFillStyle(this.AreaColor, this.ChartBorder.GetRight(), bottom, this.ChartBorder.GetLeftEx(), bottom);
  9300. }
  9301. else
  9302. {
  9303. this.Canvas.lineTo(x, bottom);
  9304. this.Canvas.lineTo(ptFirst.X, bottom);
  9305. this.SetFillStyle(this.AreaColor, left, this.ChartBorder.GetTopEx(), left, bottom);
  9306. }
  9307. this.Canvas.fill();
  9308. }
  9309. }
  9310. }
  9311. this.Canvas.restore();
  9312. if (this.Identify=="Minute-Line" && this.ChartFrame.GlobalOption)
  9313. {
  9314. var globalOption=this.ChartFrame.GlobalOption;
  9315. globalOption.LatestPoint={ X:this.LastPoint.X, Y:this.LastPoint.Y };
  9316. }
  9317. }
  9318. this.GetMaxMin = function ()
  9319. {
  9320. var xPointCount = this.ChartFrame.XPointCount;
  9321. var range = {};
  9322. if (this.YClose == null) return range;
  9323. range.Min = this.YClose;
  9324. range.Max = this.YClose;
  9325. for (var i = this.Data.DataOffset, j = 0; i < this.Data.Data.length && j < xPointCount; ++i, ++j)
  9326. {
  9327. var value = this.Data.Data[i];
  9328. if (!value) continue;
  9329. if (range.Max == null) range.Max = value;
  9330. if (range.Min == null) range.Min = value;
  9331. if (range.Max < value) range.Max = value;
  9332. if (range.Min > value) range.Min = value;
  9333. }
  9334. if (range.Max == this.YClose && range.Min == this.YClose)
  9335. {
  9336. range.Max = this.YClose + this.YClose * 0.1;
  9337. range.Min = this.YClose - this.YClose * 0.1;
  9338. return range;
  9339. }
  9340. var distance = Math.max(Math.abs(this.YClose - range.Max), Math.abs(this.YClose - range.Min));
  9341. range.Max = this.YClose + distance;
  9342. range.Min = this.YClose - distance;
  9343. return range;
  9344. }
  9345. }
  9346. ////////////////////////////////////////////////////////////////////////////////
  9347. //深度图十字光标
  9348. function DepthChartCorssCursor()
  9349. {
  9350. this.Frame;
  9351. this.Canvas; //画布
  9352. this.Data;
  9353. this.Symbol;
  9354. this.HQChart;
  9355. this.HPenType=0; //水平线样式 0=虚线 1=实线
  9356. this.VPenType=0; //垂直线颜色 0=虚线 1=实线
  9357. this.LineDash=g_JSChartResource.DepthCorss.LineDash;
  9358. this.AskColor=g_JSChartResource.DepthCorss.AskColor.Line; //卖
  9359. this.BidColor=g_JSChartResource.DepthCorss.BidColor.Line; //买
  9360. this.LineWidth=g_JSChartResource.DepthCorss.LineWidth;
  9361. this.IsShowTooltip=true;
  9362. this.Tooltip=
  9363. {
  9364. LineHeight:g_JSChartResource.DepthCorss.Tooltip.LineHeight,
  9365. Border:
  9366. {
  9367. Top:g_JSChartResource.DepthCorss.Tooltip.Border.Top,
  9368. Left:g_JSChartResource.DepthCorss.Tooltip.Border.Left,
  9369. Right:g_JSChartResource.DepthCorss.Tooltip.Border.Right,
  9370. Bottom:g_JSChartResource.DepthCorss.Tooltip.Border.Bottom,
  9371. ItemSpace: g_JSChartResource.DepthCorss.Tooltip.Border.ItemSpace
  9372. },
  9373. Font:g_JSChartResource.DepthCorss.Tooltip.Font,
  9374. TextColor:g_JSChartResource.DepthCorss.Tooltip.TextColor,
  9375. BGColor:g_JSChartResource.DepthCorss.Tooltip.BGColor
  9376. }; // Width: Height:
  9377. this.Font=g_JSChartResource.CorssCursorTextFont; //字体
  9378. this.TextColor=g_JSChartResource.CorssCursorTextColor; //文本颜色
  9379. this.TextBGColor=g_JSChartResource.CorssCursorBGColor; //文本背景色
  9380. this.TextHeight=20; //文本字体高度
  9381. this.LastPoint;
  9382. this.PointX;
  9383. this.PointY;
  9384. this.StringFormatX;
  9385. this.StringFormatY;
  9386. this.IsShowCorss=true; //是否显示十字光标
  9387. this.IsShow=true;
  9388. this.GetVol=function(price, isAsk)
  9389. {
  9390. if (!this.Data) return null;
  9391. var aryData=isAsk? this.Data.Asks:this.Data.Bids;
  9392. if (!aryData || !Array.isArray(aryData) || aryData.length<=0) return null;
  9393. for(var i in aryData)
  9394. {
  9395. var item=aryData[i];
  9396. if (item.Price==price) return item.Vol;
  9397. }
  9398. return null;
  9399. }
  9400. this.Draw=function()
  9401. {
  9402. this.Status=0;
  9403. if (!this.LastPoint) return;
  9404. if (!this.Data) return;
  9405. if (!this.IsShow) return;
  9406. var x=this.LastPoint.X;
  9407. var y=this.LastPoint.Y;
  9408. var isInClient=false;
  9409. var rtClient = new Rect(this.Frame.ChartBorder.GetLeft(), this.Frame.ChartBorder.GetTop(), this.Frame.ChartBorder.GetWidth(), this.Frame.ChartBorder.GetHeight());
  9410. isInClient = rtClient.IsPointIn(x, y);
  9411. this.PointY=null;
  9412. this.PointY==null;
  9413. if (!isInClient) return;
  9414. if (this.Frame.IsHScreen===true)
  9415. {
  9416. return;
  9417. }
  9418. var left=this.Frame.ChartBorder.GetLeft();
  9419. var right=this.Frame.ChartBorder.GetRight();
  9420. var top=this.Frame.ChartBorder.GetTopTitle();
  9421. var bottom=this.Frame.ChartBorder.GetBottom();
  9422. var rightWidth=this.Frame.ChartBorder.Right;
  9423. var chartRight=this.Frame.ChartBorder.GetChartWidth();
  9424. var xValue=this.Frame.GetXData(x);
  9425. var xInfo=this.Frame.GetXFromPrice(xValue); //调整价格到有数据的点上
  9426. if (!xInfo) return;
  9427. var yVol=this.GetVol(xInfo.Price, xInfo.IsAsk);
  9428. y=this.Frame.GetYFromData(yVol); //调整Y轴, 让它在线段上
  9429. xInfo.Vol=yVol;
  9430. xInfo.Y=y;
  9431. this.PointY=[[left,y],[right,y]];
  9432. this.PointX=[[x,top],[x,bottom]];
  9433. if (this.IsShowCorss)
  9434. {
  9435. if (xInfo.IsAsk) this.Canvas.strokeStyle=this.AskColor;
  9436. else this.Canvas.strokeStyle=this.BidColor;
  9437. this.Canvas.save();
  9438. this.Canvas.lineWidth=this.LineWidth;
  9439. var lineWidth=this.Canvas.lineWidth;
  9440. if (this.HPenType==1 || this.HPenType==0) //0=实线 1=虚线
  9441. {
  9442. if (this.HPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线
  9443. var yFix=ToFixedPoint(y);
  9444. this.Canvas.beginPath();
  9445. this.Canvas.moveTo(left,yFix);
  9446. this.Canvas.lineTo(right,yFix);
  9447. this.Canvas.stroke();
  9448. if (this.HPenType==0) this.Canvas.setLineDash([]);
  9449. }
  9450. if (this.VPenType==0) this.Canvas.setLineDash(this.LineDash); //虚线
  9451. var xFix=ToFixedPoint(xInfo.X);
  9452. this.Canvas.beginPath();
  9453. this.Canvas.moveTo(xFix,top);
  9454. this.Canvas.lineTo(xFix,bottom);
  9455. this.Canvas.stroke();
  9456. if (this.VPenType==0) this.Canvas.setLineDash([]);
  9457. this.Canvas.restore();
  9458. }
  9459. if (this.HQChart)
  9460. {
  9461. var event=this.HQChart.GetEvent(JSCHART_EVENT_ID.ON_DRAW_DEPTH_TOOLTIP);
  9462. if (event)
  9463. {
  9464. event.Callback(event,xInfo,this);
  9465. }
  9466. }
  9467. if (this.IsShowTooltip)
  9468. {
  9469. var aryText=this.GetFormatTooltip(xInfo);
  9470. this.DrawTooltip(aryText, xInfo);
  9471. }
  9472. }
  9473. //[{Title:, TitleColor:, Text:, Color:}]
  9474. this.GetFormatTooltip=function(drawData)
  9475. {
  9476. var aryText=[];
  9477. var floatPrecision=2;
  9478. if (this.Symbol) floatPrecision=JSCommonCoordinateData.GetfloatPrecision(this.Symbol); //价格小数位数
  9479. var item=
  9480. {
  9481. Title:g_JSChartLocalization.GetText('Depth-Price',this.HQChart.LanguageID),
  9482. TitleColor:this.Tooltip.TextColor,
  9483. Text:drawData.Price.toFixed(floatPrecision),
  9484. Color:this.Tooltip.TextColor
  9485. };
  9486. aryText.push(item);
  9487. var item=
  9488. {
  9489. Title:g_JSChartLocalization.GetText('Depth-Sum',this.HQChart.LanguageID),
  9490. TitleColor:this.Tooltip.TextColor,
  9491. Text:drawData.Vol.toFixed(4),
  9492. Color:this.Tooltip.TextColor
  9493. };
  9494. aryText.push(item);
  9495. return aryText;
  9496. }
  9497. this.DrawTooltip=function(aryText,data)
  9498. {
  9499. if (!IFrameSplitOperator.IsNonEmptyArray(aryText)) return;
  9500. this.Canvas.font=this.Tooltip.Font;
  9501. var maxWidth=0, lineCount=0, itemCount=0;
  9502. for(var i=0;i<aryText.length;++i)
  9503. {
  9504. var item=aryText[i];
  9505. if (!item) continue;
  9506. var isVaild=false;
  9507. if (item.Title)
  9508. {
  9509. var textWidth=this.Canvas.measureText(item.Title).width;
  9510. if (maxWidth<textWidth) maxWidth=textWidth;
  9511. ++lineCount;
  9512. isVaild=true;
  9513. }
  9514. if (item.Text)
  9515. {
  9516. var textWidth=this.Canvas.measureText(item.Text).width;
  9517. if (maxWidth<textWidth) maxWidth=textWidth;
  9518. ++lineCount;
  9519. isVaild=true;
  9520. }
  9521. if (isVaild) ++itemCount;
  9522. }
  9523. if (maxWidth<=0 || lineCount<=0) return;
  9524. var border=this.Tooltip.Border;
  9525. var chartRight=this.Frame.ChartBorder.GetRight();
  9526. var chartTop=this.Frame.ChartBorder.GetTop();
  9527. this.Tooltip.LineHeight=this.Canvas.measureText("擎").width+2;
  9528. this.Tooltip.Width=maxWidth+(border.Left+border.Right);
  9529. this.Tooltip.Height=this.Tooltip.LineHeight*lineCount + (border.Top+border.Bottom) + (border.ItemSpace)*(itemCount-1);
  9530. var left=data.X;
  9531. var top=data.Y-this.Tooltip.Height
  9532. if (left+this.Tooltip.Width>=chartRight) left=data.X-this.Tooltip.Width;
  9533. if (top<chartTop) top=data.Y;
  9534. this.Canvas.fillStyle=this.Tooltip.BGColor;
  9535. this.Canvas.fillRect(left,top,this.Tooltip.Width,this.Tooltip.Height);
  9536. this.Canvas.textBaseline="top";
  9537. this.Canvas.textAlign="left";
  9538. var x=border.Left+left;
  9539. var y=border.Top+top;
  9540. for(var i=0;i<aryText.length;++i)
  9541. {
  9542. var item=aryText[i];
  9543. var isVaild=false;
  9544. if (item.Title)
  9545. {
  9546. if (item.TitleColor) this.Canvas.fillStyle=item.TitleColor;
  9547. else this.Canvas.fillStyle=this.Tooltip.TextColor;
  9548. this.Canvas.fillText(item.Title,x,y);
  9549. y+=this.Tooltip.LineHeight;
  9550. isVaild=true;
  9551. }
  9552. if (item.Text)
  9553. {
  9554. if (item.Color) this.Canvas.fillStyle=item.Color;
  9555. else this.Canvas.fillStyle=this.Tooltip.TextColor;
  9556. this.Canvas.fillText(item.Text,x,y);
  9557. y+=this.Tooltip.LineHeight;
  9558. isVaild=true;
  9559. }
  9560. if (isVaild) y+=border.ItemSpace;
  9561. }
  9562. }
  9563. }
  9564. //深度图
  9565. function ChartOrderbookDepth()
  9566. {
  9567. this.newMethod=IChartPainting; //派生
  9568. this.newMethod();
  9569. delete this.newMethod;
  9570. this.ClassName="ChartOrderbookDepth";
  9571. this.Data=null;
  9572. this.AskColor={ Line:g_JSChartResource.DepthChart.AskColor.Line, Area:g_JSChartResource.DepthChart.AskColor.Area } //卖
  9573. this.BidColor={ Line:g_JSChartResource.DepthChart.BidColor.Line, Area:g_JSChartResource.DepthChart.BidColor.Area } //买
  9574. this.LineWidth=g_JSChartResource.DepthChart.LineWidth;
  9575. this.Draw=function()
  9576. {
  9577. if (!this.Data) return;
  9578. this.Canvas.save();
  9579. this.Canvas.lineWidth=this.LineWidth;
  9580. this.DrawArea(this.Data.Bids, this.BidColor.Line, this.BidColor.Area, true);
  9581. this.DrawArea(this.Data.Asks, this.AskColor.Line, this.AskColor.Area, false);
  9582. this.Canvas.restore();
  9583. }
  9584. this.DrawArea=function(aryData, colorLine, colorArea, isLeft)
  9585. {
  9586. var xRange=this.ChartFrame.VerticalRange;
  9587. var aryPoint=[];
  9588. for(var i in aryData)
  9589. {
  9590. var item=aryData[i];
  9591. if (isLeft)
  9592. {
  9593. if (item.Price<xRange.Min) break;
  9594. }
  9595. else
  9596. {
  9597. if (item.Price>xRange.Max) break;
  9598. }
  9599. var x=this.ChartFrame.GetXFromIndex(item.Price);
  9600. var y=this.ChartFrame.GetYFromData(item.Vol);
  9601. aryPoint.push({X:x,Y:y});
  9602. }
  9603. if (aryPoint.length<=1) return;
  9604. var left=this.ChartBorder.GetLeft();
  9605. var bottom=this.ChartBorder.GetBottom();
  9606. var right=this.ChartBorder.GetRight();
  9607. this.Canvas.beginPath();
  9608. this.Canvas.moveTo(aryPoint[0].X, bottom);
  9609. for(var i in aryPoint)
  9610. {
  9611. var item=aryPoint[i];
  9612. this.Canvas.lineTo(item.X,item.Y);
  9613. }
  9614. this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y);
  9615. this.Canvas.lineTo(isLeft?left:right,bottom);
  9616. this.Canvas.lineTo(aryPoint[0].X,bottom);
  9617. this.Canvas.closePath();
  9618. this.Canvas.fillStyle = colorArea;
  9619. this.Canvas.fill();
  9620. this.Canvas.beginPath();
  9621. this.Canvas.moveTo(aryPoint[0].X, bottom);
  9622. for(var i in aryPoint)
  9623. {
  9624. var item=aryPoint[i];
  9625. this.Canvas.lineTo(item.X,item.Y);
  9626. }
  9627. this.Canvas.lineTo(isLeft?left:right,aryPoint[aryPoint.length-1].Y);
  9628. this.Canvas.strokeStyle=colorLine;
  9629. this.Canvas.stroke();
  9630. }
  9631. this.GetMaxMin=function()
  9632. {
  9633. var range={ Min:null, Max:null, XMin:null, XMax:null };
  9634. var xRange=this.ChartFrame.VerticalRange;
  9635. for(var i in this.Data.Asks)
  9636. {
  9637. var item=this.Data.Asks[i];
  9638. if (item.Price>xRange.Max) break;
  9639. if (range.XMin==null || range.XMin>item.Price) range.XMin=item.Price;
  9640. if (range.XMax==null || range.XMax<item.Price) range.XMax=item.Price;
  9641. if (range.Min==null || range.Min>item.Vol) range.Min=item.Vol;
  9642. if (range.Max==null || range.Max<item.Vol) range.Max=item.Vol;
  9643. }
  9644. for(var i in this.Data.Bids)
  9645. {
  9646. var item=this.Data.Bids[i];
  9647. if (item.Price<xRange.Min) break;
  9648. if (range.XMin==null || range.XMin>item.Price) range.XMin=item.Price;
  9649. if (range.XMax==null || range.XMax<item.Price) range.XMax=item.Price;
  9650. if (range.Min==null || range.Min>item.Vol) range.Min=item.Vol;
  9651. if (range.Max==null || range.Max<item.Vol) range.Max=item.Vol;
  9652. }
  9653. return range;
  9654. }
  9655. }
  9656. ///////////////////////////////////////////////////////////////////////////////////////
  9657. // 公共函数
  9658. //修正线段有毛刺
  9659. function ToFixedPoint(value)
  9660. {
  9661. //return value;
  9662. return parseInt(value) + 0.5;
  9663. }
  9664. function ToFixedRect(value)
  9665. {
  9666. var rounded;
  9667. return rounded = (0.5 + value) << 0;
  9668. }
  9669. //导出统一使用JSCommon命名空间名
  9670. export
  9671. {
  9672. IChartPainting,
  9673. ChartKLine,
  9674. ChartColorKline,
  9675. ChartLine,
  9676. ChartArea,
  9677. ChartStepLine,
  9678. ChartSubLine,
  9679. ChartSingleText,
  9680. ChartDrawIcon,
  9681. ChartDrawText,
  9682. ChartDrawNumber,
  9683. ChartPointDot,
  9684. ChartStick,
  9685. ChartLineStick,
  9686. ChartStickLine,
  9687. ChartBackground,
  9688. ChartBackgroundDiv,
  9689. ChartMinuteVolumBar,
  9690. ChartOverlayKLine,
  9691. ChartLock,
  9692. ChartVolStick,
  9693. ChartBand,
  9694. ChartMinutePriceLine,
  9695. ChartOverlayMinutePriceLine,
  9696. ChartLineMultiData,
  9697. ChartStraightLine,
  9698. ChartMultiSVGIconV2,
  9699. ChartMinuteInfo,
  9700. ChartRectangle,
  9701. ChartMultiText,
  9702. ChartMultiLine,
  9703. ChartMultiPoint,
  9704. ChartMultiHtmlDom,
  9705. ChartMultiBar,
  9706. ChartBuySell,
  9707. ChartMACD,
  9708. ChartStackedBar,
  9709. ChartText,
  9710. ChartStraightArea,
  9711. ChartCorssCursor,
  9712. DepthChartCorssCursor,
  9713. ChartOrderbookDepth,
  9714. ChartSplashPaint,
  9715. GetFontHeight,
  9716. ColorToRGBA,
  9717. ChartSingleLine,
  9718. ChartPartLine,
  9719. ChartDrawText_Fix,
  9720. ChartDrawNumber_Fix
  9721. };