u-charts.ts 287 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680
  1. // Type definitions will be added in story 016.002
  2. // @ts-nocheck - Using any types as temporary measure
  3. // For now, using any types as temporary measure
  4. /*
  5. * uCharts (R)
  6. * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360/快手)、Vue、Taro等支持canvas的框架平台
  7. * Copyright (C) 2018-2022 QIUN (R) 秋云 https://www.ucharts.cn All rights reserved.
  8. * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  9. * 复制使用请保留本段注释,感谢支持开源!
  10. *
  11. * uCharts (R) 官方网站
  12. * https://www.uCharts.cn
  13. *
  14. * 开源地址:
  15. * https://gitee.com/uCharts/uCharts
  16. *
  17. * uni-app插件市场地址:
  18. * http://ext.dcloud.net.cn/plugin?id=271
  19. *
  20. */
  21. export const config = {
  22. version: 'v2.5.0-20230101',
  23. yAxisWidth: 15,
  24. xAxisHeight: 22,
  25. padding: [10, 10, 10, 10],
  26. rotate: false,
  27. fontSize: 13,
  28. fontColor: '#666666',
  29. dataPointShape: ['circle', 'circle', 'circle', 'circle'],
  30. color: ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
  31. linearColor: ['#0EE2F8', '#2BDCA8', '#FA7D8D', '#EB88E2', '#2AE3A0', '#0EE2F8', '#EB88E2', '#6773E3', '#F78A85'],
  32. pieChartLinePadding: 15,
  33. pieChartTextPadding: 5,
  34. titleFontSize: 20,
  35. subtitleFontSize: 15,
  36. radarLabelTextMargin: 13,
  37. };
  38. export const assign = function(target, ...varArgs) {
  39. if (target == null) {
  40. throw new TypeError('[uCharts] Cannot convert undefined or null to object');
  41. }
  42. if (!varArgs || varArgs.length <= 0) {
  43. return target;
  44. }
  45. // 深度合并对象
  46. function deepAssign(obj1, obj2) {
  47. for (let key in obj2) {
  48. obj1[key] = obj1[key] && obj1[key].toString() === "[object Object]" ?
  49. deepAssign(obj1[key], obj2[key]) : obj1[key] = obj2[key];
  50. }
  51. return obj1;
  52. }
  53. varArgs.forEach(val => {
  54. target = deepAssign(target, val);
  55. });
  56. return target;
  57. };
  58. export const util = {
  59. toFixed: function toFixed(num, limit) {
  60. limit = limit || 2;
  61. if (this.isFloat(num)) {
  62. num = num.toFixed(limit);
  63. }
  64. return num;
  65. },
  66. isFloat: function isFloat(num) {
  67. return num % 1 !== 0;
  68. },
  69. approximatelyEqual: function approximatelyEqual(num1, num2) {
  70. return Math.abs(num1 - num2) < 1e-10;
  71. },
  72. isSameSign: function isSameSign(num1, num2) {
  73. return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
  74. },
  75. isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
  76. return this.isSameSign(p1.x, p2.x);
  77. },
  78. isCollision: function isCollision(obj1, obj2) {
  79. obj1.end = {};
  80. obj1.end.x = obj1.start.x + obj1.width;
  81. obj1.end.y = obj1.start.y - obj1.height;
  82. obj2.end = {};
  83. obj2.end.x = obj2.start.x + obj2.width;
  84. obj2.end.y = obj2.start.y - obj2.height;
  85. let flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
  86. return !flag;
  87. }
  88. };
  89. //兼容H5点击事件
  90. export function getH5Offset(e) {
  91. e.mp = {
  92. changedTouches: []
  93. };
  94. e.mp.changedTouches.push({
  95. x: e.offsetX,
  96. y: e.offsetY
  97. });
  98. return e;
  99. }
  100. // hex 转 rgba
  101. export function hexToRgb(hexValue, opc) {
  102. let rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  103. let hex = hexValue.replace(rgx, function(m, r, g, b) {
  104. return r + r + g + g + b + b;
  105. });
  106. let rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  107. let r = parseInt(rgb[1], 16);
  108. let g = parseInt(rgb[2], 16);
  109. let b = parseInt(rgb[3], 16);
  110. return 'rgba(' + r + ',' + g + ',' + b + ',' + opc + ')';
  111. }
  112. export function findRange(num, type, limit) {
  113. if (isNaN(num)) {
  114. throw new Error('[uCharts] series数据需为Number格式');
  115. }
  116. limit = limit || 10;
  117. type = type ? type : 'upper';
  118. let multiple = 1;
  119. while (limit < 1) {
  120. limit *= 10;
  121. multiple *= 10;
  122. }
  123. if (type === 'upper') {
  124. num = Math.ceil(num * multiple);
  125. } else {
  126. num = Math.floor(num * multiple);
  127. }
  128. while (num % limit !== 0) {
  129. if (type === 'upper') {
  130. if (num == num + 1) { //修复数据值过大num++无效的bug by 向日葵 @xrk_jy
  131. break;
  132. }
  133. num++;
  134. } else {
  135. num--;
  136. }
  137. }
  138. return num / multiple;
  139. }
  140. export function calCandleMA(dayArr, nameArr, colorArr, kdata) {
  141. let seriesTemp = [];
  142. for (let k = 0; k < dayArr.length; k++) {
  143. let seriesItem = {
  144. data: [],
  145. name: nameArr[k],
  146. color: colorArr[k]
  147. };
  148. for (let i = 0, len = kdata.length; i < len; i++) {
  149. if (i < dayArr[k]) {
  150. seriesItem.data.push(null);
  151. continue;
  152. }
  153. let sum = 0;
  154. for (let j = 0; j < dayArr[k]; j++) {
  155. sum += kdata[i - j][1];
  156. }
  157. seriesItem.data.push(+(sum / dayArr[k]).toFixed(3));
  158. }
  159. seriesTemp.push(seriesItem);
  160. }
  161. return seriesTemp;
  162. }
  163. export function calValidDistance(self, distance, chartData, config, opts) {
  164. let dataChartAreaWidth = opts.width - opts.area[1] - opts.area[3];
  165. let dataChartWidth = chartData.eachSpacing * (opts.chartData.xAxisData.xAxisPoints.length - 1);
  166. if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){
  167. if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
  168. dataChartWidth += (opts.extra.mount.widthRatio - 1)*chartData.eachSpacing;
  169. }
  170. let validDistance = distance;
  171. if (distance >= 0) {
  172. validDistance = 0;
  173. self.uevent.trigger('scrollLeft');
  174. self.scrollOption.position = 'left'
  175. opts.xAxis.scrollPosition = 'left';
  176. } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
  177. validDistance = dataChartAreaWidth - dataChartWidth;
  178. self.uevent.trigger('scrollRight');
  179. self.scrollOption.position = 'right'
  180. opts.xAxis.scrollPosition = 'right';
  181. } else {
  182. self.scrollOption.position = distance
  183. opts.xAxis.scrollPosition = distance;
  184. }
  185. return validDistance;
  186. }
  187. export function isInAngleRange(angle, startAngle, endAngle) {
  188. function adjust(angle) {
  189. while (angle < 0) {
  190. angle += 2 * Math.PI;
  191. }
  192. while (angle > 2 * Math.PI) {
  193. angle -= 2 * Math.PI;
  194. }
  195. return angle;
  196. }
  197. angle = adjust(angle);
  198. startAngle = adjust(startAngle);
  199. endAngle = adjust(endAngle);
  200. if (startAngle > endAngle) {
  201. endAngle += 2 * Math.PI;
  202. if (angle < startAngle) {
  203. angle += 2 * Math.PI;
  204. }
  205. }
  206. return angle >= startAngle && angle <= endAngle;
  207. }
  208. export function createCurveControlPoints(points, i) {
  209. function isNotMiddlePoint(points, i) {
  210. if (points[i - 1] && points[i + 1]) {
  211. return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y,
  212. points[i + 1].y);
  213. } else {
  214. return false;
  215. }
  216. }
  217. function isNotMiddlePointX(points, i) {
  218. if (points[i - 1] && points[i + 1]) {
  219. return points[i].x >= Math.max(points[i - 1].x, points[i + 1].x) || points[i].x <= Math.min(points[i - 1].x,
  220. points[i + 1].x);
  221. } else {
  222. return false;
  223. }
  224. }
  225. let a = 0.2;
  226. let b = 0.2;
  227. let pAx = null;
  228. let pAy = null;
  229. let pBx = null;
  230. let pBy = null;
  231. if (i < 1) {
  232. pAx = points[0].x + (points[1].x - points[0].x) * a;
  233. pAy = points[0].y + (points[1].y - points[0].y) * a;
  234. } else {
  235. pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
  236. pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
  237. }
  238. if (i > points.length - 3) {
  239. let last = points.length - 1;
  240. pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
  241. pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
  242. } else {
  243. pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
  244. pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
  245. }
  246. if (isNotMiddlePoint(points, i + 1)) {
  247. pBy = points[i + 1].y;
  248. }
  249. if (isNotMiddlePoint(points, i)) {
  250. pAy = points[i].y;
  251. }
  252. if (isNotMiddlePointX(points, i + 1)) {
  253. pBx = points[i + 1].x;
  254. }
  255. if (isNotMiddlePointX(points, i)) {
  256. pAx = points[i].x;
  257. }
  258. if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) {
  259. pAy = points[i].y;
  260. }
  261. if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) {
  262. pBy = points[i + 1].y;
  263. }
  264. if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) {
  265. pAx = points[i].x;
  266. }
  267. if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) {
  268. pBx = points[i + 1].x;
  269. }
  270. return {
  271. ctrA: {
  272. x: pAx,
  273. y: pAy
  274. },
  275. ctrB: {
  276. x: pBx,
  277. y: pBy
  278. }
  279. };
  280. }
  281. export function convertCoordinateOrigin(x, y, center) {
  282. return {
  283. x: center.x + x,
  284. y: center.y - y
  285. };
  286. }
  287. export function avoidCollision(obj, target) {
  288. if (target) {
  289. // is collision test
  290. while (util.isCollision(obj, target)) {
  291. if (obj.start.x > 0) {
  292. obj.start.y--;
  293. } else if (obj.start.x < 0) {
  294. obj.start.y++;
  295. } else {
  296. if (obj.start.y > 0) {
  297. obj.start.y++;
  298. } else {
  299. obj.start.y--;
  300. }
  301. }
  302. }
  303. }
  304. return obj;
  305. }
  306. export function fixPieSeries(series, opts, config){
  307. let pieSeriesArr = [];
  308. if(series.length>0 && series[0].data.constructor.toString().indexOf('Array') > -1){
  309. opts._pieSeries_ = series;
  310. let oldseries = series[0].data;
  311. for (let i = 0; i < oldseries.length; i++) {
  312. oldseries[i].formatter = series[0].formatter;
  313. oldseries[i].data = oldseries[i].value;
  314. pieSeriesArr.push(oldseries[i]);
  315. }
  316. opts.series = pieSeriesArr;
  317. }else{
  318. pieSeriesArr = series;
  319. }
  320. return pieSeriesArr;
  321. }
  322. export function fillSeries(series, opts, config) {
  323. let index = 0;
  324. for (let i = 0; i < series.length; i++) {
  325. let item = series[i];
  326. if (!item.color) {
  327. item.color = config.color[index];
  328. index = (index + 1) % config.color.length;
  329. }
  330. if (!item.linearIndex) {
  331. item.linearIndex = i;
  332. }
  333. if (!item.index) {
  334. item.index = 0;
  335. }
  336. if (!item.type) {
  337. item.type = opts.type;
  338. }
  339. if (typeof item.show == "undefined") {
  340. item.show = true;
  341. }
  342. if (!item.type) {
  343. item.type = opts.type;
  344. }
  345. if (!item.pointShape) {
  346. item.pointShape = "circle";
  347. }
  348. if (!item.legendShape) {
  349. switch (item.type) {
  350. case 'line':
  351. item.legendShape = "line";
  352. break;
  353. case 'column':
  354. case 'bar':
  355. item.legendShape = "rect";
  356. break;
  357. case 'area':
  358. case 'mount':
  359. item.legendShape = "triangle";
  360. break;
  361. default:
  362. item.legendShape = "circle";
  363. }
  364. }
  365. }
  366. return series;
  367. }
  368. export function fillCustomColor(linearType, customColor, series, config) {
  369. let newcolor = customColor || [];
  370. if (linearType == 'custom' && newcolor.length == 0 ) {
  371. newcolor = config.linearColor;
  372. }
  373. if (linearType == 'custom' && newcolor.length < series.length) {
  374. let chazhi = series.length - newcolor.length;
  375. for (let i = 0; i < chazhi; i++) {
  376. newcolor.push(config.linearColor[(i + 1) % config.linearColor.length]);
  377. }
  378. }
  379. return newcolor;
  380. }
  381. export function getDataRange(minData, maxData) {
  382. let limit = 0;
  383. let range = maxData - minData;
  384. if (range >= 10000) {
  385. limit = 1000;
  386. } else if (range >= 1000) {
  387. limit = 100;
  388. } else if (range >= 100) {
  389. limit = 10;
  390. } else if (range >= 10) {
  391. limit = 5;
  392. } else if (range >= 1) {
  393. limit = 1;
  394. } else if (range >= 0.1) {
  395. limit = 0.1;
  396. } else if (range >= 0.01) {
  397. limit = 0.01;
  398. } else if (range >= 0.001) {
  399. limit = 0.001;
  400. } else if (range >= 0.0001) {
  401. limit = 0.0001;
  402. } else if (range >= 0.00001) {
  403. limit = 0.00001;
  404. } else {
  405. limit = 0.000001;
  406. }
  407. return {
  408. minRange: findRange(minData, 'lower', limit),
  409. maxRange: findRange(maxData, 'upper', limit)
  410. };
  411. }
  412. export function measureText(text, fontSize, context) {
  413. let width = 0;
  414. text = String(text);
  415. // #ifdef MP-ALIPAY || MP-BAIDU || APP-NVUE
  416. context = false;
  417. // #endif
  418. if (context !== false && context !== undefined && context.setFontSize && context.measureText) {
  419. context.setFontSize(fontSize);
  420. return context.measureText(text).width;
  421. } else {
  422. let text = text.split('');
  423. for (let i = 0; i < text.length; i++) {
  424. let item = text[i];
  425. if (/[a-zA-Z]/.test(item)) {
  426. width += 7;
  427. } else if (/[0-9]/.test(item)) {
  428. width += 5.5;
  429. } else if (/\./.test(item)) {
  430. width += 2.7;
  431. } else if (/-/.test(item)) {
  432. width += 3.25;
  433. } else if (/:/.test(item)) {
  434. width += 2.5;
  435. } else if (/[\u4e00-\u9fa5]/.test(item)) {
  436. width += 10;
  437. } else if (/\(|\)/.test(item)) {
  438. width += 3.73;
  439. } else if (/\s/.test(item)) {
  440. width += 2.5;
  441. } else if (/%/.test(item)) {
  442. width += 8;
  443. } else {
  444. width += 10;
  445. }
  446. }
  447. return width * fontSize / 10;
  448. }
  449. }
  450. export function dataCombine(series) {
  451. return series.reduce(function(a, b) {
  452. return (a.data ? a.data : a).concat(b.data);
  453. }, []);
  454. }
  455. export function dataCombineStack(series, len) {
  456. let sum = new Array(len);
  457. for (let j = 0; j < sum.length; j++) {
  458. sum[j] = 0;
  459. }
  460. for (let i = 0; i < series.length; i++) {
  461. for (let j = 0; j < sum.length; j++) {
  462. sum[j] += series[i].data[j];
  463. }
  464. }
  465. return series.reduce(function(a, b) {
  466. return (a.data ? a.data : a).concat(b.data).concat(sum);
  467. }, []);
  468. }
  469. export function getTouches(touches, opts, e) {
  470. let x, y;
  471. if (touches.clientX) {
  472. if (opts.rotate) {
  473. y = opts.height - touches.clientX * opts.pix;
  474. x = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix;
  475. } else {
  476. x = touches.clientX * opts.pix;
  477. y = (touches.pageY - e.currentTarget.offsetTop - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix;
  478. }
  479. } else {
  480. if (opts.rotate) {
  481. y = opts.height - touches.x * opts.pix;
  482. x = touches.y * opts.pix;
  483. } else {
  484. x = touches.x * opts.pix;
  485. y = touches.y * opts.pix;
  486. }
  487. }
  488. return {
  489. x: x,
  490. y: y
  491. }
  492. }
  493. function getSeriesDataItem(series, index, group) {
  494. let data = [];
  495. let newSeries = [];
  496. let indexIsArr = index.constructor.toString().indexOf('Array') > -1;
  497. if(indexIsArr){
  498. let tempSeries = filterSeries(series);
  499. for (let i = 0; i < group.length; i++) {
  500. newSeries.push(tempSeries[group[i]]);
  501. }
  502. }else{
  503. newSeries = series;
  504. };
  505. for (let i = 0; i < newSeries.length; i++) {
  506. let item = newSeries[i];
  507. let tmpindex = -1;
  508. if(indexIsArr){
  509. tmpindex = index[i];
  510. }else{
  511. tmpindex = index;
  512. }
  513. if (item.data[tmpindex] !== null && typeof item.data[tmpindex] !== 'undefined' && item.show) {
  514. let seriesItem = {};
  515. seriesItem.color = item.color;
  516. seriesItem.type = item.type;
  517. seriesItem.style = item.style;
  518. seriesItem.pointShape = item.pointShape;
  519. seriesItem.disableLegend = item.disableLegend;
  520. seriesItem.legendShape = item.legendShape;
  521. seriesItem.name = item.name;
  522. seriesItem.show = item.show;
  523. seriesItem.data = item.formatter ? item.formatter(item.data[tmpindex]) : item.data[tmpindex];
  524. data.push(seriesItem);
  525. }
  526. }
  527. return data;
  528. }
  529. function getMaxTextListLength(list, fontSize, context) {
  530. let lengthList = list.map(function(item) {
  531. return measureText(item, fontSize, context);
  532. });
  533. return Math.max.apply(null, lengthList);
  534. }
  535. function getRadarCoordinateSeries(length) {
  536. let eachAngle = 2 * Math.PI / length;
  537. let CoordinateSeries = [];
  538. for (let i = 0; i < length; i++) {
  539. CoordinateSeries.push(eachAngle * i);
  540. }
  541. return CoordinateSeries.map(function(item) {
  542. return -1 * item + Math.PI / 2;
  543. });
  544. }
  545. function getToolTipData(seriesData, opts, index, group, categories) {
  546. let option = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {};
  547. let calPoints = opts.chartData.calPoints?opts.chartData.calPoints:[];
  548. let points = {};
  549. if(group.length > 0){
  550. let filterPoints = [];
  551. for (let i = 0; i < group.length; i++) {
  552. filterPoints.push(calPoints[group[i]])
  553. }
  554. points = filterPoints[0][index[0]];
  555. }else{
  556. for (let i = 0; i < calPoints.length; i++) {
  557. if(calPoints[i][index]){
  558. points = calPoints[i][index];
  559. break;
  560. }
  561. }
  562. };
  563. let textList = seriesData.map(function(item) {
  564. let titleText = null;
  565. if (opts.categories && opts.categories.length>0) {
  566. titleText = categories[index];
  567. };
  568. return {
  569. text: option.formatter ? option.formatter(item, titleText, index, opts) : item.name + ': ' + item.data,
  570. color: item.color,
  571. legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
  572. };
  573. });
  574. let offset = {
  575. x: Math.round(points.x),
  576. y: Math.round(points.y)
  577. };
  578. return {
  579. textList: textList,
  580. offset: offset
  581. };
  582. }
  583. function getMixToolTipData(seriesData, opts, index, categories) {
  584. let option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  585. let points = opts.chartData.xAxisPoints[index] + opts.chartData.eachSpacing / 2;
  586. let textList = seriesData.map(function(item) {
  587. return {
  588. text: option.formatter ? option.formatter(item, categories[index], index, opts) : item.name + ': ' + item.data,
  589. color: item.color,
  590. disableLegend: item.disableLegend ? true : false,
  591. legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
  592. };
  593. });
  594. textList = textList.filter(function(item) {
  595. if (item.disableLegend !== true) {
  596. return item;
  597. }
  598. });
  599. let offset = {
  600. x: Math.round(points),
  601. y: 0
  602. };
  603. return {
  604. textList: textList,
  605. offset: offset
  606. };
  607. }
  608. function getCandleToolTipData(series, seriesData, opts, index, categories, extra) {
  609. let option = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {};
  610. let calPoints = opts.chartData.calPoints;
  611. let upColor = extra.color.upFill;
  612. let downColor = extra.color.downFill;
  613. //颜色顺序为开盘,收盘,最低,最高
  614. let color = [upColor, upColor, downColor, upColor];
  615. let textList = [];
  616. seriesData.map(function(item) {
  617. if (index == 0) {
  618. if (item.data[1] - item.data[0] < 0) {
  619. color[1] = downColor;
  620. } else {
  621. color[1] = upColor;
  622. }
  623. } else {
  624. if (item.data[0] < series[index - 1][1]) {
  625. color[0] = downColor;
  626. }
  627. if (item.data[1] < item.data[0]) {
  628. color[1] = downColor;
  629. }
  630. if (item.data[2] > series[index - 1][1]) {
  631. color[2] = upColor;
  632. }
  633. if (item.data[3] < series[index - 1][1]) {
  634. color[3] = downColor;
  635. }
  636. }
  637. let text1 = {
  638. text: '开盘:' + item.data[0],
  639. color: color[0],
  640. legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
  641. };
  642. let text2 = {
  643. text: '收盘:' + item.data[1],
  644. color: color[1],
  645. legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
  646. };
  647. let text3 = {
  648. text: '最低:' + item.data[2],
  649. color: color[2],
  650. legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
  651. };
  652. let text4 = {
  653. text: '最高:' + item.data[3],
  654. color: color[3],
  655. legendShape: opts.extra.tooltip.legendShape == 'auto'? item.legendShape : opts.extra.tooltip.legendShape
  656. };
  657. textList.push(text1, text2, text3, text4);
  658. });
  659. let validCalPoints = [];
  660. let offset = {
  661. x: 0,
  662. y: 0
  663. };
  664. for (let i = 0; i < calPoints.length; i++) {
  665. let points = calPoints[i];
  666. if (typeof points[index] !== 'undefined' && points[index] !== null) {
  667. validCalPoints.push(points[index]);
  668. }
  669. }
  670. offset.x = Math.round(validCalPoints[0][0].x);
  671. return {
  672. textList: textList,
  673. offset: offset
  674. };
  675. }
  676. function filterSeries(series) {
  677. let tempSeries = [];
  678. for (let i = 0; i < series.length; i++) {
  679. if (series[i].show == true) {
  680. tempSeries.push(series[i])
  681. }
  682. }
  683. return tempSeries;
  684. }
  685. function findCurrentIndex(currentPoints, calPoints, opts, config) {
  686. let offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
  687. let current={ index:-1, group:[] };
  688. let spacing = opts.chartData.eachSpacing / 2;
  689. let xAxisPoints = [];
  690. if (calPoints && calPoints.length > 0) {
  691. if (!opts.categories) {
  692. spacing = 0;
  693. }else{
  694. for (let i = 1; i < opts.chartData.xAxisPoints.length; i++) {
  695. xAxisPoints.push(opts.chartData.xAxisPoints[i] - spacing);
  696. }
  697. if ((opts.type == 'line' || opts.type == 'area') && opts.xAxis.boundaryGap == 'justify') {
  698. xAxisPoints = opts.chartData.xAxisPoints;
  699. }
  700. }
  701. if (isInExactChartArea(currentPoints, opts, config)) {
  702. if (!opts.categories) {
  703. let timePoints = Array(calPoints.length);
  704. for (let i = 0; i < calPoints.length; i++) {
  705. timePoints[i] = Array(calPoints[i].length)
  706. for (let j = 0; j < calPoints[i].length; j++) {
  707. timePoints[i][j] = (Math.abs(calPoints[i][j].x - currentPoints.x));
  708. }
  709. };
  710. let pointValue = Array(timePoints.length);
  711. let pointIndex = Array(timePoints.length);
  712. for (let i = 0; i < timePoints.length; i++) {
  713. pointValue[i] = Math.min.apply(null, timePoints[i]);
  714. pointIndex[i] = timePoints[i].indexOf(pointValue[i]);
  715. }
  716. let minValue = Math.min.apply(null, pointValue);
  717. current.index = [];
  718. for (let i = 0; i < pointValue.length; i++) {
  719. if(pointValue[i] == minValue){
  720. current.group.push(i);
  721. current.index.push(pointIndex[i]);
  722. }
  723. };
  724. }else{
  725. xAxisPoints.forEach(function(item, index) {
  726. if (currentPoints.x + offset + spacing > item) {
  727. current.index = index;
  728. }
  729. });
  730. }
  731. }
  732. }
  733. return current;
  734. }
  735. function findBarChartCurrentIndex(currentPoints, calPoints, opts, config) {
  736. let offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
  737. let current={ index:-1, group:[] };
  738. let spacing = opts.chartData.eachSpacing / 2;
  739. let yAxisPoints = opts.chartData.yAxisPoints;
  740. if (calPoints && calPoints.length > 0) {
  741. if (isInExactChartArea(currentPoints, opts, config)) {
  742. yAxisPoints.forEach(function(item, index) {
  743. if (currentPoints.y + offset + spacing > item) {
  744. current.index = index;
  745. }
  746. });
  747. }
  748. }
  749. return current;
  750. }
  751. function findLegendIndex(currentPoints, legendData, opts) {
  752. let currentIndex = -1;
  753. let gap = 0;
  754. if (isInExactLegendArea(currentPoints, legendData.area)) {
  755. let points = legendData.points;
  756. let index = -1;
  757. for (let i = 0, len = points.length; i < len; i++) {
  758. let item = points[i];
  759. for (let j = 0; j < item.length; j++) {
  760. index += 1;
  761. let area = item[j]['area'];
  762. if (area && currentPoints.x > area[0] - gap && currentPoints.x < area[2] + gap && currentPoints.y > area[1] - gap && currentPoints.y < area[3] + gap) {
  763. currentIndex = index;
  764. break;
  765. }
  766. }
  767. }
  768. return currentIndex;
  769. }
  770. return currentIndex;
  771. }
  772. function isInExactLegendArea(currentPoints, area) {
  773. return currentPoints.x > area.start.x && currentPoints.x < area.end.x && currentPoints.y > area.start.y && currentPoints.y < area.end.y;
  774. }
  775. function isInExactChartArea(currentPoints, opts, config) {
  776. return currentPoints.x <= opts.width - opts.area[1] + 10 && currentPoints.x >= opts.area[3] - 10 && currentPoints.y >= opts.area[0] && currentPoints.y <= opts.height - opts.area[2];
  777. }
  778. function findRadarChartCurrentIndex(currentPoints, radarData, count) {
  779. let eachAngleArea = 2 * Math.PI / count;
  780. let currentIndex = -1;
  781. if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
  782. let fixAngle = function fixAngle(angle) {
  783. if (angle < 0) {
  784. angle += 2 * Math.PI;
  785. }
  786. if (angle > 2 * Math.PI) {
  787. angle -= 2 * Math.PI;
  788. }
  789. return angle;
  790. };
  791. let angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
  792. angle = -1 * angle;
  793. if (angle < 0) {
  794. angle += 2 * Math.PI;
  795. }
  796. let angleList = radarData.angleList.map(function(item) {
  797. item = fixAngle(-1 * item);
  798. return item;
  799. });
  800. angleList.forEach(function(item, index) {
  801. let rangeStart = fixAngle(item - eachAngleArea / 2);
  802. let rangeEnd = fixAngle(item + eachAngleArea / 2);
  803. if (rangeEnd < rangeStart) {
  804. rangeEnd += 2 * Math.PI;
  805. }
  806. if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <= rangeEnd) {
  807. currentIndex = index;
  808. }
  809. });
  810. }
  811. return currentIndex;
  812. }
  813. function findFunnelChartCurrentIndex(currentPoints, funnelData) {
  814. let currentIndex = -1;
  815. for (let i = 0, len = funnelData.series.length; i < len; i++) {
  816. let item = funnelData.series[i];
  817. if (currentPoints.x > item.funnelArea[0] && currentPoints.x < item.funnelArea[2] && currentPoints.y > item.funnelArea[1] && currentPoints.y < item.funnelArea[3]) {
  818. currentIndex = i;
  819. break;
  820. }
  821. }
  822. return currentIndex;
  823. }
  824. function findWordChartCurrentIndex(currentPoints, wordData) {
  825. let currentIndex = -1;
  826. for (let i = 0, len = wordData.length; i < len; i++) {
  827. let item = wordData[i];
  828. if (currentPoints.x > item.area[0] && currentPoints.x < item.area[2] && currentPoints.y > item.area[1] && currentPoints.y < item.area[3]) {
  829. currentIndex = i;
  830. break;
  831. }
  832. }
  833. return currentIndex;
  834. }
  835. function findMapChartCurrentIndex(currentPoints, opts) {
  836. let currentIndex = -1;
  837. let cData = opts.chartData.mapData;
  838. let data = opts.series;
  839. let tmp = pointToCoordinate(currentPoints.y, currentPoints.x, cData.bounds, cData.scale, cData.xoffset, cData.yoffset);
  840. let poi = [tmp.x, tmp.y];
  841. for (let i = 0, len = data.length; i < len; i++) {
  842. let item = data[i].geometry.coordinates;
  843. if (isPoiWithinPoly(poi, item, opts.chartData.mapData.mercator)) {
  844. currentIndex = i;
  845. break;
  846. }
  847. }
  848. return currentIndex;
  849. }
  850. function findRoseChartCurrentIndex(currentPoints, pieData, opts) {
  851. let currentIndex = -1;
  852. let series = getRoseDataPoints(opts._series_, opts.extra.rose.type, pieData.radius, pieData.radius);
  853. if (pieData && pieData.center && isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
  854. let angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
  855. angle = -angle;
  856. if(opts.extra.rose && opts.extra.rose.offsetAngle){
  857. angle = angle - opts.extra.rose.offsetAngle * Math.PI / 180;
  858. }
  859. for (let i = 0, len = series.length; i < len; i++) {
  860. if (isInAngleRange(angle, series[i]._start_, series[i]._start_ + series[i]._rose_proportion_ * 2 * Math.PI)) {
  861. currentIndex = i;
  862. break;
  863. }
  864. }
  865. }
  866. return currentIndex;
  867. }
  868. function findPieChartCurrentIndex(currentPoints, pieData, opts) {
  869. let currentIndex = -1;
  870. let series = getPieDataPoints(pieData.series);
  871. if (pieData && pieData.center && isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
  872. let angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
  873. angle = -angle;
  874. if(opts.extra.pie && opts.extra.pie.offsetAngle){
  875. angle = angle - opts.extra.pie.offsetAngle * Math.PI / 180;
  876. }
  877. if(opts.extra.ring && opts.extra.ring.offsetAngle){
  878. angle = angle - opts.extra.ring.offsetAngle * Math.PI / 180;
  879. }
  880. for (let i = 0, len = series.length; i < len; i++) {
  881. if (isInAngleRange(angle, series[i]._start_, series[i]._start_ + series[i]._proportion_ * 2 * Math.PI)) {
  882. currentIndex = i;
  883. break;
  884. }
  885. }
  886. }
  887. return currentIndex;
  888. }
  889. function isInExactPieChartArea(currentPoints, center, radius) {
  890. return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
  891. }
  892. function splitPoints(points,eachSeries) {
  893. let newPoints = [];
  894. let items = [];
  895. points.forEach(function(item, index) {
  896. if(eachSeries.connectNulls){
  897. if (item !== null) {
  898. items.push(item);
  899. }
  900. }else{
  901. if (item !== null) {
  902. items.push(item);
  903. } else {
  904. if (items.length) {
  905. newPoints.push(items);
  906. }
  907. items = [];
  908. }
  909. }
  910. });
  911. if (items.length) {
  912. newPoints.push(items);
  913. }
  914. return newPoints;
  915. }
  916. function calLegendData(series, opts, config, chartData, context) {
  917. let legendData = {
  918. area: {
  919. start: {
  920. x: 0,
  921. y: 0
  922. },
  923. end: {
  924. x: 0,
  925. y: 0
  926. },
  927. width: 0,
  928. height: 0,
  929. wholeWidth: 0,
  930. wholeHeight: 0
  931. },
  932. points: [],
  933. widthArr: [],
  934. heightArr: []
  935. };
  936. if (opts.legend.show === false) {
  937. chartData.legendData = legendData;
  938. return legendData;
  939. }
  940. let padding = opts.legend.padding * opts.pix;
  941. let margin = opts.legend.margin * opts.pix;
  942. let fontSize = opts.legend.fontSize ? opts.legend.fontSize * opts.pix : config.fontSize;
  943. let shapeWidth = 15 * opts.pix;
  944. let shapeRight = 5 * opts.pix;
  945. let lineHeight = Math.max(opts.legend.lineHeight * opts.pix, fontSize);
  946. if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
  947. let legendList = [];
  948. let widthCount = 0;
  949. let widthCountArr = [];
  950. let currentRow = [];
  951. for (let i = 0; i < series.length; i++) {
  952. let item = series[i];
  953. const legendText = item.legendText ? item.legendText : item.name;
  954. let itemWidth = shapeWidth + shapeRight + measureText(legendText || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix;
  955. if (widthCount + itemWidth > opts.width - opts.area[1] - opts.area[3]) {
  956. legendList.push(currentRow);
  957. widthCountArr.push(widthCount - opts.legend.itemGap * opts.pix);
  958. widthCount = itemWidth;
  959. currentRow = [item];
  960. } else {
  961. widthCount += itemWidth;
  962. currentRow.push(item);
  963. }
  964. }
  965. if (currentRow.length) {
  966. legendList.push(currentRow);
  967. widthCountArr.push(widthCount - opts.legend.itemGap * opts.pix);
  968. legendData.widthArr = widthCountArr;
  969. let legendWidth = Math.max.apply(null, widthCountArr);
  970. switch (opts.legend.float) {
  971. case 'left':
  972. legendData.area.start.x = opts.area[3];
  973. legendData.area.end.x = opts.area[3] + legendWidth + 2 * padding;
  974. break;
  975. case 'right':
  976. legendData.area.start.x = opts.width - opts.area[1] - legendWidth - 2 * padding;
  977. legendData.area.end.x = opts.width - opts.area[1];
  978. break;
  979. default:
  980. legendData.area.start.x = (opts.width - legendWidth) / 2 - padding;
  981. legendData.area.end.x = (opts.width + legendWidth) / 2 + padding;
  982. }
  983. legendData.area.width = legendWidth + 2 * padding;
  984. legendData.area.wholeWidth = legendWidth + 2 * padding;
  985. legendData.area.height = legendList.length * lineHeight + 2 * padding;
  986. legendData.area.wholeHeight = legendList.length * lineHeight + 2 * padding + 2 * margin;
  987. legendData.points = legendList;
  988. }
  989. } else {
  990. let len = series.length;
  991. let maxHeight = opts.height - opts.area[0] - opts.area[2] - 2 * margin - 2 * padding;
  992. let maxLength = Math.min(Math.floor(maxHeight / lineHeight), len);
  993. legendData.area.height = maxLength * lineHeight + padding * 2;
  994. legendData.area.wholeHeight = maxLength * lineHeight + padding * 2;
  995. switch (opts.legend.float) {
  996. case 'top':
  997. legendData.area.start.y = opts.area[0] + margin;
  998. legendData.area.end.y = opts.area[0] + margin + legendData.area.height;
  999. break;
  1000. case 'bottom':
  1001. legendData.area.start.y = opts.height - opts.area[2] - margin - legendData.area.height;
  1002. legendData.area.end.y = opts.height - opts.area[2] - margin;
  1003. break;
  1004. default:
  1005. legendData.area.start.y = (opts.height - legendData.area.height) / 2;
  1006. legendData.area.end.y = (opts.height + legendData.area.height) / 2;
  1007. }
  1008. let lineNum = len % maxLength === 0 ? len / maxLength : Math.floor((len / maxLength) + 1);
  1009. let currentRow = [];
  1010. for (let i = 0; i < lineNum; i++) {
  1011. let temp = series.slice(i * maxLength, i * maxLength + maxLength);
  1012. currentRow.push(temp);
  1013. }
  1014. legendData.points = currentRow;
  1015. if (currentRow.length) {
  1016. for (let i = 0; i < currentRow.length; i++) {
  1017. let item = currentRow[i];
  1018. let maxWidth = 0;
  1019. for (let j = 0; j < item.length; j++) {
  1020. let itemWidth = shapeWidth + shapeRight + measureText(item[j].name || 'undefined', fontSize, context) + opts.legend.itemGap * opts.pix;
  1021. if (itemWidth > maxWidth) {
  1022. maxWidth = itemWidth;
  1023. }
  1024. }
  1025. legendData.widthArr.push(maxWidth);
  1026. legendData.heightArr.push(item.length * lineHeight + padding * 2);
  1027. }
  1028. let legendWidth = 0
  1029. for (let i = 0; i < legendData.widthArr.length; i++) {
  1030. legendWidth += legendData.widthArr[i];
  1031. }
  1032. legendData.area.width = legendWidth - opts.legend.itemGap * opts.pix + 2 * padding;
  1033. legendData.area.wholeWidth = legendData.area.width + padding;
  1034. }
  1035. }
  1036. switch (opts.legend.position) {
  1037. case 'top':
  1038. legendData.area.start.y = opts.area[0] + margin;
  1039. legendData.area.end.y = opts.area[0] + margin + legendData.area.height;
  1040. break;
  1041. case 'bottom':
  1042. legendData.area.start.y = opts.height - opts.area[2] - legendData.area.height - margin;
  1043. legendData.area.end.y = opts.height - opts.area[2] - margin;
  1044. break;
  1045. case 'left':
  1046. legendData.area.start.x = opts.area[3];
  1047. legendData.area.end.x = opts.area[3] + legendData.area.width;
  1048. break;
  1049. case 'right':
  1050. legendData.area.start.x = opts.width - opts.area[1] - legendData.area.width;
  1051. legendData.area.end.x = opts.width - opts.area[1];
  1052. break;
  1053. }
  1054. chartData.legendData = legendData;
  1055. return legendData;
  1056. }
  1057. function calCategoriesData(categories, opts, config, eachSpacing, context) {
  1058. let result = {
  1059. angle: 0,
  1060. xAxisHeight: opts.xAxis.lineHeight * opts.pix + opts.xAxis.marginTop * opts.pix
  1061. };
  1062. let fontSize = opts.xAxis.fontSize * opts.pix;
  1063. let categoriesTextLenth = categories.map(function(item,index) {
  1064. let xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item,index,opts) : item;
  1065. return measureText(String(xitem), fontSize, context);
  1066. });
  1067. let maxTextLength = Math.max.apply(this, categoriesTextLenth);
  1068. if (opts.xAxis.rotateLabel == true) {
  1069. result.angle = opts.xAxis.rotateAngle * Math.PI / 180;
  1070. let tempHeight = opts.xAxis.marginTop * opts.pix * 2 + Math.abs(maxTextLength * Math.sin(result.angle))
  1071. tempHeight = tempHeight < fontSize + opts.xAxis.marginTop * opts.pix * 2 ? tempHeight + opts.xAxis.marginTop * opts.pix * 2 : tempHeight;
  1072. result.xAxisHeight = tempHeight;
  1073. }
  1074. if (opts.enableScroll && opts.xAxis.scrollShow) {
  1075. result.xAxisHeight += 6 * opts.pix;
  1076. }
  1077. if (opts.xAxis.disabled){
  1078. result.xAxisHeight = 0;
  1079. }
  1080. return result;
  1081. }
  1082. function getXAxisTextList(series, opts, config, stack) {
  1083. let index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : -1;
  1084. let data;
  1085. if (stack == 'stack') {
  1086. data = dataCombineStack(series, opts.categories.length);
  1087. } else {
  1088. data = dataCombine(series);
  1089. }
  1090. let sorted = [];
  1091. // remove null from data
  1092. data = data.filter(function(item) {
  1093. //return item !== null;
  1094. if (typeof item === 'object' && item !== null) {
  1095. if (item.constructor.toString().indexOf('Array') > -1) {
  1096. return item !== null;
  1097. } else {
  1098. return item.value !== null;
  1099. }
  1100. } else {
  1101. return item !== null;
  1102. }
  1103. });
  1104. data.map(function(item) {
  1105. if (typeof item === 'object') {
  1106. if (item.constructor.toString().indexOf('Array') > -1) {
  1107. if (opts.type == 'candle') {
  1108. item.map(function(subitem) {
  1109. sorted.push(subitem);
  1110. })
  1111. } else {
  1112. sorted.push(item[0]);
  1113. }
  1114. } else {
  1115. sorted.push(item.value);
  1116. }
  1117. } else {
  1118. sorted.push(item);
  1119. }
  1120. })
  1121. let minData = 0;
  1122. let maxData = 0;
  1123. if (sorted.length > 0) {
  1124. minData = Math.min.apply(this, sorted);
  1125. maxData = Math.max.apply(this, sorted);
  1126. }
  1127. //为了兼容v1.9.0之前的项目
  1128. if (index > -1) {
  1129. if (typeof opts.xAxis.data[index].min === 'number') {
  1130. minData = Math.min(opts.xAxis.data[index].min, minData);
  1131. }
  1132. if (typeof opts.xAxis.data[index].max === 'number') {
  1133. maxData = Math.max(opts.xAxis.data[index].max, maxData);
  1134. }
  1135. } else {
  1136. if (typeof opts.xAxis.min === 'number') {
  1137. minData = Math.min(opts.xAxis.min, minData);
  1138. }
  1139. if (typeof opts.xAxis.max === 'number') {
  1140. maxData = Math.max(opts.xAxis.max, maxData);
  1141. }
  1142. }
  1143. if (minData === maxData) {
  1144. let rangeSpan = maxData || 10;
  1145. maxData += rangeSpan;
  1146. }
  1147. //let dataRange = getDataRange(minData, maxData);
  1148. let minRange = minData;
  1149. let maxRange = maxData;
  1150. let range = [];
  1151. let eachRange = (maxRange - minRange) / opts.xAxis.splitNumber;
  1152. for (let i = 0; i <= opts.xAxis.splitNumber; i++) {
  1153. range.push(minRange + eachRange * i);
  1154. }
  1155. return range;
  1156. }
  1157. function calXAxisData(series, opts, config, context) {
  1158. //堆叠图重算Y轴
  1159. let columnstyle = assign({}, {
  1160. type: ""
  1161. }, opts.extra.bar);
  1162. let result = {
  1163. angle: 0,
  1164. xAxisHeight: opts.xAxis.lineHeight * opts.pix + opts.xAxis.marginTop * opts.pix
  1165. };
  1166. result.ranges = getXAxisTextList(series, opts, config, columnstyle.type);
  1167. result.rangesFormat = result.ranges.map(function(item) {
  1168. //item = opts.xAxis.formatter ? opts.xAxis.formatter(item) : util.toFixed(item, 2);
  1169. item = util.toFixed(item, 2);
  1170. return item;
  1171. });
  1172. let xAxisScaleValues = result.ranges.map(function(item) {
  1173. // 如果刻度值是浮点数,则保留两位小数
  1174. item = util.toFixed(item, 2);
  1175. // 若有自定义格式则调用自定义的格式化函数
  1176. //item = opts.xAxis.formatter ? opts.xAxis.formatter(Number(item)) : item;
  1177. return item;
  1178. });
  1179. result = Object.assign(result, getXAxisPoints(xAxisScaleValues, opts, config));
  1180. // 计算X轴刻度的属性譬如每个刻度的间隔,刻度的起始点\结束点以及总长
  1181. let eachSpacing = result.eachSpacing;
  1182. let textLength = xAxisScaleValues.map(function(item) {
  1183. return measureText(item, opts.xAxis.fontSize * opts.pix, context);
  1184. });
  1185. if (opts.xAxis.disabled === true) {
  1186. result.xAxisHeight = 0;
  1187. }
  1188. return result;
  1189. }
  1190. function getRadarDataPoints(angleList, center, radius, series, opts) {
  1191. let radarOption = opts.extra.radar || {};
  1192. radarOption.max = radarOption.max || 0;
  1193. let maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
  1194. let data = [];
  1195. for (let i = 0; i < series.length; i++) {
  1196. let each = series[i];
  1197. let listItem = {};
  1198. listItem.color = each.color;
  1199. listItem.legendShape = each.legendShape;
  1200. listItem.pointShape = each.pointShape;
  1201. listItem.data = [];
  1202. each.data.forEach(function(item, index) {
  1203. let tmp = {};
  1204. tmp.angle = angleList[index];
  1205. tmp.proportion = item / maxData;
  1206. tmp.value = item;
  1207. tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion * process * Math.sin(tmp.angle), center);
  1208. listItem.data.push(tmp);
  1209. });
  1210. data.push(listItem);
  1211. }
  1212. return data;
  1213. }
  1214. function getPieDataPoints(series, radius) {
  1215. let count = 0;
  1216. let _start_ = 0;
  1217. for (let i = 0; i < series.length; i++) {
  1218. let item = series[i];
  1219. item.data = item.data === null ? 0 : item.data;
  1220. count += item.data;
  1221. }
  1222. for (let i = 0; i < series.length; i++) {
  1223. let item = series[i];
  1224. item.data = item.data === null ? 0 : item.data;
  1225. if (count === 0) {
  1226. item._proportion_ = 1 / series.length * process;
  1227. } else {
  1228. item._proportion_ = item.data / count * process;
  1229. }
  1230. item._radius_ = radius;
  1231. }
  1232. for (let i = 0; i < series.length; i++) {
  1233. let item = series[i];
  1234. item._start_ = _start_;
  1235. _start_ += 2 * item._proportion_ * Math.PI;
  1236. }
  1237. return series;
  1238. }
  1239. function getFunnelDataPoints(series, radius, option, eachSpacing) {
  1240. for (let i = 0; i < series.length; i++) {
  1241. if(option.type == 'funnel'){
  1242. series[i].radius = series[i].data / series[0].data * radius * process;
  1243. }else{
  1244. series[i].radius = (eachSpacing * (series.length - i)) / (eachSpacing * series.length) * radius * process;
  1245. }
  1246. series[i]._proportion_ = series[i].data / series[0].data;
  1247. }
  1248. // if(option.type !== 'pyramid'){
  1249. // series.reverse();
  1250. // }
  1251. return series;
  1252. }
  1253. function getRoseDataPoints(series, type, minRadius, radius) {
  1254. let count = 0;
  1255. let _start_ = 0;
  1256. let dataArr = [];
  1257. for (let i = 0; i < series.length; i++) {
  1258. let item = series[i];
  1259. item.data = item.data === null ? 0 : item.data;
  1260. count += item.data;
  1261. dataArr.push(item.data);
  1262. }
  1263. let minData = Math.min.apply(null, dataArr);
  1264. let maxData = Math.max.apply(null, dataArr);
  1265. let radiusLength = radius - minRadius;
  1266. for (let i = 0; i < series.length; i++) {
  1267. let item = series[i];
  1268. item.data = item.data === null ? 0 : item.data;
  1269. if (count === 0) {
  1270. item._proportion_ = 1 / series.length * process;
  1271. item._rose_proportion_ = 1 / series.length * process;
  1272. } else {
  1273. item._proportion_ = item.data / count * process;
  1274. if(type == 'area'){
  1275. item._rose_proportion_ = 1 / series.length * process;
  1276. }else{
  1277. item._rose_proportion_ = item.data / count * process;
  1278. }
  1279. }
  1280. item._radius_ = minRadius + radiusLength * ((item.data - minData) / (maxData - minData)) || radius;
  1281. }
  1282. for (let i = 0; i < series.length; i++) {
  1283. let item = series[i];
  1284. item._start_ = _start_;
  1285. _start_ += 2 * item._rose_proportion_ * Math.PI;
  1286. }
  1287. return series;
  1288. }
  1289. function getArcbarDataPoints(series, arcbarOption) {
  1290. if (process == 1) {
  1291. process = 0.999999;
  1292. }
  1293. for (let i = 0; i < series.length; i++) {
  1294. let item = series[i];
  1295. item.data = item.data === null ? 0 : item.data;
  1296. let totalAngle;
  1297. if (arcbarOption.type == 'circle') {
  1298. totalAngle = 2;
  1299. } else {
  1300. if(arcbarOption.direction == 'ccw'){
  1301. if (arcbarOption.startAngle < arcbarOption.endAngle) {
  1302. totalAngle = 2 + arcbarOption.startAngle - arcbarOption.endAngle;
  1303. } else {
  1304. totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
  1305. }
  1306. }else{
  1307. if (arcbarOption.endAngle < arcbarOption.startAngle) {
  1308. totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
  1309. } else {
  1310. totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
  1311. }
  1312. }
  1313. }
  1314. item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
  1315. if(arcbarOption.direction == 'ccw'){
  1316. item._proportion_ = arcbarOption.startAngle - totalAngle * item.data * process ;
  1317. }
  1318. if (item._proportion_ >= 2) {
  1319. item._proportion_ = item._proportion_ % 2;
  1320. }
  1321. }
  1322. return series;
  1323. }
  1324. function getGaugeArcbarDataPoints(series, arcbarOption) {
  1325. if (process == 1) {
  1326. process = 0.999999;
  1327. }
  1328. for (let i = 0; i < series.length; i++) {
  1329. let item = series[i];
  1330. item.data = item.data === null ? 0 : item.data;
  1331. let totalAngle;
  1332. if (arcbarOption.type == 'circle') {
  1333. totalAngle = 2;
  1334. } else {
  1335. if (arcbarOption.endAngle < arcbarOption.startAngle) {
  1336. totalAngle = 2 + arcbarOption.endAngle - arcbarOption.startAngle;
  1337. } else {
  1338. totalAngle = arcbarOption.startAngle - arcbarOption.endAngle;
  1339. }
  1340. }
  1341. item._proportion_ = totalAngle * item.data * process + arcbarOption.startAngle;
  1342. if (item._proportion_ >= 2) {
  1343. item._proportion_ = item._proportion_ % 2;
  1344. }
  1345. }
  1346. return series;
  1347. }
  1348. function getGaugeAxisPoints(categories, startAngle, endAngle) {
  1349. let totalAngle;
  1350. if (endAngle < startAngle) {
  1351. totalAngle = 2 + endAngle - startAngle;
  1352. } else {
  1353. totalAngle = startAngle - endAngle;
  1354. }
  1355. let tempStartAngle = startAngle;
  1356. for (let i = 0; i < categories.length; i++) {
  1357. categories[i].value = categories[i].value === null ? 0 : categories[i].value;
  1358. categories[i]._startAngle_ = tempStartAngle;
  1359. categories[i]._endAngle_ = totalAngle * categories[i].value + startAngle;
  1360. if (categories[i]._endAngle_ >= 2) {
  1361. categories[i]._endAngle_ = categories[i]._endAngle_ % 2;
  1362. }
  1363. tempStartAngle = categories[i]._endAngle_;
  1364. }
  1365. return categories;
  1366. }
  1367. function getGaugeDataPoints(series, categories, gaugeOption) {
  1368. for (let i = 0; i < series.length; i++) {
  1369. let item = series[i];
  1370. item.data = item.data === null ? 0 : item.data;
  1371. if (gaugeOption.pointer.color == 'auto') {
  1372. for (let i = 0; i < categories.length; i++) {
  1373. if (item.data <= categories[i].value) {
  1374. item.color = categories[i].color;
  1375. break;
  1376. }
  1377. }
  1378. } else {
  1379. item.color = gaugeOption.pointer.color;
  1380. }
  1381. let totalAngle;
  1382. if (gaugeOption.endAngle < gaugeOption.startAngle) {
  1383. totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
  1384. } else {
  1385. totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
  1386. }
  1387. item._endAngle_ = totalAngle * item.data + gaugeOption.startAngle;
  1388. item._oldAngle_ = gaugeOption.oldAngle;
  1389. if (gaugeOption.oldAngle < gaugeOption.endAngle) {
  1390. item._oldAngle_ += 2;
  1391. }
  1392. if (item.data >= gaugeOption.oldData) {
  1393. item._proportion_ = (item._endAngle_ - item._oldAngle_) * process + gaugeOption.oldAngle;
  1394. } else {
  1395. item._proportion_ = item._oldAngle_ - (item._oldAngle_ - item._endAngle_) * process;
  1396. }
  1397. if (item._proportion_ >= 2) {
  1398. item._proportion_ = item._proportion_ % 2;
  1399. }
  1400. }
  1401. return series;
  1402. }
  1403. function getPieTextMaxLength(series, config, context, opts) {
  1404. series = getPieDataPoints(series);
  1405. let maxLength = 0;
  1406. for (let i = 0; i < series.length; i++) {
  1407. let item = series[i];
  1408. let text = item.formatter ? item.formatter(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
  1409. maxLength = Math.max(maxLength, measureText(text, item.textSize * opts.pix || config.fontSize, context));
  1410. }
  1411. return maxLength;
  1412. }
  1413. function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
  1414. return points.map(function(item) {
  1415. if (item === null) {
  1416. return null;
  1417. }
  1418. let seriesGap = 0;
  1419. let categoryGap = 0;
  1420. if (opts.type == 'mix') {
  1421. seriesGap = opts.extra.mix.column.seriesGap * opts.pix || 0;
  1422. categoryGap = opts.extra.mix.column.categoryGap * opts.pix || 0;
  1423. } else {
  1424. seriesGap = opts.extra.column.seriesGap * opts.pix || 0;
  1425. categoryGap = opts.extra.column.categoryGap * opts.pix || 0;
  1426. }
  1427. seriesGap = Math.min(seriesGap, eachSpacing / columnLen)
  1428. categoryGap = Math.min(categoryGap, eachSpacing / columnLen)
  1429. item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen);
  1430. if (opts.extra.mix && opts.extra.mix.column.width && +opts.extra.mix.column.width > 0) {
  1431. item.width = Math.min(item.width, +opts.extra.mix.column.width * opts.pix);
  1432. }
  1433. if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
  1434. item.width = Math.min(item.width, +opts.extra.column.width * opts.pix);
  1435. }
  1436. if (item.width <= 0) {
  1437. item.width = 1;
  1438. }
  1439. item.x += (index + 0.5 - columnLen / 2) * (item.width + seriesGap);
  1440. return item;
  1441. });
  1442. }
  1443. function fixBarData(points, eachSpacing, columnLen, index, config, opts) {
  1444. return points.map(function(item) {
  1445. if (item === null) {
  1446. return null;
  1447. }
  1448. let seriesGap = 0;
  1449. let categoryGap = 0;
  1450. seriesGap = opts.extra.bar.seriesGap * opts.pix || 0;
  1451. categoryGap = opts.extra.bar.categoryGap * opts.pix || 0;
  1452. seriesGap = Math.min(seriesGap, eachSpacing / columnLen)
  1453. categoryGap = Math.min(categoryGap, eachSpacing / columnLen)
  1454. item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen);
  1455. if (opts.extra.bar && opts.extra.bar.width && +opts.extra.bar.width > 0) {
  1456. item.width = Math.min(item.width, +opts.extra.bar.width * opts.pix);
  1457. }
  1458. if (item.width <= 0) {
  1459. item.width = 1;
  1460. }
  1461. item.y += (index + 0.5 - columnLen / 2) * (item.width + seriesGap);
  1462. return item;
  1463. });
  1464. }
  1465. function fixColumeMeterData(points, eachSpacing, columnLen, index, config, opts, border) {
  1466. let categoryGap = opts.extra.column.categoryGap * opts.pix || 0;
  1467. return points.map(function(item) {
  1468. if (item === null) {
  1469. return null;
  1470. }
  1471. item.width = eachSpacing - 2 * categoryGap;
  1472. if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
  1473. item.width = Math.min(item.width, +opts.extra.column.width * opts.pix);
  1474. }
  1475. if (index > 0) {
  1476. item.width -= border;
  1477. }
  1478. return item;
  1479. });
  1480. }
  1481. function fixColumeStackData(points, eachSpacing, columnLen, index, config, opts, series) {
  1482. let categoryGap = opts.extra.column.categoryGap * opts.pix || 0;
  1483. return points.map(function(item, indexn) {
  1484. if (item === null) {
  1485. return null;
  1486. }
  1487. item.width = Math.ceil(eachSpacing - 2 * categoryGap);
  1488. if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
  1489. item.width = Math.min(item.width, +opts.extra.column.width * opts.pix);
  1490. }
  1491. if (item.width <= 0) {
  1492. item.width = 1;
  1493. }
  1494. return item;
  1495. });
  1496. }
  1497. function fixBarStackData(points, eachSpacing, columnLen, index, config, opts, series) {
  1498. let categoryGap = opts.extra.bar.categoryGap * opts.pix || 0;
  1499. return points.map(function(item, indexn) {
  1500. if (item === null) {
  1501. return null;
  1502. }
  1503. item.width = Math.ceil(eachSpacing - 2 * categoryGap);
  1504. if (opts.extra.bar && opts.extra.bar.width && +opts.extra.bar.width > 0) {
  1505. item.width = Math.min(item.width, +opts.extra.bar.width * opts.pix);
  1506. }
  1507. if (item.width <= 0) {
  1508. item.width = 1;
  1509. }
  1510. return item;
  1511. });
  1512. }
  1513. function getXAxisPoints(categories, opts, config) {
  1514. let spacingValid = opts.width - opts.area[1] - opts.area[3];
  1515. let dataCount = opts.enableScroll ? Math.min(opts.xAxis.itemCount, categories.length) : categories.length;
  1516. if ((opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' || opts.type == 'bar') && dataCount > 1 && opts.xAxis.boundaryGap == 'justify') {
  1517. dataCount -= 1;
  1518. }
  1519. let widthRatio = 0;
  1520. if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){
  1521. if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
  1522. widthRatio = opts.extra.mount.widthRatio - 1;
  1523. dataCount += widthRatio;
  1524. }
  1525. let eachSpacing = spacingValid / dataCount;
  1526. let xAxisPoints = [];
  1527. let startX = opts.area[3];
  1528. let endX = opts.width - opts.area[1];
  1529. categories.forEach(function(item, index) {
  1530. xAxisPoints.push(startX + widthRatio / 2 * eachSpacing + index * eachSpacing);
  1531. });
  1532. if (opts.xAxis.boundaryGap !== 'justify') {
  1533. if (opts.enableScroll === true) {
  1534. xAxisPoints.push(startX + widthRatio * eachSpacing + categories.length * eachSpacing);
  1535. } else {
  1536. xAxisPoints.push(endX);
  1537. }
  1538. }
  1539. return {
  1540. xAxisPoints: xAxisPoints,
  1541. startX: startX,
  1542. endX: endX,
  1543. eachSpacing: eachSpacing
  1544. };
  1545. }
  1546. function getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
  1547. let points = [];
  1548. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1549. data.forEach(function(item, index) {
  1550. if (item === null) {
  1551. points.push(null);
  1552. } else {
  1553. let cPoints = [];
  1554. item.forEach(function(items, indexs) {
  1555. let point = {};
  1556. point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
  1557. let value = items.value || items;
  1558. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1559. height *= process;
  1560. point.y = opts.height - Math.round(height) - opts.area[2];
  1561. cPoints.push(point);
  1562. });
  1563. points.push(cPoints);
  1564. }
  1565. });
  1566. return points;
  1567. }
  1568. function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
  1569. let boundaryGap = 'center';
  1570. if (opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' ) {
  1571. boundaryGap = opts.xAxis.boundaryGap;
  1572. }
  1573. let points = [];
  1574. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1575. let validWidth = opts.width - opts.area[1] - opts.area[3];
  1576. data.forEach(function(item, index) {
  1577. if (item === null) {
  1578. points.push(null);
  1579. } else {
  1580. let point = {};
  1581. point.color = item.color;
  1582. point.x = xAxisPoints[index];
  1583. let value = item;
  1584. if (typeof item === 'object' && item !== null) {
  1585. if (item.constructor.toString().indexOf('Array') > -1) {
  1586. let xranges, xminRange, xmaxRange;
  1587. xranges = [].concat(opts.chartData.xAxisData.ranges);
  1588. xminRange = xranges.shift();
  1589. xmaxRange = xranges.pop();
  1590. value = item[1];
  1591. point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
  1592. if(opts.type == 'bubble'){
  1593. point.r = item[2];
  1594. point.t = item[3];
  1595. }
  1596. } else {
  1597. value = item.value;
  1598. }
  1599. }
  1600. if (boundaryGap == 'center') {
  1601. point.x += eachSpacing / 2;
  1602. }
  1603. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1604. height *= process;
  1605. point.y = opts.height - height - opts.area[2];
  1606. points.push(point);
  1607. }
  1608. });
  1609. return points;
  1610. }
  1611. function getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, chartProcess){
  1612. let boundaryGap = opts.xAxis.boundaryGap;
  1613. let points = [];
  1614. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1615. let validWidth = opts.width - opts.area[1] - opts.area[3];
  1616. data.forEach(function(item, index) {
  1617. if (item === null) {
  1618. points.push(null);
  1619. } else {
  1620. let point = {};
  1621. point.color = item.color;
  1622. if(lineOption.animation == 'vertical'){
  1623. point.x = xAxisPoints[index];
  1624. let value = item;
  1625. if (typeof item === 'object' && item !== null) {
  1626. if (item.constructor.toString().indexOf('Array') > -1) {
  1627. let xranges, xminRange, xmaxRange;
  1628. xranges = [].concat(opts.chartData.xAxisData.ranges);
  1629. xminRange = xranges.shift();
  1630. xmaxRange = xranges.pop();
  1631. value = item[1];
  1632. point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
  1633. } else {
  1634. value = item.value;
  1635. }
  1636. }
  1637. if (boundaryGap == 'center') {
  1638. point.x += eachSpacing / 2;
  1639. }
  1640. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1641. height *= process;
  1642. point.y = opts.height - height - opts.area[2];
  1643. points.push(point);
  1644. }else{
  1645. point.x = xAxisPoints[0] + eachSpacing * index * process;
  1646. let value = item;
  1647. if (boundaryGap == 'center') {
  1648. point.x += eachSpacing / 2;
  1649. }
  1650. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1651. point.y = opts.height - height - opts.area[2];
  1652. points.push(point);
  1653. }
  1654. }
  1655. });
  1656. return points;
  1657. }
  1658. function getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, chartProcess){
  1659. let points = [];
  1660. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1661. let validWidth = opts.width - opts.area[1] - opts.area[3];
  1662. data.forEach(function(item, index) {
  1663. if (item === null) {
  1664. points.push(null);
  1665. } else {
  1666. let point = {};
  1667. point.color = item.color;
  1668. point.x = xAxisPoints[index];
  1669. let value = item;
  1670. if (typeof item === 'object' && item !== null) {
  1671. if (item.constructor.toString().indexOf('Array') > -1) {
  1672. let xranges, xminRange, xmaxRange;
  1673. xranges = [].concat(opts.chartData.xAxisData.ranges);
  1674. xminRange = xranges.shift();
  1675. xmaxRange = xranges.pop();
  1676. value = item[1];
  1677. point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
  1678. } else {
  1679. value = item.value;
  1680. }
  1681. }
  1682. point.x += eachSpacing / 2;
  1683. let height = validHeight * (value * process - minRange) / (maxRange - minRange);
  1684. point.y = opts.height - height - opts.area[2];
  1685. points.push(point);
  1686. }
  1687. });
  1688. return points;
  1689. }
  1690. function getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints) {
  1691. let points = [];
  1692. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1693. let validWidth = opts.width - opts.area[1] - opts.area[3];
  1694. let mountWidth = eachSpacing * mountOption.widthRatio;
  1695. series.forEach(function(item, index) {
  1696. if (item === null) {
  1697. points.push(null);
  1698. } else {
  1699. let point = {};
  1700. point.color = item.color;
  1701. point.x = xAxisPoints[index];
  1702. point.x += eachSpacing / 2;
  1703. let value = item.data;
  1704. let height = validHeight * (value * process - minRange) / (maxRange - minRange);
  1705. point.y = opts.height - height - opts.area[2];
  1706. point.value = value;
  1707. point.width = mountWidth;
  1708. points.push(point);
  1709. }
  1710. });
  1711. return points;
  1712. }
  1713. function getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config) {
  1714. let points = [];
  1715. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1716. let validWidth = opts.width - opts.area[1] - opts.area[3];
  1717. data.forEach(function(item, index) {
  1718. if (item === null) {
  1719. points.push(null);
  1720. } else {
  1721. let point = {};
  1722. point.color = item.color;
  1723. point.y = yAxisPoints[index];
  1724. let value = item;
  1725. if (typeof item === 'object' && item !== null) {
  1726. value = item.value;
  1727. }
  1728. let height = validWidth * (value - minRange) / (maxRange - minRange);
  1729. height *= process;
  1730. point.height = height;
  1731. point.value = value;
  1732. point.x = height + opts.area[3];
  1733. points.push(point);
  1734. }
  1735. });
  1736. return points;
  1737. }
  1738. function getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
  1739. let points = [];
  1740. let validHeight = opts.height - opts.area[0] - opts.area[2];
  1741. data.forEach(function(item, index) {
  1742. if (item === null) {
  1743. points.push(null);
  1744. } else {
  1745. let point = {};
  1746. point.color = item.color;
  1747. point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
  1748. if (seriesIndex > 0) {
  1749. let value = 0;
  1750. for (let i = 0; i <= seriesIndex; i++) {
  1751. value += stackSeries[i].data[index];
  1752. }
  1753. let value0 = value - item;
  1754. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1755. let height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
  1756. } else {
  1757. let value = item;
  1758. if (typeof item === 'object' && item !== null) {
  1759. value = item.value;
  1760. }
  1761. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1762. let height0 = 0;
  1763. }
  1764. let heightc = height0;
  1765. height *= process;
  1766. heightc *= process;
  1767. point.y = opts.height - Math.round(height) - opts.area[2];
  1768. point.y0 = opts.height - Math.round(heightc) - opts.area[2];
  1769. points.push(point);
  1770. }
  1771. });
  1772. return points;
  1773. }
  1774. function getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, stackSeries) {
  1775. let points = [];
  1776. let validHeight = opts.width - opts.area[1] - opts.area[3];
  1777. data.forEach(function(item, index) {
  1778. if (item === null) {
  1779. points.push(null);
  1780. } else {
  1781. let point = {};
  1782. point.color = item.color;
  1783. point.y = yAxisPoints[index];
  1784. if (seriesIndex > 0) {
  1785. let value = 0;
  1786. for (let i = 0; i <= seriesIndex; i++) {
  1787. value += stackSeries[i].data[index];
  1788. }
  1789. let value0 = value - item;
  1790. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1791. let height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
  1792. } else {
  1793. let value = item;
  1794. if (typeof item === 'object' && item !== null) {
  1795. value = item.value;
  1796. }
  1797. let height = validHeight * (value - minRange) / (maxRange - minRange);
  1798. let height0 = 0;
  1799. }
  1800. let heightc = height0;
  1801. height *= process;
  1802. heightc *= process;
  1803. point.height = height - heightc;
  1804. point.x = opts.area[3] + height;
  1805. point.x0 = opts.area[3] + heightc;
  1806. points.push(point);
  1807. }
  1808. });
  1809. return points;
  1810. }
  1811. function getYAxisTextList(series, opts, config, stack, yData) {
  1812. let index = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : -1;
  1813. let data;
  1814. if (stack == 'stack') {
  1815. data = dataCombineStack(series, opts.categories.length);
  1816. } else {
  1817. data = dataCombine(series);
  1818. }
  1819. let sorted = [];
  1820. // remove null from data
  1821. data = data.filter(function(item) {
  1822. //return item !== null;
  1823. if (typeof item === 'object' && item !== null) {
  1824. if (item.constructor.toString().indexOf('Array') > -1) {
  1825. return item !== null;
  1826. } else {
  1827. return item.value !== null;
  1828. }
  1829. } else {
  1830. return item !== null;
  1831. }
  1832. });
  1833. data.map(function(item) {
  1834. if (typeof item === 'object') {
  1835. if (item.constructor.toString().indexOf('Array') > -1) {
  1836. if (opts.type == 'candle') {
  1837. item.map(function(subitem) {
  1838. sorted.push(subitem);
  1839. })
  1840. } else {
  1841. sorted.push(item[1]);
  1842. }
  1843. } else {
  1844. sorted.push(item.value);
  1845. }
  1846. } else {
  1847. sorted.push(item);
  1848. }
  1849. })
  1850. let minData = yData.min || 0;
  1851. let maxData = yData.max || 0;
  1852. if (sorted.length > 0) {
  1853. minData = Math.min.apply(this, sorted);
  1854. maxData = Math.max.apply(this, sorted);
  1855. }
  1856. if (minData === maxData) {
  1857. if(maxData == 0){
  1858. maxData = 10;
  1859. }else{
  1860. minData = 0;
  1861. }
  1862. }
  1863. let dataRange = getDataRange(minData, maxData);
  1864. let minRange = (yData.min === undefined || yData.min === null) ? dataRange.minRange : yData.min;
  1865. let maxRange = (yData.max === undefined || yData.max === null) ? dataRange.maxRange : yData.max;
  1866. let eachRange = (maxRange - minRange) / opts.yAxis.splitNumber;
  1867. let range = [];
  1868. for (let i = 0; i <= opts.yAxis.splitNumber; i++) {
  1869. range.push(minRange + eachRange * i);
  1870. }
  1871. return range.reverse();
  1872. }
  1873. function calYAxisData(series, opts, config, context) {
  1874. //堆叠图重算Y轴
  1875. let columnstyle = assign({}, {
  1876. type: ""
  1877. }, opts.extra.column);
  1878. //如果是多Y轴,重新计算
  1879. let YLength = opts.yAxis.data.length;
  1880. let newSeries = new Array(YLength);
  1881. if (YLength > 0) {
  1882. for (let i = 0; i < YLength; i++) {
  1883. newSeries[i] = [];
  1884. for (let j = 0; j < series.length; j++) {
  1885. if (series[j].index == i) {
  1886. newSeries[i].push(series[j]);
  1887. }
  1888. }
  1889. }
  1890. let rangesArr = new Array(YLength);
  1891. let rangesFormatArr = new Array(YLength);
  1892. let yAxisWidthArr = new Array(YLength);
  1893. for (let i = 0; i < YLength; i++) {
  1894. let yData = opts.yAxis.data[i];
  1895. //如果总开关不显示,强制每个Y轴为不显示
  1896. if (opts.yAxis.disabled == true) {
  1897. yData.disabled = true;
  1898. }
  1899. if(yData.type === 'categories'){
  1900. if(!yData.formatter){
  1901. yData.formatter = (val,index,opts) => {return val + (yData.unit || '')};
  1902. }
  1903. yData.categories = yData.categories || opts.categories;
  1904. rangesArr[i] = yData.categories;
  1905. }else{
  1906. if(!yData.formatter){
  1907. yData.formatter = (val,index,opts) => {return util.toFixed(val, yData.tofix || 0) + (yData.unit || '')};
  1908. }
  1909. rangesArr[i] = getYAxisTextList(newSeries[i], opts, config, columnstyle.type, yData, i);
  1910. }
  1911. let yAxisFontSizes = yData.fontSize * opts.pix || config.fontSize;
  1912. yAxisWidthArr[i] = {
  1913. position: yData.position ? yData.position : 'left',
  1914. width: 0
  1915. };
  1916. rangesFormatArr[i] = rangesArr[i].map(function(items,index) {
  1917. items = yData.formatter(items,index,opts);
  1918. yAxisWidthArr[i].width = Math.max(yAxisWidthArr[i].width, measureText(items, yAxisFontSizes, context) + 5);
  1919. return items;
  1920. });
  1921. let calibration = yData.calibration ? 4 * opts.pix : 0;
  1922. yAxisWidthArr[i].width += calibration + 3 * opts.pix;
  1923. if (yData.disabled === true) {
  1924. yAxisWidthArr[i].width = 0;
  1925. }
  1926. }
  1927. } else {
  1928. let rangesArr = new Array(1);
  1929. let rangesFormatArr = new Array(1);
  1930. let yAxisWidthArr = new Array(1);
  1931. if(opts.type === 'bar'){
  1932. rangesArr[0] = opts.categories;
  1933. if(!opts.yAxis.formatter){
  1934. opts.yAxis.formatter = (val,index,opts) => {return val + (opts.yAxis.unit || '')}
  1935. }
  1936. }else{
  1937. if(!opts.yAxis.formatter){
  1938. opts.yAxis.formatter = (val,index,opts) => {return val.toFixed(opts.yAxis.tofix ) + (opts.yAxis.unit || '')}
  1939. }
  1940. rangesArr[0] = getYAxisTextList(series, opts, config, columnstyle.type, {});
  1941. }
  1942. yAxisWidthArr[0] = {
  1943. position: 'left',
  1944. width: 0
  1945. };
  1946. let yAxisFontSize = opts.yAxis.fontSize * opts.pix || config.fontSize;
  1947. rangesFormatArr[0] = rangesArr[0].map(function(item,index) {
  1948. item = opts.yAxis.formatter(item,index,opts);
  1949. yAxisWidthArr[0].width = Math.max(yAxisWidthArr[0].width, measureText(item, yAxisFontSize, context) + 5);
  1950. return item;
  1951. });
  1952. yAxisWidthArr[0].width += 3 * opts.pix;
  1953. if (opts.yAxis.disabled === true) {
  1954. yAxisWidthArr[0] = {
  1955. position: 'left',
  1956. width: 0
  1957. };
  1958. opts.yAxis.data[0] = {
  1959. disabled: true
  1960. };
  1961. } else {
  1962. opts.yAxis.data[0] = {
  1963. disabled: false,
  1964. position: 'left',
  1965. max: opts.yAxis.max,
  1966. min: opts.yAxis.min,
  1967. formatter: opts.yAxis.formatter
  1968. };
  1969. if(opts.type === 'bar'){
  1970. opts.yAxis.data[0].categories = opts.categories;
  1971. opts.yAxis.data[0].type = 'categories';
  1972. }
  1973. }
  1974. }
  1975. return {
  1976. rangesFormat: rangesFormatArr,
  1977. ranges: rangesArr,
  1978. yAxisWidth: yAxisWidthArr
  1979. };
  1980. }
  1981. function calTooltipYAxisData(point, series, opts, config, eachSpacing) {
  1982. let ranges = [].concat(opts.chartData.yAxisData.ranges);
  1983. let spacingValid = opts.height - opts.area[0] - opts.area[2];
  1984. let minAxis = opts.area[0];
  1985. let items = [];
  1986. for (let i = 0; i < ranges.length; i++) {
  1987. let maxVal = Math.max.apply(this, ranges[i]);
  1988. let minVal = Math.min.apply(this, ranges[i]);
  1989. let item = maxVal - (maxVal - minVal) * (point - minAxis) / spacingValid;
  1990. item = opts.yAxis.data && opts.yAxis.data[i].formatter ? opts.yAxis.data[i].formatter(item, i, opts) : item.toFixed(0);
  1991. items.push(String(item))
  1992. }
  1993. return items;
  1994. }
  1995. function calMarkLineData(points, opts) {
  1996. let minRange, maxRange;
  1997. let spacingValid = opts.height - opts.area[0] - opts.area[2];
  1998. for (let i = 0; i < points.length; i++) {
  1999. points[i].yAxisIndex = points[i].yAxisIndex ? points[i].yAxisIndex : 0;
  2000. let range = [].concat(opts.chartData.yAxisData.ranges[points[i].yAxisIndex]);
  2001. minRange = range.pop();
  2002. maxRange = range.shift();
  2003. let height = spacingValid * (points[i].value - minRange) / (maxRange - minRange);
  2004. points[i].y = opts.height - Math.round(height) - opts.area[2];
  2005. }
  2006. return points;
  2007. }
  2008. function contextRotate(context, opts) {
  2009. if (opts.rotateLock !== true) {
  2010. context.translate(opts.height, 0);
  2011. context.rotate(90 * Math.PI / 180);
  2012. } else if (opts._rotate_ !== true) {
  2013. context.translate(opts.height, 0);
  2014. context.rotate(90 * Math.PI / 180);
  2015. opts._rotate_ = true;
  2016. }
  2017. }
  2018. function drawPointShape(points, color, shape, context, opts) {
  2019. context.beginPath();
  2020. if (opts.dataPointShapeType == 'hollow') {
  2021. context.setStrokeStyle(color);
  2022. context.setFillStyle(opts.background);
  2023. context.setLineWidth(2 * opts.pix);
  2024. } else {
  2025. context.setStrokeStyle("#ffffff");
  2026. context.setFillStyle(color);
  2027. context.setLineWidth(1 * opts.pix);
  2028. }
  2029. if (shape === 'diamond') {
  2030. points.forEach(function(item, index) {
  2031. if (item !== null) {
  2032. context.moveTo(item.x, item.y - 4.5);
  2033. context.lineTo(item.x - 4.5, item.y);
  2034. context.lineTo(item.x, item.y + 4.5);
  2035. context.lineTo(item.x + 4.5, item.y);
  2036. context.lineTo(item.x, item.y - 4.5);
  2037. }
  2038. });
  2039. } else if (shape === 'circle') {
  2040. points.forEach(function(item, index) {
  2041. if (item !== null) {
  2042. context.moveTo(item.x + 2.5 * opts.pix, item.y);
  2043. context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false);
  2044. }
  2045. });
  2046. } else if (shape === 'square') {
  2047. points.forEach(function(item, index) {
  2048. if (item !== null) {
  2049. context.moveTo(item.x - 3.5, item.y - 3.5);
  2050. context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
  2051. }
  2052. });
  2053. } else if (shape === 'triangle') {
  2054. points.forEach(function(item, index) {
  2055. if (item !== null) {
  2056. context.moveTo(item.x, item.y - 4.5);
  2057. context.lineTo(item.x - 4.5, item.y + 4.5);
  2058. context.lineTo(item.x + 4.5, item.y + 4.5);
  2059. context.lineTo(item.x, item.y - 4.5);
  2060. }
  2061. });
  2062. } else if (shape === 'none') {
  2063. return;
  2064. }
  2065. context.closePath();
  2066. context.fill();
  2067. context.stroke();
  2068. }
  2069. function drawActivePoint(points, color, shape, context, opts, option, seriesIndex) {
  2070. if(!opts.tooltip){
  2071. return
  2072. }
  2073. if(opts.tooltip.group.length>0 && opts.tooltip.group.includes(seriesIndex) == false){
  2074. return
  2075. }
  2076. let pointIndex = typeof opts.tooltip.index === 'number' ? opts.tooltip.index : opts.tooltip.index[opts.tooltip.group.indexOf(seriesIndex)];
  2077. context.beginPath();
  2078. if (option.activeType == 'hollow') {
  2079. context.setStrokeStyle(color);
  2080. context.setFillStyle(opts.background);
  2081. context.setLineWidth(2 * opts.pix);
  2082. } else {
  2083. context.setStrokeStyle("#ffffff");
  2084. context.setFillStyle(color);
  2085. context.setLineWidth(1 * opts.pix);
  2086. }
  2087. if (shape === 'diamond') {
  2088. points.forEach(function(item, index) {
  2089. if (item !== null && pointIndex == index ) {
  2090. context.moveTo(item.x, item.y - 4.5);
  2091. context.lineTo(item.x - 4.5, item.y);
  2092. context.lineTo(item.x, item.y + 4.5);
  2093. context.lineTo(item.x + 4.5, item.y);
  2094. context.lineTo(item.x, item.y - 4.5);
  2095. }
  2096. });
  2097. } else if (shape === 'circle') {
  2098. points.forEach(function(item, index) {
  2099. if (item !== null && pointIndex == index) {
  2100. context.moveTo(item.x + 2.5 * opts.pix, item.y);
  2101. context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false);
  2102. }
  2103. });
  2104. } else if (shape === 'square') {
  2105. points.forEach(function(item, index) {
  2106. if (item !== null && pointIndex == index) {
  2107. context.moveTo(item.x - 3.5, item.y - 3.5);
  2108. context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
  2109. }
  2110. });
  2111. } else if (shape === 'triangle') {
  2112. points.forEach(function(item, index) {
  2113. if (item !== null && pointIndex == index) {
  2114. context.moveTo(item.x, item.y - 4.5);
  2115. context.lineTo(item.x - 4.5, item.y + 4.5);
  2116. context.lineTo(item.x + 4.5, item.y + 4.5);
  2117. context.lineTo(item.x, item.y - 4.5);
  2118. }
  2119. });
  2120. } else if (shape === 'none') {
  2121. return;
  2122. }
  2123. context.closePath();
  2124. context.fill();
  2125. context.stroke();
  2126. }
  2127. function drawRingTitle(opts, config, context, center) {
  2128. let titlefontSize = opts.title.fontSize || config.titleFontSize;
  2129. let subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize;
  2130. let title = opts.title.name || '';
  2131. let subtitle = opts.subtitle.name || '';
  2132. let titleFontColor = opts.title.color || opts.fontColor;
  2133. let subtitleFontColor = opts.subtitle.color || opts.fontColor;
  2134. let titleHeight = title ? titlefontSize : 0;
  2135. let subtitleHeight = subtitle ? subtitlefontSize : 0;
  2136. let margin = 5;
  2137. if (subtitle) {
  2138. let textWidth = measureText(subtitle, subtitlefontSize * opts.pix, context);
  2139. let startX = center.x - textWidth / 2 + (opts.subtitle.offsetX|| 0) * opts.pix ;
  2140. let startY = center.y + subtitlefontSize * opts.pix / 2 + (opts.subtitle.offsetY || 0) * opts.pix;
  2141. if (title) {
  2142. startY += (titleHeight * opts.pix + margin) / 2;
  2143. }
  2144. context.beginPath();
  2145. context.setFontSize(subtitlefontSize * opts.pix);
  2146. context.setFillStyle(subtitleFontColor);
  2147. context.fillText(subtitle, startX, startY);
  2148. context.closePath();
  2149. context.stroke();
  2150. }
  2151. if (title) {
  2152. let _textWidth = measureText(title, titlefontSize * opts.pix, context);
  2153. let _startX = center.x - _textWidth / 2 + (opts.title.offsetX || 0);
  2154. let _startY = center.y + titlefontSize * opts.pix / 2 + (opts.title.offsetY || 0) * opts.pix;
  2155. if (subtitle) {
  2156. _startY -= (subtitleHeight * opts.pix + margin) / 2;
  2157. }
  2158. context.beginPath();
  2159. context.setFontSize(titlefontSize * opts.pix);
  2160. context.setFillStyle(titleFontColor);
  2161. context.fillText(title, _startX, _startY);
  2162. context.closePath();
  2163. context.stroke();
  2164. }
  2165. }
  2166. function drawPointText(points, series, config, context, opts) {
  2167. // 绘制数据文案
  2168. let data = series.data;
  2169. let textOffset = series.textOffset ? series.textOffset : 0;
  2170. points.forEach(function(item, index) {
  2171. if (item !== null) {
  2172. context.beginPath();
  2173. let fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize;
  2174. context.setFontSize(fontSize);
  2175. context.setFillStyle(series.textColor || opts.fontColor);
  2176. let value = data[index]
  2177. if (typeof data[index] === 'object' && data[index] !== null) {
  2178. if (data[index].constructor.toString().indexOf('Array')>-1) {
  2179. value = data[index][1];
  2180. } else {
  2181. value = data[index].value
  2182. }
  2183. }
  2184. let formatVal = series.formatter ? series.formatter(value,index,series,opts) : value;
  2185. context.setTextAlign('center');
  2186. context.fillText(String(formatVal), item.x, item.y - 4 + textOffset * opts.pix);
  2187. context.closePath();
  2188. context.stroke();
  2189. context.setTextAlign('left');
  2190. }
  2191. });
  2192. }
  2193. function drawColumePointText(points, series, config, context, opts) {
  2194. // 绘制数据文案
  2195. let data = series.data;
  2196. let textOffset = series.textOffset ? series.textOffset : 0;
  2197. let Position = opts.extra.column.labelPosition;
  2198. points.forEach(function(item, index) {
  2199. if (item !== null) {
  2200. context.beginPath();
  2201. let fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize;
  2202. context.setFontSize(fontSize);
  2203. context.setFillStyle(series.textColor || opts.fontColor);
  2204. let value = data[index]
  2205. if (typeof data[index] === 'object' && data[index] !== null) {
  2206. if (data[index].constructor.toString().indexOf('Array')>-1) {
  2207. value = data[index][1];
  2208. } else {
  2209. value = data[index].value
  2210. }
  2211. }
  2212. let formatVal = series.formatter ? series.formatter(value,index,series,opts) : value;
  2213. context.setTextAlign('center');
  2214. let startY = item.y - 4 * opts.pix + textOffset * opts.pix;
  2215. if(item.y > series.zeroPoints){
  2216. startY = item.y + textOffset * opts.pix + fontSize;
  2217. }
  2218. if(Position == 'insideTop'){
  2219. startY = item.y + fontSize + textOffset * opts.pix;
  2220. if(item.y > series.zeroPoints){
  2221. startY = item.y - textOffset * opts.pix - 4 * opts.pix;
  2222. }
  2223. }
  2224. if(Position == 'center'){
  2225. startY = item.y + textOffset * opts.pix + (opts.height - opts.area[2] - item.y + fontSize)/2;
  2226. if(series.zeroPoints < opts.height - opts.area[2]){
  2227. startY = item.y + textOffset * opts.pix + (series.zeroPoints - item.y + fontSize)/2;
  2228. }
  2229. if(item.y > series.zeroPoints){
  2230. startY = item.y - textOffset * opts.pix - (item.y - series.zeroPoints - fontSize)/2;
  2231. }
  2232. if(opts.extra.column.type == 'stack'){
  2233. startY = item.y + textOffset * opts.pix + (item.y0 - item.y + fontSize)/2;
  2234. }
  2235. }
  2236. if(Position == 'bottom'){
  2237. startY = opts.height - opts.area[2] + textOffset * opts.pix - 4 * opts.pix;
  2238. if(series.zeroPoints < opts.height - opts.area[2]){
  2239. startY = series.zeroPoints + textOffset * opts.pix - 4 * opts.pix;
  2240. }
  2241. if(item.y > series.zeroPoints){
  2242. startY = series.zeroPoints - textOffset * opts.pix + fontSize + 2 * opts.pix;
  2243. }
  2244. if(opts.extra.column.type == 'stack'){
  2245. startY = item.y0 + textOffset * opts.pix - 4 * opts.pix;
  2246. }
  2247. }
  2248. context.fillText(String(formatVal), item.x, startY);
  2249. context.closePath();
  2250. context.stroke();
  2251. context.setTextAlign('left');
  2252. }
  2253. });
  2254. }
  2255. function drawMountPointText(points, series, config, context, opts, zeroPoints) {
  2256. // 绘制数据文案
  2257. let data = series.data;
  2258. let textOffset = series.textOffset ? series.textOffset : 0;
  2259. let Position = opts.extra.mount.labelPosition;
  2260. points.forEach(function(item, index) {
  2261. if (item !== null) {
  2262. context.beginPath();
  2263. let fontSize = series[index].textSize ? series[index].textSize * opts.pix : config.fontSize;
  2264. context.setFontSize(fontSize);
  2265. context.setFillStyle(series[index].textColor || opts.fontColor);
  2266. let value = item.value
  2267. let formatVal = series[index].formatter ? series[index].formatter(value,index,series,opts) : value;
  2268. context.setTextAlign('center');
  2269. let startY = item.y - 4 * opts.pix + textOffset * opts.pix;
  2270. if(item.y > zeroPoints){
  2271. startY = item.y + textOffset * opts.pix + fontSize;
  2272. }
  2273. context.fillText(String(formatVal), item.x, startY);
  2274. context.closePath();
  2275. context.stroke();
  2276. context.setTextAlign('left');
  2277. }
  2278. });
  2279. }
  2280. function drawBarPointText(points, series, config, context, opts) {
  2281. // 绘制数据文案
  2282. let data = series.data;
  2283. let textOffset = series.textOffset ? series.textOffset : 0;
  2284. points.forEach(function(item, index) {
  2285. if (item !== null) {
  2286. context.beginPath();
  2287. let fontSize = series.textSize ? series.textSize * opts.pix : config.fontSize;
  2288. context.setFontSize(fontSize);
  2289. context.setFillStyle(series.textColor || opts.fontColor);
  2290. let value = data[index]
  2291. if (typeof data[index] === 'object' && data[index] !== null) {
  2292. value = data[index].value ;
  2293. }
  2294. let formatVal = series.formatter ? series.formatter(value,index,series,opts) : value;
  2295. context.setTextAlign('left');
  2296. context.fillText(String(formatVal), item.x + 4 * opts.pix , item.y + fontSize / 2 - 3 );
  2297. context.closePath();
  2298. context.stroke();
  2299. }
  2300. });
  2301. }
  2302. function drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context) {
  2303. radius -= gaugeOption.width / 2 + gaugeOption.labelOffset * opts.pix;
  2304. radius = radius < 10 ? 10 : radius;
  2305. let totalAngle;
  2306. if (gaugeOption.endAngle < gaugeOption.startAngle) {
  2307. totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
  2308. } else {
  2309. totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
  2310. }
  2311. let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
  2312. let totalNumber = gaugeOption.endNumber - gaugeOption.startNumber;
  2313. let splitNumber = totalNumber / gaugeOption.splitLine.splitNumber;
  2314. let nowAngle = gaugeOption.startAngle;
  2315. let nowNumber = gaugeOption.startNumber;
  2316. for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
  2317. let pos = {
  2318. x: radius * Math.cos(nowAngle * Math.PI),
  2319. y: radius * Math.sin(nowAngle * Math.PI)
  2320. };
  2321. let labelText = gaugeOption.formatter ? gaugeOption.formatter(nowNumber,i,opts) : nowNumber;
  2322. pos.x += centerPosition.x - measureText(labelText, config.fontSize, context) / 2;
  2323. pos.y += centerPosition.y;
  2324. let startX = pos.x;
  2325. let startY = pos.y;
  2326. context.beginPath();
  2327. context.setFontSize(config.fontSize);
  2328. context.setFillStyle(gaugeOption.labelColor || opts.fontColor);
  2329. context.fillText(labelText, startX, startY + config.fontSize / 2);
  2330. context.closePath();
  2331. context.stroke();
  2332. nowAngle += splitAngle;
  2333. if (nowAngle >= 2) {
  2334. nowAngle = nowAngle % 2;
  2335. }
  2336. nowNumber += splitNumber;
  2337. }
  2338. }
  2339. function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
  2340. let radarOption = opts.extra.radar || {};
  2341. angleList.forEach(function(angle, index) {
  2342. if(radarOption.labelPointShow === true && opts.categories[index] !== ''){
  2343. let posPoint = {
  2344. x: radius * Math.cos(angle),
  2345. y: radius * Math.sin(angle)
  2346. };
  2347. let posPointAxis = convertCoordinateOrigin(posPoint.x, posPoint.y, centerPosition);
  2348. context.setFillStyle(radarOption.labelPointColor);
  2349. context.beginPath();
  2350. context.arc(posPointAxis.x, posPointAxis.y, radarOption.labelPointRadius * opts.pix, 0, 2 * Math.PI, false);
  2351. context.closePath();
  2352. context.fill();
  2353. }
  2354. if(radarOption.labelShow === true){
  2355. let pos = {
  2356. x: (radius + config.radarLabelTextMargin * opts.pix) * Math.cos(angle),
  2357. y: (radius + config.radarLabelTextMargin * opts.pix) * Math.sin(angle)
  2358. };
  2359. let posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
  2360. let startX = posRelativeCanvas.x;
  2361. let startY = posRelativeCanvas.y;
  2362. if (util.approximatelyEqual(pos.x, 0)) {
  2363. startX -= measureText(opts.categories[index] || '', config.fontSize, context) / 2;
  2364. } else if (pos.x < 0) {
  2365. startX -= measureText(opts.categories[index] || '', config.fontSize, context);
  2366. }
  2367. context.beginPath();
  2368. context.setFontSize(config.fontSize);
  2369. context.setFillStyle(radarOption.labelColor || opts.fontColor);
  2370. context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
  2371. context.closePath();
  2372. context.stroke();
  2373. }
  2374. });
  2375. }
  2376. function drawPieText(series, opts, config, context, radius, center) {
  2377. let lineRadius = config.pieChartLinePadding;
  2378. let textObjectCollection = [];
  2379. let lastTextObject = null;
  2380. let seriesConvert = series.map(function(item,index) {
  2381. let text = item.formatter ? item.formatter(item,index,series,opts) : util.toFixed(item._proportion_.toFixed(4) * 100) + '%';
  2382. text = item.labelText ? item.labelText : text;
  2383. let arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
  2384. if (item._rose_proportion_) {
  2385. arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._rose_proportion_ / 2);
  2386. }
  2387. let color = item.color;
  2388. let radius = item._radius_;
  2389. return {
  2390. arc: arc,
  2391. text: text,
  2392. color: color,
  2393. radius: radius,
  2394. textColor: item.textColor,
  2395. textSize: item.textSize,
  2396. labelShow: item.labelShow
  2397. };
  2398. });
  2399. for (let i = 0; i < seriesConvert.length; i++) {
  2400. let item = seriesConvert[i];
  2401. // line end
  2402. let orginX1 = Math.cos(item.arc) * (item.radius + lineRadius);
  2403. let orginY1 = Math.sin(item.arc) * (item.radius + lineRadius);
  2404. // line start
  2405. let orginX2 = Math.cos(item.arc) * item.radius;
  2406. let orginY2 = Math.sin(item.arc) * item.radius;
  2407. // text start
  2408. let orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
  2409. let orginY3 = orginY1;
  2410. let textWidth = measureText(item.text, item.textSize * opts.pix || config.fontSize, context);
  2411. let startY = orginY3;
  2412. if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, {
  2413. x: orginX3
  2414. })) {
  2415. if (orginX3 > 0) {
  2416. startY = Math.min(orginY3, lastTextObject.start.y);
  2417. } else if (orginX1 < 0) {
  2418. startY = Math.max(orginY3, lastTextObject.start.y);
  2419. } else {
  2420. if (orginY3 > 0) {
  2421. startY = Math.max(orginY3, lastTextObject.start.y);
  2422. } else {
  2423. startY = Math.min(orginY3, lastTextObject.start.y);
  2424. }
  2425. }
  2426. }
  2427. if (orginX3 < 0) {
  2428. orginX3 -= textWidth;
  2429. }
  2430. let textObject = {
  2431. lineStart: {
  2432. x: orginX2,
  2433. y: orginY2
  2434. },
  2435. lineEnd: {
  2436. x: orginX1,
  2437. y: orginY1
  2438. },
  2439. start: {
  2440. x: orginX3,
  2441. y: startY
  2442. },
  2443. width: textWidth,
  2444. height: config.fontSize,
  2445. text: item.text,
  2446. color: item.color,
  2447. textColor: item.textColor,
  2448. textSize: item.textSize
  2449. };
  2450. lastTextObject = avoidCollision(textObject, lastTextObject);
  2451. textObjectCollection.push(lastTextObject);
  2452. }
  2453. for (let i = 0; i < textObjectCollection.length; i++) {
  2454. if(seriesConvert[i].labelShow === false){
  2455. continue;
  2456. }
  2457. let item = textObjectCollection[i];
  2458. let lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
  2459. let lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
  2460. let textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
  2461. context.setLineWidth(1 * opts.pix);
  2462. context.setFontSize(item.textSize * opts.pix || config.fontSize);
  2463. context.beginPath();
  2464. context.setStrokeStyle(item.color);
  2465. context.setFillStyle(item.color);
  2466. context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
  2467. let curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
  2468. let textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
  2469. context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
  2470. context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
  2471. context.stroke();
  2472. context.closePath();
  2473. context.beginPath();
  2474. context.moveTo(textPosition.x + item.width, textPosition.y);
  2475. context.arc(curveStartX, textPosition.y, 2 * opts.pix, 0, 2 * Math.PI);
  2476. context.closePath();
  2477. context.fill();
  2478. context.beginPath();
  2479. context.setFontSize(item.textSize * opts.pix || config.fontSize);
  2480. context.setFillStyle(item.textColor || opts.fontColor);
  2481. context.fillText(item.text, textStartX, textPosition.y + 3);
  2482. context.closePath();
  2483. context.stroke();
  2484. context.closePath();
  2485. }
  2486. }
  2487. function drawToolTipSplitLine(offsetX, opts, config, context) {
  2488. let toolTipOption = opts.extra.tooltip || {};
  2489. toolTipOption.gridType = toolTipOption.gridType == undefined ? 'solid' : toolTipOption.gridType;
  2490. toolTipOption.dashLength = toolTipOption.dashLength == undefined ? 4 : toolTipOption.dashLength;
  2491. let startY = opts.area[0];
  2492. let endY = opts.height - opts.area[2];
  2493. if (toolTipOption.gridType == 'dash') {
  2494. context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
  2495. }
  2496. context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
  2497. context.setLineWidth(1 * opts.pix);
  2498. context.beginPath();
  2499. context.moveTo(offsetX, startY);
  2500. context.lineTo(offsetX, endY);
  2501. context.stroke();
  2502. context.setLineDash([]);
  2503. if (toolTipOption.xAxisLabel) {
  2504. let labelText = opts.categories[opts.tooltip.index];
  2505. context.setFontSize(config.fontSize);
  2506. let textWidth = measureText(labelText, config.fontSize, context);
  2507. let textX = offsetX - 0.5 * textWidth;
  2508. let textY = endY + 2 * opts.pix;
  2509. context.beginPath();
  2510. context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
  2511. context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
  2512. context.setLineWidth(1 * opts.pix);
  2513. context.rect(textX - toolTipOption.boxPadding * opts.pix, textY, textWidth + 2 * toolTipOption.boxPadding * opts.pix, config.fontSize + 2 * toolTipOption.boxPadding * opts.pix);
  2514. context.closePath();
  2515. context.stroke();
  2516. context.fill();
  2517. context.beginPath();
  2518. context.setFontSize(config.fontSize);
  2519. context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor);
  2520. context.fillText(String(labelText), textX, textY + toolTipOption.boxPadding * opts.pix + config.fontSize);
  2521. context.closePath();
  2522. context.stroke();
  2523. }
  2524. }
  2525. function drawMarkLine(opts, config, context) {
  2526. let markLineOption = assign({}, {
  2527. type: 'solid',
  2528. dashLength: 4,
  2529. data: []
  2530. }, opts.extra.markLine);
  2531. let startX = opts.area[3];
  2532. let endX = opts.width - opts.area[1];
  2533. let points = calMarkLineData(markLineOption.data, opts);
  2534. for (let i = 0; i < points.length; i++) {
  2535. let item = assign({}, {
  2536. lineColor: '#DE4A42',
  2537. showLabel: false,
  2538. labelFontSize: 13,
  2539. labelPadding: 6,
  2540. labelFontColor: '#666666',
  2541. labelBgColor: '#DFE8FF',
  2542. labelBgOpacity: 0.8,
  2543. labelAlign: 'left',
  2544. labelOffsetX: 0,
  2545. labelOffsetY: 0,
  2546. }, points[i]);
  2547. if (markLineOption.type == 'dash') {
  2548. context.setLineDash([markLineOption.dashLength, markLineOption.dashLength]);
  2549. }
  2550. context.setStrokeStyle(item.lineColor);
  2551. context.setLineWidth(1 * opts.pix);
  2552. context.beginPath();
  2553. context.moveTo(startX, item.y);
  2554. context.lineTo(endX, item.y);
  2555. context.stroke();
  2556. context.setLineDash([]);
  2557. if (item.showLabel) {
  2558. let fontSize = item.labelFontSize * opts.pix;
  2559. let labelText = item.labelText ? item.labelText : item.value;
  2560. context.setFontSize(fontSize);
  2561. let textWidth = measureText(labelText, fontSize, context);
  2562. let bgWidth = textWidth + item.labelPadding * opts.pix * 2;
  2563. let bgStartX = item.labelAlign == 'left' ? opts.area[3] - bgWidth : opts.width - opts.area[1];
  2564. bgStartX += item.labelOffsetX;
  2565. let bgStartY = item.y - 0.5 * fontSize - item.labelPadding * opts.pix;
  2566. bgStartY += item.labelOffsetY;
  2567. let textX = bgStartX + item.labelPadding * opts.pix;
  2568. let textY = item.y;
  2569. context.setFillStyle(hexToRgb(item.labelBgColor, item.labelBgOpacity));
  2570. context.setStrokeStyle(item.labelBgColor);
  2571. context.setLineWidth(1 * opts.pix);
  2572. context.beginPath();
  2573. context.rect(bgStartX, bgStartY, bgWidth, fontSize + 2 * item.labelPadding * opts.pix);
  2574. context.closePath();
  2575. context.stroke();
  2576. context.fill();
  2577. context.setFontSize(fontSize);
  2578. context.setTextAlign('left');
  2579. context.setFillStyle(item.labelFontColor);
  2580. context.fillText(String(labelText), textX, bgStartY + fontSize + item.labelPadding * opts.pix/2);
  2581. context.stroke();
  2582. context.setTextAlign('left');
  2583. }
  2584. }
  2585. }
  2586. function drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints) {
  2587. let toolTipOption = assign({}, {
  2588. gridType: 'solid',
  2589. dashLength: 4
  2590. }, opts.extra.tooltip);
  2591. let startX = opts.area[3];
  2592. let endX = opts.width - opts.area[1];
  2593. if (toolTipOption.gridType == 'dash') {
  2594. context.setLineDash([toolTipOption.dashLength, toolTipOption.dashLength]);
  2595. }
  2596. context.setStrokeStyle(toolTipOption.gridColor || '#cccccc');
  2597. context.setLineWidth(1 * opts.pix);
  2598. context.beginPath();
  2599. context.moveTo(startX, opts.tooltip.offset.y);
  2600. context.lineTo(endX, opts.tooltip.offset.y);
  2601. context.stroke();
  2602. context.setLineDash([]);
  2603. if (toolTipOption.yAxisLabel) {
  2604. let boxPadding = toolTipOption.boxPadding * opts.pix;
  2605. let labelText = calTooltipYAxisData(opts.tooltip.offset.y, opts.series, opts, config, eachSpacing);
  2606. let widthArr = opts.chartData.yAxisData.yAxisWidth;
  2607. let tStartLeft = opts.area[3];
  2608. let tStartRight = opts.width - opts.area[1];
  2609. for (let i = 0; i < labelText.length; i++) {
  2610. context.setFontSize(toolTipOption.fontSize * opts.pix);
  2611. let textWidth = measureText(labelText[i], toolTipOption.fontSize * opts.pix, context);
  2612. let bgStartX, bgEndX, bgWidth;
  2613. if (widthArr[i].position == 'left') {
  2614. bgStartX = tStartLeft - (textWidth + boxPadding * 2) - 2 * opts.pix;
  2615. bgEndX = Math.max(bgStartX, bgStartX + textWidth + boxPadding * 2);
  2616. } else {
  2617. bgStartX = tStartRight + 2 * opts.pix;
  2618. bgEndX = Math.max(bgStartX + widthArr[i].width, bgStartX + textWidth + boxPadding * 2);
  2619. }
  2620. bgWidth = bgEndX - bgStartX;
  2621. let textX = bgStartX + (bgWidth - textWidth) / 2;
  2622. let textY = opts.tooltip.offset.y;
  2623. context.beginPath();
  2624. context.setFillStyle(hexToRgb(toolTipOption.labelBgColor || config.toolTipBackground, toolTipOption.labelBgOpacity || config.toolTipOpacity));
  2625. context.setStrokeStyle(toolTipOption.labelBgColor || config.toolTipBackground);
  2626. context.setLineWidth(1 * opts.pix);
  2627. context.rect(bgStartX, textY - 0.5 * config.fontSize - boxPadding, bgWidth, config.fontSize + 2 * boxPadding);
  2628. context.closePath();
  2629. context.stroke();
  2630. context.fill();
  2631. context.beginPath();
  2632. context.setFontSize(config.fontSize);
  2633. context.setFillStyle(toolTipOption.labelFontColor || opts.fontColor);
  2634. context.fillText(labelText[i], textX, textY + 0.5 * config.fontSize);
  2635. context.closePath();
  2636. context.stroke();
  2637. if (widthArr[i].position == 'left') {
  2638. tStartLeft -= (widthArr[i].width + opts.yAxis.padding * opts.pix);
  2639. } else {
  2640. tStartRight += widthArr[i].width + opts.yAxis.padding * opts.pix;
  2641. }
  2642. }
  2643. }
  2644. }
  2645. function drawToolTipSplitArea(offsetX, opts, config, context, eachSpacing) {
  2646. let toolTipOption = assign({}, {
  2647. activeBgColor: '#000000',
  2648. activeBgOpacity: 0.08,
  2649. activeWidth: eachSpacing
  2650. }, opts.extra.column);
  2651. toolTipOption.activeWidth = toolTipOption.activeWidth > eachSpacing ? eachSpacing : toolTipOption.activeWidth;
  2652. let startY = opts.area[0];
  2653. let endY = opts.height - opts.area[2];
  2654. context.beginPath();
  2655. context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity));
  2656. context.rect(offsetX - toolTipOption.activeWidth / 2, startY, toolTipOption.activeWidth, endY - startY);
  2657. context.closePath();
  2658. context.fill();
  2659. context.setFillStyle("#FFFFFF");
  2660. }
  2661. function drawBarToolTipSplitArea(offsetX, opts, config, context, eachSpacing) {
  2662. let toolTipOption = assign({}, {
  2663. activeBgColor: '#000000',
  2664. activeBgOpacity: 0.08
  2665. }, opts.extra.bar);
  2666. let startX = opts.area[3];
  2667. let endX = opts.width - opts.area[1];
  2668. context.beginPath();
  2669. context.setFillStyle(hexToRgb(toolTipOption.activeBgColor, toolTipOption.activeBgOpacity));
  2670. context.rect( startX ,offsetX - eachSpacing / 2 , endX - startX,eachSpacing);
  2671. context.closePath();
  2672. context.fill();
  2673. context.setFillStyle("#FFFFFF");
  2674. }
  2675. function drawToolTip(textList, offset, opts, config, context, eachSpacing, xAxisPoints) {
  2676. let toolTipOption = assign({}, {
  2677. showBox: true,
  2678. showArrow: true,
  2679. showCategory: false,
  2680. bgColor: '#000000',
  2681. bgOpacity: 0.7,
  2682. borderColor: '#000000',
  2683. borderWidth: 0,
  2684. borderRadius: 0,
  2685. borderOpacity: 0.7,
  2686. boxPadding: 3,
  2687. fontColor: '#FFFFFF',
  2688. fontSize: 13,
  2689. lineHeight: 20,
  2690. legendShow: true,
  2691. legendShape: 'auto',
  2692. splitLine: true,
  2693. }, opts.extra.tooltip);
  2694. if(toolTipOption.showCategory==true && opts.categories){
  2695. textList.unshift({text:opts.categories[opts.tooltip.index],color:null})
  2696. }
  2697. let fontSize = toolTipOption.fontSize * opts.pix;
  2698. let lineHeight = toolTipOption.lineHeight * opts.pix;
  2699. let boxPadding = toolTipOption.boxPadding * opts.pix;
  2700. let legendWidth = fontSize;
  2701. let legendMarginRight = 5 * opts.pix;
  2702. if(toolTipOption.legendShow == false){
  2703. legendWidth = 0;
  2704. legendMarginRight = 0;
  2705. }
  2706. let arrowWidth = toolTipOption.showArrow ? 8 * opts.pix : 0;
  2707. let isOverRightBorder = false;
  2708. if (opts.type == 'line' || opts.type == 'mount' || opts.type == 'area' || opts.type == 'candle' || opts.type == 'mix') {
  2709. if (toolTipOption.splitLine == true) {
  2710. drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
  2711. }
  2712. }
  2713. offset = assign({
  2714. x: 0,
  2715. y: 0
  2716. }, offset);
  2717. offset.y -= 8 * opts.pix;
  2718. let textWidth = textList.map(function(item) {
  2719. return measureText(item.text, fontSize, context);
  2720. });
  2721. let toolTipWidth = legendWidth + legendMarginRight + 4 * boxPadding + Math.max.apply(null, textWidth);
  2722. let toolTipHeight = 2 * boxPadding + textList.length * lineHeight;
  2723. if (toolTipOption.showBox == false) {
  2724. return
  2725. }
  2726. // if beyond the right border
  2727. if (offset.x - Math.abs(opts._scrollDistance_ || 0) + arrowWidth + toolTipWidth > opts.width) {
  2728. isOverRightBorder = true;
  2729. }
  2730. if (toolTipHeight + offset.y > opts.height) {
  2731. offset.y = opts.height - toolTipHeight;
  2732. }
  2733. // draw background rect
  2734. context.beginPath();
  2735. context.setFillStyle(hexToRgb(toolTipOption.bgColor, toolTipOption.bgOpacity));
  2736. context.setLineWidth(toolTipOption.borderWidth * opts.pix);
  2737. context.setStrokeStyle(hexToRgb(toolTipOption.borderColor, toolTipOption.borderOpacity));
  2738. let radius = toolTipOption.borderRadius;
  2739. if (isOverRightBorder) {
  2740. // 增加左侧仍然超出的判断
  2741. if(toolTipWidth + arrowWidth > opts.width){
  2742. offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width)
  2743. }
  2744. if(toolTipWidth > offset.x){
  2745. offset.x = opts.width + Math.abs(opts._scrollDistance_ || 0) + arrowWidth + (toolTipWidth - opts.width)
  2746. }
  2747. if (toolTipOption.showArrow) {
  2748. context.moveTo(offset.x, offset.y + 10 * opts.pix);
  2749. context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix);
  2750. }
  2751. context.arc(offset.x - arrowWidth - radius, offset.y + toolTipHeight - radius, radius, 0, Math.PI / 2, false);
  2752. context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + toolTipHeight - radius, radius,
  2753. Math.PI / 2, Math.PI, false);
  2754. context.arc(offset.x - arrowWidth - Math.round(toolTipWidth) + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false);
  2755. context.arc(offset.x - arrowWidth - radius, offset.y + radius, radius, -Math.PI / 2, 0, false);
  2756. if (toolTipOption.showArrow) {
  2757. context.lineTo(offset.x - arrowWidth, offset.y + 10 * opts.pix - 5 * opts.pix);
  2758. context.lineTo(offset.x, offset.y + 10 * opts.pix);
  2759. }
  2760. } else {
  2761. if (toolTipOption.showArrow) {
  2762. context.moveTo(offset.x, offset.y + 10 * opts.pix);
  2763. context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pix - 5 * opts.pix);
  2764. }
  2765. context.arc(offset.x + arrowWidth + radius, offset.y + radius, radius, -Math.PI, -Math.PI / 2, false);
  2766. context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + radius, radius, -Math.PI / 2, 0,
  2767. false);
  2768. context.arc(offset.x + arrowWidth + Math.round(toolTipWidth) - radius, offset.y + toolTipHeight - radius, radius, 0,
  2769. Math.PI / 2, false);
  2770. context.arc(offset.x + arrowWidth + radius, offset.y + toolTipHeight - radius, radius, Math.PI / 2, Math.PI, false);
  2771. if (toolTipOption.showArrow) {
  2772. context.lineTo(offset.x + arrowWidth, offset.y + 10 * opts.pix + 5 * opts.pix);
  2773. context.lineTo(offset.x, offset.y + 10 * opts.pix);
  2774. }
  2775. }
  2776. context.closePath();
  2777. context.fill();
  2778. if (toolTipOption.borderWidth > 0) {
  2779. context.stroke();
  2780. }
  2781. // draw legend
  2782. if(toolTipOption.legendShow){
  2783. textList.forEach(function(item, index) {
  2784. if (item.color !== null) {
  2785. context.beginPath();
  2786. context.setFillStyle(item.color);
  2787. let startX = offset.x + arrowWidth + 2 * boxPadding;
  2788. let startY = offset.y + (lineHeight - fontSize) / 2 + lineHeight * index + boxPadding + 1;
  2789. if (isOverRightBorder) {
  2790. startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding;
  2791. }
  2792. switch (item.legendShape) {
  2793. case 'line':
  2794. context.moveTo(startX, startY + 0.5 * legendWidth - 2 * opts.pix);
  2795. context.fillRect(startX, startY + 0.5 * legendWidth - 2 * opts.pix, legendWidth, 4 * opts.pix);
  2796. break;
  2797. case 'triangle':
  2798. context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
  2799. context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix);
  2800. context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix);
  2801. context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
  2802. break;
  2803. case 'diamond':
  2804. context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
  2805. context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * legendWidth);
  2806. context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth + 5 * opts.pix);
  2807. context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * legendWidth);
  2808. context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
  2809. break;
  2810. case 'circle':
  2811. context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth);
  2812. context.arc(startX + 7.5 * opts.pix, startY + 0.5 * legendWidth, 5 * opts.pix, 0, 2 * Math.PI);
  2813. break;
  2814. case 'rect':
  2815. context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix);
  2816. context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
  2817. break;
  2818. case 'square':
  2819. context.moveTo(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix);
  2820. context.fillRect(startX + 2 * opts.pix, startY + 0.5 * legendWidth - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix);
  2821. break;
  2822. default:
  2823. context.moveTo(startX, startY + 0.5 * legendWidth - 5 * opts.pix);
  2824. context.fillRect(startX, startY + 0.5 * legendWidth - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
  2825. }
  2826. context.closePath();
  2827. context.fill();
  2828. }
  2829. });
  2830. }
  2831. // draw text list
  2832. textList.forEach(function(item, index) {
  2833. let startX = offset.x + arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight;
  2834. if (isOverRightBorder) {
  2835. startX = offset.x - toolTipWidth - arrowWidth + 2 * boxPadding + legendWidth + legendMarginRight;
  2836. }
  2837. let startY = offset.y + lineHeight * index + (lineHeight - fontSize)/2 - 1 + boxPadding + fontSize;
  2838. context.beginPath();
  2839. context.setFontSize(fontSize);
  2840. context.setTextBaseline('normal');
  2841. context.setFillStyle(toolTipOption.fontColor);
  2842. context.fillText(item.text, startX, startY);
  2843. context.closePath();
  2844. context.stroke();
  2845. });
  2846. }
  2847. function drawColumnDataPoints(series, opts, config, context) {
  2848. let xAxisData = opts.chartData.xAxisData,
  2849. xAxisPoints = xAxisData.xAxisPoints,
  2850. eachSpacing = xAxisData.eachSpacing;
  2851. let columnOption = assign({}, {
  2852. type: 'group',
  2853. width: eachSpacing / 2,
  2854. meterBorder: 4,
  2855. meterFillColor: '#FFFFFF',
  2856. barBorderCircle: false,
  2857. barBorderRadius: [],
  2858. seriesGap: 2,
  2859. linearType: 'none',
  2860. linearOpacity: 1,
  2861. customColor: [],
  2862. colorStop: 0,
  2863. labelPosition: 'outside'
  2864. }, opts.extra.column);
  2865. let calPoints = [];
  2866. context.save();
  2867. let leftNum = -2;
  2868. let rightNum = xAxisPoints.length + 2;
  2869. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  2870. context.translate(opts._scrollDistance_, 0);
  2871. leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2;
  2872. rightNum = leftNum + opts.xAxis.itemCount + 4;
  2873. }
  2874. if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
  2875. drawToolTipSplitArea(opts.tooltip.offset.x, opts, config, context, eachSpacing);
  2876. }
  2877. columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config);
  2878. series.forEach(function(eachSeries, seriesIndex) {
  2879. let ranges, minRange, maxRange;
  2880. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  2881. minRange = ranges.pop();
  2882. maxRange = ranges.shift();
  2883. // 计算0轴坐标
  2884. let spacingValid = opts.height - opts.area[0] - opts.area[2];
  2885. let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange);
  2886. let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2];
  2887. eachSeries.zeroPoints = zeroPoints;
  2888. let data = eachSeries.data;
  2889. switch (columnOption.type) {
  2890. case 'group':
  2891. let points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, chartProcess);
  2892. let tooltipPoints = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, chartProcess);
  2893. calPoints.push(tooltipPoints);
  2894. points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
  2895. for (let i = 0; i < points.length; i++) {
  2896. let item = points[i];
  2897. //fix issues/I27B1N yyoinge & Joeshu
  2898. if (item !== null && i > leftNum && i < rightNum) {
  2899. let startX = item.x - item.width / 2;
  2900. let height = opts.height - item.y - opts.area[2];
  2901. context.beginPath();
  2902. let fillColor = item.color || eachSeries.color
  2903. let strokeColor = item.color || eachSeries.color
  2904. if (columnOption.linearType !== 'none') {
  2905. let grd = context.createLinearGradient(startX, item.y, startX, zeroPoints);
  2906. //透明渐变
  2907. if (columnOption.linearType == 'opacity') {
  2908. grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity));
  2909. grd.addColorStop(1, hexToRgb(fillColor, 1));
  2910. } else {
  2911. grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
  2912. grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex],columnOption.linearOpacity));
  2913. grd.addColorStop(1, hexToRgb(fillColor, 1));
  2914. }
  2915. fillColor = grd
  2916. }
  2917. // 圆角边框
  2918. if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
  2919. const left = startX;
  2920. const top = item.y > zeroPoints ? zeroPoints : item.y;
  2921. const width = item.width;
  2922. const height = Math.abs(zeroPoints - item.y);
  2923. if (columnOption.barBorderCircle) {
  2924. columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
  2925. }
  2926. if(item.y > zeroPoints){
  2927. columnOption.barBorderRadius = [0, 0,width / 2, width / 2];
  2928. }
  2929. let [r0, r1, r2, r3] = columnOption.barBorderRadius;
  2930. let minRadius = Math.min(width/2,height/2);
  2931. r0 = r0 > minRadius ? minRadius : r0;
  2932. r1 = r1 > minRadius ? minRadius : r1;
  2933. r2 = r2 > minRadius ? minRadius : r2;
  2934. r3 = r3 > minRadius ? minRadius : r3;
  2935. r0 = r0 < 0 ? 0 : r0;
  2936. r1 = r1 < 0 ? 0 : r1;
  2937. r2 = r2 < 0 ? 0 : r2;
  2938. r3 = r3 < 0 ? 0 : r3;
  2939. context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2);
  2940. context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0);
  2941. context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2);
  2942. context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
  2943. } else {
  2944. context.moveTo(startX, item.y);
  2945. context.lineTo(startX + item.width, item.y);
  2946. context.lineTo(startX + item.width, zeroPoints);
  2947. context.lineTo(startX, zeroPoints);
  2948. context.lineTo(startX, item.y);
  2949. context.setLineWidth(1)
  2950. context.setStrokeStyle(strokeColor);
  2951. }
  2952. context.setFillStyle(fillColor);
  2953. context.closePath();
  2954. //context.stroke();
  2955. context.fill();
  2956. }
  2957. };
  2958. break;
  2959. case 'stack':
  2960. // 绘制堆叠数据图
  2961. let points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, chartProcess);
  2962. calPoints.push(points);
  2963. points = fixColumeStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series);
  2964. for (let i = 0; i < points.length; i++) {
  2965. let item = points[i];
  2966. if (item !== null && i > leftNum && i < rightNum) {
  2967. context.beginPath();
  2968. let fillColor = item.color || eachSeries.color;
  2969. let startX = item.x - item.width / 2 + 1;
  2970. let height = opts.height - item.y - opts.area[2];
  2971. let height0 = opts.height - item.y0 - opts.area[2];
  2972. if (seriesIndex > 0) {
  2973. height -= height0;
  2974. }
  2975. context.setFillStyle(fillColor);
  2976. context.moveTo(startX, item.y);
  2977. context.fillRect(startX, item.y, item.width, height);
  2978. context.closePath();
  2979. context.fill();
  2980. }
  2981. };
  2982. break;
  2983. case 'meter':
  2984. // 绘制温度计数据图
  2985. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  2986. calPoints.push(points);
  2987. points = fixColumeMeterData(points, eachSpacing, series.length, seriesIndex, config, opts, columnOption.meterBorder);
  2988. for (let i = 0; i < points.length; i++) {
  2989. let item = points[i];
  2990. if (item !== null && i > leftNum && i < rightNum) {
  2991. //画背景颜色
  2992. context.beginPath();
  2993. if (seriesIndex == 0 && columnOption.meterBorder > 0) {
  2994. context.setStrokeStyle(eachSeries.color);
  2995. context.setLineWidth(columnOption.meterBorder * opts.pix);
  2996. }
  2997. if(seriesIndex == 0){
  2998. context.setFillStyle(columnOption.meterFillColor);
  2999. }else{
  3000. context.setFillStyle(item.color || eachSeries.color);
  3001. }
  3002. let startX = item.x - item.width / 2;
  3003. let height = opts.height - item.y - opts.area[2];
  3004. if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
  3005. const left = startX;
  3006. const top = item.y;
  3007. const width = item.width;
  3008. const height = zeroPoints - item.y;
  3009. if (columnOption.barBorderCircle) {
  3010. columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
  3011. }
  3012. let [r0, r1, r2, r3] = columnOption.barBorderRadius;
  3013. let minRadius = Math.min(width/2,height/2);
  3014. r0 = r0 > minRadius ? minRadius : r0;
  3015. r1 = r1 > minRadius ? minRadius : r1;
  3016. r2 = r2 > minRadius ? minRadius : r2;
  3017. r3 = r3 > minRadius ? minRadius : r3;
  3018. r0 = r0 < 0 ? 0 : r0;
  3019. r1 = r1 < 0 ? 0 : r1;
  3020. r2 = r2 < 0 ? 0 : r2;
  3021. r3 = r3 < 0 ? 0 : r3;
  3022. context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2);
  3023. context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0);
  3024. context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2);
  3025. context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
  3026. context.fill();
  3027. }else{
  3028. context.moveTo(startX, item.y);
  3029. context.lineTo(startX + item.width, item.y);
  3030. context.lineTo(startX + item.width, zeroPoints);
  3031. context.lineTo(startX, zeroPoints);
  3032. context.lineTo(startX, item.y);
  3033. context.fill();
  3034. }
  3035. if (seriesIndex == 0 && columnOption.meterBorder > 0) {
  3036. context.closePath();
  3037. context.stroke();
  3038. }
  3039. }
  3040. }
  3041. break;
  3042. }
  3043. });
  3044. if (opts.dataLabel !== false && process === 1) {
  3045. series.forEach(function(eachSeries, seriesIndex) {
  3046. let ranges, minRange, maxRange;
  3047. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3048. minRange = ranges.pop();
  3049. maxRange = ranges.shift();
  3050. let data = eachSeries.data;
  3051. switch (columnOption.type) {
  3052. case 'group':
  3053. let points = getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3054. points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
  3055. drawColumePointText(points, eachSeries, config, context, opts);
  3056. break;
  3057. case 'stack':
  3058. let points = getStackDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, seriesIndex, series, chartProcess);
  3059. drawColumePointText(points, eachSeries, config, context, opts);
  3060. break;
  3061. case 'meter':
  3062. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3063. drawColumePointText(points, eachSeries, config, context, opts);
  3064. break;
  3065. }
  3066. });
  3067. }
  3068. context.restore();
  3069. return {
  3070. xAxisPoints: xAxisPoints,
  3071. calPoints: calPoints,
  3072. eachSpacing: eachSpacing
  3073. };
  3074. }
  3075. function drawMountDataPoints(series, opts, config, context) {
  3076. let xAxisData = opts.chartData.xAxisData,
  3077. xAxisPoints = xAxisData.xAxisPoints,
  3078. eachSpacing = xAxisData.eachSpacing;
  3079. let mountOption = assign({}, {
  3080. type: 'mount',
  3081. widthRatio: 1,
  3082. borderWidth: 1,
  3083. barBorderCircle: false,
  3084. barBorderRadius: [],
  3085. linearType: 'none',
  3086. linearOpacity: 1,
  3087. customColor: [],
  3088. colorStop: 0,
  3089. }, opts.extra.mount);
  3090. mountOption.widthRatio = mountOption.widthRatio <= 0 ? 0 : mountOption.widthRatio;
  3091. mountOption.widthRatio = mountOption.widthRatio >= 2 ? 2 : mountOption.widthRatio;
  3092. let calPoints = [];
  3093. context.save();
  3094. let leftNum = -2;
  3095. let rightNum = xAxisPoints.length + 2;
  3096. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  3097. context.translate(opts._scrollDistance_, 0);
  3098. leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2;
  3099. rightNum = leftNum + opts.xAxis.itemCount + 4;
  3100. }
  3101. mountOption.customColor = fillCustomColor(mountOption.linearType, mountOption.customColor, series, config);
  3102. let ranges, minRange, maxRange;
  3103. ranges = [].concat(opts.chartData.yAxisData.ranges[0]);
  3104. minRange = ranges.pop();
  3105. maxRange = ranges.shift();
  3106. // 计算0轴坐标
  3107. let spacingValid = opts.height - opts.area[0] - opts.area[2];
  3108. let zeroHeight = spacingValid * (0 - minRange) / (maxRange - minRange);
  3109. let zeroPoints = opts.height - Math.round(zeroHeight) - opts.area[2];
  3110. let points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, chartProcess);
  3111. switch (mountOption.type) {
  3112. case 'bar':
  3113. for (let i = 0; i < points.length; i++) {
  3114. let item = points[i];
  3115. if (item !== null && i > leftNum && i < rightNum) {
  3116. let startX = item.x - eachSpacing*mountOption.widthRatio/2;
  3117. let height = opts.height - item.y - opts.area[2];
  3118. context.beginPath();
  3119. let fillColor = item.color || series[i].color
  3120. let strokeColor = item.color || series[i].color
  3121. if (mountOption.linearType !== 'none') {
  3122. let grd = context.createLinearGradient(startX, item.y, startX, zeroPoints);
  3123. //透明渐变
  3124. if (mountOption.linearType == 'opacity') {
  3125. grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
  3126. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3127. } else {
  3128. grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
  3129. grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
  3130. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3131. }
  3132. fillColor = grd
  3133. }
  3134. // 圆角边框
  3135. if ((mountOption.barBorderRadius && mountOption.barBorderRadius.length === 4) || mountOption.barBorderCircle === true) {
  3136. const left = startX;
  3137. const top = item.y > zeroPoints ? zeroPoints : item.y;
  3138. const width = item.width;
  3139. const height = Math.abs(zeroPoints - item.y);
  3140. if (mountOption.barBorderCircle) {
  3141. mountOption.barBorderRadius = [width / 2, width / 2, 0, 0];
  3142. }
  3143. if(item.y > zeroPoints){
  3144. mountOption.barBorderRadius = [0, 0,width / 2, width / 2];
  3145. }
  3146. let [r0, r1, r2, r3] = mountOption.barBorderRadius;
  3147. let minRadius = Math.min(width/2,height/2);
  3148. r0 = r0 > minRadius ? minRadius : r0;
  3149. r1 = r1 > minRadius ? minRadius : r1;
  3150. r2 = r2 > minRadius ? minRadius : r2;
  3151. r3 = r3 > minRadius ? minRadius : r3;
  3152. r0 = r0 < 0 ? 0 : r0;
  3153. r1 = r1 < 0 ? 0 : r1;
  3154. r2 = r2 < 0 ? 0 : r2;
  3155. r3 = r3 < 0 ? 0 : r3;
  3156. context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2);
  3157. context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0);
  3158. context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2);
  3159. context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
  3160. } else {
  3161. context.moveTo(startX, item.y);
  3162. context.lineTo(startX + item.width, item.y);
  3163. context.lineTo(startX + item.width, zeroPoints);
  3164. context.lineTo(startX, zeroPoints);
  3165. context.lineTo(startX, item.y);
  3166. }
  3167. context.setStrokeStyle(strokeColor);
  3168. context.setFillStyle(fillColor);
  3169. if(mountOption.borderWidth > 0){
  3170. context.setLineWidth(mountOption.borderWidth * opts.pix);
  3171. context.closePath();
  3172. context.stroke();
  3173. }
  3174. context.fill();
  3175. }
  3176. };
  3177. break;
  3178. case 'triangle':
  3179. for (let i = 0; i < points.length; i++) {
  3180. let item = points[i];
  3181. if (item !== null && i > leftNum && i < rightNum) {
  3182. let startX = item.x - eachSpacing*mountOption.widthRatio/2;
  3183. let height = opts.height - item.y - opts.area[2];
  3184. context.beginPath();
  3185. let fillColor = item.color || series[i].color
  3186. let strokeColor = item.color || series[i].color
  3187. if (mountOption.linearType !== 'none') {
  3188. let grd = context.createLinearGradient(startX, item.y, startX, zeroPoints);
  3189. //透明渐变
  3190. if (mountOption.linearType == 'opacity') {
  3191. grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
  3192. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3193. } else {
  3194. grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
  3195. grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
  3196. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3197. }
  3198. fillColor = grd
  3199. }
  3200. context.moveTo(startX, zeroPoints);
  3201. context.lineTo(item.x, item.y);
  3202. context.lineTo(startX + item.width, zeroPoints);
  3203. context.setStrokeStyle(strokeColor);
  3204. context.setFillStyle(fillColor);
  3205. if(mountOption.borderWidth > 0){
  3206. context.setLineWidth(mountOption.borderWidth * opts.pix);
  3207. context.stroke();
  3208. }
  3209. context.fill();
  3210. }
  3211. };
  3212. break;
  3213. case 'mount':
  3214. for (let i = 0; i < points.length; i++) {
  3215. let item = points[i];
  3216. if (item !== null && i > leftNum && i < rightNum) {
  3217. let startX = item.x - eachSpacing*mountOption.widthRatio/2;
  3218. let height = opts.height - item.y - opts.area[2];
  3219. context.beginPath();
  3220. let fillColor = item.color || series[i].color
  3221. let strokeColor = item.color || series[i].color
  3222. if (mountOption.linearType !== 'none') {
  3223. let grd = context.createLinearGradient(startX, item.y, startX, zeroPoints);
  3224. //透明渐变
  3225. if (mountOption.linearType == 'opacity') {
  3226. grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
  3227. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3228. } else {
  3229. grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
  3230. grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
  3231. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3232. }
  3233. fillColor = grd
  3234. }
  3235. context.moveTo(startX, zeroPoints);
  3236. context.bezierCurveTo(item.x - item.width/4, zeroPoints, item.x - item.width/4, item.y, item.x, item.y);
  3237. context.bezierCurveTo(item.x + item.width/4, item.y, item.x + item.width/4, zeroPoints, startX + item.width, zeroPoints);
  3238. context.setStrokeStyle(strokeColor);
  3239. context.setFillStyle(fillColor);
  3240. if(mountOption.borderWidth > 0){
  3241. context.setLineWidth(mountOption.borderWidth * opts.pix);
  3242. context.stroke();
  3243. }
  3244. context.fill();
  3245. }
  3246. };
  3247. break;
  3248. case 'sharp':
  3249. for (let i = 0; i < points.length; i++) {
  3250. let item = points[i];
  3251. if (item !== null && i > leftNum && i < rightNum) {
  3252. let startX = item.x - eachSpacing*mountOption.widthRatio/2;
  3253. let height = opts.height - item.y - opts.area[2];
  3254. context.beginPath();
  3255. let fillColor = item.color || series[i].color
  3256. let strokeColor = item.color || series[i].color
  3257. if (mountOption.linearType !== 'none') {
  3258. let grd = context.createLinearGradient(startX, item.y, startX, zeroPoints);
  3259. //透明渐变
  3260. if (mountOption.linearType == 'opacity') {
  3261. grd.addColorStop(0, hexToRgb(fillColor, mountOption.linearOpacity));
  3262. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3263. } else {
  3264. grd.addColorStop(0, hexToRgb(mountOption.customColor[series[i].linearIndex], mountOption.linearOpacity));
  3265. grd.addColorStop(mountOption.colorStop, hexToRgb(mountOption.customColor[series[i].linearIndex],mountOption.linearOpacity));
  3266. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3267. }
  3268. fillColor = grd
  3269. }
  3270. context.moveTo(startX, zeroPoints);
  3271. context.quadraticCurveTo(item.x - 0, zeroPoints - height/4, item.x, item.y);
  3272. context.quadraticCurveTo(item.x + 0, zeroPoints - height/4, startX + item.width, zeroPoints)
  3273. context.setStrokeStyle(strokeColor);
  3274. context.setFillStyle(fillColor);
  3275. if(mountOption.borderWidth > 0){
  3276. context.setLineWidth(mountOption.borderWidth * opts.pix);
  3277. context.stroke();
  3278. }
  3279. context.fill();
  3280. }
  3281. };
  3282. break;
  3283. }
  3284. if (opts.dataLabel !== false && process === 1) {
  3285. let ranges, minRange, maxRange;
  3286. ranges = [].concat(opts.chartData.yAxisData.ranges[0]);
  3287. minRange = ranges.pop();
  3288. maxRange = ranges.shift();
  3289. let points = getMountDataPoints(series, minRange, maxRange, xAxisPoints, eachSpacing, opts, mountOption, zeroPoints, chartProcess);
  3290. drawMountPointText(points, series, config, context, opts, zeroPoints);
  3291. }
  3292. context.restore();
  3293. return {
  3294. xAxisPoints: xAxisPoints,
  3295. calPoints: points,
  3296. eachSpacing: eachSpacing
  3297. };
  3298. }
  3299. function drawBarDataPoints(series, opts, config, context) {
  3300. let yAxisPoints = [];
  3301. let eachSpacing = (opts.height - opts.area[0] - opts.area[2])/opts.categories.length;
  3302. for (let i = 0; i < opts.categories.length; i++) {
  3303. yAxisPoints.push(opts.area[0] + eachSpacing / 2 + eachSpacing * i);
  3304. }
  3305. let columnOption = assign({}, {
  3306. type: 'group',
  3307. width: eachSpacing / 2,
  3308. meterBorder: 4,
  3309. meterFillColor: '#FFFFFF',
  3310. barBorderCircle: false,
  3311. barBorderRadius: [],
  3312. seriesGap: 2,
  3313. linearType: 'none',
  3314. linearOpacity: 1,
  3315. customColor: [],
  3316. colorStop: 0,
  3317. }, opts.extra.bar);
  3318. let calPoints = [];
  3319. context.save();
  3320. let leftNum = -2;
  3321. let rightNum = yAxisPoints.length + 2;
  3322. if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
  3323. drawBarToolTipSplitArea(opts.tooltip.offset.y, opts, config, context, eachSpacing);
  3324. }
  3325. columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config);
  3326. series.forEach(function(eachSeries, seriesIndex) {
  3327. let ranges, minRange, maxRange;
  3328. ranges = [].concat(opts.chartData.xAxisData.ranges);
  3329. maxRange = ranges.pop();
  3330. minRange = ranges.shift();
  3331. let data = eachSeries.data;
  3332. switch (columnOption.type) {
  3333. case 'group':
  3334. let points = getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, chartProcess);
  3335. let tooltipPoints = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, chartProcess);
  3336. calPoints.push(tooltipPoints);
  3337. points = fixBarData(points, eachSpacing, series.length, seriesIndex, config, opts);
  3338. for (let i = 0; i < points.length; i++) {
  3339. let item = points[i];
  3340. //fix issues/I27B1N yyoinge & Joeshu
  3341. if (item !== null && i > leftNum && i < rightNum) {
  3342. //let startX = item.x - item.width / 2;
  3343. let startX = opts.area[3];
  3344. let startY = item.y - item.width / 2;
  3345. let height = item.height;
  3346. context.beginPath();
  3347. let fillColor = item.color || eachSeries.color
  3348. let strokeColor = item.color || eachSeries.color
  3349. if (columnOption.linearType !== 'none') {
  3350. let grd = context.createLinearGradient(startX, item.y, item.x, item.y);
  3351. //透明渐变
  3352. if (columnOption.linearType == 'opacity') {
  3353. grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity));
  3354. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3355. } else {
  3356. grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
  3357. grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex],columnOption.linearOpacity));
  3358. grd.addColorStop(1, hexToRgb(fillColor, 1));
  3359. }
  3360. fillColor = grd
  3361. }
  3362. // 圆角边框
  3363. if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle === true) {
  3364. const left = startX;
  3365. const width = item.width;
  3366. const top = item.y - item.width / 2;
  3367. const height = item.height;
  3368. if (columnOption.barBorderCircle) {
  3369. columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
  3370. }
  3371. let [r0, r1, r2, r3] = columnOption.barBorderRadius;
  3372. let minRadius = Math.min(width/2,height/2);
  3373. r0 = r0 > minRadius ? minRadius : r0;
  3374. r1 = r1 > minRadius ? minRadius : r1;
  3375. r2 = r2 > minRadius ? minRadius : r2;
  3376. r3 = r3 > minRadius ? minRadius : r3;
  3377. r0 = r0 < 0 ? 0 : r0;
  3378. r1 = r1 < 0 ? 0 : r1;
  3379. r2 = r2 < 0 ? 0 : r2;
  3380. r3 = r3 < 0 ? 0 : r3;
  3381. context.arc(left + r3, top + r3, r3, -Math.PI, -Math.PI / 2);
  3382. context.arc(item.x - r0, top + r0, r0, -Math.PI / 2, 0);
  3383. context.arc(item.x - r1, top + width - r1, r1, 0, Math.PI / 2);
  3384. context.arc(left + r2, top + width - r2, r2, Math.PI / 2, Math.PI);
  3385. } else {
  3386. context.moveTo(startX, startY);
  3387. context.lineTo(item.x, startY);
  3388. context.lineTo(item.x, startY + item.width);
  3389. context.lineTo(startX, startY + item.width);
  3390. context.lineTo(startX, startY);
  3391. context.setLineWidth(1)
  3392. context.setStrokeStyle(strokeColor);
  3393. }
  3394. context.setFillStyle(fillColor);
  3395. context.closePath();
  3396. //context.stroke();
  3397. context.fill();
  3398. }
  3399. };
  3400. break;
  3401. case 'stack':
  3402. // 绘制堆叠数据图
  3403. let points = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, chartProcess);
  3404. calPoints.push(points);
  3405. points = fixBarStackData(points, eachSpacing, series.length, seriesIndex, config, opts, series);
  3406. for (let i = 0; i < points.length; i++) {
  3407. let item = points[i];
  3408. if (item !== null && i > leftNum && i < rightNum) {
  3409. context.beginPath();
  3410. let fillColor = item.color || eachSeries.color;
  3411. let startX = item.x0;
  3412. context.setFillStyle(fillColor);
  3413. context.moveTo(startX, item.y - item.width/2);
  3414. context.fillRect(startX, item.y - item.width/2, item.height , item.width);
  3415. context.closePath();
  3416. context.fill();
  3417. }
  3418. };
  3419. break;
  3420. }
  3421. });
  3422. if (opts.dataLabel !== false && process === 1) {
  3423. series.forEach(function(eachSeries, seriesIndex) {
  3424. let ranges, minRange, maxRange;
  3425. ranges = [].concat(opts.chartData.xAxisData.ranges);
  3426. maxRange = ranges.pop();
  3427. minRange = ranges.shift();
  3428. let data = eachSeries.data;
  3429. switch (columnOption.type) {
  3430. case 'group':
  3431. let points = getBarDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, chartProcess);
  3432. points = fixBarData(points, eachSpacing, series.length, seriesIndex, config, opts);
  3433. drawBarPointText(points, eachSeries, config, context, opts);
  3434. break;
  3435. case 'stack':
  3436. let points = getBarStackDataPoints(data, minRange, maxRange, yAxisPoints, eachSpacing, opts, config, seriesIndex, series, chartProcess);
  3437. drawBarPointText(points, eachSeries, config, context, opts);
  3438. break;
  3439. }
  3440. });
  3441. }
  3442. return {
  3443. yAxisPoints: yAxisPoints,
  3444. calPoints: calPoints,
  3445. eachSpacing: eachSpacing
  3446. };
  3447. }
  3448. function drawCandleDataPoints(series, seriesMA, opts, config, context) {
  3449. let candleOption = assign({}, {
  3450. color: {},
  3451. average: {}
  3452. }, opts.extra.candle);
  3453. candleOption.color = assign({}, {
  3454. upLine: '#f04864',
  3455. upFill: '#f04864',
  3456. downLine: '#2fc25b',
  3457. downFill: '#2fc25b'
  3458. }, candleOption.color);
  3459. candleOption.average = assign({}, {
  3460. show: false,
  3461. name: [],
  3462. day: [],
  3463. color: config.color
  3464. }, candleOption.average);
  3465. opts.extra.candle = candleOption;
  3466. let xAxisData = opts.chartData.xAxisData,
  3467. xAxisPoints = xAxisData.xAxisPoints,
  3468. eachSpacing = xAxisData.eachSpacing;
  3469. let calPoints = [];
  3470. context.save();
  3471. let leftNum = -2;
  3472. let rightNum = xAxisPoints.length + 2;
  3473. let leftSpace = 0;
  3474. let rightSpace = opts.width + eachSpacing;
  3475. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  3476. context.translate(opts._scrollDistance_, 0);
  3477. leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2;
  3478. rightNum = leftNum + opts.xAxis.itemCount + 4;
  3479. leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
  3480. rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
  3481. }
  3482. //画均线
  3483. if (candleOption.average.show || seriesMA) { //Merge pull request !12 from 邱贵翔
  3484. seriesMA.forEach(function(eachSeries, seriesIndex) {
  3485. let ranges, minRange, maxRange;
  3486. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3487. minRange = ranges.pop();
  3488. maxRange = ranges.shift();
  3489. let data = eachSeries.data;
  3490. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3491. let splitPointList = splitPoints(points,eachSeries);
  3492. for (let i = 0; i < splitPointList.length; i++) {
  3493. let points = splitPointList[i];
  3494. context.beginPath();
  3495. context.setStrokeStyle(eachSeries.color);
  3496. context.setLineWidth(1);
  3497. if (points.length === 1) {
  3498. context.moveTo(points[0].x, points[0].y);
  3499. context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
  3500. } else {
  3501. context.moveTo(points[0].x, points[0].y);
  3502. let startPoint = 0;
  3503. for (let j = 0; j < points.length; j++) {
  3504. let item = points[j];
  3505. if (startPoint == 0 && item.x > leftSpace) {
  3506. context.moveTo(item.x, item.y);
  3507. startPoint = 1;
  3508. }
  3509. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3510. let ctrlPoint = createCurveControlPoints(points, j - 1);
  3511. context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x,
  3512. item.y);
  3513. }
  3514. }
  3515. context.moveTo(points[0].x, points[0].y);
  3516. }
  3517. context.closePath();
  3518. context.stroke();
  3519. }
  3520. });
  3521. }
  3522. //画K线
  3523. series.forEach(function(eachSeries, seriesIndex) {
  3524. let ranges, minRange, maxRange;
  3525. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3526. minRange = ranges.pop();
  3527. maxRange = ranges.shift();
  3528. let data = eachSeries.data;
  3529. let points = getCandleDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3530. calPoints.push(points);
  3531. let splitPointList = splitPoints(points,eachSeries);
  3532. for (let i = 0; i < splitPointList[0].length; i++) {
  3533. if (i > leftNum && i < rightNum) {
  3534. let item = splitPointList[0][i];
  3535. context.beginPath();
  3536. //如果上涨
  3537. if (data[i][1] - data[i][0] > 0) {
  3538. context.setStrokeStyle(candleOption.color.upLine);
  3539. context.setFillStyle(candleOption.color.upFill);
  3540. context.setLineWidth(1 * opts.pix);
  3541. context.moveTo(item[3].x, item[3].y); //顶点
  3542. context.lineTo(item[1].x, item[1].y); //收盘中间点
  3543. context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
  3544. context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
  3545. context.lineTo(item[0].x, item[0].y); //开盘中间点
  3546. context.lineTo(item[2].x, item[2].y); //底点
  3547. context.lineTo(item[0].x, item[0].y); //开盘中间点
  3548. context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
  3549. context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
  3550. context.lineTo(item[1].x, item[1].y); //收盘中间点
  3551. context.moveTo(item[3].x, item[3].y); //顶点
  3552. } else {
  3553. context.setStrokeStyle(candleOption.color.downLine);
  3554. context.setFillStyle(candleOption.color.downFill);
  3555. context.setLineWidth(1 * opts.pix);
  3556. context.moveTo(item[3].x, item[3].y); //顶点
  3557. context.lineTo(item[0].x, item[0].y); //开盘中间点
  3558. context.lineTo(item[0].x - eachSpacing / 4, item[0].y); //开盘左侧点
  3559. context.lineTo(item[1].x - eachSpacing / 4, item[1].y); //收盘左侧点
  3560. context.lineTo(item[1].x, item[1].y); //收盘中间点
  3561. context.lineTo(item[2].x, item[2].y); //底点
  3562. context.lineTo(item[1].x, item[1].y); //收盘中间点
  3563. context.lineTo(item[1].x + eachSpacing / 4, item[1].y); //收盘右侧点
  3564. context.lineTo(item[0].x + eachSpacing / 4, item[0].y); //开盘右侧点
  3565. context.lineTo(item[0].x, item[0].y); //开盘中间点
  3566. context.moveTo(item[3].x, item[3].y); //顶点
  3567. }
  3568. context.closePath();
  3569. context.fill();
  3570. context.stroke();
  3571. }
  3572. }
  3573. });
  3574. context.restore();
  3575. return {
  3576. xAxisPoints: xAxisPoints,
  3577. calPoints: calPoints,
  3578. eachSpacing: eachSpacing
  3579. };
  3580. }
  3581. function drawAreaDataPoints(series, opts, config, context) {
  3582. let areaOption = assign({}, {
  3583. type: 'straight',
  3584. opacity: 0.2,
  3585. addLine: false,
  3586. width: 2,
  3587. gradient: false,
  3588. activeType: 'none'
  3589. }, opts.extra.area);
  3590. let xAxisData = opts.chartData.xAxisData,
  3591. xAxisPoints = xAxisData.xAxisPoints,
  3592. eachSpacing = xAxisData.eachSpacing;
  3593. let endY = opts.height - opts.area[2];
  3594. let calPoints = [];
  3595. context.save();
  3596. let leftSpace = 0;
  3597. let rightSpace = opts.width + eachSpacing;
  3598. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  3599. context.translate(opts._scrollDistance_, 0);
  3600. leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
  3601. rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
  3602. }
  3603. series.forEach(function(eachSeries, seriesIndex) {
  3604. let ranges, minRange, maxRange;
  3605. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3606. minRange = ranges.pop();
  3607. maxRange = ranges.shift();
  3608. let data = eachSeries.data;
  3609. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3610. calPoints.push(points);
  3611. let splitPointList = splitPoints(points,eachSeries);
  3612. for (let i = 0; i < splitPointList.length; i++) {
  3613. let points = splitPointList[i];
  3614. // 绘制区域数
  3615. context.beginPath();
  3616. context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity));
  3617. if (areaOption.gradient) {
  3618. let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height - opts.area[2]);
  3619. gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity));
  3620. gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1));
  3621. context.setFillStyle(gradient);
  3622. } else {
  3623. context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity));
  3624. }
  3625. context.setLineWidth(areaOption.width * opts.pix);
  3626. if (points.length > 1) {
  3627. let firstPoint = points[0];
  3628. let lastPoint = points[points.length - 1];
  3629. context.moveTo(firstPoint.x, firstPoint.y);
  3630. let startPoint = 0;
  3631. if (areaOption.type === 'curve') {
  3632. for (let j = 0; j < points.length; j++) {
  3633. let item = points[j];
  3634. if (startPoint == 0 && item.x > leftSpace) {
  3635. context.moveTo(item.x, item.y);
  3636. startPoint = 1;
  3637. }
  3638. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3639. let ctrlPoint = createCurveControlPoints(points, j - 1);
  3640. context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
  3641. }
  3642. };
  3643. }
  3644. if (areaOption.type === 'straight') {
  3645. for (let j = 0; j < points.length; j++) {
  3646. let item = points[j];
  3647. if (startPoint == 0 && item.x > leftSpace) {
  3648. context.moveTo(item.x, item.y);
  3649. startPoint = 1;
  3650. }
  3651. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3652. context.lineTo(item.x, item.y);
  3653. }
  3654. };
  3655. }
  3656. if (areaOption.type === 'step') {
  3657. for (let j = 0; j < points.length; j++) {
  3658. let item = points[j];
  3659. if (startPoint == 0 && item.x > leftSpace) {
  3660. context.moveTo(item.x, item.y);
  3661. startPoint = 1;
  3662. }
  3663. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3664. context.lineTo(item.x, points[j - 1].y);
  3665. context.lineTo(item.x, item.y);
  3666. }
  3667. };
  3668. }
  3669. context.lineTo(lastPoint.x, endY);
  3670. context.lineTo(firstPoint.x, endY);
  3671. context.lineTo(firstPoint.x, firstPoint.y);
  3672. } else {
  3673. let item = points[0];
  3674. context.moveTo(item.x - eachSpacing / 2, item.y);
  3675. // context.lineTo(item.x + eachSpacing / 2, item.y);
  3676. // context.lineTo(item.x + eachSpacing / 2, endY);
  3677. // context.lineTo(item.x - eachSpacing / 2, endY);
  3678. // context.moveTo(item.x - eachSpacing / 2, item.y);
  3679. }
  3680. context.closePath();
  3681. context.fill();
  3682. //画连线
  3683. if (areaOption.addLine) {
  3684. if (eachSeries.lineType == 'dash') {
  3685. let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8;
  3686. dashLength *= opts.pix;
  3687. context.setLineDash([dashLength, dashLength]);
  3688. }
  3689. context.beginPath();
  3690. context.setStrokeStyle(eachSeries.color);
  3691. context.setLineWidth(areaOption.width * opts.pix);
  3692. if (points.length === 1) {
  3693. context.moveTo(points[0].x, points[0].y);
  3694. // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
  3695. } else {
  3696. context.moveTo(points[0].x, points[0].y);
  3697. let startPoint = 0;
  3698. if (areaOption.type === 'curve') {
  3699. for (let j = 0; j < points.length; j++) {
  3700. let item = points[j];
  3701. if (startPoint == 0 && item.x > leftSpace) {
  3702. context.moveTo(item.x, item.y);
  3703. startPoint = 1;
  3704. }
  3705. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3706. let ctrlPoint = createCurveControlPoints(points, j - 1);
  3707. context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
  3708. }
  3709. };
  3710. }
  3711. if (areaOption.type === 'straight') {
  3712. for (let j = 0; j < points.length; j++) {
  3713. let item = points[j];
  3714. if (startPoint == 0 && item.x > leftSpace) {
  3715. context.moveTo(item.x, item.y);
  3716. startPoint = 1;
  3717. }
  3718. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3719. context.lineTo(item.x, item.y);
  3720. }
  3721. };
  3722. }
  3723. if (areaOption.type === 'step') {
  3724. for (let j = 0; j < points.length; j++) {
  3725. let item = points[j];
  3726. if (startPoint == 0 && item.x > leftSpace) {
  3727. context.moveTo(item.x, item.y);
  3728. startPoint = 1;
  3729. }
  3730. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3731. context.lineTo(item.x, points[j - 1].y);
  3732. context.lineTo(item.x, item.y);
  3733. }
  3734. };
  3735. }
  3736. context.moveTo(points[0].x, points[0].y);
  3737. }
  3738. context.stroke();
  3739. context.setLineDash([]);
  3740. }
  3741. }
  3742. //画点
  3743. if (opts.dataPointShape !== false) {
  3744. drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
  3745. }
  3746. drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, areaOption,seriesIndex);
  3747. });
  3748. if (opts.dataLabel !== false && process === 1) {
  3749. series.forEach(function(eachSeries, seriesIndex) {
  3750. let ranges, minRange, maxRange;
  3751. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3752. minRange = ranges.pop();
  3753. maxRange = ranges.shift();
  3754. let data = eachSeries.data;
  3755. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3756. drawPointText(points, eachSeries, config, context, opts);
  3757. });
  3758. }
  3759. context.restore();
  3760. return {
  3761. xAxisPoints: xAxisPoints,
  3762. calPoints: calPoints,
  3763. eachSpacing: eachSpacing
  3764. };
  3765. }
  3766. function drawScatterDataPoints(series, opts, config, context) {
  3767. let scatterOption = assign({}, {
  3768. type: 'circle'
  3769. }, opts.extra.scatter);
  3770. let xAxisData = opts.chartData.xAxisData,
  3771. xAxisPoints = xAxisData.xAxisPoints,
  3772. eachSpacing = xAxisData.eachSpacing;
  3773. let calPoints = [];
  3774. context.save();
  3775. let leftSpace = 0;
  3776. let rightSpace = opts.width + eachSpacing;
  3777. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  3778. context.translate(opts._scrollDistance_, 0);
  3779. leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
  3780. rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
  3781. }
  3782. series.forEach(function(eachSeries, seriesIndex) {
  3783. let ranges, minRange, maxRange;
  3784. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3785. minRange = ranges.pop();
  3786. maxRange = ranges.shift();
  3787. let data = eachSeries.data;
  3788. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3789. context.beginPath();
  3790. context.setStrokeStyle(eachSeries.color);
  3791. context.setFillStyle(eachSeries.color);
  3792. context.setLineWidth(1 * opts.pix);
  3793. let shape = eachSeries.pointShape;
  3794. if (shape === 'diamond') {
  3795. points.forEach(function(item, index) {
  3796. if (item !== null) {
  3797. context.moveTo(item.x, item.y - 4.5);
  3798. context.lineTo(item.x - 4.5, item.y);
  3799. context.lineTo(item.x, item.y + 4.5);
  3800. context.lineTo(item.x + 4.5, item.y);
  3801. context.lineTo(item.x, item.y - 4.5);
  3802. }
  3803. });
  3804. } else if (shape === 'circle') {
  3805. points.forEach(function(item, index) {
  3806. if (item !== null) {
  3807. context.moveTo(item.x + 2.5 * opts.pix, item.y);
  3808. context.arc(item.x, item.y, 3 * opts.pix, 0, 2 * Math.PI, false);
  3809. }
  3810. });
  3811. } else if (shape === 'square') {
  3812. points.forEach(function(item, index) {
  3813. if (item !== null) {
  3814. context.moveTo(item.x - 3.5, item.y - 3.5);
  3815. context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
  3816. }
  3817. });
  3818. } else if (shape === 'triangle') {
  3819. points.forEach(function(item, index) {
  3820. if (item !== null) {
  3821. context.moveTo(item.x, item.y - 4.5);
  3822. context.lineTo(item.x - 4.5, item.y + 4.5);
  3823. context.lineTo(item.x + 4.5, item.y + 4.5);
  3824. context.lineTo(item.x, item.y - 4.5);
  3825. }
  3826. });
  3827. } else if (shape === 'triangle') {
  3828. return;
  3829. }
  3830. context.closePath();
  3831. context.fill();
  3832. context.stroke();
  3833. });
  3834. if (opts.dataLabel !== false && process === 1) {
  3835. series.forEach(function(eachSeries, seriesIndex) {
  3836. let ranges, minRange, maxRange;
  3837. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3838. minRange = ranges.pop();
  3839. maxRange = ranges.shift();
  3840. let data = eachSeries.data;
  3841. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3842. drawPointText(points, eachSeries, config, context, opts);
  3843. });
  3844. }
  3845. context.restore();
  3846. return {
  3847. xAxisPoints: xAxisPoints,
  3848. calPoints: calPoints,
  3849. eachSpacing: eachSpacing
  3850. };
  3851. }
  3852. function drawBubbleDataPoints(series, opts, config, context) {
  3853. let bubbleOption = assign({}, {
  3854. opacity: 1,
  3855. border:2
  3856. }, opts.extra.bubble);
  3857. let xAxisData = opts.chartData.xAxisData,
  3858. xAxisPoints = xAxisData.xAxisPoints,
  3859. eachSpacing = xAxisData.eachSpacing;
  3860. let calPoints = [];
  3861. context.save();
  3862. let leftSpace = 0;
  3863. let rightSpace = opts.width + eachSpacing;
  3864. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  3865. context.translate(opts._scrollDistance_, 0);
  3866. leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
  3867. rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
  3868. }
  3869. series.forEach(function(eachSeries, seriesIndex) {
  3870. let ranges, minRange, maxRange;
  3871. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3872. minRange = ranges.pop();
  3873. maxRange = ranges.shift();
  3874. let data = eachSeries.data;
  3875. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  3876. context.beginPath();
  3877. context.setStrokeStyle(eachSeries.color);
  3878. context.setLineWidth(bubbleOption.border * opts.pix);
  3879. context.setFillStyle(hexToRgb(eachSeries.color, bubbleOption.opacity));
  3880. points.forEach(function(item, index) {
  3881. context.moveTo(item.x + item.r, item.y);
  3882. context.arc(item.x, item.y, item.r * opts.pix, 0, 2 * Math.PI, false);
  3883. });
  3884. context.closePath();
  3885. context.fill();
  3886. context.stroke();
  3887. if (opts.dataLabel !== false && process === 1) {
  3888. points.forEach(function(item, index) {
  3889. context.beginPath();
  3890. let fontSize = eachSeries.textSize * opts.pix || config.fontSize;
  3891. context.setFontSize(fontSize);
  3892. context.setFillStyle(eachSeries.textColor || "#FFFFFF");
  3893. context.setTextAlign('center');
  3894. context.fillText(String(item.t), item.x, item.y + fontSize/2);
  3895. context.closePath();
  3896. context.stroke();
  3897. context.setTextAlign('left');
  3898. });
  3899. }
  3900. });
  3901. context.restore();
  3902. return {
  3903. xAxisPoints: xAxisPoints,
  3904. calPoints: calPoints,
  3905. eachSpacing: eachSpacing
  3906. };
  3907. }
  3908. function drawLineDataPoints(series, opts, config, context) {
  3909. let lineOption = assign({}, {
  3910. type: 'straight',
  3911. width: 2,
  3912. activeType: 'none',
  3913. linearType: 'none',
  3914. onShadow: false,
  3915. animation: 'vertical',
  3916. }, opts.extra.line);
  3917. lineOption.width *= opts.pix;
  3918. let xAxisData = opts.chartData.xAxisData,
  3919. xAxisPoints = xAxisData.xAxisPoints,
  3920. eachSpacing = xAxisData.eachSpacing;
  3921. let calPoints = [];
  3922. context.save();
  3923. let leftSpace = 0;
  3924. let rightSpace = opts.width + eachSpacing;
  3925. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  3926. context.translate(opts._scrollDistance_, 0);
  3927. leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
  3928. rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
  3929. }
  3930. series.forEach(function(eachSeries, seriesIndex) {
  3931. // 这段很神奇的代码用于解决ios16的setStrokeStyle失效的bug
  3932. context.beginPath();
  3933. context.setStrokeStyle(eachSeries.color);
  3934. context.moveTo(-10000, -10000);
  3935. context.lineTo(-10001, -10001);
  3936. context.stroke();
  3937. let ranges, minRange, maxRange;
  3938. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  3939. minRange = ranges.pop();
  3940. maxRange = ranges.shift();
  3941. let data = eachSeries.data;
  3942. let points = getLineDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, lineOption, chartProcess);
  3943. calPoints.push(points);
  3944. let splitPointList = splitPoints(points,eachSeries);
  3945. if (eachSeries.lineType == 'dash') {
  3946. let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8;
  3947. dashLength *= opts.pix;
  3948. context.setLineDash([dashLength, dashLength]);
  3949. }
  3950. context.beginPath();
  3951. let strokeColor = eachSeries.color;
  3952. if (lineOption.linearType !== 'none' && eachSeries.linearColor && eachSeries.linearColor.length > 0) {
  3953. let grd = context.createLinearGradient(opts.chartData.xAxisData.startX, opts.height/2, opts.chartData.xAxisData.endX, opts.height/2);
  3954. for (let i = 0; i < eachSeries.linearColor.length; i++) {
  3955. grd.addColorStop(eachSeries.linearColor[i][0], hexToRgb(eachSeries.linearColor[i][1], 1));
  3956. }
  3957. strokeColor = grd
  3958. }
  3959. context.setStrokeStyle(strokeColor);
  3960. if (lineOption.onShadow == true && eachSeries.setShadow && eachSeries.setShadow.length > 0) {
  3961. context.setShadow(eachSeries.setShadow[0], eachSeries.setShadow[1], eachSeries.setShadow[2], eachSeries.setShadow[3]);
  3962. }else{
  3963. context.setShadow(0, 0, 0, 'rgba(0,0,0,0)');
  3964. }
  3965. context.setLineWidth(lineOption.width);
  3966. splitPointList.forEach(function(points, index) {
  3967. if (points.length === 1) {
  3968. context.moveTo(points[0].x, points[0].y);
  3969. // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
  3970. } else {
  3971. context.moveTo(points[0].x, points[0].y);
  3972. let startPoint = 0;
  3973. if (lineOption.type === 'curve') {
  3974. for (let j = 0; j < points.length; j++) {
  3975. let item = points[j];
  3976. if (startPoint == 0 && item.x > leftSpace) {
  3977. context.moveTo(item.x, item.y);
  3978. startPoint = 1;
  3979. }
  3980. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3981. let ctrlPoint = createCurveControlPoints(points, j - 1);
  3982. context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
  3983. }
  3984. };
  3985. }
  3986. if (lineOption.type === 'straight') {
  3987. for (let j = 0; j < points.length; j++) {
  3988. let item = points[j];
  3989. if (startPoint == 0 && item.x > leftSpace) {
  3990. context.moveTo(item.x, item.y);
  3991. startPoint = 1;
  3992. }
  3993. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  3994. context.lineTo(item.x, item.y);
  3995. }
  3996. };
  3997. }
  3998. if (lineOption.type === 'step') {
  3999. for (let j = 0; j < points.length; j++) {
  4000. let item = points[j];
  4001. if (startPoint == 0 && item.x > leftSpace) {
  4002. context.moveTo(item.x, item.y);
  4003. startPoint = 1;
  4004. }
  4005. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  4006. context.lineTo(item.x, points[j - 1].y);
  4007. context.lineTo(item.x, item.y);
  4008. }
  4009. };
  4010. }
  4011. context.moveTo(points[0].x, points[0].y);
  4012. }
  4013. });
  4014. context.stroke();
  4015. context.setLineDash([]);
  4016. if (opts.dataPointShape !== false) {
  4017. drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
  4018. }
  4019. drawActivePoint(points, eachSeries.color, eachSeries.pointShape, context, opts, lineOption);
  4020. });
  4021. if (opts.dataLabel !== false && process === 1) {
  4022. series.forEach(function(eachSeries, seriesIndex) {
  4023. let ranges, minRange, maxRange;
  4024. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  4025. minRange = ranges.pop();
  4026. maxRange = ranges.shift();
  4027. let data = eachSeries.data;
  4028. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  4029. drawPointText(points, eachSeries, config, context, opts);
  4030. });
  4031. }
  4032. context.restore();
  4033. return {
  4034. xAxisPoints: xAxisPoints,
  4035. calPoints: calPoints,
  4036. eachSpacing: eachSpacing
  4037. };
  4038. }
  4039. function drawMixDataPoints(series, opts, config, context) {
  4040. let xAxisData = opts.chartData.xAxisData,
  4041. xAxisPoints = xAxisData.xAxisPoints,
  4042. eachSpacing = xAxisData.eachSpacing;
  4043. let columnOption = assign({}, {
  4044. width: eachSpacing / 2,
  4045. barBorderCircle: false,
  4046. barBorderRadius: [],
  4047. seriesGap: 2,
  4048. linearType: 'none',
  4049. linearOpacity: 1,
  4050. customColor: [],
  4051. colorStop: 0,
  4052. }, opts.extra.mix.column);
  4053. let areaOption = assign({}, {
  4054. opacity: 0.2,
  4055. gradient: false
  4056. }, opts.extra.mix.area);
  4057. let lineOption = assign({}, {
  4058. width: 2
  4059. }, opts.extra.mix.line);
  4060. let endY = opts.height - opts.area[2];
  4061. let calPoints = [];
  4062. let columnIndex = 0;
  4063. let columnLength = 0;
  4064. series.forEach(function(eachSeries, seriesIndex) {
  4065. if (eachSeries.type == 'column') {
  4066. columnLength += 1;
  4067. }
  4068. });
  4069. context.save();
  4070. let leftNum = -2;
  4071. let rightNum = xAxisPoints.length + 2;
  4072. let leftSpace = 0;
  4073. let rightSpace = opts.width + eachSpacing;
  4074. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  4075. context.translate(opts._scrollDistance_, 0);
  4076. leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2;
  4077. rightNum = leftNum + opts.xAxis.itemCount + 4;
  4078. leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area[3];
  4079. rightSpace = leftSpace + (opts.xAxis.itemCount + 4) * eachSpacing;
  4080. }
  4081. columnOption.customColor = fillCustomColor(columnOption.linearType, columnOption.customColor, series, config);
  4082. series.forEach(function(eachSeries, seriesIndex) {
  4083. let ranges, minRange, maxRange;
  4084. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  4085. minRange = ranges.pop();
  4086. maxRange = ranges.shift();
  4087. let data = eachSeries.data;
  4088. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  4089. calPoints.push(points);
  4090. // 绘制柱状数据图
  4091. if (eachSeries.type == 'column') {
  4092. points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
  4093. for (let i = 0; i < points.length; i++) {
  4094. let item = points[i];
  4095. if (item !== null && i > leftNum && i < rightNum) {
  4096. let startX = item.x - item.width / 2;
  4097. let height = opts.height - item.y - opts.area[2];
  4098. context.beginPath();
  4099. let fillColor = item.color || eachSeries.color
  4100. let strokeColor = item.color || eachSeries.color
  4101. if (columnOption.linearType !== 'none') {
  4102. let grd = context.createLinearGradient(startX, item.y, startX, opts.height - opts.area[2]);
  4103. //透明渐变
  4104. if (columnOption.linearType == 'opacity') {
  4105. grd.addColorStop(0, hexToRgb(fillColor, columnOption.linearOpacity));
  4106. grd.addColorStop(1, hexToRgb(fillColor, 1));
  4107. } else {
  4108. grd.addColorStop(0, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
  4109. grd.addColorStop(columnOption.colorStop, hexToRgb(columnOption.customColor[eachSeries.linearIndex], columnOption.linearOpacity));
  4110. grd.addColorStop(1, hexToRgb(fillColor, 1));
  4111. }
  4112. fillColor = grd
  4113. }
  4114. // 圆角边框
  4115. if ((columnOption.barBorderRadius && columnOption.barBorderRadius.length === 4) || columnOption.barBorderCircle) {
  4116. const left = startX;
  4117. const top = item.y;
  4118. const width = item.width;
  4119. const height = opts.height - opts.area[2] - item.y;
  4120. if (columnOption.barBorderCircle) {
  4121. columnOption.barBorderRadius = [width / 2, width / 2, 0, 0];
  4122. }
  4123. let [r0, r1, r2, r3] = columnOption.barBorderRadius;
  4124. let minRadius = Math.min(width/2,height/2);
  4125. r0 = r0 > minRadius ? minRadius : r0;
  4126. r1 = r1 > minRadius ? minRadius : r1;
  4127. r2 = r2 > minRadius ? minRadius : r2;
  4128. r3 = r3 > minRadius ? minRadius : r3;
  4129. r0 = r0 < 0 ? 0 : r0;
  4130. r1 = r1 < 0 ? 0 : r1;
  4131. r2 = r2 < 0 ? 0 : r2;
  4132. r3 = r3 < 0 ? 0 : r3;
  4133. context.arc(left + r0, top + r0, r0, -Math.PI, -Math.PI / 2);
  4134. context.arc(left + width - r1, top + r1, r1, -Math.PI / 2, 0);
  4135. context.arc(left + width - r2, top + height - r2, r2, 0, Math.PI / 2);
  4136. context.arc(left + r3, top + height - r3, r3, Math.PI / 2, Math.PI);
  4137. } else {
  4138. context.moveTo(startX, item.y);
  4139. context.lineTo(startX + item.width, item.y);
  4140. context.lineTo(startX + item.width, opts.height - opts.area[2]);
  4141. context.lineTo(startX, opts.height - opts.area[2]);
  4142. context.lineTo(startX, item.y);
  4143. context.setLineWidth(1)
  4144. context.setStrokeStyle(strokeColor);
  4145. }
  4146. context.setFillStyle(fillColor);
  4147. context.closePath();
  4148. context.fill();
  4149. }
  4150. }
  4151. columnIndex += 1;
  4152. }
  4153. //绘制区域图数据
  4154. if (eachSeries.type == 'area') {
  4155. let splitPointList = splitPoints(points,eachSeries);
  4156. for (let i = 0; i < splitPointList.length; i++) {
  4157. let points = splitPointList[i];
  4158. // 绘制区域数据
  4159. context.beginPath();
  4160. context.setStrokeStyle(eachSeries.color);
  4161. context.setStrokeStyle(hexToRgb(eachSeries.color, areaOption.opacity));
  4162. if (areaOption.gradient) {
  4163. let gradient = context.createLinearGradient(0, opts.area[0], 0, opts.height - opts.area[2]);
  4164. gradient.addColorStop('0', hexToRgb(eachSeries.color, areaOption.opacity));
  4165. gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1));
  4166. context.setFillStyle(gradient);
  4167. } else {
  4168. context.setFillStyle(hexToRgb(eachSeries.color, areaOption.opacity));
  4169. }
  4170. context.setLineWidth(2 * opts.pix);
  4171. if (points.length > 1) {
  4172. let firstPoint = points[0];
  4173. let lastPoint = points[points.length - 1];
  4174. context.moveTo(firstPoint.x, firstPoint.y);
  4175. let startPoint = 0;
  4176. if (eachSeries.style === 'curve') {
  4177. for (let j = 0; j < points.length; j++) {
  4178. let item = points[j];
  4179. if (startPoint == 0 && item.x > leftSpace) {
  4180. context.moveTo(item.x, item.y);
  4181. startPoint = 1;
  4182. }
  4183. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  4184. let ctrlPoint = createCurveControlPoints(points, j - 1);
  4185. context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
  4186. }
  4187. };
  4188. } else {
  4189. for (let j = 0; j < points.length; j++) {
  4190. let item = points[j];
  4191. if (startPoint == 0 && item.x > leftSpace) {
  4192. context.moveTo(item.x, item.y);
  4193. startPoint = 1;
  4194. }
  4195. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  4196. context.lineTo(item.x, item.y);
  4197. }
  4198. };
  4199. }
  4200. context.lineTo(lastPoint.x, endY);
  4201. context.lineTo(firstPoint.x, endY);
  4202. context.lineTo(firstPoint.x, firstPoint.y);
  4203. } else {
  4204. let item = points[0];
  4205. context.moveTo(item.x - eachSpacing / 2, item.y);
  4206. // context.lineTo(item.x + eachSpacing / 2, item.y);
  4207. // context.lineTo(item.x + eachSpacing / 2, endY);
  4208. // context.lineTo(item.x - eachSpacing / 2, endY);
  4209. // context.moveTo(item.x - eachSpacing / 2, item.y);
  4210. }
  4211. context.closePath();
  4212. context.fill();
  4213. }
  4214. }
  4215. // 绘制折线数据图
  4216. if (eachSeries.type == 'line') {
  4217. let splitPointList = splitPoints(points,eachSeries);
  4218. splitPointList.forEach(function(points, index) {
  4219. if (eachSeries.lineType == 'dash') {
  4220. let dashLength = eachSeries.dashLength ? eachSeries.dashLength : 8;
  4221. dashLength *= opts.pix;
  4222. context.setLineDash([dashLength, dashLength]);
  4223. }
  4224. context.beginPath();
  4225. context.setStrokeStyle(eachSeries.color);
  4226. context.setLineWidth(lineOption.width * opts.pix);
  4227. if (points.length === 1) {
  4228. context.moveTo(points[0].x, points[0].y);
  4229. // context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
  4230. } else {
  4231. context.moveTo(points[0].x, points[0].y);
  4232. let startPoint = 0;
  4233. if (eachSeries.style == 'curve') {
  4234. for (let j = 0; j < points.length; j++) {
  4235. let item = points[j];
  4236. if (startPoint == 0 && item.x > leftSpace) {
  4237. context.moveTo(item.x, item.y);
  4238. startPoint = 1;
  4239. }
  4240. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  4241. let ctrlPoint = createCurveControlPoints(points, j - 1);
  4242. context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y,
  4243. item.x, item.y);
  4244. }
  4245. }
  4246. } else {
  4247. for (let j = 0; j < points.length; j++) {
  4248. let item = points[j];
  4249. if (startPoint == 0 && item.x > leftSpace) {
  4250. context.moveTo(item.x, item.y);
  4251. startPoint = 1;
  4252. }
  4253. if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
  4254. context.lineTo(item.x, item.y);
  4255. }
  4256. }
  4257. }
  4258. context.moveTo(points[0].x, points[0].y);
  4259. }
  4260. context.stroke();
  4261. context.setLineDash([]);
  4262. });
  4263. }
  4264. // 绘制点数据图
  4265. if (eachSeries.type == 'point') {
  4266. eachSeries.addPoint = true;
  4267. }
  4268. if (eachSeries.addPoint == true && eachSeries.type !== 'column') {
  4269. drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
  4270. }
  4271. });
  4272. if (opts.dataLabel !== false && process === 1) {
  4273. let columnIndex = 0;
  4274. series.forEach(function(eachSeries, seriesIndex) {
  4275. let ranges, minRange, maxRange;
  4276. ranges = [].concat(opts.chartData.yAxisData.ranges[eachSeries.index]);
  4277. minRange = ranges.pop();
  4278. maxRange = ranges.shift();
  4279. let data = eachSeries.data;
  4280. let points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, chartProcess);
  4281. if (eachSeries.type !== 'column') {
  4282. drawPointText(points, eachSeries, config, context, opts);
  4283. } else {
  4284. points = fixColumeData(points, eachSpacing, columnLength, columnIndex, config, opts);
  4285. drawPointText(points, eachSeries, config, context, opts);
  4286. columnIndex += 1;
  4287. }
  4288. });
  4289. }
  4290. context.restore();
  4291. return {
  4292. xAxisPoints: xAxisPoints,
  4293. calPoints: calPoints,
  4294. eachSpacing: eachSpacing,
  4295. }
  4296. }
  4297. function drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints) {
  4298. let toolTipOption = opts.extra.tooltip || {};
  4299. if (toolTipOption.horizentalLine && opts.tooltip && process === 1 && (opts.type == 'line' || opts.type == 'area' || opts.type == 'column' || opts.type == 'mount' || opts.type == 'candle' || opts.type == 'mix')) {
  4300. drawToolTipHorizentalLine(opts, config, context, eachSpacing, xAxisPoints)
  4301. }
  4302. context.save();
  4303. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  4304. context.translate(opts._scrollDistance_, 0);
  4305. }
  4306. if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
  4307. drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context, eachSpacing, xAxisPoints);
  4308. }
  4309. context.restore();
  4310. }
  4311. function drawXAxis(categories, opts, config, context) {
  4312. let xAxisData = opts.chartData.xAxisData,
  4313. xAxisPoints = xAxisData.xAxisPoints,
  4314. startX = xAxisData.startX,
  4315. endX = xAxisData.endX,
  4316. eachSpacing = xAxisData.eachSpacing;
  4317. let boundaryGap = 'center';
  4318. if (opts.type == 'bar' || opts.type == 'line' || opts.type == 'area'|| opts.type == 'scatter' || opts.type == 'bubble') {
  4319. boundaryGap = opts.xAxis.boundaryGap;
  4320. }
  4321. let startY = opts.height - opts.area[2];
  4322. let endY = opts.area[0];
  4323. //绘制滚动条
  4324. if (opts.enableScroll && opts.xAxis.scrollShow) {
  4325. let scrollY = opts.height - opts.area[2] + config.xAxisHeight;
  4326. let scrollScreenWidth = endX - startX;
  4327. let scrollTotalWidth = eachSpacing * (xAxisPoints.length - 1);
  4328. if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1){
  4329. if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
  4330. scrollTotalWidth += (opts.extra.mount.widthRatio - 1)*eachSpacing;
  4331. }
  4332. let scrollWidth = scrollScreenWidth * scrollScreenWidth / scrollTotalWidth;
  4333. let scrollLeft = 0;
  4334. if (opts._scrollDistance_) {
  4335. scrollLeft = -opts._scrollDistance_ * (scrollScreenWidth) / scrollTotalWidth;
  4336. }
  4337. context.beginPath();
  4338. context.setLineCap('round');
  4339. context.setLineWidth(6 * opts.pix);
  4340. context.setStrokeStyle(opts.xAxis.scrollBackgroundColor || "#EFEBEF");
  4341. context.moveTo(startX, scrollY);
  4342. context.lineTo(endX, scrollY);
  4343. context.stroke();
  4344. context.closePath();
  4345. context.beginPath();
  4346. context.setLineCap('round');
  4347. context.setLineWidth(6 * opts.pix);
  4348. context.setStrokeStyle(opts.xAxis.scrollColor || "#A6A6A6");
  4349. context.moveTo(startX + scrollLeft, scrollY);
  4350. context.lineTo(startX + scrollLeft + scrollWidth, scrollY);
  4351. context.stroke();
  4352. context.closePath();
  4353. context.setLineCap('butt');
  4354. }
  4355. context.save();
  4356. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
  4357. context.translate(opts._scrollDistance_, 0);
  4358. }
  4359. //绘制X轴刻度线
  4360. if (opts.xAxis.calibration === true) {
  4361. context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
  4362. context.setLineCap('butt');
  4363. context.setLineWidth(1 * opts.pix);
  4364. xAxisPoints.forEach(function(item, index) {
  4365. if (index > 0) {
  4366. context.beginPath();
  4367. context.moveTo(item - eachSpacing / 2, startY);
  4368. context.lineTo(item - eachSpacing / 2, startY + 3 * opts.pix);
  4369. context.closePath();
  4370. context.stroke();
  4371. }
  4372. });
  4373. }
  4374. //绘制X轴网格
  4375. if (opts.xAxis.disableGrid !== true) {
  4376. context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
  4377. context.setLineCap('butt');
  4378. context.setLineWidth(1 * opts.pix);
  4379. if (opts.xAxis.gridType == 'dash') {
  4380. context.setLineDash([opts.xAxis.dashLength * opts.pix, opts.xAxis.dashLength * opts.pix]);
  4381. }
  4382. opts.xAxis.gridEval = opts.xAxis.gridEval || 1;
  4383. xAxisPoints.forEach(function(item, index) {
  4384. if (index % opts.xAxis.gridEval == 0) {
  4385. context.beginPath();
  4386. context.moveTo(item, startY);
  4387. context.lineTo(item, endY);
  4388. context.stroke();
  4389. }
  4390. });
  4391. context.setLineDash([]);
  4392. }
  4393. //绘制X轴文案
  4394. if (opts.xAxis.disabled !== true) {
  4395. // 对X轴列表做抽稀处理
  4396. //默认全部显示X轴标签
  4397. let maxXAxisListLength = categories.length;
  4398. //如果设置了X轴单屏数量
  4399. if (opts.xAxis.labelCount) {
  4400. //如果设置X轴密度
  4401. if (opts.xAxis.itemCount) {
  4402. maxXAxisListLength = Math.ceil(categories.length / opts.xAxis.itemCount * opts.xAxis.labelCount);
  4403. } else {
  4404. maxXAxisListLength = opts.xAxis.labelCount;
  4405. }
  4406. maxXAxisListLength -= 1;
  4407. }
  4408. let ratio = Math.ceil(categories.length / maxXAxisListLength);
  4409. let newCategories = [];
  4410. let cgLength = categories.length;
  4411. for (let i = 0; i < cgLength; i++) {
  4412. if (i % ratio !== 0) {
  4413. newCategories.push("");
  4414. } else {
  4415. newCategories.push(categories[i]);
  4416. }
  4417. }
  4418. newCategories[cgLength - 1] = categories[cgLength - 1];
  4419. let xAxisFontSize = opts.xAxis.fontSize * opts.pix || config.fontSize;
  4420. if (config._xAxisTextAngle_ === 0) {
  4421. newCategories.forEach(function(item, index) {
  4422. let xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item,index,opts) : item;
  4423. let offset = -measureText(String(xitem), xAxisFontSize, context) / 2;
  4424. if (boundaryGap == 'center') {
  4425. offset += eachSpacing / 2;
  4426. }
  4427. let scrollHeight = 0;
  4428. if (opts.xAxis.scrollShow) {
  4429. scrollHeight = 6 * opts.pix;
  4430. }
  4431. // 如果在主视图区域内
  4432. let _scrollDistance_ = opts._scrollDistance_ || 0;
  4433. let truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index];
  4434. if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){
  4435. context.beginPath();
  4436. context.setFontSize(xAxisFontSize);
  4437. context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
  4438. context.fillText(String(xitem), xAxisPoints[index] + offset, startY + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.fontSize) * opts.pix / 2 + opts.xAxis.fontSize * opts.pix);
  4439. context.closePath();
  4440. context.stroke();
  4441. }
  4442. });
  4443. } else {
  4444. newCategories.forEach(function(item, index) {
  4445. let xitem = opts.xAxis.formatter ? opts.xAxis.formatter(item) : item;
  4446. // 如果在主视图区域内
  4447. let _scrollDistance_ = opts._scrollDistance_ || 0;
  4448. let truePoints = boundaryGap == 'center' ? xAxisPoints[index] + eachSpacing / 2 : xAxisPoints[index];
  4449. if((truePoints - Math.abs(_scrollDistance_)) >= (opts.area[3] - 1) && (truePoints - Math.abs(_scrollDistance_)) <= (opts.width - opts.area[1] + 1)){
  4450. context.save();
  4451. context.beginPath();
  4452. context.setFontSize(xAxisFontSize);
  4453. context.setFillStyle(opts.xAxis.fontColor || opts.fontColor);
  4454. let textWidth = measureText(String(xitem), xAxisFontSize, context);
  4455. let offsetX = xAxisPoints[index];
  4456. if (boundaryGap == 'center') {
  4457. offsetX = xAxisPoints[index] + eachSpacing / 2;
  4458. }
  4459. let scrollHeight = 0;
  4460. if (opts.xAxis.scrollShow) {
  4461. scrollHeight = 6 * opts.pix;
  4462. }
  4463. let offsetY = startY + opts.xAxis.marginTop * opts.pix + xAxisFontSize - xAxisFontSize * Math.abs(Math.sin(config._xAxisTextAngle_));
  4464. if(opts.xAxis.rotateAngle < 0){
  4465. offsetX -= xAxisFontSize / 2;
  4466. textWidth = 0;
  4467. }else{
  4468. offsetX += xAxisFontSize / 2;
  4469. textWidth = -textWidth;
  4470. }
  4471. context.translate(offsetX, offsetY);
  4472. context.rotate(-1 * config._xAxisTextAngle_);
  4473. context.fillText(String(xitem), textWidth , 0 );
  4474. context.closePath();
  4475. context.stroke();
  4476. context.restore();
  4477. }
  4478. });
  4479. }
  4480. }
  4481. context.restore();
  4482. //画X轴标题
  4483. if (opts.xAxis.title) {
  4484. context.beginPath();
  4485. context.setFontSize(opts.xAxis.titleFontSize * opts.pix);
  4486. context.setFillStyle(opts.xAxis.titleFontColor);
  4487. context.fillText(String(opts.xAxis.title), opts.width - opts.area[1] + opts.xAxis.titleOffsetX * opts.pix,opts.height - opts.area[2] + opts.xAxis.marginTop * opts.pix + (opts.xAxis.lineHeight - opts.xAxis.titleFontSize) * opts.pix / 2 + (opts.xAxis.titleFontSize + opts.xAxis.titleOffsetY) * opts.pix);
  4488. context.closePath();
  4489. context.stroke();
  4490. }
  4491. //绘制X轴轴线
  4492. if (opts.xAxis.axisLine) {
  4493. context.beginPath();
  4494. context.setStrokeStyle(opts.xAxis.axisLineColor);
  4495. context.setLineWidth(1 * opts.pix);
  4496. context.moveTo(startX, opts.height - opts.area[2]);
  4497. context.lineTo(endX, opts.height - opts.area[2]);
  4498. context.stroke();
  4499. }
  4500. }
  4501. function drawYAxisGrid(categories, opts, config, context) {
  4502. if (opts.yAxis.disableGrid === true) {
  4503. return;
  4504. }
  4505. let spacingValid = opts.height - opts.area[0] - opts.area[2];
  4506. let eachSpacing = spacingValid / opts.yAxis.splitNumber;
  4507. let startX = opts.area[3];
  4508. let xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
  4509. xAxiseachSpacing = opts.chartData.xAxisData.eachSpacing;
  4510. let TotalWidth = xAxiseachSpacing * (xAxisPoints.length - 1);
  4511. if(opts.type == 'mount' && opts.extra && opts.extra.mount && opts.extra.mount.widthRatio && opts.extra.mount.widthRatio > 1 ){
  4512. if(opts.extra.mount.widthRatio>2) opts.extra.mount.widthRatio = 2
  4513. TotalWidth += (opts.extra.mount.widthRatio - 1) * xAxiseachSpacing;
  4514. }
  4515. let endX = startX + TotalWidth;
  4516. let points = [];
  4517. let startY = 1
  4518. if (opts.xAxis.axisLine === false) {
  4519. startY = 0
  4520. }
  4521. for (let i = startY; i < opts.yAxis.splitNumber + 1; i++) {
  4522. points.push(opts.height - opts.area[2] - eachSpacing * i);
  4523. }
  4524. context.save();
  4525. if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
  4526. context.translate(opts._scrollDistance_, 0);
  4527. }
  4528. if (opts.yAxis.gridType == 'dash') {
  4529. context.setLineDash([opts.yAxis.dashLength * opts.pix, opts.yAxis.dashLength * opts.pix]);
  4530. }
  4531. context.setStrokeStyle(opts.yAxis.gridColor);
  4532. context.setLineWidth(1 * opts.pix);
  4533. points.forEach(function(item, index) {
  4534. context.beginPath();
  4535. context.moveTo(startX, item);
  4536. context.lineTo(endX, item);
  4537. context.stroke();
  4538. });
  4539. context.setLineDash([]);
  4540. context.restore();
  4541. }
  4542. function drawYAxis(series, opts, config, context) {
  4543. if (opts.yAxis.disabled === true) {
  4544. return;
  4545. }
  4546. let spacingValid = opts.height - opts.area[0] - opts.area[2];
  4547. let eachSpacing = spacingValid / opts.yAxis.splitNumber;
  4548. let startX = opts.area[3];
  4549. let endX = opts.width - opts.area[1];
  4550. let endY = opts.height - opts.area[2];
  4551. // set YAxis background
  4552. context.beginPath();
  4553. context.setFillStyle(opts.background);
  4554. if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'left') {
  4555. context.fillRect(0, 0, startX, endY + 2 * opts.pix);
  4556. }
  4557. if (opts.enableScroll == true && opts.xAxis.scrollPosition && opts.xAxis.scrollPosition !== 'right') {
  4558. context.fillRect(endX, 0, opts.width, endY + 2 * opts.pix);
  4559. }
  4560. context.closePath();
  4561. context.stroke();
  4562. let tStartLeft = opts.area[3];
  4563. let tStartRight = opts.width - opts.area[1];
  4564. let tStartCenter = opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2;
  4565. if (opts.yAxis.data) {
  4566. for (let i = 0; i < opts.yAxis.data.length; i++) {
  4567. let yData = opts.yAxis.data[i];
  4568. let points = [];
  4569. if(yData.type === 'categories'){
  4570. for (let i = 0; i <= yData.categories.length; i++) {
  4571. points.push(opts.area[0] + spacingValid / yData.categories.length / 2 + spacingValid / yData.categories.length * i);
  4572. }
  4573. }else{
  4574. for (let i = 0; i <= opts.yAxis.splitNumber; i++) {
  4575. points.push(opts.area[0] + eachSpacing * i);
  4576. }
  4577. }
  4578. if (yData.disabled !== true) {
  4579. let rangesFormat = opts.chartData.yAxisData.rangesFormat[i];
  4580. let yAxisFontSize = yData.fontSize ? yData.fontSize * opts.pix : config.fontSize;
  4581. let yAxisWidth = opts.chartData.yAxisData.yAxisWidth[i];
  4582. let textAlign = yData.textAlign || "right";
  4583. //画Y轴刻度及文案
  4584. rangesFormat.forEach(function(item, index) {
  4585. let pos = points[index];
  4586. context.beginPath();
  4587. context.setFontSize(yAxisFontSize);
  4588. context.setLineWidth(1 * opts.pix);
  4589. context.setStrokeStyle(yData.axisLineColor || '#cccccc');
  4590. context.setFillStyle(yData.fontColor || opts.fontColor);
  4591. let tmpstrat = 0;
  4592. let gapwidth = 4 * opts.pix;
  4593. if (yAxisWidth.position == 'left') {
  4594. //画刻度线
  4595. if (yData.calibration == true) {
  4596. context.moveTo(tStartLeft, pos);
  4597. context.lineTo(tStartLeft - 3 * opts.pix, pos);
  4598. gapwidth += 3 * opts.pix;
  4599. }
  4600. //画文字
  4601. switch (textAlign) {
  4602. case "left":
  4603. context.setTextAlign('left');
  4604. tmpstrat = tStartLeft - yAxisWidth.width
  4605. break;
  4606. case "right":
  4607. context.setTextAlign('right');
  4608. tmpstrat = tStartLeft - gapwidth
  4609. break;
  4610. default:
  4611. context.setTextAlign('center');
  4612. tmpstrat = tStartLeft - yAxisWidth.width / 2
  4613. }
  4614. context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix);
  4615. } else if (yAxisWidth.position == 'right') {
  4616. //画刻度线
  4617. if (yData.calibration == true) {
  4618. context.moveTo(tStartRight, pos);
  4619. context.lineTo(tStartRight + 3 * opts.pix, pos);
  4620. gapwidth += 3 * opts.pix;
  4621. }
  4622. switch (textAlign) {
  4623. case "left":
  4624. context.setTextAlign('left');
  4625. tmpstrat = tStartRight + gapwidth
  4626. break;
  4627. case "right":
  4628. context.setTextAlign('right');
  4629. tmpstrat = tStartRight + yAxisWidth.width
  4630. break;
  4631. default:
  4632. context.setTextAlign('center');
  4633. tmpstrat = tStartRight + yAxisWidth.width / 2
  4634. }
  4635. context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix);
  4636. } else if (yAxisWidth.position == 'center') {
  4637. //画刻度线
  4638. if (yData.calibration == true) {
  4639. context.moveTo(tStartCenter, pos);
  4640. context.lineTo(tStartCenter - 3 * opts.pix, pos);
  4641. gapwidth += 3 * opts.pix;
  4642. }
  4643. //画文字
  4644. switch (textAlign) {
  4645. case "left":
  4646. context.setTextAlign('left');
  4647. tmpstrat = tStartCenter - yAxisWidth.width
  4648. break;
  4649. case "right":
  4650. context.setTextAlign('right');
  4651. tmpstrat = tStartCenter - gapwidth
  4652. break;
  4653. default:
  4654. context.setTextAlign('center');
  4655. tmpstrat = tStartCenter - yAxisWidth.width / 2
  4656. }
  4657. context.fillText(String(item), tmpstrat, pos + yAxisFontSize / 2 - 3 * opts.pix);
  4658. }
  4659. context.closePath();
  4660. context.stroke();
  4661. context.setTextAlign('left');
  4662. });
  4663. //画Y轴轴线
  4664. if (yData.axisLine !== false) {
  4665. context.beginPath();
  4666. context.setStrokeStyle(yData.axisLineColor || '#cccccc');
  4667. context.setLineWidth(1 * opts.pix);
  4668. if (yAxisWidth.position == 'left') {
  4669. context.moveTo(tStartLeft, opts.height - opts.area[2]);
  4670. context.lineTo(tStartLeft, opts.area[0]);
  4671. } else if (yAxisWidth.position == 'right') {
  4672. context.moveTo(tStartRight, opts.height - opts.area[2]);
  4673. context.lineTo(tStartRight, opts.area[0]);
  4674. } else if (yAxisWidth.position == 'center') {
  4675. context.moveTo(tStartCenter, opts.height - opts.area[2]);
  4676. context.lineTo(tStartCenter, opts.area[0]);
  4677. }
  4678. context.stroke();
  4679. }
  4680. //画Y轴标题
  4681. if (opts.yAxis.showTitle) {
  4682. let titleFontSize = yData.titleFontSize * opts.pix || config.fontSize;
  4683. let title = yData.title;
  4684. context.beginPath();
  4685. context.setFontSize(titleFontSize);
  4686. context.setFillStyle(yData.titleFontColor || opts.fontColor);
  4687. if (yAxisWidth.position == 'left') {
  4688. context.fillText(title, tStartLeft - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix);
  4689. } else if (yAxisWidth.position == 'right') {
  4690. context.fillText(title, tStartRight - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix);
  4691. } else if (yAxisWidth.position == 'center') {
  4692. context.fillText(title, tStartCenter - measureText(title, titleFontSize, context) / 2 + (yData.titleOffsetX || 0), opts.area[0] - (10 - (yData.titleOffsetY || 0)) * opts.pix);
  4693. }
  4694. context.closePath();
  4695. context.stroke();
  4696. }
  4697. if (yAxisWidth.position == 'left') {
  4698. tStartLeft -= (yAxisWidth.width + opts.yAxis.padding * opts.pix);
  4699. } else {
  4700. tStartRight += yAxisWidth.width + opts.yAxis.padding * opts.pix;
  4701. }
  4702. }
  4703. }
  4704. }
  4705. }
  4706. function drawLegend(series, opts, config, context, chartData) {
  4707. if (opts.legend.show === false) {
  4708. return;
  4709. }
  4710. let legendData = chartData.legendData;
  4711. let legendList = legendData.points;
  4712. let legendArea = legendData.area;
  4713. let padding = opts.legend.padding * opts.pix;
  4714. let fontSize = opts.legend.fontSize * opts.pix;
  4715. let shapeWidth = 15 * opts.pix;
  4716. let shapeRight = 5 * opts.pix;
  4717. let itemGap = opts.legend.itemGap * opts.pix;
  4718. let lineHeight = Math.max(opts.legend.lineHeight * opts.pix, fontSize);
  4719. //画背景及边框
  4720. context.beginPath();
  4721. context.setLineWidth(opts.legend.borderWidth * opts.pix);
  4722. context.setStrokeStyle(opts.legend.borderColor);
  4723. context.setFillStyle(opts.legend.backgroundColor);
  4724. context.moveTo(legendArea.start.x, legendArea.start.y);
  4725. context.rect(legendArea.start.x, legendArea.start.y, legendArea.width, legendArea.height);
  4726. context.closePath();
  4727. context.fill();
  4728. context.stroke();
  4729. legendList.forEach(function(itemList, listIndex) {
  4730. let width = 0;
  4731. let height = 0;
  4732. width = legendData.widthArr[listIndex];
  4733. height = legendData.heightArr[listIndex];
  4734. let startX = 0;
  4735. let startY = 0;
  4736. if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
  4737. switch (opts.legend.float) {
  4738. case 'left':
  4739. startX = legendArea.start.x + padding;
  4740. break;
  4741. case 'right':
  4742. startX = legendArea.start.x + legendArea.width - width;
  4743. break;
  4744. default:
  4745. startX = legendArea.start.x + (legendArea.width - width) / 2;
  4746. }
  4747. startY = legendArea.start.y + padding + listIndex * lineHeight;
  4748. } else {
  4749. if (listIndex == 0) {
  4750. width = 0;
  4751. } else {
  4752. width = legendData.widthArr[listIndex - 1];
  4753. }
  4754. startX = legendArea.start.x + padding + width;
  4755. startY = legendArea.start.y + padding + (legendArea.height - height) / 2;
  4756. }
  4757. context.setFontSize(config.fontSize);
  4758. for (let i = 0; i < itemList.length; i++) {
  4759. let item = itemList[i];
  4760. item.area = [0, 0, 0, 0];
  4761. item.area[0] = startX;
  4762. item.area[1] = startY;
  4763. item.area[3] = startY + lineHeight;
  4764. context.beginPath();
  4765. context.setLineWidth(1 * opts.pix);
  4766. context.setStrokeStyle(item.show ? item.color : opts.legend.hiddenColor);
  4767. context.setFillStyle(item.show ? item.color : opts.legend.hiddenColor);
  4768. switch (item.legendShape) {
  4769. case 'line':
  4770. context.moveTo(startX, startY + 0.5 * lineHeight - 2 * opts.pix);
  4771. context.fillRect(startX, startY + 0.5 * lineHeight - 2 * opts.pix, 15 * opts.pix, 4 * opts.pix);
  4772. break;
  4773. case 'triangle':
  4774. context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
  4775. context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix);
  4776. context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix);
  4777. context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
  4778. break;
  4779. case 'diamond':
  4780. context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
  4781. context.lineTo(startX + 2.5 * opts.pix, startY + 0.5 * lineHeight);
  4782. context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight + 5 * opts.pix);
  4783. context.lineTo(startX + 12.5 * opts.pix, startY + 0.5 * lineHeight);
  4784. context.lineTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
  4785. break;
  4786. case 'circle':
  4787. context.moveTo(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight);
  4788. context.arc(startX + 7.5 * opts.pix, startY + 0.5 * lineHeight, 5 * opts.pix, 0, 2 * Math.PI);
  4789. break;
  4790. case 'rect':
  4791. context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pix);
  4792. context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
  4793. break;
  4794. case 'square':
  4795. context.moveTo(startX + 5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix);
  4796. context.fillRect(startX + 5 * opts.pix, startY + 0.5 * lineHeight - 5 * opts.pix, 10 * opts.pix, 10 * opts.pix);
  4797. break;
  4798. case 'none':
  4799. break;
  4800. default:
  4801. context.moveTo(startX, startY + 0.5 * lineHeight - 5 * opts.pix);
  4802. context.fillRect(startX, startY + 0.5 * lineHeight - 5 * opts.pix, 15 * opts.pix, 10 * opts.pix);
  4803. }
  4804. context.closePath();
  4805. context.fill();
  4806. context.stroke();
  4807. startX += shapeWidth + shapeRight;
  4808. let fontTrans = 0.5 * lineHeight + 0.5 * fontSize - 2;
  4809. const legendText = item.legendText ? item.legendText : item.name;
  4810. context.beginPath();
  4811. context.setFontSize(fontSize);
  4812. context.setFillStyle(item.show ? opts.legend.fontColor : opts.legend.hiddenColor);
  4813. context.fillText(legendText, startX, startY + fontTrans);
  4814. context.closePath();
  4815. context.stroke();
  4816. if (opts.legend.position == 'top' || opts.legend.position == 'bottom') {
  4817. startX += measureText(legendText, fontSize, context) + itemGap;
  4818. item.area[2] = startX;
  4819. } else {
  4820. item.area[2] = startX + measureText(legendText, fontSize, context) + itemGap;;
  4821. startX -= shapeWidth + shapeRight;
  4822. startY += lineHeight;
  4823. }
  4824. }
  4825. });
  4826. }
  4827. function drawPieDataPoints(series, opts, config, context) {
  4828. let pieOption = assign({}, {
  4829. activeOpacity: 0.5,
  4830. activeRadius: 10,
  4831. offsetAngle: 0,
  4832. labelWidth: 15,
  4833. ringWidth: 30,
  4834. customRadius: 0,
  4835. border: false,
  4836. borderWidth: 2,
  4837. borderColor: '#FFFFFF',
  4838. centerColor: '#FFFFFF',
  4839. linearType: 'none',
  4840. customColor: [],
  4841. }, opts.type == "pie" ? opts.extra.pie : opts.extra.ring);
  4842. let centerPosition = {
  4843. x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
  4844. y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
  4845. };
  4846. if (config.pieChartLinePadding == 0) {
  4847. config.pieChartLinePadding = pieOption.activeRadius * opts.pix;
  4848. }
  4849. let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
  4850. radius = radius < 10 ? 10 : radius;
  4851. if (pieOption.customRadius > 0) {
  4852. radius = pieOption.customRadius * opts.pix;
  4853. }
  4854. series = getPieDataPoints(series, radius, chartProcess);
  4855. let activeRadius = pieOption.activeRadius * opts.pix;
  4856. pieOption.customColor = fillCustomColor(pieOption.linearType, pieOption.customColor, series, config);
  4857. series = series.map(function(eachSeries) {
  4858. eachSeries._start_ += (pieOption.offsetAngle) * Math.PI / 180;
  4859. return eachSeries;
  4860. });
  4861. series.forEach(function(eachSeries, seriesIndex) {
  4862. if (opts.tooltip) {
  4863. if (opts.tooltip.index == seriesIndex) {
  4864. context.beginPath();
  4865. context.setFillStyle(hexToRgb(eachSeries.color, pieOption.activeOpacity || 0.5));
  4866. context.moveTo(centerPosition.x, centerPosition.y);
  4867. context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_ + activeRadius, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
  4868. context.closePath();
  4869. context.fill();
  4870. }
  4871. }
  4872. context.beginPath();
  4873. context.setLineWidth(pieOption.borderWidth * opts.pix);
  4874. context.lineJoin = "round";
  4875. context.setStrokeStyle(pieOption.borderColor);
  4876. let fillcolor = eachSeries.color;
  4877. if (pieOption.linearType == 'custom') {
  4878. let grd;
  4879. if(context.createCircularGradient){
  4880. grd = context.createCircularGradient(centerPosition.x, centerPosition.y, eachSeries._radius_)
  4881. }else{
  4882. grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, eachSeries._radius_)
  4883. }
  4884. grd.addColorStop(0, hexToRgb(pieOption.customColor[eachSeries.linearIndex], 1))
  4885. grd.addColorStop(1, hexToRgb(eachSeries.color, 1))
  4886. fillcolor = grd
  4887. }
  4888. context.setFillStyle(fillcolor);
  4889. context.moveTo(centerPosition.x, centerPosition.y);
  4890. context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
  4891. context.closePath();
  4892. context.fill();
  4893. if (pieOption.border == true) {
  4894. context.stroke();
  4895. }
  4896. });
  4897. if (opts.type === 'ring') {
  4898. let innerPieWidth = radius * 0.6;
  4899. if (typeof pieOption.ringWidth === 'number' && pieOption.ringWidth > 0) {
  4900. innerPieWidth = Math.max(0, radius - pieOption.ringWidth * opts.pix);
  4901. }
  4902. context.beginPath();
  4903. context.setFillStyle(pieOption.centerColor);
  4904. context.moveTo(centerPosition.x, centerPosition.y);
  4905. context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
  4906. context.closePath();
  4907. context.fill();
  4908. }
  4909. if (opts.dataLabel !== false && process === 1) {
  4910. drawPieText(series, opts, config, context, radius, centerPosition);
  4911. }
  4912. if (process === 1 && opts.type === 'ring') {
  4913. drawRingTitle(opts, config, context, centerPosition);
  4914. }
  4915. return {
  4916. center: centerPosition,
  4917. radius: radius,
  4918. series: series
  4919. };
  4920. }
  4921. function drawRoseDataPoints(series, opts, config, context) {
  4922. let roseOption = assign({}, {
  4923. type: 'area',
  4924. activeOpacity: 0.5,
  4925. activeRadius: 10,
  4926. offsetAngle: 0,
  4927. labelWidth: 15,
  4928. border: false,
  4929. borderWidth: 2,
  4930. borderColor: '#FFFFFF',
  4931. linearType: 'none',
  4932. customColor: [],
  4933. }, opts.extra.rose);
  4934. if (config.pieChartLinePadding == 0) {
  4935. config.pieChartLinePadding = roseOption.activeRadius * opts.pix;
  4936. }
  4937. let centerPosition = {
  4938. x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
  4939. y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
  4940. };
  4941. let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, (opts.height - opts.area[0] - opts.area[2]) / 2 - config.pieChartLinePadding - config.pieChartTextPadding);
  4942. radius = radius < 10 ? 10 : radius;
  4943. let minRadius = roseOption.minRadius || radius * 0.5;
  4944. if(radius < minRadius){
  4945. radius = minRadius + 10;
  4946. }
  4947. series = getRoseDataPoints(series, roseOption.type, minRadius, radius, chartProcess);
  4948. let activeRadius = roseOption.activeRadius * opts.pix;
  4949. roseOption.customColor = fillCustomColor(roseOption.linearType, roseOption.customColor, series, config);
  4950. series = series.map(function(eachSeries) {
  4951. eachSeries._start_ += (roseOption.offsetAngle || 0) * Math.PI / 180;
  4952. return eachSeries;
  4953. });
  4954. series.forEach(function(eachSeries, seriesIndex) {
  4955. if (opts.tooltip) {
  4956. if (opts.tooltip.index == seriesIndex) {
  4957. context.beginPath();
  4958. context.setFillStyle(hexToRgb(eachSeries.color, roseOption.activeOpacity || 0.5));
  4959. context.moveTo(centerPosition.x, centerPosition.y);
  4960. context.arc(centerPosition.x, centerPosition.y, activeRadius + eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
  4961. context.closePath();
  4962. context.fill();
  4963. }
  4964. }
  4965. context.beginPath();
  4966. context.setLineWidth(roseOption.borderWidth * opts.pix);
  4967. context.lineJoin = "round";
  4968. context.setStrokeStyle(roseOption.borderColor);
  4969. let fillcolor = eachSeries.color;
  4970. if (roseOption.linearType == 'custom') {
  4971. let grd;
  4972. if(context.createCircularGradient){
  4973. grd = context.createCircularGradient(centerPosition.x, centerPosition.y, eachSeries._radius_)
  4974. }else{
  4975. grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, eachSeries._radius_)
  4976. }
  4977. grd.addColorStop(0, hexToRgb(roseOption.customColor[eachSeries.linearIndex], 1))
  4978. grd.addColorStop(1, hexToRgb(eachSeries.color, 1))
  4979. fillcolor = grd
  4980. }
  4981. context.setFillStyle(fillcolor);
  4982. context.moveTo(centerPosition.x, centerPosition.y);
  4983. context.arc(centerPosition.x, centerPosition.y, eachSeries._radius_, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._rose_proportion_ * Math.PI);
  4984. context.closePath();
  4985. context.fill();
  4986. if (roseOption.border == true) {
  4987. context.stroke();
  4988. }
  4989. });
  4990. if (opts.dataLabel !== false && process === 1) {
  4991. drawPieText(series, opts, config, context, radius, centerPosition);
  4992. }
  4993. return {
  4994. center: centerPosition,
  4995. radius: radius,
  4996. series: series
  4997. };
  4998. }
  4999. function drawArcbarDataPoints(series, opts, config, context) {
  5000. let arcbarOption = assign({}, {
  5001. startAngle: 0.75,
  5002. endAngle: 0.25,
  5003. type: 'default',
  5004. direction: 'cw',
  5005. lineCap: 'round',
  5006. width: 12 ,
  5007. gap: 2 ,
  5008. linearType: 'none',
  5009. customColor: [],
  5010. }, opts.extra.arcbar);
  5011. series = getArcbarDataPoints(series, arcbarOption, chartProcess);
  5012. let centerPosition;
  5013. if (arcbarOption.centerX || arcbarOption.centerY) {
  5014. centerPosition = {
  5015. x: arcbarOption.centerX ? arcbarOption.centerX : opts.width / 2,
  5016. y: arcbarOption.centerY ? arcbarOption.centerY : opts.height / 2
  5017. };
  5018. } else {
  5019. centerPosition = {
  5020. x: opts.width / 2,
  5021. y: opts.height / 2
  5022. };
  5023. }
  5024. let radius;
  5025. if (arcbarOption.radius) {
  5026. radius = arcbarOption.radius;
  5027. } else {
  5028. radius = Math.min(centerPosition.x, centerPosition.y);
  5029. radius -= 5 * opts.pix;
  5030. radius -= arcbarOption.width / 2;
  5031. }
  5032. radius = radius < 10 ? 10 : radius;
  5033. arcbarOption.customColor = fillCustomColor(arcbarOption.linearType, arcbarOption.customColor, series, config);
  5034. for (let i = 0; i < series.length; i++) {
  5035. let eachSeries = series[i];
  5036. //背景颜色
  5037. context.setLineWidth(arcbarOption.width * opts.pix);
  5038. context.setStrokeStyle(arcbarOption.backgroundColor || '#E9E9E9');
  5039. context.setLineCap(arcbarOption.lineCap);
  5040. context.beginPath();
  5041. if (arcbarOption.type == 'default') {
  5042. context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, arcbarOption.endAngle * Math.PI, arcbarOption.direction == 'ccw');
  5043. } else {
  5044. context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, 0, 2 * Math.PI, arcbarOption.direction == 'ccw');
  5045. }
  5046. context.stroke();
  5047. //进度条
  5048. let fillColor = eachSeries.color
  5049. if(arcbarOption.linearType == 'custom'){
  5050. let grd = context.createLinearGradient(centerPosition.x - radius, centerPosition.y, centerPosition.x + radius, centerPosition.y);
  5051. grd.addColorStop(1, hexToRgb(arcbarOption.customColor[eachSeries.linearIndex], 1))
  5052. grd.addColorStop(0, hexToRgb(eachSeries.color, 1))
  5053. fillColor = grd;
  5054. }
  5055. context.setLineWidth(arcbarOption.width * opts.pix);
  5056. context.setStrokeStyle(fillColor);
  5057. context.setLineCap(arcbarOption.lineCap);
  5058. context.beginPath();
  5059. context.arc(centerPosition.x, centerPosition.y, radius - (arcbarOption.width * opts.pix + arcbarOption.gap * opts.pix) * i, arcbarOption.startAngle * Math.PI, eachSeries._proportion_ * Math.PI, arcbarOption.direction == 'ccw');
  5060. context.stroke();
  5061. }
  5062. drawRingTitle(opts, config, context, centerPosition);
  5063. return {
  5064. center: centerPosition,
  5065. radius: radius,
  5066. series: series
  5067. };
  5068. }
  5069. function drawGaugeDataPoints(categories, series, opts, config, context) {
  5070. let gaugeOption = assign({}, {
  5071. type: 'default',
  5072. startAngle: 0.75,
  5073. endAngle: 0.25,
  5074. width: 15,
  5075. labelOffset:13,
  5076. splitLine: {
  5077. fixRadius: 0,
  5078. splitNumber: 10,
  5079. width: 15,
  5080. color: '#FFFFFF',
  5081. childNumber: 5,
  5082. childWidth: 5
  5083. },
  5084. pointer: {
  5085. width: 15,
  5086. color: 'auto'
  5087. }
  5088. }, opts.extra.gauge);
  5089. if (gaugeOption.oldAngle == undefined) {
  5090. gaugeOption.oldAngle = gaugeOption.startAngle;
  5091. }
  5092. if (gaugeOption.oldData == undefined) {
  5093. gaugeOption.oldData = 0;
  5094. }
  5095. categories = getGaugeAxisPoints(categories, gaugeOption.startAngle, gaugeOption.endAngle);
  5096. let centerPosition = {
  5097. x: opts.width / 2,
  5098. y: opts.height / 2
  5099. };
  5100. let radius = Math.min(centerPosition.x, centerPosition.y);
  5101. radius -= 5 * opts.pix;
  5102. radius -= gaugeOption.width / 2;
  5103. radius = radius < 10 ? 10 : radius;
  5104. let innerRadius = radius - gaugeOption.width;
  5105. let totalAngle = 0;
  5106. //判断仪表盘的样式:default百度样式,progress新样式
  5107. if (gaugeOption.type == 'progress') {
  5108. //## 第一步画中心圆形背景和进度条背景
  5109. //中心圆形背景
  5110. let pieRadius = radius - gaugeOption.width * 3;
  5111. context.beginPath();
  5112. let gradient = context.createLinearGradient(centerPosition.x, centerPosition.y - pieRadius, centerPosition.x, centerPosition.y + pieRadius);
  5113. //配置渐变填充(起点:中心点向上减半径;结束点中心点向下加半径)
  5114. gradient.addColorStop('0', hexToRgb(series[0].color, 0.3));
  5115. gradient.addColorStop('1.0', hexToRgb("#FFFFFF", 0.1));
  5116. context.setFillStyle(gradient);
  5117. context.arc(centerPosition.x, centerPosition.y, pieRadius, 0, 2 * Math.PI, false);
  5118. context.fill();
  5119. //画进度条背景
  5120. context.setLineWidth(gaugeOption.width);
  5121. context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
  5122. context.setLineCap('round');
  5123. context.beginPath();
  5124. context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, gaugeOption.endAngle * Math.PI, false);
  5125. context.stroke();
  5126. //## 第二步画刻度线
  5127. if (gaugeOption.endAngle < gaugeOption.startAngle) {
  5128. totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
  5129. } else {
  5130. totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
  5131. }
  5132. let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
  5133. let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
  5134. let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
  5135. let endX = -radius - gaugeOption.width - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
  5136. context.save();
  5137. context.translate(centerPosition.x, centerPosition.y);
  5138. context.rotate((gaugeOption.startAngle - 1) * Math.PI);
  5139. let len = gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1;
  5140. let proc = series[0].data * process;
  5141. for (let i = 0; i < len; i++) {
  5142. context.beginPath();
  5143. //刻度线随进度变色
  5144. if (proc > (i / len)) {
  5145. context.setStrokeStyle(hexToRgb(series[0].color, 1));
  5146. } else {
  5147. context.setStrokeStyle(hexToRgb(series[0].color, 0.3));
  5148. }
  5149. context.setLineWidth(3 * opts.pix);
  5150. context.moveTo(startX, 0);
  5151. context.lineTo(endX, 0);
  5152. context.stroke();
  5153. context.rotate(childAngle * Math.PI);
  5154. }
  5155. context.restore();
  5156. //## 第三步画进度条
  5157. series = getGaugeArcbarDataPoints(series, gaugeOption, chartProcess);
  5158. context.setLineWidth(gaugeOption.width);
  5159. context.setStrokeStyle(series[0].color);
  5160. context.setLineCap('round');
  5161. context.beginPath();
  5162. context.arc(centerPosition.x, centerPosition.y, innerRadius, gaugeOption.startAngle * Math.PI, series[0]._proportion_ * Math.PI, false);
  5163. context.stroke();
  5164. //## 第四步画指针
  5165. let pointerRadius = radius - gaugeOption.width * 2.5;
  5166. context.save();
  5167. context.translate(centerPosition.x, centerPosition.y);
  5168. context.rotate((series[0]._proportion_ - 1) * Math.PI);
  5169. context.beginPath();
  5170. context.setLineWidth(gaugeOption.width / 3);
  5171. let gradient3 = context.createLinearGradient(0, -pointerRadius * 0.6, 0, pointerRadius * 0.6);
  5172. gradient3.addColorStop('0', hexToRgb('#FFFFFF', 0));
  5173. gradient3.addColorStop('0.5', hexToRgb(series[0].color, 1));
  5174. gradient3.addColorStop('1.0', hexToRgb('#FFFFFF', 0));
  5175. context.setStrokeStyle(gradient3);
  5176. context.arc(0, 0, pointerRadius, 0.85 * Math.PI, 1.15 * Math.PI, false);
  5177. context.stroke();
  5178. context.beginPath();
  5179. context.setLineWidth(1);
  5180. context.setStrokeStyle(series[0].color);
  5181. context.setFillStyle(series[0].color);
  5182. context.moveTo(-pointerRadius - gaugeOption.width / 3 / 2, -4);
  5183. context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2 - 4, 0);
  5184. context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2, 4);
  5185. context.lineTo(-pointerRadius - gaugeOption.width / 3 / 2, -4);
  5186. context.stroke();
  5187. context.fill();
  5188. context.restore();
  5189. //default百度样式
  5190. } else {
  5191. //画背景
  5192. context.setLineWidth(gaugeOption.width);
  5193. context.setLineCap('butt');
  5194. for (let i = 0; i < categories.length; i++) {
  5195. let eachCategories = categories[i];
  5196. context.beginPath();
  5197. context.setStrokeStyle(eachCategories.color);
  5198. context.arc(centerPosition.x, centerPosition.y, radius, eachCategories._startAngle_ * Math.PI, eachCategories._endAngle_ * Math.PI, false);
  5199. context.stroke();
  5200. }
  5201. context.save();
  5202. //画刻度线
  5203. if (gaugeOption.endAngle < gaugeOption.startAngle) {
  5204. totalAngle = 2 + gaugeOption.endAngle - gaugeOption.startAngle;
  5205. } else {
  5206. totalAngle = gaugeOption.startAngle - gaugeOption.endAngle;
  5207. }
  5208. let splitAngle = totalAngle / gaugeOption.splitLine.splitNumber;
  5209. let childAngle = totalAngle / gaugeOption.splitLine.splitNumber / gaugeOption.splitLine.childNumber;
  5210. let startX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius;
  5211. let endX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.width;
  5212. let childendX = -radius - gaugeOption.width * 0.5 - gaugeOption.splitLine.fixRadius + gaugeOption.splitLine.childWidth;
  5213. context.translate(centerPosition.x, centerPosition.y);
  5214. context.rotate((gaugeOption.startAngle - 1) * Math.PI);
  5215. for (let i = 0; i < gaugeOption.splitLine.splitNumber + 1; i++) {
  5216. context.beginPath();
  5217. context.setStrokeStyle(gaugeOption.splitLine.color);
  5218. context.setLineWidth(2 * opts.pix);
  5219. context.moveTo(startX, 0);
  5220. context.lineTo(endX, 0);
  5221. context.stroke();
  5222. context.rotate(splitAngle * Math.PI);
  5223. }
  5224. context.restore();
  5225. context.save();
  5226. context.translate(centerPosition.x, centerPosition.y);
  5227. context.rotate((gaugeOption.startAngle - 1) * Math.PI);
  5228. for (let i = 0; i < gaugeOption.splitLine.splitNumber * gaugeOption.splitLine.childNumber + 1; i++) {
  5229. context.beginPath();
  5230. context.setStrokeStyle(gaugeOption.splitLine.color);
  5231. context.setLineWidth(1 * opts.pix);
  5232. context.moveTo(startX, 0);
  5233. context.lineTo(childendX, 0);
  5234. context.stroke();
  5235. context.rotate(childAngle * Math.PI);
  5236. }
  5237. context.restore();
  5238. //画指针
  5239. series = getGaugeDataPoints(series, categories, gaugeOption, chartProcess);
  5240. for (let i = 0; i < series.length; i++) {
  5241. let eachSeries = series[i];
  5242. context.save();
  5243. context.translate(centerPosition.x, centerPosition.y);
  5244. context.rotate((eachSeries._proportion_ - 1) * Math.PI);
  5245. context.beginPath();
  5246. context.setFillStyle(eachSeries.color);
  5247. context.moveTo(gaugeOption.pointer.width, 0);
  5248. context.lineTo(0, -gaugeOption.pointer.width / 2);
  5249. context.lineTo(-innerRadius, 0);
  5250. context.lineTo(0, gaugeOption.pointer.width / 2);
  5251. context.lineTo(gaugeOption.pointer.width, 0);
  5252. context.closePath();
  5253. context.fill();
  5254. context.beginPath();
  5255. context.setFillStyle('#FFFFFF');
  5256. context.arc(0, 0, gaugeOption.pointer.width / 6, 0, 2 * Math.PI, false);
  5257. context.fill();
  5258. context.restore();
  5259. }
  5260. if (opts.dataLabel !== false) {
  5261. drawGaugeLabel(gaugeOption, radius, centerPosition, opts, config, context);
  5262. }
  5263. }
  5264. //画仪表盘标题,副标题
  5265. drawRingTitle(opts, config, context, centerPosition);
  5266. if (process === 1 && opts.type === 'gauge') {
  5267. opts.extra.gauge.oldAngle = series[0]._proportion_;
  5268. opts.extra.gauge.oldData = series[0].data;
  5269. }
  5270. return {
  5271. center: centerPosition,
  5272. radius: radius,
  5273. innerRadius: innerRadius,
  5274. categories: categories,
  5275. totalAngle: totalAngle
  5276. };
  5277. }
  5278. function drawRadarDataPoints(series, opts, config, context) {
  5279. let radarOption = assign({}, {
  5280. gridColor: '#cccccc',
  5281. gridType: 'radar',
  5282. gridEval:1,
  5283. axisLabel:false,
  5284. axisLabelTofix:0,
  5285. labelShow:true,
  5286. labelColor:'#666666',
  5287. labelPointShow:false,
  5288. labelPointRadius:3,
  5289. labelPointColor:'#cccccc',
  5290. opacity: 0.2,
  5291. gridCount: 3,
  5292. border:false,
  5293. borderWidth:2,
  5294. linearType: 'none',
  5295. customColor: [],
  5296. }, opts.extra.radar);
  5297. let coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
  5298. let centerPosition = {
  5299. x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
  5300. y: opts.area[0] + (opts.height - opts.area[0] - opts.area[2]) / 2
  5301. };
  5302. let xr = (opts.width - opts.area[1] - opts.area[3]) / 2
  5303. let yr = (opts.height - opts.area[0] - opts.area[2]) / 2
  5304. let radius = Math.min(xr - (getMaxTextListLength(opts.categories, config.fontSize, context) + config.radarLabelTextMargin), yr - config.radarLabelTextMargin);
  5305. radius -= config.radarLabelTextMargin * opts.pix;
  5306. radius = radius < 10 ? 10 : radius;
  5307. radius = radarOption.radius ? radarOption.radius : radius;
  5308. // 画分割线
  5309. context.beginPath();
  5310. context.setLineWidth(1 * opts.pix);
  5311. context.setStrokeStyle(radarOption.gridColor);
  5312. coordinateAngle.forEach(function(angle,index) {
  5313. let pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
  5314. context.moveTo(centerPosition.x, centerPosition.y);
  5315. if (index % radarOption.gridEval == 0) {
  5316. context.lineTo(pos.x, pos.y);
  5317. }
  5318. });
  5319. context.stroke();
  5320. context.closePath();
  5321. // 画背景网格
  5322. let _loop = function _loop(i) {
  5323. let startPos = {};
  5324. context.beginPath();
  5325. context.setLineWidth(1 * opts.pix);
  5326. context.setStrokeStyle(radarOption.gridColor);
  5327. if (radarOption.gridType == 'radar') {
  5328. coordinateAngle.forEach(function(angle, index) {
  5329. let pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(angle), radius /
  5330. radarOption.gridCount * i * Math.sin(angle), centerPosition);
  5331. if (index === 0) {
  5332. startPos = pos;
  5333. context.moveTo(pos.x, pos.y);
  5334. } else {
  5335. context.lineTo(pos.x, pos.y);
  5336. }
  5337. });
  5338. context.lineTo(startPos.x, startPos.y);
  5339. } else {
  5340. let pos = convertCoordinateOrigin(radius / radarOption.gridCount * i * Math.cos(1.5), radius / radarOption.gridCount * i * Math.sin(1.5), centerPosition);
  5341. context.arc(centerPosition.x, centerPosition.y, centerPosition.y - pos.y, 0, 2 * Math.PI, false);
  5342. }
  5343. context.stroke();
  5344. context.closePath();
  5345. };
  5346. for (let i = 1; i <= radarOption.gridCount; i++) {
  5347. _loop(i);
  5348. }
  5349. radarOption.customColor = fillCustomColor(radarOption.linearType, radarOption.customColor, series, config);
  5350. let radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, chartProcess);
  5351. radarDataPoints.forEach(function(eachSeries, seriesIndex) {
  5352. // 绘制区域数据
  5353. context.beginPath();
  5354. context.setLineWidth(radarOption.borderWidth * opts.pix);
  5355. context.setStrokeStyle(eachSeries.color);
  5356. let fillcolor = hexToRgb(eachSeries.color, radarOption.opacity);
  5357. if (radarOption.linearType == 'custom') {
  5358. let grd;
  5359. if(context.createCircularGradient){
  5360. grd = context.createCircularGradient(centerPosition.x, centerPosition.y, radius)
  5361. }else{
  5362. grd = context.createRadialGradient(centerPosition.x, centerPosition.y, 0,centerPosition.x, centerPosition.y, radius)
  5363. }
  5364. grd.addColorStop(0, hexToRgb(radarOption.customColor[series[seriesIndex].linearIndex], radarOption.opacity))
  5365. grd.addColorStop(1, hexToRgb(eachSeries.color, radarOption.opacity))
  5366. fillcolor = grd
  5367. }
  5368. context.setFillStyle(fillcolor);
  5369. eachSeries.data.forEach(function(item, index) {
  5370. if (index === 0) {
  5371. context.moveTo(item.position.x, item.position.y);
  5372. } else {
  5373. context.lineTo(item.position.x, item.position.y);
  5374. }
  5375. });
  5376. context.closePath();
  5377. context.fill();
  5378. if(radarOption.border === true){
  5379. context.stroke();
  5380. }
  5381. context.closePath();
  5382. if (opts.dataPointShape !== false) {
  5383. let points = eachSeries.data.map(function(item) {
  5384. return item.position;
  5385. });
  5386. drawPointShape(points, eachSeries.color, eachSeries.pointShape, context, opts);
  5387. }
  5388. });
  5389. // 画刻度值
  5390. if(radarOption.axisLabel === true){
  5391. const maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
  5392. const stepLength = radius / radarOption.gridCount;
  5393. const fontSize = opts.fontSize * opts.pix;
  5394. context.setFontSize(fontSize);
  5395. context.setFillStyle(opts.fontColor);
  5396. context.setTextAlign('left');
  5397. for (let i = 0; i < radarOption.gridCount + 1; i++) {
  5398. let label = i * maxData / radarOption.gridCount;
  5399. label = label.toFixed(radarOption.axisLabelTofix);
  5400. context.fillText(String(label), centerPosition.x + 3 * opts.pix, centerPosition.y - i * stepLength + fontSize / 2);
  5401. }
  5402. }
  5403. // draw label text
  5404. drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
  5405. // draw dataLabel
  5406. if (opts.dataLabel !== false && process === 1) {
  5407. radarDataPoints.forEach(function(eachSeries, seriesIndex) {
  5408. context.beginPath();
  5409. let fontSize = eachSeries.textSize * opts.pix || config.fontSize;
  5410. context.setFontSize(fontSize);
  5411. context.setFillStyle(eachSeries.textColor || opts.fontColor);
  5412. eachSeries.data.forEach(function(item, index) {
  5413. //如果是中心点垂直的上下点位
  5414. if(Math.abs(item.position.x - centerPosition.x)<2){
  5415. //如果在上面
  5416. if(item.position.y < centerPosition.y){
  5417. context.setTextAlign('center');
  5418. context.fillText(item.value, item.position.x, item.position.y - 4);
  5419. }else{
  5420. context.setTextAlign('center');
  5421. context.fillText(item.value, item.position.x, item.position.y + fontSize + 2);
  5422. }
  5423. }else{
  5424. //如果在左侧
  5425. if(item.position.x < centerPosition.x){
  5426. context.setTextAlign('right');
  5427. context.fillText(item.value, item.position.x - 4, item.position.y + fontSize / 2 - 2);
  5428. }else{
  5429. context.setTextAlign('left');
  5430. context.fillText(item.value, item.position.x + 4, item.position.y + fontSize / 2 - 2);
  5431. }
  5432. }
  5433. });
  5434. context.closePath();
  5435. context.stroke();
  5436. });
  5437. context.setTextAlign('left');
  5438. }
  5439. return {
  5440. center: centerPosition,
  5441. radius: radius,
  5442. angleList: coordinateAngle
  5443. };
  5444. }
  5445. // 经纬度转墨卡托
  5446. function lonlat2mercator(longitude, latitude) {
  5447. let mercator = Array(2);
  5448. let x = longitude * 20037508.34 / 180;
  5449. let y = Math.log(Math.tan((90 + latitude) * Math.PI / 360)) / (Math.PI / 180);
  5450. y = y * 20037508.34 / 180;
  5451. mercator[0] = x;
  5452. mercator[1] = y;
  5453. return mercator;
  5454. }
  5455. // 墨卡托转经纬度
  5456. function mercator2lonlat(longitude, latitude) {
  5457. let lonlat = Array(2)
  5458. let x = longitude / 20037508.34 * 180;
  5459. let y = latitude / 20037508.34 * 180;
  5460. y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);
  5461. lonlat[0] = x;
  5462. lonlat[1] = y;
  5463. return lonlat;
  5464. }
  5465. function getBoundingBox(data) {
  5466. let bounds = {},coords;
  5467. bounds.xMin = 180;
  5468. bounds.xMax = 0;
  5469. bounds.yMin = 90;
  5470. bounds.yMax = 0
  5471. for (let i = 0; i < data.length; i++) {
  5472. let coorda = data[i].geometry.coordinates
  5473. for (let k = 0; k < coorda.length; k++) {
  5474. coords = coorda[k];
  5475. if (coords.length == 1) {
  5476. coords = coords[0]
  5477. }
  5478. for (let j = 0; j < coords.length; j++) {
  5479. let longitude = coords[j][0];
  5480. let latitude = coords[j][1];
  5481. let point = {
  5482. x: longitude,
  5483. y: latitude
  5484. }
  5485. bounds.xMin = bounds.xMin < point.x ? bounds.xMin : point.x;
  5486. bounds.xMax = bounds.xMax > point.x ? bounds.xMax : point.x;
  5487. bounds.yMin = bounds.yMin < point.y ? bounds.yMin : point.y;
  5488. bounds.yMax = bounds.yMax > point.y ? bounds.yMax : point.y;
  5489. }
  5490. }
  5491. }
  5492. return bounds;
  5493. }
  5494. function coordinateToPoint(latitude, longitude, bounds, scale, xoffset, yoffset) {
  5495. return {
  5496. x: (longitude - bounds.xMin) * scale + xoffset,
  5497. y: (bounds.yMax - latitude) * scale + yoffset
  5498. };
  5499. }
  5500. function pointToCoordinate(pointY, pointX, bounds, scale, xoffset, yoffset) {
  5501. return {
  5502. x: (pointX - xoffset) / scale + bounds.xMin,
  5503. y: bounds.yMax - (pointY - yoffset) / scale
  5504. };
  5505. }
  5506. function isRayIntersectsSegment(poi, s_poi, e_poi) {
  5507. if (s_poi[1] == e_poi[1]) {
  5508. return false;
  5509. }
  5510. if (s_poi[1] > poi[1] && e_poi[1] > poi[1]) {
  5511. return false;
  5512. }
  5513. if (s_poi[1] < poi[1] && e_poi[1] < poi[1]) {
  5514. return false;
  5515. }
  5516. if (s_poi[1] == poi[1] && e_poi[1] > poi[1]) {
  5517. return false;
  5518. }
  5519. if (e_poi[1] == poi[1] && s_poi[1] > poi[1]) {
  5520. return false;
  5521. }
  5522. if (s_poi[0] < poi[0] && e_poi[1] < poi[1]) {
  5523. return false;
  5524. }
  5525. let xseg = e_poi[0] - (e_poi[0] - s_poi[0]) * (e_poi[1] - poi[1]) / (e_poi[1] - s_poi[1]);
  5526. if (xseg < poi[0]) {
  5527. return false;
  5528. } else {
  5529. return true;
  5530. }
  5531. }
  5532. function isPoiWithinPoly(poi, poly, mercator) {
  5533. let sinsc = 0;
  5534. for (let i = 0; i < poly.length; i++) {
  5535. let epoly = poly[i][0];
  5536. if (poly.length == 1) {
  5537. epoly = poly[i][0]
  5538. }
  5539. for (let j = 0; j < epoly.length - 1; j++) {
  5540. let s_poi = epoly[j];
  5541. let e_poi = epoly[j + 1];
  5542. if (mercator) {
  5543. s_poi = lonlat2mercator(epoly[j][0], epoly[j][1]);
  5544. e_poi = lonlat2mercator(epoly[j + 1][0], epoly[j + 1][1]);
  5545. }
  5546. if (isRayIntersectsSegment(poi, s_poi, e_poi)) {
  5547. sinsc += 1;
  5548. }
  5549. }
  5550. }
  5551. if (sinsc % 2 == 1) {
  5552. return true;
  5553. } else {
  5554. return false;
  5555. }
  5556. }
  5557. function drawMapDataPoints(series, opts, config, context) {
  5558. let mapOption = assign({}, {
  5559. border: true,
  5560. mercator: false,
  5561. borderWidth: 1,
  5562. active:true,
  5563. borderColor: '#666666',
  5564. fillOpacity: 0.6,
  5565. activeBorderColor: '#f04864',
  5566. activeFillColor: '#facc14',
  5567. activeFillOpacity: 1
  5568. }, opts.extra.map);
  5569. let coords, point;
  5570. let data = series;
  5571. let bounds = getBoundingBox(data);
  5572. if (mapOption.mercator) {
  5573. let max = lonlat2mercator(bounds.xMax, bounds.yMax)
  5574. let min = lonlat2mercator(bounds.xMin, bounds.yMin)
  5575. bounds.xMax = max[0]
  5576. bounds.yMax = max[1]
  5577. bounds.xMin = min[0]
  5578. bounds.yMin = min[1]
  5579. }
  5580. let xScale = opts.width / Math.abs(bounds.xMax - bounds.xMin);
  5581. let yScale = opts.height / Math.abs(bounds.yMax - bounds.yMin);
  5582. let scale = xScale < yScale ? xScale : yScale;
  5583. let xoffset = opts.width / 2 - Math.abs(bounds.xMax - bounds.xMin) / 2 * scale;
  5584. let yoffset = opts.height / 2 - Math.abs(bounds.yMax - bounds.yMin) / 2 * scale;
  5585. for (let i = 0; i < data.length; i++) {
  5586. context.beginPath();
  5587. context.setLineWidth(mapOption.borderWidth * opts.pix);
  5588. context.setStrokeStyle(mapOption.borderColor);
  5589. context.setFillStyle(hexToRgb(series[i].color, series[i].fillOpacity||mapOption.fillOpacity));
  5590. if (mapOption.active == true && opts.tooltip) {
  5591. if (opts.tooltip.index == i) {
  5592. context.setStrokeStyle(mapOption.activeBorderColor);
  5593. context.setFillStyle(hexToRgb(mapOption.activeFillColor, mapOption.activeFillOpacity));
  5594. }
  5595. }
  5596. let coorda = data[i].geometry.coordinates
  5597. for (let k = 0; k < coorda.length; k++) {
  5598. coords = coorda[k];
  5599. if (coords.length == 1) {
  5600. coords = coords[0]
  5601. }
  5602. for (let j = 0; j < coords.length; j++) {
  5603. let gaosi = Array(2);
  5604. if (mapOption.mercator) {
  5605. gaosi = lonlat2mercator(coords[j][0], coords[j][1])
  5606. } else {
  5607. gaosi = coords[j]
  5608. }
  5609. point = coordinateToPoint(gaosi[1], gaosi[0], bounds, scale, xoffset, yoffset)
  5610. if (j === 0) {
  5611. context.beginPath();
  5612. context.moveTo(point.x, point.y);
  5613. } else {
  5614. context.lineTo(point.x, point.y);
  5615. }
  5616. }
  5617. context.fill();
  5618. if (mapOption.border == true) {
  5619. context.stroke();
  5620. }
  5621. }
  5622. }
  5623. if (opts.dataLabel == true) {
  5624. for (let i = 0; i < data.length; i++) {
  5625. let centerPoint = data[i].properties.centroid;
  5626. if (centerPoint) {
  5627. if (mapOption.mercator) {
  5628. centerPoint = lonlat2mercator(data[i].properties.centroid[0], data[i].properties.centroid[1])
  5629. }
  5630. point = coordinateToPoint(centerPoint[1], centerPoint[0], bounds, scale, xoffset, yoffset);
  5631. let fontSize = data[i].textSize * opts.pix || config.fontSize;
  5632. let fontColor = data[i].textColor || opts.fontColor;
  5633. if(mapOption.active && mapOption.activeTextColor && opts.tooltip && opts.tooltip.index == i){
  5634. fontColor = mapOption.activeTextColor;
  5635. }
  5636. let text = data[i].properties.name;
  5637. context.beginPath();
  5638. context.setFontSize(fontSize)
  5639. context.setFillStyle(fontColor)
  5640. context.fillText(text, point.x - measureText(text, fontSize, context) / 2, point.y + fontSize / 2);
  5641. context.closePath();
  5642. context.stroke();
  5643. }
  5644. }
  5645. }
  5646. opts.chartData.mapData = {
  5647. bounds: bounds,
  5648. scale: scale,
  5649. xoffset: xoffset,
  5650. yoffset: yoffset,
  5651. mercator: mapOption.mercator
  5652. }
  5653. drawToolTipBridge(opts, config, context, 1);
  5654. context.draw();
  5655. }
  5656. function normalInt(min, max, iter) {
  5657. iter = iter == 0 ? 1 : iter;
  5658. let arr = [];
  5659. for (let i = 0; i < iter; i++) {
  5660. arr[i] = Math.random();
  5661. };
  5662. return Math.floor(arr.reduce(function(i, j) {
  5663. return i + j
  5664. }) / iter * (max - min)) + min;
  5665. };
  5666. function collisionNew(area, points, width, height) {
  5667. let isIn = false;
  5668. for (let i = 0; i < points.length; i++) {
  5669. if (points[i].area) {
  5670. if (area[3] < points[i].area[1] || area[0] > points[i].area[2] || area[1] > points[i].area[3] || area[2] < points[i].area[0]) {
  5671. if (area[0] < 0 || area[1] < 0 || area[2] > width || area[3] > height) {
  5672. isIn = true;
  5673. break;
  5674. } else {
  5675. isIn = false;
  5676. }
  5677. } else {
  5678. isIn = true;
  5679. break;
  5680. }
  5681. }
  5682. }
  5683. return isIn;
  5684. };
  5685. function getWordCloudPoint(opts, type, context) {
  5686. let points = opts.series;
  5687. switch (type) {
  5688. case 'normal':
  5689. for (let i = 0; i < points.length; i++) {
  5690. let text = points[i].name;
  5691. let tHeight = points[i].textSize * opts.pix;
  5692. let tWidth = measureText(text, tHeight, context);
  5693. let x, y;
  5694. let area;
  5695. let breaknum = 0;
  5696. while (true) {
  5697. breaknum++;
  5698. x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2;
  5699. y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2;
  5700. area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 +
  5701. opts.height / 2
  5702. ];
  5703. let isCollision = collisionNew(area, points, opts.width, opts.height);
  5704. if (!isCollision) break;
  5705. if (breaknum == 1000) {
  5706. area = [-100, -100, -100, -100];
  5707. break;
  5708. }
  5709. };
  5710. points[i].area = area;
  5711. }
  5712. break;
  5713. case 'vertical':
  5714. function Spin() {
  5715. //获取均匀随机值,是否旋转,旋转的概率为(1-0.5)
  5716. if (Math.random() > 0.7) {
  5717. return true;
  5718. } else {
  5719. return false
  5720. };
  5721. };
  5722. for (let i = 0; i < points.length; i++) {
  5723. let text = points[i].name;
  5724. let tHeight = points[i].textSize * opts.pix;
  5725. let tWidth = measureText(text, tHeight, context);
  5726. let isSpin = Spin();
  5727. let x, y, area, areav;
  5728. let breaknum = 0;
  5729. while (true) {
  5730. breaknum++;
  5731. let isCollision;
  5732. if (isSpin) {
  5733. x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2;
  5734. y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2;
  5735. area = [y - 5 - tWidth + opts.width / 2, (-x - 5 + opts.height / 2), y + 5 + opts.width / 2, (-x + tHeight + 5 + opts.height / 2)];
  5736. areav = [opts.width - (opts.width / 2 - opts.height / 2) - (-x + tHeight + 5 + opts.height / 2) - 5, (opts.height / 2 - opts.width / 2) + (y - 5 - tWidth + opts.width / 2) - 5, opts.width - (opts.width / 2 - opts.height / 2) - (-x + tHeight + 5 + opts.height / 2) + tHeight, (opts.height / 2 - opts.width / 2) + (y - 5 - tWidth + opts.width / 2) + tWidth + 5];
  5737. isCollision = collisionNew(areav, points, opts.height, opts.width);
  5738. } else {
  5739. x = normalInt(-opts.width / 2, opts.width / 2, 5) - tWidth / 2;
  5740. y = normalInt(-opts.height / 2, opts.height / 2, 5) + tHeight / 2;
  5741. area = [x - 5 + opts.width / 2, y - 5 - tHeight + opts.height / 2, x + tWidth + 5 + opts.width / 2, y + 5 + opts.height / 2];
  5742. isCollision = collisionNew(area, points, opts.width, opts.height);
  5743. }
  5744. if (!isCollision) break;
  5745. if (breaknum == 1000) {
  5746. area = [-1000, -1000, -1000, -1000];
  5747. break;
  5748. }
  5749. };
  5750. if (isSpin) {
  5751. points[i].area = areav;
  5752. points[i].areav = area;
  5753. } else {
  5754. points[i].area = area;
  5755. }
  5756. points[i].rotate = isSpin;
  5757. };
  5758. break;
  5759. }
  5760. return points;
  5761. }
  5762. function drawWordCloudDataPoints(series, opts, config, context) {
  5763. let wordOption = assign({}, {
  5764. type: 'normal',
  5765. autoColors: true
  5766. }, opts.extra.word);
  5767. if (!opts.chartData.wordCloudData) {
  5768. opts.chartData.wordCloudData = getWordCloudPoint(opts, wordOption.type, context);
  5769. }
  5770. context.beginPath();
  5771. context.setFillStyle(opts.background);
  5772. context.rect(0, 0, opts.width, opts.height);
  5773. context.fill();
  5774. context.save();
  5775. let points = opts.chartData.wordCloudData;
  5776. context.translate(opts.width / 2, opts.height / 2);
  5777. for (let i = 0; i < points.length; i++) {
  5778. context.save();
  5779. if (points[i].rotate) {
  5780. context.rotate(90 * Math.PI / 180);
  5781. }
  5782. let text = points[i].name;
  5783. let tHeight = points[i].textSize * opts.pix;
  5784. let tWidth = measureText(text, tHeight, context);
  5785. context.beginPath();
  5786. context.setStrokeStyle(points[i].color);
  5787. context.setFillStyle(points[i].color);
  5788. context.setFontSize(tHeight);
  5789. if (points[i].rotate) {
  5790. if (points[i].areav[0] > 0) {
  5791. if (opts.tooltip) {
  5792. if (opts.tooltip.index == i) {
  5793. context.strokeText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process);
  5794. } else {
  5795. context.fillText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process);
  5796. }
  5797. } else {
  5798. context.fillText(text, (points[i].areav[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].areav[1] + 5 + tHeight - opts.height / 2) * process);
  5799. }
  5800. }
  5801. } else {
  5802. if (points[i].area[0] > 0) {
  5803. if (opts.tooltip) {
  5804. if (opts.tooltip.index == i) {
  5805. context.strokeText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process);
  5806. } else {
  5807. context.fillText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process);
  5808. }
  5809. } else {
  5810. context.fillText(text, (points[i].area[0] + 5 - opts.width / 2) * process - tWidth * (1 - process) / 2, (points[i].area[1] + 5 + tHeight - opts.height / 2) * process);
  5811. }
  5812. }
  5813. }
  5814. context.stroke();
  5815. context.restore();
  5816. }
  5817. context.restore();
  5818. }
  5819. function drawFunnelDataPoints(series, opts, config, context) {
  5820. let funnelOption = assign({}, {
  5821. type:'funnel',
  5822. activeWidth: 10,
  5823. activeOpacity: 0.3,
  5824. border: false,
  5825. borderWidth: 2,
  5826. borderColor: '#FFFFFF',
  5827. fillOpacity: 1,
  5828. minSize: 0,
  5829. labelAlign: 'right',
  5830. linearType: 'none',
  5831. customColor: [],
  5832. }, opts.extra.funnel);
  5833. let eachSpacing = (opts.height - opts.area[0] - opts.area[2]) / series.length;
  5834. let centerPosition = {
  5835. x: opts.area[3] + (opts.width - opts.area[1] - opts.area[3]) / 2,
  5836. y: opts.height - opts.area[2]
  5837. };
  5838. let activeWidth = funnelOption.activeWidth * opts.pix;
  5839. let radius = Math.min((opts.width - opts.area[1] - opts.area[3]) / 2 - activeWidth, (opts.height - opts.area[0] - opts.area[2]) / 2 - activeWidth);
  5840. let seriesNew = getFunnelDataPoints(series, radius, funnelOption, eachSpacing, chartProcess);
  5841. context.save();
  5842. context.translate(centerPosition.x, centerPosition.y);
  5843. funnelOption.customColor = fillCustomColor(funnelOption.linearType, funnelOption.customColor, series, config);
  5844. if(funnelOption.type == 'pyramid'){
  5845. for (let i = 0; i < seriesNew.length; i++) {
  5846. if (i == seriesNew.length -1) {
  5847. if (opts.tooltip) {
  5848. if (opts.tooltip.index == i) {
  5849. context.beginPath();
  5850. context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
  5851. context.moveTo(-activeWidth, -eachSpacing);
  5852. context.lineTo(-seriesNew[i].radius - activeWidth, 0);
  5853. context.lineTo(seriesNew[i].radius + activeWidth, 0);
  5854. context.lineTo(activeWidth, -eachSpacing);
  5855. context.lineTo(-activeWidth, -eachSpacing);
  5856. context.closePath();
  5857. context.fill();
  5858. }
  5859. }
  5860. seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i];
  5861. context.beginPath();
  5862. context.setLineWidth(funnelOption.borderWidth * opts.pix);
  5863. context.setStrokeStyle(funnelOption.borderColor);
  5864. let fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
  5865. if (funnelOption.linearType == 'custom') {
  5866. let grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
  5867. grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5868. grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
  5869. grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5870. fillColor = grd
  5871. }
  5872. context.setFillStyle(fillColor);
  5873. context.moveTo(0, -eachSpacing);
  5874. context.lineTo(-seriesNew[i].radius, 0);
  5875. context.lineTo(seriesNew[i].radius, 0);
  5876. context.lineTo(0, -eachSpacing);
  5877. context.closePath();
  5878. context.fill();
  5879. if (funnelOption.border == true) {
  5880. context.stroke();
  5881. }
  5882. } else {
  5883. if (opts.tooltip) {
  5884. if (opts.tooltip.index == i) {
  5885. context.beginPath();
  5886. context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
  5887. context.moveTo(0, 0);
  5888. context.lineTo(-seriesNew[i].radius - activeWidth, 0);
  5889. context.lineTo(-seriesNew[i + 1].radius - activeWidth, -eachSpacing);
  5890. context.lineTo(seriesNew[i + 1].radius + activeWidth, -eachSpacing);
  5891. context.lineTo(seriesNew[i].radius + activeWidth, 0);
  5892. context.lineTo(0, 0);
  5893. context.closePath();
  5894. context.fill();
  5895. }
  5896. }
  5897. seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (i + 1), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * i];
  5898. context.beginPath();
  5899. context.setLineWidth(funnelOption.borderWidth * opts.pix);
  5900. context.setStrokeStyle(funnelOption.borderColor);
  5901. let fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
  5902. if (funnelOption.linearType == 'custom') {
  5903. let grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
  5904. grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5905. grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
  5906. grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5907. fillColor = grd
  5908. }
  5909. context.setFillStyle(fillColor);
  5910. context.moveTo(0, 0);
  5911. context.lineTo(-seriesNew[i].radius, 0);
  5912. context.lineTo(-seriesNew[i + 1].radius, -eachSpacing);
  5913. context.lineTo(seriesNew[i + 1].radius, -eachSpacing);
  5914. context.lineTo(seriesNew[i].radius, 0);
  5915. context.lineTo(0, 0);
  5916. context.closePath();
  5917. context.fill();
  5918. if (funnelOption.border == true) {
  5919. context.stroke();
  5920. }
  5921. }
  5922. context.translate(0, -eachSpacing)
  5923. }
  5924. }else{
  5925. context.translate(0, - (seriesNew.length - 1) * eachSpacing);
  5926. for (let i = 0; i < seriesNew.length; i++) {
  5927. if (i == seriesNew.length - 1) {
  5928. if (opts.tooltip) {
  5929. if (opts.tooltip.index == i) {
  5930. context.beginPath();
  5931. context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
  5932. context.moveTo(-activeWidth - funnelOption.minSize/2, 0);
  5933. context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing);
  5934. context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing);
  5935. context.lineTo(activeWidth + funnelOption.minSize/2, 0);
  5936. context.lineTo(-activeWidth - funnelOption.minSize/2, 0);
  5937. context.closePath();
  5938. context.fill();
  5939. }
  5940. }
  5941. seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing, centerPosition.x + seriesNew[i].radius, centerPosition.y ];
  5942. context.beginPath();
  5943. context.setLineWidth(funnelOption.borderWidth * opts.pix);
  5944. context.setStrokeStyle(funnelOption.borderColor);
  5945. let fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
  5946. if (funnelOption.linearType == 'custom') {
  5947. let grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
  5948. grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5949. grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
  5950. grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5951. fillColor = grd
  5952. }
  5953. context.setFillStyle(fillColor);
  5954. context.moveTo(0, 0);
  5955. context.lineTo(-funnelOption.minSize/2, 0);
  5956. context.lineTo(-seriesNew[i].radius, -eachSpacing);
  5957. context.lineTo(seriesNew[i].radius, -eachSpacing);
  5958. context.lineTo(funnelOption.minSize/2, 0);
  5959. context.lineTo(0, 0);
  5960. context.closePath();
  5961. context.fill();
  5962. if (funnelOption.border == true) {
  5963. context.stroke();
  5964. }
  5965. } else {
  5966. if (opts.tooltip) {
  5967. if (opts.tooltip.index == i) {
  5968. context.beginPath();
  5969. context.setFillStyle(hexToRgb(seriesNew[i].color, funnelOption.activeOpacity));
  5970. context.moveTo(0, 0);
  5971. context.lineTo(-seriesNew[i + 1].radius - activeWidth, 0);
  5972. context.lineTo(-seriesNew[i].radius - activeWidth, -eachSpacing);
  5973. context.lineTo(seriesNew[i].radius + activeWidth, -eachSpacing);
  5974. context.lineTo(seriesNew[i + 1].radius + activeWidth, 0);
  5975. context.lineTo(0, 0);
  5976. context.closePath();
  5977. context.fill();
  5978. }
  5979. }
  5980. seriesNew[i].funnelArea = [centerPosition.x - seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i), centerPosition.x + seriesNew[i].radius, centerPosition.y - eachSpacing * (seriesNew.length - i - 1)];
  5981. context.beginPath();
  5982. context.setLineWidth(funnelOption.borderWidth * opts.pix);
  5983. context.setStrokeStyle(funnelOption.borderColor);
  5984. let fillColor = hexToRgb(seriesNew[i].color, funnelOption.fillOpacity);
  5985. if (funnelOption.linearType == 'custom') {
  5986. let grd = context.createLinearGradient(seriesNew[i].radius, -eachSpacing, -seriesNew[i].radius, -eachSpacing);
  5987. grd.addColorStop(0, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5988. grd.addColorStop(0.5, hexToRgb(funnelOption.customColor[seriesNew[i].linearIndex], funnelOption.fillOpacity));
  5989. grd.addColorStop(1, hexToRgb(seriesNew[i].color, funnelOption.fillOpacity));
  5990. fillColor = grd
  5991. }
  5992. context.setFillStyle(fillColor);
  5993. context.moveTo(0, 0);
  5994. context.lineTo(-seriesNew[i + 1].radius, 0);
  5995. context.lineTo(-seriesNew[i].radius, -eachSpacing);
  5996. context.lineTo(seriesNew[i].radius, -eachSpacing);
  5997. context.lineTo(seriesNew[i + 1].radius, 0);
  5998. context.lineTo(0, 0);
  5999. context.closePath();
  6000. context.fill();
  6001. if (funnelOption.border == true) {
  6002. context.stroke();
  6003. }
  6004. }
  6005. context.translate(0, eachSpacing)
  6006. }
  6007. }
  6008. context.restore();
  6009. if (opts.dataLabel !== false && process === 1) {
  6010. drawFunnelText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition);
  6011. }
  6012. if (process === 1) {
  6013. drawFunnelCenterText(seriesNew, opts, context, eachSpacing, funnelOption.labelAlign, activeWidth, centerPosition);
  6014. }
  6015. return {
  6016. center: centerPosition,
  6017. radius: radius,
  6018. series: seriesNew
  6019. };
  6020. }
  6021. function drawFunnelText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) {
  6022. for (let i = 0; i < series.length; i++) {
  6023. let item = series[i];
  6024. if(item.labelShow === false){
  6025. continue;
  6026. }
  6027. let startX, endX, startY, fontSize;
  6028. let text = item.formatter ? item.formatter(item,i,series,opts) : util.toFixed(item._proportion_ * 100) + '%';
  6029. text = item.labelText ? item.labelText : text;
  6030. if (labelAlign == 'right') {
  6031. if (i == series.length -1) {
  6032. startX = (item.funnelArea[2] + centerPosition.x) / 2;
  6033. } else {
  6034. startX = (item.funnelArea[2] + series[i + 1].funnelArea[2]) / 2;
  6035. }
  6036. endX = startX + activeWidth * 2;
  6037. startY = item.funnelArea[1] + eachSpacing / 2;
  6038. fontSize = item.textSize * opts.pix || opts.fontSize * opts.pix;
  6039. context.setLineWidth(1 * opts.pix);
  6040. context.setStrokeStyle(item.color);
  6041. context.setFillStyle(item.color);
  6042. context.beginPath();
  6043. context.moveTo(startX, startY);
  6044. context.lineTo(endX, startY);
  6045. context.stroke();
  6046. context.closePath();
  6047. context.beginPath();
  6048. context.moveTo(endX, startY);
  6049. context.arc(endX, startY, 2 * opts.pix, 0, 2 * Math.PI);
  6050. context.closePath();
  6051. context.fill();
  6052. context.beginPath();
  6053. context.setFontSize(fontSize);
  6054. context.setFillStyle(item.textColor || opts.fontColor);
  6055. context.fillText(text, endX + 5, startY + fontSize / 2 - 2);
  6056. context.closePath();
  6057. context.stroke();
  6058. context.closePath();
  6059. }
  6060. if (labelAlign == 'left') {
  6061. if (i == series.length -1) {
  6062. startX = (item.funnelArea[0] + centerPosition.x) / 2;
  6063. } else {
  6064. startX = (item.funnelArea[0] + series[i + 1].funnelArea[0]) / 2;
  6065. }
  6066. endX = startX - activeWidth * 2;
  6067. startY = item.funnelArea[1] + eachSpacing / 2;
  6068. fontSize = item.textSize * opts.pix || opts.fontSize * opts.pix;
  6069. context.setLineWidth(1 * opts.pix);
  6070. context.setStrokeStyle(item.color);
  6071. context.setFillStyle(item.color);
  6072. context.beginPath();
  6073. context.moveTo(startX, startY);
  6074. context.lineTo(endX, startY);
  6075. context.stroke();
  6076. context.closePath();
  6077. context.beginPath();
  6078. context.moveTo(endX, startY);
  6079. context.arc(endX, startY, 2, 0, 2 * Math.PI);
  6080. context.closePath();
  6081. context.fill();
  6082. context.beginPath();
  6083. context.setFontSize(fontSize);
  6084. context.setFillStyle(item.textColor || opts.fontColor);
  6085. context.fillText(text, endX - 5 - measureText(text, fontSize, context), startY + fontSize / 2 - 2);
  6086. context.closePath();
  6087. context.stroke();
  6088. context.closePath();
  6089. }
  6090. }
  6091. }
  6092. function drawFunnelCenterText(series, opts, context, eachSpacing, labelAlign, activeWidth, centerPosition) {
  6093. for (let i = 0; i < series.length; i++) {
  6094. let item = series[i];
  6095. let startY, fontSize;
  6096. if (item.centerText) {
  6097. startY = item.funnelArea[1] + eachSpacing / 2;
  6098. fontSize = item.centerTextSize * opts.pix || opts.fontSize * opts.pix;
  6099. context.beginPath();
  6100. context.setFontSize(fontSize);
  6101. context.setFillStyle(item.centerTextColor || "#FFFFFF");
  6102. context.fillText(item.centerText, centerPosition.x - measureText(item.centerText, fontSize, context) / 2, startY + fontSize / 2 - 2);
  6103. context.closePath();
  6104. context.stroke();
  6105. context.closePath();
  6106. }
  6107. }
  6108. }
  6109. function drawCanvas(opts, context) {
  6110. context.save();
  6111. context.translate(0, 0.5);
  6112. context.restore();
  6113. context.draw();
  6114. }
  6115. let Timing = {
  6116. easeIn: function easeIn(pos) {
  6117. return Math.pow(pos, 3);
  6118. },
  6119. easeOut: function easeOut(pos) {
  6120. return Math.pow(pos - 1, 3) + 1;
  6121. },
  6122. easeInOut: function easeInOut(pos) {
  6123. if ((pos /= 0.5) < 1) {
  6124. return 0.5 * Math.pow(pos, 3);
  6125. } else {
  6126. return 0.5 * (Math.pow(pos - 2, 3) + 2);
  6127. }
  6128. },
  6129. linear: function linear(pos) {
  6130. return pos;
  6131. }
  6132. };
  6133. function Animation(opts) {
  6134. this.isStop = false;
  6135. opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
  6136. opts.timing = opts.timing || 'easeInOut';
  6137. let delay = 17;
  6138. function createAnimationFrame() {
  6139. if (typeof setTimeout !== 'undefined') {
  6140. return function(step, delay) {
  6141. setTimeout(function() {
  6142. let timeStamp = +new Date();
  6143. step(timeStamp);
  6144. }, delay);
  6145. };
  6146. } else if (typeof requestAnimationFrame !== 'undefined') {
  6147. return requestAnimationFrame;
  6148. } else {
  6149. return function(step) {
  6150. step(null);
  6151. };
  6152. }
  6153. };
  6154. let animationFrame = createAnimationFrame();
  6155. let startTimeStamp = null;
  6156. let _step = function step(timestamp) {
  6157. if (timestamp === null || this.isStop === true) {
  6158. opts.onProcess && opts.onProcess(1);
  6159. opts.onAnimationFinish && opts.onAnimationFinish();
  6160. return;
  6161. }
  6162. if (startTimeStamp === null) {
  6163. startTimeStamp = timestamp;
  6164. }
  6165. if (timestamp - startTimeStamp < opts.duration) {
  6166. let process = (timestamp - startTimeStamp) / opts.duration;
  6167. let timingFunction = Timing[opts.timing];
  6168. process = timingFunction(process);
  6169. opts.onProcess && opts.onProcess(process);
  6170. animationFrame(_step, delay);
  6171. } else {
  6172. opts.onProcess && opts.onProcess(1);
  6173. opts.onAnimationFinish && opts.onAnimationFinish();
  6174. }
  6175. };
  6176. _step = _step.bind(this);
  6177. animationFrame(_step, delay);
  6178. }
  6179. Animation.prototype.stop = function() {
  6180. this.isStop = true;
  6181. };
  6182. function drawCharts(type, opts, config, context) {
  6183. let _this = this;
  6184. let series = opts.series;
  6185. //兼容ECharts饼图类数据格式
  6186. if (type === 'pie' || type === 'ring' || type === 'mount' || type === 'rose' || type === 'funnel') {
  6187. series = fixPieSeries(series, opts, config);
  6188. }
  6189. let categories = opts.categories;
  6190. if (type === 'mount') {
  6191. categories = [];
  6192. for (let j = 0; j < series.length; j++) {
  6193. if(series[j].show !== false) categories.push(series[j].name)
  6194. }
  6195. opts.categories = categories;
  6196. }
  6197. series = fillSeries(series, opts, config);
  6198. let duration = opts.animation ? opts.duration : 0;
  6199. _this.animationInstance && _this.animationInstance.stop();
  6200. let seriesMA = null;
  6201. if (type == 'candle') {
  6202. let average = assign({}, opts.extra.candle.average);
  6203. if (average.show) {
  6204. seriesMA = calCandleMA(average.day, average.name, average.color, series[0].data);
  6205. seriesMA = fillSeries(seriesMA, opts, config);
  6206. opts.seriesMA = seriesMA;
  6207. } else if (opts.seriesMA) {
  6208. seriesMA = opts.seriesMA = fillSeries(opts.seriesMA, opts, config);
  6209. } else {
  6210. seriesMA = series;
  6211. }
  6212. } else {
  6213. seriesMA = series;
  6214. }
  6215. /* 过滤掉show=false的series */
  6216. opts._series_ = series = filterSeries(series);
  6217. //重新计算图表区域
  6218. opts.area = new Array(4);
  6219. //复位绘图区域
  6220. for (let j = 0; j < 4; j++) {
  6221. opts.area[j] = opts.padding[j] * opts.pix;
  6222. }
  6223. //通过计算三大区域:图例、X轴、Y轴的大小,确定绘图区域
  6224. let _calLegendData = calLegendData(seriesMA, opts, config, opts.chartData, context),
  6225. legendHeight = _calLegendData.area.wholeHeight,
  6226. legendWidth = _calLegendData.area.wholeWidth;
  6227. switch (opts.legend.position) {
  6228. case 'top':
  6229. opts.area[0] += legendHeight;
  6230. break;
  6231. case 'bottom':
  6232. opts.area[2] += legendHeight;
  6233. break;
  6234. case 'left':
  6235. opts.area[3] += legendWidth;
  6236. break;
  6237. case 'right':
  6238. opts.area[1] += legendWidth;
  6239. break;
  6240. }
  6241. let _calYAxisData = {},
  6242. yAxisWidth = 0;
  6243. if (opts.type === 'line' || opts.type === 'column'|| opts.type === 'mount' || opts.type === 'area' || opts.type === 'mix' || opts.type === 'candle' || opts.type === 'scatter' || opts.type === 'bubble' || opts.type === 'bar') {
  6244. _calYAxisData = calYAxisData(series, opts, config, context);
  6245. yAxisWidth = _calYAxisData.yAxisWidth;
  6246. //如果显示Y轴标题
  6247. if (opts.yAxis.showTitle) {
  6248. let maxTitleHeight = 0;
  6249. for (let i = 0; i < opts.yAxis.data.length; i++) {
  6250. maxTitleHeight = Math.max(maxTitleHeight, opts.yAxis.data[i].titleFontSize ? opts.yAxis.data[i].titleFontSize * opts.pix : config.fontSize)
  6251. }
  6252. opts.area[0] += maxTitleHeight;
  6253. }
  6254. let rightIndex = 0,
  6255. leftIndex = 0;
  6256. //计算主绘图区域左右位置
  6257. for (let i = 0; i < yAxisWidth.length; i++) {
  6258. if (yAxisWidth[i].position == 'left') {
  6259. if (leftIndex > 0) {
  6260. opts.area[3] += yAxisWidth[i].width + opts.yAxis.padding * opts.pix;
  6261. } else {
  6262. opts.area[3] += yAxisWidth[i].width;
  6263. }
  6264. leftIndex += 1;
  6265. } else if (yAxisWidth[i].position == 'right') {
  6266. if (rightIndex > 0) {
  6267. opts.area[1] += yAxisWidth[i].width + opts.yAxis.padding * opts.pix;
  6268. } else {
  6269. opts.area[1] += yAxisWidth[i].width;
  6270. }
  6271. rightIndex += 1;
  6272. }
  6273. }
  6274. } else {
  6275. config.yAxisWidth = yAxisWidth;
  6276. }
  6277. opts.chartData.yAxisData = _calYAxisData;
  6278. if (opts.categories && opts.categories.length && opts.type !== 'radar' && opts.type !== 'gauge' && opts.type !== 'bar') {
  6279. opts.chartData.xAxisData = getXAxisPoints(opts.categories, opts, config);
  6280. let _calCategoriesData = calCategoriesData(opts.categories, opts, config, opts.chartData.xAxisData.eachSpacing, context),
  6281. xAxisHeight = _calCategoriesData.xAxisHeight,
  6282. angle = _calCategoriesData.angle;
  6283. config.xAxisHeight = xAxisHeight;
  6284. config._xAxisTextAngle_ = angle;
  6285. opts.area[2] += xAxisHeight;
  6286. opts.chartData.categoriesData = _calCategoriesData;
  6287. } else {
  6288. if (opts.type === 'line' || opts.type === 'area' || opts.type === 'scatter' || opts.type === 'bubble' || opts.type === 'bar') {
  6289. opts.chartData.xAxisData = calXAxisData(series, opts, config, context);
  6290. categories = opts.chartData.xAxisData.rangesFormat;
  6291. let _calCategoriesData = calCategoriesData(categories, opts, config, opts.chartData.xAxisData.eachSpacing, context),
  6292. xAxisHeight = _calCategoriesData.xAxisHeight,
  6293. angle = _calCategoriesData.angle;
  6294. config.xAxisHeight = xAxisHeight;
  6295. config._xAxisTextAngle_ = angle;
  6296. opts.area[2] += xAxisHeight;
  6297. opts.chartData.categoriesData = _calCategoriesData;
  6298. } else {
  6299. opts.chartData.xAxisData = {
  6300. xAxisPoints: []
  6301. };
  6302. }
  6303. }
  6304. //计算右对齐偏移距离
  6305. if (opts.enableScroll && opts.xAxis.scrollAlign == 'right' && opts._scrollDistance_ === undefined) {
  6306. let offsetLeft = 0,
  6307. xAxisPoints = opts.chartData.xAxisData.xAxisPoints,
  6308. startX = opts.chartData.xAxisData.startX,
  6309. endX = opts.chartData.xAxisData.endX,
  6310. eachSpacing = opts.chartData.xAxisData.eachSpacing;
  6311. let totalWidth = eachSpacing * (xAxisPoints.length - 1);
  6312. let screenWidth = endX - startX;
  6313. offsetLeft = screenWidth - totalWidth;
  6314. _this.scrollOption.currentOffset = offsetLeft;
  6315. _this.scrollOption.startTouchX = offsetLeft;
  6316. _this.scrollOption.distance = 0;
  6317. _this.scrollOption.lastMoveTime = 0;
  6318. opts._scrollDistance_ = offsetLeft;
  6319. }
  6320. if (type === 'pie' || type === 'ring' || type === 'rose') {
  6321. config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(seriesMA, config, context, opts);
  6322. }
  6323. switch (type) {
  6324. case 'word':
  6325. this.animationInstance = new Animation({
  6326. timing: opts.timing,
  6327. duration: duration,
  6328. onProcess: function(process) {
  6329. context.clearRect(0, 0, opts.width, opts.height);
  6330. if (opts.rotate) {
  6331. contextRotate(context, opts);
  6332. }
  6333. drawWordCloudDataPoints(series, opts, config, context, chartProcess);
  6334. drawCanvas(opts, context);
  6335. },
  6336. onAnimationFinish: function onAnimationFinish() {
  6337. _this.uevent.trigger('renderComplete');
  6338. }
  6339. });
  6340. break;
  6341. case 'map':
  6342. context.clearRect(0, 0, opts.width, opts.height);
  6343. drawMapDataPoints(series, opts, config, context);
  6344. setTimeout(()=>{
  6345. this.uevent.trigger('renderComplete');
  6346. },50)
  6347. break;
  6348. case 'funnel':
  6349. this.animationInstance = new Animation({
  6350. timing: opts.timing,
  6351. duration: duration,
  6352. onProcess: function(process) {
  6353. context.clearRect(0, 0, opts.width, opts.height);
  6354. if (opts.rotate) {
  6355. contextRotate(context, opts);
  6356. }
  6357. opts.chartData.funnelData = drawFunnelDataPoints(series, opts, config, context, chartProcess);
  6358. drawLegend(opts.series, opts, config, context, opts.chartData);
  6359. drawToolTipBridge(opts, config, context, chartProcess);
  6360. drawCanvas(opts, context);
  6361. },
  6362. onAnimationFinish: function onAnimationFinish() {
  6363. _this.uevent.trigger('renderComplete');
  6364. }
  6365. });
  6366. break;
  6367. case 'line':
  6368. this.animationInstance = new Animation({
  6369. timing: opts.timing,
  6370. duration: duration,
  6371. onProcess: function onProcess(process) {
  6372. context.clearRect(0, 0, opts.width, opts.height);
  6373. if (opts.rotate) {
  6374. contextRotate(context, opts);
  6375. }
  6376. drawYAxisGrid(categories, opts, config, context);
  6377. drawXAxis(categories, opts, config, context);
  6378. let _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, chartProcess),
  6379. xAxisPoints = _drawLineDataPoints.xAxisPoints,
  6380. calPoints = _drawLineDataPoints.calPoints,
  6381. eachSpacing = _drawLineDataPoints.eachSpacing;
  6382. opts.chartData.xAxisPoints = xAxisPoints;
  6383. opts.chartData.calPoints = calPoints;
  6384. opts.chartData.eachSpacing = eachSpacing;
  6385. drawYAxis(series, opts, config, context);
  6386. if (opts.enableMarkLine !== false && process === 1) {
  6387. drawMarkLine(opts, config, context);
  6388. }
  6389. drawLegend(opts.series, opts, config, context, opts.chartData);
  6390. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6391. drawCanvas(opts, context);
  6392. },
  6393. onAnimationFinish: function onAnimationFinish() {
  6394. _this.uevent.trigger('renderComplete');
  6395. }
  6396. });
  6397. break;
  6398. case 'scatter':
  6399. this.animationInstance = new Animation({
  6400. timing: opts.timing,
  6401. duration: duration,
  6402. onProcess: function onProcess(process) {
  6403. context.clearRect(0, 0, opts.width, opts.height);
  6404. if (opts.rotate) {
  6405. contextRotate(context, opts);
  6406. }
  6407. drawYAxisGrid(categories, opts, config, context);
  6408. drawXAxis(categories, opts, config, context);
  6409. let _drawScatterDataPoints = drawScatterDataPoints(series, opts, config, context, chartProcess),
  6410. xAxisPoints = _drawScatterDataPoints.xAxisPoints,
  6411. calPoints = _drawScatterDataPoints.calPoints,
  6412. eachSpacing = _drawScatterDataPoints.eachSpacing;
  6413. opts.chartData.xAxisPoints = xAxisPoints;
  6414. opts.chartData.calPoints = calPoints;
  6415. opts.chartData.eachSpacing = eachSpacing;
  6416. drawYAxis(series, opts, config, context);
  6417. if (opts.enableMarkLine !== false && process === 1) {
  6418. drawMarkLine(opts, config, context);
  6419. }
  6420. drawLegend(opts.series, opts, config, context, opts.chartData);
  6421. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6422. drawCanvas(opts, context);
  6423. },
  6424. onAnimationFinish: function onAnimationFinish() {
  6425. _this.uevent.trigger('renderComplete');
  6426. }
  6427. });
  6428. break;
  6429. case 'bubble':
  6430. this.animationInstance = new Animation({
  6431. timing: opts.timing,
  6432. duration: duration,
  6433. onProcess: function onProcess(process) {
  6434. context.clearRect(0, 0, opts.width, opts.height);
  6435. if (opts.rotate) {
  6436. contextRotate(context, opts);
  6437. }
  6438. drawYAxisGrid(categories, opts, config, context);
  6439. drawXAxis(categories, opts, config, context);
  6440. let _drawBubbleDataPoints = drawBubbleDataPoints(series, opts, config, context, chartProcess),
  6441. xAxisPoints = _drawBubbleDataPoints.xAxisPoints,
  6442. calPoints = _drawBubbleDataPoints.calPoints,
  6443. eachSpacing = _drawBubbleDataPoints.eachSpacing;
  6444. opts.chartData.xAxisPoints = xAxisPoints;
  6445. opts.chartData.calPoints = calPoints;
  6446. opts.chartData.eachSpacing = eachSpacing;
  6447. drawYAxis(series, opts, config, context);
  6448. if (opts.enableMarkLine !== false && process === 1) {
  6449. drawMarkLine(opts, config, context);
  6450. }
  6451. drawLegend(opts.series, opts, config, context, opts.chartData);
  6452. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6453. drawCanvas(opts, context);
  6454. },
  6455. onAnimationFinish: function onAnimationFinish() {
  6456. _this.uevent.trigger('renderComplete');
  6457. }
  6458. });
  6459. break;
  6460. case 'mix':
  6461. this.animationInstance = new Animation({
  6462. timing: opts.timing,
  6463. duration: duration,
  6464. onProcess: function onProcess(process) {
  6465. context.clearRect(0, 0, opts.width, opts.height);
  6466. if (opts.rotate) {
  6467. contextRotate(context, opts);
  6468. }
  6469. drawYAxisGrid(categories, opts, config, context);
  6470. drawXAxis(categories, opts, config, context);
  6471. let _drawMixDataPoints = drawMixDataPoints(series, opts, config, context, chartProcess),
  6472. xAxisPoints = _drawMixDataPoints.xAxisPoints,
  6473. calPoints = _drawMixDataPoints.calPoints,
  6474. eachSpacing = _drawMixDataPoints.eachSpacing;
  6475. opts.chartData.xAxisPoints = xAxisPoints;
  6476. opts.chartData.calPoints = calPoints;
  6477. opts.chartData.eachSpacing = eachSpacing;
  6478. drawYAxis(series, opts, config, context);
  6479. if (opts.enableMarkLine !== false && process === 1) {
  6480. drawMarkLine(opts, config, context);
  6481. }
  6482. drawLegend(opts.series, opts, config, context, opts.chartData);
  6483. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6484. drawCanvas(opts, context);
  6485. },
  6486. onAnimationFinish: function onAnimationFinish() {
  6487. _this.uevent.trigger('renderComplete');
  6488. }
  6489. });
  6490. break;
  6491. case 'column':
  6492. this.animationInstance = new Animation({
  6493. timing: opts.timing,
  6494. duration: duration,
  6495. onProcess: function onProcess(process) {
  6496. context.clearRect(0, 0, opts.width, opts.height);
  6497. if (opts.rotate) {
  6498. contextRotate(context, opts);
  6499. }
  6500. drawYAxisGrid(categories, opts, config, context);
  6501. drawXAxis(categories, opts, config, context);
  6502. let _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, chartProcess),
  6503. xAxisPoints = _drawColumnDataPoints.xAxisPoints,
  6504. calPoints = _drawColumnDataPoints.calPoints,
  6505. eachSpacing = _drawColumnDataPoints.eachSpacing;
  6506. opts.chartData.xAxisPoints = xAxisPoints;
  6507. opts.chartData.calPoints = calPoints;
  6508. opts.chartData.eachSpacing = eachSpacing;
  6509. drawYAxis(series, opts, config, context);
  6510. if (opts.enableMarkLine !== false && process === 1) {
  6511. drawMarkLine(opts, config, context);
  6512. }
  6513. drawLegend(opts.series, opts, config, context, opts.chartData);
  6514. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6515. drawCanvas(opts, context);
  6516. },
  6517. onAnimationFinish: function onAnimationFinish() {
  6518. _this.uevent.trigger('renderComplete');
  6519. }
  6520. });
  6521. break;
  6522. case 'mount':
  6523. this.animationInstance = new Animation({
  6524. timing: opts.timing,
  6525. duration: duration,
  6526. onProcess: function onProcess(process) {
  6527. context.clearRect(0, 0, opts.width, opts.height);
  6528. if (opts.rotate) {
  6529. contextRotate(context, opts);
  6530. }
  6531. drawYAxisGrid(categories, opts, config, context);
  6532. drawXAxis(categories, opts, config, context);
  6533. let _drawMountDataPoints = drawMountDataPoints(series, opts, config, context, chartProcess),
  6534. xAxisPoints = _drawMountDataPoints.xAxisPoints,
  6535. calPoints = _drawMountDataPoints.calPoints,
  6536. eachSpacing = _drawMountDataPoints.eachSpacing;
  6537. opts.chartData.xAxisPoints = xAxisPoints;
  6538. opts.chartData.calPoints = calPoints;
  6539. opts.chartData.eachSpacing = eachSpacing;
  6540. drawYAxis(series, opts, config, context);
  6541. if (opts.enableMarkLine !== false && process === 1) {
  6542. drawMarkLine(opts, config, context);
  6543. }
  6544. drawLegend(opts.series, opts, config, context, opts.chartData);
  6545. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6546. drawCanvas(opts, context);
  6547. },
  6548. onAnimationFinish: function onAnimationFinish() {
  6549. _this.uevent.trigger('renderComplete');
  6550. }
  6551. });
  6552. break;
  6553. case 'bar':
  6554. this.animationInstance = new Animation({
  6555. timing: opts.timing,
  6556. duration: duration,
  6557. onProcess: function onProcess(process) {
  6558. context.clearRect(0, 0, opts.width, opts.height);
  6559. if (opts.rotate) {
  6560. contextRotate(context, opts);
  6561. }
  6562. drawXAxis(categories, opts, config, context);
  6563. let _drawBarDataPoints = drawBarDataPoints(series, opts, config, context, chartProcess),
  6564. yAxisPoints = _drawBarDataPoints.yAxisPoints,
  6565. calPoints = _drawBarDataPoints.calPoints,
  6566. eachSpacing = _drawBarDataPoints.eachSpacing;
  6567. opts.chartData.yAxisPoints = yAxisPoints;
  6568. opts.chartData.xAxisPoints = opts.chartData.xAxisData.xAxisPoints;
  6569. opts.chartData.calPoints = calPoints;
  6570. opts.chartData.eachSpacing = eachSpacing;
  6571. drawYAxis(series, opts, config, context);
  6572. if (opts.enableMarkLine !== false && process === 1) {
  6573. drawMarkLine(opts, config, context);
  6574. }
  6575. drawLegend(opts.series, opts, config, context, opts.chartData);
  6576. drawToolTipBridge(opts, config, context, process, eachSpacing, yAxisPoints);
  6577. drawCanvas(opts, context);
  6578. },
  6579. onAnimationFinish: function onAnimationFinish() {
  6580. _this.uevent.trigger('renderComplete');
  6581. }
  6582. });
  6583. break;
  6584. case 'area':
  6585. this.animationInstance = new Animation({
  6586. timing: opts.timing,
  6587. duration: duration,
  6588. onProcess: function onProcess(process) {
  6589. context.clearRect(0, 0, opts.width, opts.height);
  6590. if (opts.rotate) {
  6591. contextRotate(context, opts);
  6592. }
  6593. drawYAxisGrid(categories, opts, config, context);
  6594. drawXAxis(categories, opts, config, context);
  6595. let _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, chartProcess),
  6596. xAxisPoints = _drawAreaDataPoints.xAxisPoints,
  6597. calPoints = _drawAreaDataPoints.calPoints,
  6598. eachSpacing = _drawAreaDataPoints.eachSpacing;
  6599. opts.chartData.xAxisPoints = xAxisPoints;
  6600. opts.chartData.calPoints = calPoints;
  6601. opts.chartData.eachSpacing = eachSpacing;
  6602. drawYAxis(series, opts, config, context);
  6603. if (opts.enableMarkLine !== false && process === 1) {
  6604. drawMarkLine(opts, config, context);
  6605. }
  6606. drawLegend(opts.series, opts, config, context, opts.chartData);
  6607. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6608. drawCanvas(opts, context);
  6609. },
  6610. onAnimationFinish: function onAnimationFinish() {
  6611. _this.uevent.trigger('renderComplete');
  6612. }
  6613. });
  6614. break;
  6615. case 'ring':
  6616. this.animationInstance = new Animation({
  6617. timing: opts.timing,
  6618. duration: duration,
  6619. onProcess: function onProcess(process) {
  6620. context.clearRect(0, 0, opts.width, opts.height);
  6621. if (opts.rotate) {
  6622. contextRotate(context, opts);
  6623. }
  6624. opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, chartProcess);
  6625. drawLegend(opts.series, opts, config, context, opts.chartData);
  6626. drawToolTipBridge(opts, config, context, chartProcess);
  6627. drawCanvas(opts, context);
  6628. },
  6629. onAnimationFinish: function onAnimationFinish() {
  6630. _this.uevent.trigger('renderComplete');
  6631. }
  6632. });
  6633. break;
  6634. case 'pie':
  6635. this.animationInstance = new Animation({
  6636. timing: opts.timing,
  6637. duration: duration,
  6638. onProcess: function onProcess(process) {
  6639. context.clearRect(0, 0, opts.width, opts.height);
  6640. if (opts.rotate) {
  6641. contextRotate(context, opts);
  6642. }
  6643. opts.chartData.pieData = drawPieDataPoints(series, opts, config, context, chartProcess);
  6644. drawLegend(opts.series, opts, config, context, opts.chartData);
  6645. drawToolTipBridge(opts, config, context, chartProcess);
  6646. drawCanvas(opts, context);
  6647. },
  6648. onAnimationFinish: function onAnimationFinish() {
  6649. _this.uevent.trigger('renderComplete');
  6650. }
  6651. });
  6652. break;
  6653. case 'rose':
  6654. this.animationInstance = new Animation({
  6655. timing: opts.timing,
  6656. duration: duration,
  6657. onProcess: function onProcess(process) {
  6658. context.clearRect(0, 0, opts.width, opts.height);
  6659. if (opts.rotate) {
  6660. contextRotate(context, opts);
  6661. }
  6662. opts.chartData.pieData = drawRoseDataPoints(series, opts, config, context, chartProcess);
  6663. drawLegend(opts.series, opts, config, context, opts.chartData);
  6664. drawToolTipBridge(opts, config, context, chartProcess);
  6665. drawCanvas(opts, context);
  6666. },
  6667. onAnimationFinish: function onAnimationFinish() {
  6668. _this.uevent.trigger('renderComplete');
  6669. }
  6670. });
  6671. break;
  6672. case 'radar':
  6673. this.animationInstance = new Animation({
  6674. timing: opts.timing,
  6675. duration: duration,
  6676. onProcess: function onProcess(process) {
  6677. context.clearRect(0, 0, opts.width, opts.height);
  6678. if (opts.rotate) {
  6679. contextRotate(context, opts);
  6680. }
  6681. opts.chartData.radarData = drawRadarDataPoints(series, opts, config, context, chartProcess);
  6682. drawLegend(opts.series, opts, config, context, opts.chartData);
  6683. drawToolTipBridge(opts, config, context, chartProcess);
  6684. drawCanvas(opts, context);
  6685. },
  6686. onAnimationFinish: function onAnimationFinish() {
  6687. _this.uevent.trigger('renderComplete');
  6688. }
  6689. });
  6690. break;
  6691. case 'arcbar':
  6692. this.animationInstance = new Animation({
  6693. timing: opts.timing,
  6694. duration: duration,
  6695. onProcess: function onProcess(process) {
  6696. context.clearRect(0, 0, opts.width, opts.height);
  6697. if (opts.rotate) {
  6698. contextRotate(context, opts);
  6699. }
  6700. opts.chartData.arcbarData = drawArcbarDataPoints(series, opts, config, context, chartProcess);
  6701. drawCanvas(opts, context);
  6702. },
  6703. onAnimationFinish: function onAnimationFinish() {
  6704. _this.uevent.trigger('renderComplete');
  6705. }
  6706. });
  6707. break;
  6708. case 'gauge':
  6709. this.animationInstance = new Animation({
  6710. timing: opts.timing,
  6711. duration: duration,
  6712. onProcess: function onProcess(process) {
  6713. context.clearRect(0, 0, opts.width, opts.height);
  6714. if (opts.rotate) {
  6715. contextRotate(context, opts);
  6716. }
  6717. opts.chartData.gaugeData = drawGaugeDataPoints(categories, series, opts, config, context, chartProcess);
  6718. drawCanvas(opts, context);
  6719. },
  6720. onAnimationFinish: function onAnimationFinish() {
  6721. _this.uevent.trigger('renderComplete');
  6722. }
  6723. });
  6724. break;
  6725. case 'candle':
  6726. this.animationInstance = new Animation({
  6727. timing: opts.timing,
  6728. duration: duration,
  6729. onProcess: function onProcess(process) {
  6730. context.clearRect(0, 0, opts.width, opts.height);
  6731. if (opts.rotate) {
  6732. contextRotate(context, opts);
  6733. }
  6734. drawYAxisGrid(categories, opts, config, context);
  6735. drawXAxis(categories, opts, config, context);
  6736. let _drawCandleDataPoints = drawCandleDataPoints(series, seriesMA, opts, config, context, chartProcess),
  6737. xAxisPoints = _drawCandleDataPoints.xAxisPoints,
  6738. calPoints = _drawCandleDataPoints.calPoints,
  6739. eachSpacing = _drawCandleDataPoints.eachSpacing;
  6740. opts.chartData.xAxisPoints = xAxisPoints;
  6741. opts.chartData.calPoints = calPoints;
  6742. opts.chartData.eachSpacing = eachSpacing;
  6743. drawYAxis(series, opts, config, context);
  6744. if (opts.enableMarkLine !== false && process === 1) {
  6745. drawMarkLine(opts, config, context);
  6746. }
  6747. if (seriesMA) {
  6748. drawLegend(seriesMA, opts, config, context, opts.chartData);
  6749. } else {
  6750. drawLegend(opts.series, opts, config, context, opts.chartData);
  6751. }
  6752. drawToolTipBridge(opts, config, context, process, eachSpacing, xAxisPoints);
  6753. drawCanvas(opts, context);
  6754. },
  6755. onAnimationFinish: function onAnimationFinish() {
  6756. _this.uevent.trigger('renderComplete');
  6757. }
  6758. });
  6759. break;
  6760. }
  6761. }
  6762. export class uChartsEvent {
  6763. constructor() { this.events = {}; }
  6764. addEventListener(type, listener) {
  6765. this.events[type] = this.events[type] || [];
  6766. this.events[type].push(listener);
  6767. }
  6768. delEventListener(type) {
  6769. this.events[type] = [];
  6770. }
  6771. trigger() {
  6772. for (let _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  6773. args[_key] = arguments[_key];
  6774. }
  6775. let type = args[0];
  6776. let params = args.slice(1);
  6777. if (!!this.events[type]) {
  6778. this.events[type].forEach(function(listener) {
  6779. try {
  6780. listener.apply(null, params);
  6781. } catch (e) {
  6782. //console.log('[uCharts] '+e);
  6783. }
  6784. });
  6785. }
  6786. }
  6787. }
  6788. export class uCharts {
  6789. constructor(opts) {
  6790. opts.pix = opts.pixelRatio ? opts.pixelRatio : 1;
  6791. opts.fontSize = opts.fontSize ? opts.fontSize : 13;
  6792. opts.fontColor = opts.fontColor ? opts.fontColor : config.fontColor;
  6793. if (opts.background == "" || opts.background == "none") {
  6794. opts.background = "#FFFFFF"
  6795. }
  6796. opts.title = assign({}, opts.title);
  6797. opts.subtitle = assign({}, opts.subtitle);
  6798. opts.duration = opts.duration ? opts.duration : 1000;
  6799. opts.yAxis = assign({}, {
  6800. data: [],
  6801. showTitle: false,
  6802. disabled: false,
  6803. disableGrid: false,
  6804. gridSet: 'number',
  6805. splitNumber: 5,
  6806. gridType: 'solid',
  6807. dashLength: 4 * opts.pix,
  6808. gridColor: '#cccccc',
  6809. padding: 10,
  6810. fontColor: '#666666'
  6811. }, opts.yAxis);
  6812. opts.xAxis = assign({}, {
  6813. rotateLabel: false,
  6814. rotateAngle:45,
  6815. disabled: false,
  6816. disableGrid: false,
  6817. splitNumber: 5,
  6818. calibration:false,
  6819. fontColor: '#666666',
  6820. fontSize: 13,
  6821. lineHeight: 20,
  6822. marginTop: 0,
  6823. gridType: 'solid',
  6824. dashLength: 4,
  6825. scrollAlign: 'left',
  6826. boundaryGap: 'center',
  6827. axisLine: true,
  6828. axisLineColor: '#cccccc',
  6829. titleFontSize: 13,
  6830. titleOffsetY: 0,
  6831. titleOffsetX: 0,
  6832. titleFontColor: '#666666'
  6833. }, opts.xAxis);
  6834. opts.xAxis.scrollPosition = opts.xAxis.scrollAlign;
  6835. opts.legend = assign({}, {
  6836. show: true,
  6837. position: 'bottom',
  6838. float: 'center',
  6839. backgroundColor: 'rgba(0,0,0,0)',
  6840. borderColor: 'rgba(0,0,0,0)',
  6841. borderWidth: 0,
  6842. padding: 5,
  6843. margin: 5,
  6844. itemGap: 10,
  6845. fontSize: opts.fontSize,
  6846. lineHeight: opts.fontSize,
  6847. fontColor: opts.fontColor,
  6848. formatter: {},
  6849. hiddenColor: '#CECECE'
  6850. }, opts.legend);
  6851. opts.extra = assign({
  6852. tooltip:{
  6853. legendShape: 'auto'
  6854. }
  6855. }, opts.extra);
  6856. opts.rotate = opts.rotate ? true : false;
  6857. opts.animation = opts.animation ? true : false;
  6858. opts.rotate = opts.rotate ? true : false;
  6859. opts.canvas2d = opts.canvas2d ? true : false;
  6860. let config = assign({}, config);
  6861. config.color = opts.color ? opts.color : config.color;
  6862. if (opts.type == 'pie') {
  6863. config.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.pie.labelWidth * opts.pix || config.pieChartLinePadding * opts.pix;
  6864. }
  6865. if (opts.type == 'ring') {
  6866. config.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.ring.labelWidth * opts.pix || config.pieChartLinePadding * opts.pix;
  6867. }
  6868. if (opts.type == 'rose') {
  6869. config.pieChartLinePadding = opts.dataLabel === false ? 0 : opts.extra.rose.labelWidth * opts.pix || config.pieChartLinePadding * opts.pix;
  6870. }
  6871. config.pieChartTextPadding = opts.dataLabel === false ? 0 : config.pieChartTextPadding * opts.pix;
  6872. //屏幕旋转
  6873. config.rotate = opts.rotate;
  6874. if (opts.rotate) {
  6875. let tempWidth = opts.width;
  6876. let tempHeight = opts.height;
  6877. opts.width = tempHeight;
  6878. opts.height = tempWidth;
  6879. }
  6880. //适配高分屏
  6881. opts.padding = opts.padding ? opts.padding : config.padding;
  6882. config.yAxisWidth = config.yAxisWidth * opts.pix;
  6883. config.fontSize = opts.fontSize * opts.pix;
  6884. config.titleFontSize = config.titleFontSize * opts.pix;
  6885. config.subtitleFontSize = config.subtitleFontSize * opts.pix;
  6886. if(!opts.context){
  6887. throw new Error('[uCharts] 未获取到context!注意:v2.0版本后,需要自行获取canvas的绘图上下文并传入opts.context!');
  6888. }
  6889. this.context = opts.context;
  6890. if (!this.context.setTextAlign) {
  6891. this.context.setStrokeStyle = function(e) {
  6892. return this.strokeStyle = e;
  6893. }
  6894. this.context.setLineWidth = function(e) {
  6895. return this.lineWidth = e;
  6896. }
  6897. this.context.setLineCap = function(e) {
  6898. return this.lineCap = e;
  6899. }
  6900. this.context.setFontSize = function(e) {
  6901. return this.font = e + "px sans-serif";
  6902. }
  6903. this.context.setFillStyle = function(e) {
  6904. return this.fillStyle = e;
  6905. }
  6906. this.context.setTextAlign = function(e) {
  6907. return this.textAlign = e;
  6908. }
  6909. this.context.setTextBaseline = function(e) {
  6910. return this.textBaseline = e;
  6911. }
  6912. this.context.setShadow = function(offsetX,offsetY,blur,color) {
  6913. this.shadowColor = color;
  6914. this.shadowOffsetX = offsetX;
  6915. this.shadowOffsetY = offsetY;
  6916. this.shadowBlur = blur;
  6917. }
  6918. this.context.draw = function() {}
  6919. }
  6920. //兼容NVUEsetLineDash
  6921. if(!this.context.setLineDash){
  6922. this.context.setLineDash = function(e) {}
  6923. }
  6924. opts.chartData = {};
  6925. this.uevent = new uChartsEvent();
  6926. this.scrollOption = {
  6927. currentOffset: 0,
  6928. startTouchX: 0,
  6929. distance: 0,
  6930. lastMoveTime: 0
  6931. };
  6932. this.opts = opts;
  6933. this.config = config;
  6934. drawCharts.call(this, opts.type, opts, config, this.context);
  6935. };
  6936. updateData() {
  6937. let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  6938. this.opts = assign({}, this.opts, data);
  6939. this.opts.updateData = true;
  6940. let scrollPosition = data.scrollPosition || 'current';
  6941. switch (scrollPosition) {
  6942. case 'current':
  6943. this.opts._scrollDistance_ = this.scrollOption.currentOffset;
  6944. break;
  6945. case 'left':
  6946. this.opts._scrollDistance_ = 0;
  6947. this.scrollOption = {
  6948. currentOffset: 0,
  6949. startTouchX: 0,
  6950. distance: 0,
  6951. lastMoveTime: 0
  6952. };
  6953. break;
  6954. case 'right':
  6955. let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context), yAxisWidth = _calYAxisData.yAxisWidth;
  6956. this.config.yAxisWidth = yAxisWidth;
  6957. let offsetLeft = 0;
  6958. let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config), xAxisPoints = _getXAxisPoints0.xAxisPoints,
  6959. startX = _getXAxisPoints0.startX,
  6960. endX = _getXAxisPoints0.endX,
  6961. eachSpacing = _getXAxisPoints0.eachSpacing;
  6962. let totalWidth = eachSpacing * (xAxisPoints.length - 1);
  6963. let screenWidth = endX - startX;
  6964. offsetLeft = screenWidth - totalWidth;
  6965. this.scrollOption = {
  6966. currentOffset: offsetLeft,
  6967. startTouchX: offsetLeft,
  6968. distance: 0,
  6969. lastMoveTime: 0
  6970. };
  6971. this.opts._scrollDistance_ = offsetLeft;
  6972. break;
  6973. }
  6974. drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
  6975. };
  6976. zoom() {
  6977. let val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.opts.xAxis.itemCount;
  6978. if (this.opts.enableScroll !== true) {
  6979. console.log('[uCharts] 请启用滚动条后使用')
  6980. return;
  6981. }
  6982. //当前屏幕中间点
  6983. let centerPoint = Math.round(Math.abs(this.scrollOption.currentOffset) / this.opts.chartData.eachSpacing) + Math.round(this.opts.xAxis.itemCount / 2);
  6984. this.opts.animation = false;
  6985. this.opts.xAxis.itemCount = val.itemCount;
  6986. //重新计算x轴偏移距离
  6987. let _calYAxisData = calYAxisData(this.opts.series, this.opts, this.config, this.context),
  6988. yAxisWidth = _calYAxisData.yAxisWidth;
  6989. this.config.yAxisWidth = yAxisWidth;
  6990. let offsetLeft = 0;
  6991. let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
  6992. xAxisPoints = _getXAxisPoints0.xAxisPoints,
  6993. startX = _getXAxisPoints0.startX,
  6994. endX = _getXAxisPoints0.endX,
  6995. eachSpacing = _getXAxisPoints0.eachSpacing;
  6996. let centerLeft = eachSpacing * centerPoint;
  6997. let screenWidth = endX - startX;
  6998. let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
  6999. offsetLeft = screenWidth / 2 - centerLeft;
  7000. if (offsetLeft > 0) {
  7001. offsetLeft = 0;
  7002. }
  7003. if (offsetLeft < MaxLeft) {
  7004. offsetLeft = MaxLeft;
  7005. }
  7006. this.scrollOption = {
  7007. currentOffset: offsetLeft,
  7008. startTouchX: 0,
  7009. distance: 0,
  7010. lastMoveTime: 0
  7011. };
  7012. calValidDistance(this, offsetLeft, this.opts.chartData, this.config, this.opts);
  7013. this.opts._scrollDistance_ = offsetLeft;
  7014. drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
  7015. };
  7016. dobuleZoom(e) {
  7017. if (this.opts.enableScroll !== true) {
  7018. console.log('[uCharts] 请启用滚动条后使用')
  7019. return;
  7020. }
  7021. const tcs = e.changedTouches;
  7022. if (tcs.length < 2) {
  7023. return;
  7024. }
  7025. for (let i = 0; i < tcs.length; i++) {
  7026. tcs[i].x = tcs[i].x ? tcs[i].x : tcs[i].clientX;
  7027. tcs[i].y = tcs[i].y ? tcs[i].y : tcs[i].clientY;
  7028. }
  7029. const ntcs = [getTouches(tcs[0], this.opts, e),getTouches(tcs[1], this.opts, e)];
  7030. const xlength = Math.abs(ntcs[0].x - ntcs[1].x);
  7031. // 记录初始的两指之间的数据
  7032. if(!this.scrollOption.moveCount){
  7033. let cts0 = {changedTouches:[{x:tcs[0].x,y:this.opts.area[0] / this.opts.pix + 2}]};
  7034. let cts1 = {changedTouches:[{x:tcs[1].x,y:this.opts.area[0] / this.opts.pix + 2}]};
  7035. if(this.opts.rotate){
  7036. cts0 = {changedTouches:[{x:this.opts.height / this.opts.pix - this.opts.area[0] / this.opts.pix - 2,y:tcs[0].y}]};
  7037. cts1 = {changedTouches:[{x:this.opts.height / this.opts.pix - this.opts.area[0] / this.opts.pix - 2,y:tcs[1].y}]};
  7038. }
  7039. const moveCurrent1 = this.getCurrentDataIndex(cts0).index;
  7040. const moveCurrent2 = this.getCurrentDataIndex(cts1).index;
  7041. const moveCount = Math.abs(moveCurrent1 - moveCurrent2);
  7042. this.scrollOption.moveCount = moveCount;
  7043. this.scrollOption.moveCurrent1 = Math.min(moveCurrent1, moveCurrent2);
  7044. this.scrollOption.moveCurrent2 = Math.max(moveCurrent1, moveCurrent2);
  7045. return;
  7046. }
  7047. let currentEachSpacing = xlength / this.scrollOption.moveCount;
  7048. let itemCount = (this.opts.width - this.opts.area[1] - this.opts.area[3]) / currentEachSpacing;
  7049. itemCount = itemCount <= 2 ? 2 : itemCount;
  7050. itemCount = itemCount >= this.opts.categories.length ? this.opts.categories.length : itemCount;
  7051. this.opts.animation = false;
  7052. this.opts.xAxis.itemCount = itemCount;
  7053. // 重新计算滚动条偏移距离
  7054. let offsetLeft = 0;
  7055. let _getXAxisPoints0 = getXAxisPoints(this.opts.categories, this.opts, this.config),
  7056. xAxisPoints = _getXAxisPoints0.xAxisPoints,
  7057. startX = _getXAxisPoints0.startX,
  7058. endX = _getXAxisPoints0.endX,
  7059. eachSpacing = _getXAxisPoints0.eachSpacing;
  7060. let currentLeft = eachSpacing * this.scrollOption.moveCurrent1;
  7061. let screenWidth = endX - startX;
  7062. let MaxLeft = screenWidth - eachSpacing * (xAxisPoints.length - 1);
  7063. offsetLeft = -currentLeft+Math.min(ntcs[0].x,ntcs[1].x)-this.opts.area[3]-eachSpacing;
  7064. if (offsetLeft > 0) {
  7065. offsetLeft = 0;
  7066. }
  7067. if (offsetLeft < MaxLeft) {
  7068. offsetLeft = MaxLeft;
  7069. }
  7070. this.scrollOption.currentOffset= offsetLeft;
  7071. this.scrollOption.startTouchX= 0;
  7072. this.scrollOption.distance=0;
  7073. calValidDistance(this, offsetLeft, this.opts.chartData, this.config, this.opts);
  7074. this.opts._scrollDistance_ = offsetLeft;
  7075. drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
  7076. }
  7077. stopAnimation() {
  7078. this.animationInstance && this.animationInstance.stop();
  7079. };
  7080. addEventListener(type, listener) {
  7081. this.uevent.addEventListener(type, listener);
  7082. };
  7083. delEventListener(type) {
  7084. this.uevent.delEventListener(type);
  7085. };
  7086. getCurrentDataIndex(e) {
  7087. let touches = null;
  7088. if (e.changedTouches) {
  7089. touches = e.changedTouches[0];
  7090. } else {
  7091. touches = e.mp.changedTouches[0];
  7092. }
  7093. if (touches) {
  7094. let _touches$ = getTouches(touches, this.opts, e);
  7095. if (this.opts.type === 'pie' || this.opts.type === 'ring') {
  7096. return findPieChartCurrentIndex({
  7097. x: _touches$.x,
  7098. y: _touches$.y
  7099. }, this.opts.chartData.pieData, this.opts);
  7100. } else if (this.opts.type === 'rose') {
  7101. return findRoseChartCurrentIndex({
  7102. x: _touches$.x,
  7103. y: _touches$.y
  7104. }, this.opts.chartData.pieData, this.opts);
  7105. } else if (this.opts.type === 'radar') {
  7106. return findRadarChartCurrentIndex({
  7107. x: _touches$.x,
  7108. y: _touches$.y
  7109. }, this.opts.chartData.radarData, this.opts.categories.length);
  7110. } else if (this.opts.type === 'funnel') {
  7111. return findFunnelChartCurrentIndex({
  7112. x: _touches$.x,
  7113. y: _touches$.y
  7114. }, this.opts.chartData.funnelData);
  7115. } else if (this.opts.type === 'map') {
  7116. return findMapChartCurrentIndex({
  7117. x: _touches$.x,
  7118. y: _touches$.y
  7119. }, this.opts);
  7120. } else if (this.opts.type === 'word') {
  7121. return findWordChartCurrentIndex({
  7122. x: _touches$.x,
  7123. y: _touches$.y
  7124. }, this.opts.chartData.wordCloudData);
  7125. } else if (this.opts.type === 'bar') {
  7126. return findBarChartCurrentIndex({
  7127. x: _touches$.x,
  7128. y: _touches$.y
  7129. }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
  7130. } else {
  7131. return findCurrentIndex({
  7132. x: _touches$.x,
  7133. y: _touches$.y
  7134. }, this.opts.chartData.calPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
  7135. }
  7136. }
  7137. return -1;
  7138. };
  7139. getLegendDataIndex(e) {
  7140. let touches = null;
  7141. if (e.changedTouches) {
  7142. touches = e.changedTouches[0];
  7143. } else {
  7144. touches = e.mp.changedTouches[0];
  7145. }
  7146. if (touches) {
  7147. let _touches$ = getTouches(touches, this.opts, e);
  7148. return findLegendIndex({
  7149. x: _touches$.x,
  7150. y: _touches$.y
  7151. }, this.opts.chartData.legendData);
  7152. }
  7153. return -1;
  7154. };
  7155. touchLegend(e) {
  7156. let option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  7157. let touches = null;
  7158. if (e.changedTouches) {
  7159. touches = e.changedTouches[0];
  7160. } else {
  7161. touches = e.mp.changedTouches[0];
  7162. }
  7163. if (touches) {
  7164. let _touches$ = getTouches(touches, this.opts, e);
  7165. let index = this.getLegendDataIndex(e);
  7166. if (index >= 0) {
  7167. if (this.opts.type == 'candle') {
  7168. this.opts.seriesMA[index].show = !this.opts.seriesMA[index].show;
  7169. } else {
  7170. this.opts.series[index].show = !this.opts.series[index].show;
  7171. }
  7172. this.opts.animation = option.animation ? true : false;
  7173. this.opts._scrollDistance_ = this.scrollOption.currentOffset;
  7174. drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
  7175. }
  7176. }
  7177. };
  7178. showToolTip(e) {
  7179. let option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  7180. let touches = null;
  7181. if (e.changedTouches) {
  7182. touches = e.changedTouches[0];
  7183. } else {
  7184. touches = e.mp.changedTouches[0];
  7185. }
  7186. if (!touches) {
  7187. console.log("[uCharts] 未获取到event坐标信息");
  7188. }
  7189. let _touches$ = getTouches(touches, this.opts, e);
  7190. let currentOffset = this.scrollOption.currentOffset;
  7191. let opts = assign({}, this.opts, {
  7192. _scrollDistance_: currentOffset,
  7193. animation: false
  7194. });
  7195. if (this.opts.type === 'line' || this.opts.type === 'area' || this.opts.type === 'column' || this.opts.type === 'scatter' || this.opts.type === 'bubble') {
  7196. let current = this.getCurrentDataIndex(e);
  7197. let index = option.index == undefined ? current.index : option.index;
  7198. if (index > -1 || index.length>0) {
  7199. let seriesData = getSeriesDataItem(this.opts.series, index, current.group);
  7200. if (seriesData.length !== 0) {
  7201. let _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option),
  7202. textList = _getToolTipData.textList,
  7203. offset = _getToolTipData.offset;
  7204. offset.y = _touches$.y;
  7205. opts.tooltip = {
  7206. textList: option.textList !== undefined ? option.textList : textList,
  7207. offset: option.offset !== undefined ? option.offset : offset,
  7208. option: option,
  7209. index: index,
  7210. group: current.group
  7211. };
  7212. }
  7213. }
  7214. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7215. }
  7216. if (this.opts.type === 'mount') {
  7217. let index = option.index == undefined ? this.getCurrentDataIndex(e).index : option.index;
  7218. if (index > -1) {
  7219. let opts = assign({}, this.opts, {animation: false});
  7220. let seriesData = assign({}, opts._series_[index]);
  7221. let textList = [{
  7222. text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data,
  7223. color: seriesData.color,
  7224. legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
  7225. }];
  7226. let offset = {
  7227. x: opts.chartData.calPoints[index].x,
  7228. y: _touches$.y
  7229. };
  7230. opts.tooltip = {
  7231. textList: option.textList ? option.textList : textList,
  7232. offset: option.offset !== undefined ? option.offset : offset,
  7233. option: option,
  7234. index: index
  7235. };
  7236. }
  7237. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7238. }
  7239. if (this.opts.type === 'bar') {
  7240. let current = this.getCurrentDataIndex(e);
  7241. let index = option.index == undefined ? current.index : option.index;
  7242. if (index > -1 || index.length>0) {
  7243. let seriesData = getSeriesDataItem(this.opts.series, index, current.group);
  7244. if (seriesData.length !== 0) {
  7245. let _getToolTipData = getToolTipData(seriesData, this.opts, index, current.group, this.opts.categories, option),
  7246. textList = _getToolTipData.textList,
  7247. offset = _getToolTipData.offset;
  7248. offset.x = _touches$.x;
  7249. opts.tooltip = {
  7250. textList: option.textList !== undefined ? option.textList : textList,
  7251. offset: option.offset !== undefined ? option.offset : offset,
  7252. option: option,
  7253. index: index
  7254. };
  7255. }
  7256. }
  7257. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7258. }
  7259. if (this.opts.type === 'mix') {
  7260. let current = this.getCurrentDataIndex(e);
  7261. let index = option.index == undefined ? current.index : option.index;
  7262. if (index > -1) {
  7263. let currentOffset = this.scrollOption.currentOffset;
  7264. let opts = assign({}, this.opts, {
  7265. _scrollDistance_: currentOffset,
  7266. animation: false
  7267. });
  7268. let seriesData = getSeriesDataItem(this.opts.series, index);
  7269. if (seriesData.length !== 0) {
  7270. let _getMixToolTipData = getMixToolTipData(seriesData, this.opts, index, this.opts.categories, option),
  7271. textList = _getMixToolTipData.textList,
  7272. offset = _getMixToolTipData.offset;
  7273. offset.y = _touches$.y;
  7274. opts.tooltip = {
  7275. textList: option.textList ? option.textList : textList,
  7276. offset: option.offset !== undefined ? option.offset : offset,
  7277. option: option,
  7278. index: index
  7279. };
  7280. }
  7281. }
  7282. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7283. }
  7284. if (this.opts.type === 'candle') {
  7285. let current = this.getCurrentDataIndex(e);
  7286. let index = option.index == undefined ? current.index : option.index;
  7287. if (index > -1) {
  7288. let currentOffset = this.scrollOption.currentOffset;
  7289. let opts = assign({}, this.opts, {
  7290. _scrollDistance_: currentOffset,
  7291. animation: false
  7292. });
  7293. let seriesData = getSeriesDataItem(this.opts.series, index);
  7294. if (seriesData.length !== 0) {
  7295. let _getToolTipData = getCandleToolTipData(this.opts.series[0].data, seriesData, this.opts, index, this.opts.categories, this.opts.extra.candle, option),
  7296. textList = _getToolTipData.textList,
  7297. offset = _getToolTipData.offset;
  7298. offset.y = _touches$.y;
  7299. opts.tooltip = {
  7300. textList: option.textList ? option.textList : textList,
  7301. offset: option.offset !== undefined ? option.offset : offset,
  7302. option: option,
  7303. index: index
  7304. };
  7305. }
  7306. }
  7307. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7308. }
  7309. if (this.opts.type === 'pie' || this.opts.type === 'ring' || this.opts.type === 'rose' || this.opts.type === 'funnel') {
  7310. let index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
  7311. if (index > -1) {
  7312. let opts = assign({}, this.opts, {animation: false});
  7313. let seriesData = assign({}, opts._series_[index]);
  7314. let textList = [{
  7315. text: option.formatter ? option.formatter(seriesData, undefined, index, opts) : seriesData.name + ': ' + seriesData.data,
  7316. color: seriesData.color,
  7317. legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
  7318. }];
  7319. let offset = {
  7320. x: _touches$.x,
  7321. y: _touches$.y
  7322. };
  7323. opts.tooltip = {
  7324. textList: option.textList ? option.textList : textList,
  7325. offset: option.offset !== undefined ? option.offset : offset,
  7326. option: option,
  7327. index: index
  7328. };
  7329. }
  7330. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7331. }
  7332. if (this.opts.type === 'map') {
  7333. let index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
  7334. if (index > -1) {
  7335. let opts = assign({}, this.opts, {animation: false});
  7336. let seriesData = assign({}, this.opts.series[index]);
  7337. seriesData.name = seriesData.properties.name
  7338. let textList = [{
  7339. text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name,
  7340. color: seriesData.color,
  7341. legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
  7342. }];
  7343. let offset = {
  7344. x: _touches$.x,
  7345. y: _touches$.y
  7346. };
  7347. opts.tooltip = {
  7348. textList: option.textList ? option.textList : textList,
  7349. offset: option.offset !== undefined ? option.offset : offset,
  7350. option: option,
  7351. index: index
  7352. };
  7353. }
  7354. opts.updateData = false;
  7355. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7356. }
  7357. if (this.opts.type === 'word') {
  7358. let index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
  7359. if (index > -1) {
  7360. let opts = assign({}, this.opts, {animation: false});
  7361. let seriesData = assign({}, this.opts.series[index]);
  7362. let textList = [{
  7363. text: option.formatter ? option.formatter(seriesData, undefined, index, this.opts) : seriesData.name,
  7364. color: seriesData.color,
  7365. legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? seriesData.legendShape : this.opts.extra.tooltip.legendShape
  7366. }];
  7367. let offset = {
  7368. x: _touches$.x,
  7369. y: _touches$.y
  7370. };
  7371. opts.tooltip = {
  7372. textList: option.textList ? option.textList : textList,
  7373. offset: option.offset !== undefined ? option.offset : offset,
  7374. option: option,
  7375. index: index
  7376. };
  7377. }
  7378. opts.updateData = false;
  7379. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7380. }
  7381. if (this.opts.type === 'radar') {
  7382. let index = option.index == undefined ? this.getCurrentDataIndex(e) : option.index;
  7383. if (index > -1) {
  7384. let opts = assign({}, this.opts, {animation: false});
  7385. let seriesData = getSeriesDataItem(this.opts.series, index);
  7386. if (seriesData.length !== 0) {
  7387. let textList = seriesData.map((item) => {
  7388. return {
  7389. text: option.formatter ? option.formatter(item, this.opts.categories[index], index, this.opts) : item.name + ': ' + item.data,
  7390. color: item.color,
  7391. legendShape: this.opts.extra.tooltip.legendShape == 'auto' ? item.legendShape : this.opts.extra.tooltip.legendShape
  7392. };
  7393. });
  7394. let offset = {
  7395. x: _touches$.x,
  7396. y: _touches$.y
  7397. };
  7398. opts.tooltip = {
  7399. textList: option.textList ? option.textList : textList,
  7400. offset: option.offset !== undefined ? option.offset : offset,
  7401. option: option,
  7402. index: index
  7403. };
  7404. }
  7405. }
  7406. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7407. }
  7408. };
  7409. translate(distance) {
  7410. this.scrollOption = {
  7411. currentOffset: distance,
  7412. startTouchX: distance,
  7413. distance: 0,
  7414. lastMoveTime: 0
  7415. };
  7416. let opts = assign({}, this.opts, {
  7417. _scrollDistance_: distance,
  7418. animation: false
  7419. });
  7420. drawCharts.call(this, this.opts.type, opts, this.config, this.context);
  7421. };
  7422. scrollStart(e) {
  7423. let touches = null;
  7424. if (e.changedTouches) {
  7425. touches = e.changedTouches[0];
  7426. } else {
  7427. touches = e.mp.changedTouches[0];
  7428. }
  7429. let _touches$ = getTouches(touches, this.opts, e);
  7430. if (touches && this.opts.enableScroll === true) {
  7431. this.scrollOption.startTouchX = _touches$.x;
  7432. }
  7433. };
  7434. scroll(e) {
  7435. if (this.scrollOption.lastMoveTime === 0) {
  7436. this.scrollOption.lastMoveTime = Date.now();
  7437. }
  7438. let Limit = this.opts.touchMoveLimit || 60;
  7439. let currMoveTime = Date.now();
  7440. let duration = currMoveTime - this.scrollOption.lastMoveTime;
  7441. if (duration < Math.floor(1000 / Limit)) return;
  7442. if (this.scrollOption.startTouchX == 0) return;
  7443. this.scrollOption.lastMoveTime = currMoveTime;
  7444. let touches = null;
  7445. if (e.changedTouches) {
  7446. touches = e.changedTouches[0];
  7447. } else {
  7448. touches = e.mp.changedTouches[0];
  7449. }
  7450. if (touches && this.opts.enableScroll === true) {
  7451. let _touches$ = getTouches(touches, this.opts, e);
  7452. let _distance;
  7453. _distance = _touches$.x - this.scrollOption.startTouchX;
  7454. let currentOffset = this.scrollOption.currentOffset;
  7455. let validDistance = calValidDistance(this, currentOffset + _distance, this.opts.chartData, this.config, this.opts);
  7456. this.scrollOption.distance = _distance = validDistance - currentOffset;
  7457. let opts = assign({}, this.opts, {
  7458. _scrollDistance_: currentOffset + _distance,
  7459. animation: false
  7460. });
  7461. this.opts = opts;
  7462. drawCharts.call(this, opts.type, opts, this.config, this.context);
  7463. return currentOffset + _distance;
  7464. }
  7465. };
  7466. scrollEnd(e) {
  7467. if (this.opts.enableScroll === true) {
  7468. let _scrollOption = this.scrollOption,
  7469. currentOffset = _scrollOption.currentOffset,
  7470. distance = _scrollOption.distance;
  7471. this.scrollOption.currentOffset = currentOffset + distance;
  7472. this.scrollOption.distance = 0;
  7473. this.scrollOption.moveCount = 0;
  7474. }
  7475. }
  7476. }
  7477. export default uCharts;